From 31680a1bc9520c1097634e083cec0d97c3bda3b6 Mon Sep 17 00:00:00 2001 From: busya Date: Mon, 25 May 2026 08:36:33 +0300 Subject: [PATCH] fix(maintenance): auto-expiry + adaptive markdown height + tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Auto-expiry: expired events auto-end on GET /events via task manager - Height: _estimate_markdown_height adapted to unit=8px scale with padding detection - CRITICAL-1: removed dead import remove_chart_from_position (QA finding) - CRITICAL-2: added chart alive check in ensure_banner_chart (QA finding) - CRITICAL-3: fixed test assertions update_markdown_chart → update_banner_on_dashboard - @POST contract: fixed return range [2,12] → [19,200] - Tests: 8 new tests (auto-expiry + layout height) --- .axiom/semantic_index/index.json | 17992 +++++++++------- .env.enterprise-clean.example | 5 - .kilo/agents/backend-coder.md | 2 +- .kilo/agents/swarm-master.md | 2 +- .opencode/agents/fullstack-coder.md | 2 +- .opencode/agents/reflection-agent.md | 2 +- .opencode/agents/swarm-master.md | 4 +- backend/.axiom/runtime/belief_events.jsonl | 4 + backend/:memory:test_auth | Bin 0 -> 909312 bytes backend/:memory:test_main | Bin 0 -> 917504 bytes backend/:memory:test_tasks | Bin 0 -> 634880 bytes backend/alembic/env.py | 2 +- backend/src/api/routes/__init__.py | 1 + .../src/api/routes/maintenance/__init__.py | 10 + backend/src/api/routes/maintenance/_router.py | 14 + backend/src/api/routes/maintenance/_routes.py | 562 + .../src/api/routes/maintenance/_schemas.py | 156 + backend/src/api/routes/settings.py | 11 + backend/src/api/routes/validation.py | 18 +- backend/src/app.py | 3 + backend/src/core/config_manager.py | 8 + backend/src/core/config_models.py | 15 +- backend/src/core/database.py | 1 + backend/src/core/logger.py | 9 + backend/src/core/scheduler.py | 182 + backend/src/core/superset_client/__init__.py | 3 + .../core/superset_client/_dashboards_write.py | 291 + backend/src/core/superset_client/_datasets.py | 8 +- .../src/core/superset_client/_layout_utils.py | 197 + backend/src/core/timezone.py | 91 + backend/src/models/maintenance.py | 215 + backend/src/models/storage.py | 2 +- backend/src/plugins/git_plugin.py | 30 +- backend/src/plugins/llm_analysis/service.py | 95 +- backend/src/plugins/maintenance_banner.py | 176 + .../src/scripts/seed_superset_load_test.py | 18 +- backend/src/services/health_service.py | 4 + backend/src/services/maintenance/__init__.py | 30 + .../services/maintenance/_banner_renderer.py | 254 + .../services/maintenance/_chart_manager.py | 359 + .../maintenance/_dashboard_scanner.py | 205 + .../services/maintenance/_orchestrators.py | 338 + backend/src/services/sql_table_extractor.py | 226 + .../src/services/validation_run_service.py | 7 +- backend/tests/test_core_scheduler.py | 345 +- backend/tests/test_layout_utils.py | 55 + backend/tests/test_maintenance_api.py | 466 + backend/tests/test_maintenance_service.py | 622 + backend/tests/test_sql_table_extractor.py | 118 + backend/tests/test_storage_audit_fixes.py | 2 +- backend/tests/test_storage_config.py | 364 + build.sh | 16 +- docker-compose.e2e.yml | 3 +- docker-compose.enterprise-clean.yml | 6 +- docker-compose.yml | 5 +- frontend/e2e/fixtures/global-setup.js | 9 +- frontend/e2e/run-enterprise-clean-e2e.sh | 566 + .../e2e/tests/enterprise-clean-setup.e2e.js | 182 + frontend/e2e/tests/live-project-check.e2e.js | 321 + frontend/src/components/TaskHistory.svelte | 12 +- frontend/src/lib/api/maintenance.js | 69 + .../DashboardMaintenanceBadge.svelte | 47 + .../components/MaintenanceEventsTable.svelte | 283 + .../MaintenanceSettingsPanel.svelte | 324 + .../components/StartMaintenanceForm.svelte | 279 + .../health/ScheduleAtAGlance.svelte | 407 + .../components/layout/sidebarNavigation.js | 12 + .../translate/ScheduleConfig.svelte | 16 +- frontend/src/lib/i18n/index.ts | 4 + frontend/src/lib/i18n/locales/en/health.json | 11 +- .../src/lib/i18n/locales/en/maintenance.json | 90 + frontend/src/lib/i18n/locales/en/nav.json | 1 + .../src/lib/i18n/locales/en/settings.json | 26 +- .../src/lib/i18n/locales/en/translate.json | 5 +- .../src/lib/i18n/locales/en/validation.json | 3 + frontend/src/lib/i18n/locales/ru/health.json | 11 +- .../src/lib/i18n/locales/ru/maintenance.json | 90 + frontend/src/lib/i18n/locales/ru/nav.json | 1 + .../src/lib/i18n/locales/ru/settings.json | 26 +- .../src/lib/i18n/locales/ru/translate.json | 5 +- .../src/lib/i18n/locales/ru/validation.json | 3 + frontend/src/lib/stores/maintenance.svelte.js | 180 + frontend/src/lib/ui/HelpTooltip.svelte | 75 + frontend/src/routes/dashboards/+page.svelte | 19 +- .../src/routes/dashboards/health/+page.svelte | 36 +- frontend/src/routes/maintenance/+page.svelte | 81 + frontend/src/routes/migration/+page.svelte | 2 +- .../routes/reports/llm/[taskId]/+page.svelte | 4 +- frontend/src/routes/settings/+page.svelte | 16 + .../routes/settings/FeaturesSettings.svelte | 19 +- .../src/routes/settings/LlmSettings.svelte | 121 +- .../routes/settings/MigrationSettings.svelte | 17 +- .../src/routes/settings/SystemSettings.svelte | 84 + frontend/src/routes/settings/git/+page.svelte | 105 +- .../src/routes/validation/[id]/+page.svelte | 28 +- frontend/tests/maintenance-api.test.ts | 42 + frontend/tests/maintenance-store.test.ts | 174 + frontend/tests/maintenance.test.ts | 189 + frontend/vite.config.js | 4 +- frontend/vitest.config.js | 3 +- 100 files changed, 19635 insertions(+), 7923 deletions(-) create mode 100644 backend/.axiom/runtime/belief_events.jsonl create mode 100644 backend/:memory:test_auth create mode 100644 backend/:memory:test_main create mode 100644 backend/:memory:test_tasks create mode 100644 backend/src/api/routes/maintenance/__init__.py create mode 100644 backend/src/api/routes/maintenance/_router.py create mode 100644 backend/src/api/routes/maintenance/_routes.py create mode 100644 backend/src/api/routes/maintenance/_schemas.py create mode 100644 backend/src/core/superset_client/_dashboards_write.py create mode 100644 backend/src/core/superset_client/_layout_utils.py create mode 100644 backend/src/core/timezone.py create mode 100644 backend/src/models/maintenance.py create mode 100644 backend/src/plugins/maintenance_banner.py create mode 100644 backend/src/services/maintenance/__init__.py create mode 100644 backend/src/services/maintenance/_banner_renderer.py create mode 100644 backend/src/services/maintenance/_chart_manager.py create mode 100644 backend/src/services/maintenance/_dashboard_scanner.py create mode 100644 backend/src/services/maintenance/_orchestrators.py create mode 100644 backend/src/services/sql_table_extractor.py create mode 100644 backend/tests/test_layout_utils.py create mode 100644 backend/tests/test_maintenance_api.py create mode 100644 backend/tests/test_maintenance_service.py create mode 100644 backend/tests/test_sql_table_extractor.py create mode 100644 backend/tests/test_storage_config.py create mode 100755 frontend/e2e/run-enterprise-clean-e2e.sh create mode 100644 frontend/e2e/tests/enterprise-clean-setup.e2e.js create mode 100644 frontend/e2e/tests/live-project-check.e2e.js create mode 100644 frontend/src/lib/api/maintenance.js create mode 100644 frontend/src/lib/components/DashboardMaintenanceBadge.svelte create mode 100644 frontend/src/lib/components/MaintenanceEventsTable.svelte create mode 100644 frontend/src/lib/components/MaintenanceSettingsPanel.svelte create mode 100644 frontend/src/lib/components/StartMaintenanceForm.svelte create mode 100644 frontend/src/lib/components/health/ScheduleAtAGlance.svelte create mode 100644 frontend/src/lib/i18n/locales/en/maintenance.json create mode 100644 frontend/src/lib/i18n/locales/ru/maintenance.json create mode 100644 frontend/src/lib/stores/maintenance.svelte.js create mode 100644 frontend/src/lib/ui/HelpTooltip.svelte create mode 100644 frontend/src/routes/maintenance/+page.svelte create mode 100644 frontend/src/routes/settings/SystemSettings.svelte create mode 100644 frontend/tests/maintenance-api.test.ts create mode 100644 frontend/tests/maintenance-store.test.ts create mode 100644 frontend/tests/maintenance.test.ts diff --git a/.axiom/semantic_index/index.json b/.axiom/semantic_index/index.json index 54293b3e..826afcd7 100644 --- a/.axiom/semantic_index/index.json +++ b/.axiom/semantic_index/index.json @@ -1,9 +1,9 @@ { - "generated_at": "2026-05-20T21:02:02.102482917Z", + "generated_at": "2026-05-21T17:00:02.724155271Z", "root_path": "/home/busya/dev/ss-tools", - "contract_count": 2710, + "contract_count": 2781, "edge_count": 1947, - "file_count": 647, + "file_count": 654, "contracts": [ { "contract_id": "SrcRoot", @@ -277,7 +277,7 @@ "contract_type": "Module", "file_path": "backend/src/api/routes/__init__.py", "start_line": 1, - "end_line": 60, + "end_line": 59, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -305,14 +305,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ApiRoutesModule [C:5] [TYPE Module] [SEMANTICS api, package, router, lazy, import]\n# @BRIEF Provide lazy route module loading to avoid heavyweight imports during tests.\n# @LAYER: API\n# @RELATION CALLS -> [ApiRoutesGetAttr]\n# @RELATION BINDS_TO -> [Route_Group_Contracts]\n# @PRE: FastAPI app initialized, route modules available in package\n# @POST: Route modules are lazily loadable via __getattr__\n# @INVARIANT: Only names listed in __all__ are importable via __getattr__.\n\n# #region Route_Group_Contracts [C:3] [TYPE Block]\n# @BRIEF Declare the canonical route-module registry used by lazy imports and app router inclusion.\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ConnectionsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @SIDE_EFFECT: Registers route group imports via __getattr__\n# @DATA_CONTRACT: Package -> RouterModule mapping\n__all__ = [\n \"admin\",\n \"assistant\",\n \"clean_release\",\n \"clean_release_v2\",\n \"connections\",\n \"dashboards\",\n \"dataset_review\",\n \"datasets\",\n \"environments\",\n \"git\",\n \"health\",\n \"llm\",\n \"mappings\",\n \"migration\",\n \"plugins\",\n \"profile\",\n \"reports\",\n \"settings\",\n \"storage\",\n \"tasks\",\n \"translate\",\n]\n# #endregion Route_Group_Contracts\n\n\n# #region ApiRoutesGetAttr [C:3] [TYPE Function]\n# @BRIEF Lazily import route module by attribute name.\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @PRE: name is module candidate exposed in __all__.\n# @POST: Returns imported submodule or raises AttributeError.\ndef __getattr__(name):\n if name in __all__:\n import importlib\n\n return importlib.import_module(f\".{name}\", __name__)\n raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\")\n\n\n# #endregion ApiRoutesGetAttr\n# #endregion ApiRoutesModule\n" + "body": "# #region ApiRoutesModule [C:5] [TYPE Module] [SEMANTICS api, package, router, lazy, import]\n# @BRIEF Provide lazy route module loading to avoid heavyweight imports during tests.\n# @LAYER: API\n# @RELATION CALLS -> [ApiRoutesGetAttr]\n# @RELATION BINDS_TO -> [Route_Group_Contracts]\n# @PRE: FastAPI app initialized, route modules available in package\n# @POST: Route modules are lazily loadable via __getattr__\n# @INVARIANT: Only names listed in __all__ are importable via __getattr__.\n\n# #region Route_Group_Contracts [C:3] [TYPE Block]\n# @BRIEF Declare the canonical route-module registry used by lazy imports and app router inclusion.\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @SIDE_EFFECT: Registers route group imports via __getattr__\n# @DATA_CONTRACT: Package -> RouterModule mapping\n__all__ = [\n \"admin\",\n \"assistant\",\n \"clean_release\",\n \"clean_release_v2\",\n \"dashboards\",\n \"dataset_review\",\n \"datasets\",\n \"environments\",\n \"git\",\n \"health\",\n \"llm\",\n \"mappings\",\n \"migration\",\n \"plugins\",\n \"profile\",\n \"reports\",\n \"settings\",\n \"storage\",\n \"tasks\",\n \"translate\",\n \"validation\",\n]\n# #endregion Route_Group_Contracts\n\n\n# #region ApiRoutesGetAttr [C:3] [TYPE Function]\n# @BRIEF Lazily import route module by attribute name.\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @PRE: name is module candidate exposed in __all__.\n# @POST: Returns imported submodule or raises AttributeError.\ndef __getattr__(name):\n if name in __all__:\n import importlib\n\n return importlib.import_module(f\".{name}\", __name__)\n raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\")\n\n\n# #endregion ApiRoutesGetAttr\n# #endregion ApiRoutesModule\n" }, { "contract_id": "Route_Group_Contracts", "contract_type": "Block", "file_path": "backend/src/api/routes/__init__.py", "start_line": 10, - "end_line": 43, + "end_line": 42, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -340,12 +340,6 @@ "target_id": "SettingsRouter", "target_ref": "[SettingsRouter]" }, - { - "source_id": "Route_Group_Contracts", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionsRouter", - "target_ref": "[ConnectionsRouter]" - }, { "source_id": "Route_Group_Contracts", "relation_type": "DEPENDS_ON", @@ -411,14 +405,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region Route_Group_Contracts [C:3] [TYPE Block]\n# @BRIEF Declare the canonical route-module registry used by lazy imports and app router inclusion.\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ConnectionsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @SIDE_EFFECT: Registers route group imports via __getattr__\n# @DATA_CONTRACT: Package -> RouterModule mapping\n__all__ = [\n \"admin\",\n \"assistant\",\n \"clean_release\",\n \"clean_release_v2\",\n \"connections\",\n \"dashboards\",\n \"dataset_review\",\n \"datasets\",\n \"environments\",\n \"git\",\n \"health\",\n \"llm\",\n \"mappings\",\n \"migration\",\n \"plugins\",\n \"profile\",\n \"reports\",\n \"settings\",\n \"storage\",\n \"tasks\",\n \"translate\",\n]\n# #endregion Route_Group_Contracts\n" + "body": "# #region Route_Group_Contracts [C:3] [TYPE Block]\n# @BRIEF Declare the canonical route-module registry used by lazy imports and app router inclusion.\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @SIDE_EFFECT: Registers route group imports via __getattr__\n# @DATA_CONTRACT: Package -> RouterModule mapping\n__all__ = [\n \"admin\",\n \"assistant\",\n \"clean_release\",\n \"clean_release_v2\",\n \"dashboards\",\n \"dataset_review\",\n \"datasets\",\n \"environments\",\n \"git\",\n \"health\",\n \"llm\",\n \"mappings\",\n \"migration\",\n \"plugins\",\n \"profile\",\n \"reports\",\n \"settings\",\n \"storage\",\n \"tasks\",\n \"translate\",\n \"validation\",\n]\n# #endregion Route_Group_Contracts\n" }, { "contract_id": "ApiRoutesGetAttr", "contract_type": "Function", "file_path": "backend/src/api/routes/__init__.py", - "start_line": 46, - "end_line": 59, + "start_line": 45, + "end_line": 58, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -1068,54 +1062,6 @@ "tier_source": "AutoCalculated", "body": "# #region test_release_reject_contract [TYPE Function]\n# @RELATION BINDS_TO -> CleanReleaseV2ReleaseApiTests\n# @BRIEF Verify reject endpoint returns successful rejection decision payload.\ndef test_release_reject_contract() -> None:\n \"\"\"Contract for reject endpoint.\"\"\"\n candidate_id, report_id = _seed_candidate_and_passed_report()\n reject_response = client.post(\n f\"/api/v2/clean-release/candidates/{candidate_id}/reject\",\n json={\"report_id\": report_id, \"decided_by\": \"api-test\", \"comment\": \"rejected\"},\n )\n assert reject_response.status_code == 200\n payload = reject_response.json()\n assert payload[\"status\"] == \"ok\"\n assert payload[\"decision\"] == \"REJECTED\"\n# #endregion test_release_reject_contract\n" }, - { - "contract_id": "test_list_connections_bootstraps_missing_table", - "contract_type": "Function", - "file_path": "backend/src/api/routes/__tests__/test_connections_routes.py", - "start_line": 39, - "end_line": 48, - "tier": "TIER_1", - "complexity": 2, - "metadata": { - "PURPOSE": "Ensure listing connections auto-creates missing table and returns empty payload." - }, - "relations": [ - { - "source_id": "test_list_connections_bootstraps_missing_table", - "relation_type": "BINDS_TO", - "target_id": "ConnectionsRoutesTests", - "target_ref": "ConnectionsRoutesTests" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region test_list_connections_bootstraps_missing_table [TYPE Function]\n# @RELATION BINDS_TO -> ConnectionsRoutesTests\n# @BRIEF Ensure listing connections auto-creates missing table and returns empty payload.\ndef test_list_connections_bootstraps_missing_table(db_session):\n from src.api.routes.connections import list_connections\n result = asyncio.run(list_connections(db=db_session))\n inspector = inspect(db_session.get_bind())\n assert result == []\n assert \"connection_configs\" in inspector.get_table_names()\n# #endregion test_list_connections_bootstraps_missing_table\n" - }, - { - "contract_id": "test_create_connection_bootstraps_missing_table", - "contract_type": "Function", - "file_path": "backend/src/api/routes/__tests__/test_connections_routes.py", - "start_line": 49, - "end_line": 68, - "tier": "TIER_1", - "complexity": 2, - "metadata": { - "PURPOSE": "Ensure connection creation bootstraps table and persists returned connection fields." - }, - "relations": [ - { - "source_id": "test_create_connection_bootstraps_missing_table", - "relation_type": "BINDS_TO", - "target_id": "ConnectionsRoutesTests", - "target_ref": "ConnectionsRoutesTests" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region test_create_connection_bootstraps_missing_table [TYPE Function]\n# @RELATION BINDS_TO -> ConnectionsRoutesTests\n# @BRIEF Ensure connection creation bootstraps table and persists returned connection fields.\ndef test_create_connection_bootstraps_missing_table(db_session):\n from src.api.routes.connections import ConnectionCreate, create_connection\n payload = ConnectionCreate(\n name=\"Analytics Warehouse\",\n type=\"postgres\",\n host=\"warehouse.internal\",\n port=5432,\n database=\"analytics\",\n username=\"reporter\",\n password=\"secret\",\n )\n created = asyncio.run(create_connection(connection=payload, db=db_session))\n inspector = inspect(db_session.get_bind())\n assert created.name == \"Analytics Warehouse\"\n assert created.host == \"warehouse.internal\"\n assert \"connection_configs\" in inspector.get_table_names()\n# #endregion test_create_connection_bootstraps_missing_table\n" - }, { "contract_id": "test_get_dashboards_success", "contract_type": "Function", @@ -2705,7 +2651,7 @@ "complexity": 2, "metadata": { "POST": "Returns task_id", - "PRE": "Valid env_id, dataset_ids, source_type", + "PRE": "Valid env_id, dataset_ids, source_type (sqllab)", "PURPOSE": "Validate map-columns request creates an async mapping task and returns its identifier.", "TEST": "POST /api/datasets/map-columns creates mapping task" }, @@ -2727,7 +2673,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region test_map_columns_success [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns request creates an async mapping task and returns its identifier.\n# @TEST: POST /api/datasets/map-columns creates mapping task\n# @PRE: Valid env_id, dataset_ids, source_type\n# @POST: Returns task_id\ndef test_map_columns_success(mock_deps):\n # Mock environment\n mock_env = MagicMock()\n mock_env.id = \"prod\"\n mock_deps[\"config\"].get_environments.return_value = [mock_env]\n # Mock task manager\n mock_task = MagicMock()\n mock_task.id = \"task-123\"\n mock_deps[\"task\"].create_task = AsyncMock(return_value=mock_task)\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [1, 2, 3], \"source_type\": \"postgresql\"},\n )\n assert response.status_code == 200\n data = response.json()\n assert \"task_id\" in data\n # @POST/@SIDE_EFFECT: create_task was called\n mock_deps[\"task\"].create_task.assert_called_once()\n# #endregion test_map_columns_success\n" + "body": "# #region test_map_columns_success [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns request creates an async mapping task and returns its identifier.\n# @TEST: POST /api/datasets/map-columns creates mapping task\n# @PRE: Valid env_id, dataset_ids, source_type (sqllab)\n# @POST: Returns task_id\ndef test_map_columns_success(mock_deps):\n # Mock environment\n mock_env = MagicMock()\n mock_env.id = \"prod\"\n mock_deps[\"config\"].get_environments.return_value = [mock_env]\n # Mock task manager\n mock_task = MagicMock()\n mock_task.id = \"task-123\"\n mock_deps[\"task\"].create_task = AsyncMock(return_value=mock_task)\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [1, 2, 3], \"source_type\": \"sqllab\", \"database_id\": 1},\n )\n assert response.status_code == 200\n data = response.json()\n assert \"task_id\" in data\n # @POST/@SIDE_EFFECT: create_task was called\n mock_deps[\"task\"].create_task.assert_called_once()\n# #endregion test_map_columns_success\n" }, { "contract_id": "test_map_columns_invalid_source_type", @@ -2739,7 +2685,7 @@ "complexity": 2, "metadata": { "POST": "Returns 400 error", - "PRE": "source_type is not 'postgresql' or 'xlsx'", + "PRE": "source_type is not 'sqllab' or 'xlsx'", "PURPOSE": "Validate map-columns rejects unsupported source types with a 400 contract response.", "TEST": "POST /api/datasets/map-columns returns 400 for invalid source_type" }, @@ -2761,7 +2707,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region test_map_columns_invalid_source_type [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns rejects unsupported source types with a 400 contract response.\n# @TEST: POST /api/datasets/map-columns returns 400 for invalid source_type\n# @PRE: source_type is not 'postgresql' or 'xlsx'\n# @POST: Returns 400 error\ndef test_map_columns_invalid_source_type(mock_deps):\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [1], \"source_type\": \"invalid\"},\n )\n assert response.status_code == 400\n assert \"Source type must be 'postgresql' or 'xlsx'\" in response.json()[\"detail\"]\n# #endregion test_map_columns_invalid_source_type\n" + "body": "# #region test_map_columns_invalid_source_type [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns rejects unsupported source types with a 400 contract response.\n# @TEST: POST /api/datasets/map-columns returns 400 for invalid source_type\n# @PRE: source_type is not 'sqllab' or 'xlsx'\n# @POST: Returns 400 error\ndef test_map_columns_invalid_source_type(mock_deps):\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [1], \"source_type\": \"invalid\"},\n )\n assert response.status_code == 400\n assert \"Source type must be 'sqllab' or 'xlsx'\" in response.json()[\"detail\"]\n# #endregion test_map_columns_invalid_source_type\n" }, { "contract_id": "test_generate_docs_success", @@ -2829,14 +2775,47 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region test_map_columns_empty_ids [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns rejects empty dataset identifier lists.\n# @TEST: POST /api/datasets/map-columns returns 400 for empty dataset_ids\n# @PRE: dataset_ids is empty\n# @POST: Returns 400 error\ndef test_map_columns_empty_ids(mock_deps):\n \"\"\"@PRE: dataset_ids must be non-empty.\"\"\"\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [], \"source_type\": \"postgresql\"},\n )\n assert response.status_code == 400\n assert \"At least one dataset ID must be provided\" in response.json()[\"detail\"]\n# #endregion test_map_columns_empty_ids\n" + "body": "# #region test_map_columns_empty_ids [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns rejects empty dataset identifier lists.\n# @TEST: POST /api/datasets/map-columns returns 400 for empty dataset_ids\n# @PRE: dataset_ids is empty\n# @POST: Returns 400 error\ndef test_map_columns_empty_ids(mock_deps):\n \"\"\"@PRE: dataset_ids must be non-empty.\"\"\"\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [], \"source_type\": \"sqllab\", \"database_id\": 1},\n )\n assert response.status_code == 400\n assert \"At least one dataset ID must be provided\" in response.json()[\"detail\"]\n# #endregion test_map_columns_empty_ids\n" + }, + { + "contract_id": "test_map_columns_missing_database_id", + "contract_type": "Function", + "file_path": "backend/src/api/routes/__tests__/test_datasets.py", + "start_line": 210, + "end_line": 222, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "POST": "Returns 400 error", + "PURPOSE": "Validate map-columns rejects sqllab source without database_id.", + "TEST": "POST /api/datasets/map-columns returns 400 for sqllab without database_id" + }, + "relations": [ + { + "source_id": "test_map_columns_missing_database_id", + "relation_type": "BINDS_TO", + "target_id": "DatasetsApiTests:Module", + "target_ref": "[DatasetsApiTests:Module]" + } + ], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "TEST", + "message": "@TEST is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_map_columns_missing_database_id [TYPE Function]\n# @RELATION BINDS_TO -> [DatasetsApiTests:Module]\n# @BRIEF Validate map-columns rejects sqllab source without database_id.\n# @TEST: POST /api/datasets/map-columns returns 400 for sqllab without database_id\n# @POST: Returns 400 error\ndef test_map_columns_missing_database_id(mock_deps):\n response = client.post(\n \"/api/datasets/map-columns\",\n json={\"env_id\": \"prod\", \"dataset_ids\": [1], \"source_type\": \"sqllab\"},\n )\n assert response.status_code == 400\n assert \"database_id is required\" in response.json()[\"detail\"]\n# #endregion test_map_columns_missing_database_id\n" }, { "contract_id": "test_generate_docs_empty_ids", "contract_type": "Function", "file_path": "backend/src/api/routes/__tests__/test_datasets.py", - "start_line": 210, - "end_line": 224, + "start_line": 223, + "end_line": 237, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -2869,8 +2848,8 @@ "contract_id": "test_generate_docs_env_not_found", "contract_type": "Function", "file_path": "backend/src/api/routes/__tests__/test_datasets.py", - "start_line": 225, - "end_line": 240, + "start_line": 238, + "end_line": 253, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -2903,8 +2882,8 @@ "contract_id": "test_get_datasets_superset_failure", "contract_type": "Function", "file_path": "backend/src/api/routes/__tests__/test_datasets.py", - "start_line": 241, - "end_line": 258, + "start_line": 254, + "end_line": 271, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -6998,214 +6977,6 @@ "tier_source": "AutoCalculated", "body": "# #region revoke_publication_endpoint [C:3] [TYPE Function]\n# @BRIEF Endpoint to revoke a previous publication.\n# @RELATION CALLS -> [revoke_publication]\n@router.post(\"/publications/{publication_id}/revoke\")\nasync def revoke_publication_endpoint(\n publication_id: str,\n payload: dict[str, Any],\n repository: CleanReleaseRepository = Depends(get_clean_release_repository),\n):\n try:\n publication = revoke_publication(\n repository=repository,\n publication_id=publication_id,\n revoked_by=str(payload[\"revoked_by\"]),\n comment=payload.get(\"comment\"),\n )\n except Exception as exc:\n raise HTTPException(\n status_code=409,\n detail={\"message\": str(exc), \"code\": \"PUBLICATION_GATE_ERROR\"},\n )\n\n return {\n \"status\": \"ok\",\n \"publication\": {\n \"id\": publication.id,\n \"candidate_id\": publication.candidate_id,\n \"report_id\": publication.report_id,\n \"published_by\": publication.published_by,\n \"published_at\": publication.published_at.isoformat()\n if publication.published_at\n else None,\n \"target_channel\": publication.target_channel,\n \"publication_ref\": publication.publication_ref,\n \"status\": publication.status,\n },\n }\n\n\n# #endregion revoke_publication_endpoint\n" }, - { - "contract_id": "ConnectionsRouter", - "contract_type": "Module", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 1, - "end_line": 141, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "LAYER": "API", - "PURPOSE": "Defines the FastAPI router for managing external database connections." - }, - "relations": [ - { - "source_id": "ConnectionsRouter", - "relation_type": "DEPENDS_ON", - "target_id": "get_db", - "target_ref": "[get_db]" - }, - { - "source_id": "ConnectionsRouter", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "[ConnectionConfig]" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ConnectionsRouter [C:3] [TYPE Module] [SEMANTICS fastapi, connection, api, search]\n# @BRIEF Defines the FastAPI router for managing external database connections.\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [get_db]\n# @RELATION DEPENDS_ON -> [ConnectionConfig]\n\nfrom datetime import datetime\n\nfrom fastapi import APIRouter, Depends, HTTPException, status\nfrom pydantic import BaseModel\nfrom sqlalchemy.orm import Session\n\nfrom ...core.database import ensure_connection_configs_table, get_db\nfrom ...core.logger import belief_scope, logger\nfrom ...models.connection import ConnectionConfig\n\nrouter = APIRouter()\n\n\n# #region _ensure_connections_schema [C:3] [TYPE Function]\n# @BRIEF Ensures the connection_configs table exists before CRUD access.\n# @PRE: db is an active SQLAlchemy session.\n# @POST: The current bind can safely query ConnectionConfig.\n# @RELATION CALLS -> ensure_connection_configs_table\ndef _ensure_connections_schema(db: Session):\n with belief_scope(\"ConnectionsRouter.ensure_schema\"):\n ensure_connection_configs_table(db.get_bind())\n\n\n# #endregion _ensure_connections_schema\n\n\n# #region ConnectionSchema [C:3] [TYPE Class]\n# @BRIEF Pydantic model for connection response.\n# @RELATION BINDS_TO -> ConnectionConfig\nclass ConnectionSchema(BaseModel):\n id: str\n name: str\n type: str\n host: str | None = None\n port: int | None = None\n database: str | None = None\n username: str | None = None\n created_at: datetime\n\n class Config:\n orm_mode = True\n\n\n# #endregion ConnectionSchema\n\n\n# #region ConnectionCreate [C:3] [TYPE Class]\n# @BRIEF Pydantic model for creating a connection.\n# @RELATION BINDS_TO -> ConnectionConfig\nclass ConnectionCreate(BaseModel):\n name: str\n type: str\n host: str | None = None\n port: int | None = None\n database: str | None = None\n username: str | None = None\n password: str | None = None\n\n\n# #endregion ConnectionCreate\n\n\n# #region list_connections [C:3] [TYPE Function]\n# @BRIEF Lists all saved connections.\n# @PRE: Database session is active.\n# @POST: Returns list of connection configs.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.get(\"\", response_model=list[ConnectionSchema])\nasync def list_connections(db: Session = Depends(get_db)):\n with belief_scope(\"ConnectionsRouter.list_connections\"):\n _ensure_connections_schema(db)\n connections = db.query(ConnectionConfig).all()\n return connections\n\n\n# #endregion list_connections\n\n\n# #region create_connection [C:3] [TYPE Function]\n# @BRIEF Creates a new connection configuration.\n# @PRE: Connection name is unique.\n# @POST: Connection is saved to DB.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.post(\"\", response_model=ConnectionSchema, status_code=status.HTTP_201_CREATED)\nasync def create_connection(\n connection: ConnectionCreate, db: Session = Depends(get_db)\n):\n with belief_scope(\"ConnectionsRouter.create_connection\", f\"name={connection.name}\"):\n _ensure_connections_schema(db)\n db_connection = ConnectionConfig(**connection.dict())\n db.add(db_connection)\n db.commit()\n db.refresh(db_connection)\n logger.info(\n f\"[ConnectionsRouter.create_connection][Success] Created connection {db_connection.id}\"\n )\n return db_connection\n\n\n# #endregion create_connection\n\n\n# #region delete_connection [C:3] [TYPE Function]\n# @BRIEF Deletes a connection configuration.\n# @PRE: Connection ID exists.\n# @POST: Connection is removed from DB.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.delete(\"/{connection_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_connection(connection_id: str, db: Session = Depends(get_db)):\n with belief_scope(\"ConnectionsRouter.delete_connection\", f\"id={connection_id}\"):\n _ensure_connections_schema(db)\n db_connection = (\n db.query(ConnectionConfig)\n .filter(ConnectionConfig.id == connection_id)\n .first()\n )\n if not db_connection:\n logger.error(\n f\"[ConnectionsRouter.delete_connection][State] Connection {connection_id} not found\"\n )\n raise HTTPException(status_code=404, detail=\"Connection not found\")\n db.delete(db_connection)\n db.commit()\n logger.info(\n f\"[ConnectionsRouter.delete_connection][Success] Deleted connection {connection_id}\"\n )\n return\n\n\n# #endregion delete_connection\n\n# #endregion ConnectionsRouter\n" - }, - { - "contract_id": "_ensure_connections_schema", - "contract_type": "Function", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 20, - "end_line": 30, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "POST": "The current bind can safely query ConnectionConfig.", - "PRE": "db is an active SQLAlchemy session.", - "PURPOSE": "Ensures the connection_configs table exists before CRUD access." - }, - "relations": [ - { - "source_id": "_ensure_connections_schema", - "relation_type": "CALLS", - "target_id": "ensure_connection_configs_table", - "target_ref": "ensure_connection_configs_table" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region _ensure_connections_schema [C:3] [TYPE Function]\n# @BRIEF Ensures the connection_configs table exists before CRUD access.\n# @PRE: db is an active SQLAlchemy session.\n# @POST: The current bind can safely query ConnectionConfig.\n# @RELATION CALLS -> ensure_connection_configs_table\ndef _ensure_connections_schema(db: Session):\n with belief_scope(\"ConnectionsRouter.ensure_schema\"):\n ensure_connection_configs_table(db.get_bind())\n\n\n# #endregion _ensure_connections_schema\n" - }, - { - "contract_id": "ConnectionSchema", - "contract_type": "Class", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 33, - "end_line": 50, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "PURPOSE": "Pydantic model for connection response." - }, - "relations": [ - { - "source_id": "ConnectionSchema", - "relation_type": "BINDS_TO", - "target_id": "ConnectionConfig", - "target_ref": "ConnectionConfig" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ConnectionSchema [C:3] [TYPE Class]\n# @BRIEF Pydantic model for connection response.\n# @RELATION BINDS_TO -> ConnectionConfig\nclass ConnectionSchema(BaseModel):\n id: str\n name: str\n type: str\n host: str | None = None\n port: int | None = None\n database: str | None = None\n username: str | None = None\n created_at: datetime\n\n class Config:\n orm_mode = True\n\n\n# #endregion ConnectionSchema\n" - }, - { - "contract_id": "ConnectionCreate", - "contract_type": "Class", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 53, - "end_line": 66, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "PURPOSE": "Pydantic model for creating a connection." - }, - "relations": [ - { - "source_id": "ConnectionCreate", - "relation_type": "BINDS_TO", - "target_id": "ConnectionConfig", - "target_ref": "ConnectionConfig" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ConnectionCreate [C:3] [TYPE Class]\n# @BRIEF Pydantic model for creating a connection.\n# @RELATION BINDS_TO -> ConnectionConfig\nclass ConnectionCreate(BaseModel):\n name: str\n type: str\n host: str | None = None\n port: int | None = None\n database: str | None = None\n username: str | None = None\n password: str | None = None\n\n\n# #endregion ConnectionCreate\n" - }, - { - "contract_id": "list_connections", - "contract_type": "Function", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 69, - "end_line": 83, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "POST": "Returns list of connection configs.", - "PRE": "Database session is active.", - "PURPOSE": "Lists all saved connections." - }, - "relations": [ - { - "source_id": "list_connections", - "relation_type": "CALLS", - "target_id": "_ensure_connections_schema", - "target_ref": "_ensure_connections_schema" - }, - { - "source_id": "list_connections", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "ConnectionConfig" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region list_connections [C:3] [TYPE Function]\n# @BRIEF Lists all saved connections.\n# @PRE: Database session is active.\n# @POST: Returns list of connection configs.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.get(\"\", response_model=list[ConnectionSchema])\nasync def list_connections(db: Session = Depends(get_db)):\n with belief_scope(\"ConnectionsRouter.list_connections\"):\n _ensure_connections_schema(db)\n connections = db.query(ConnectionConfig).all()\n return connections\n\n\n# #endregion list_connections\n" - }, - { - "contract_id": "create_connection", - "contract_type": "Function", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 86, - "end_line": 108, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "POST": "Connection is saved to DB.", - "PRE": "Connection name is unique.", - "PURPOSE": "Creates a new connection configuration." - }, - "relations": [ - { - "source_id": "create_connection", - "relation_type": "CALLS", - "target_id": "_ensure_connections_schema", - "target_ref": "_ensure_connections_schema" - }, - { - "source_id": "create_connection", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "ConnectionConfig" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region create_connection [C:3] [TYPE Function]\n# @BRIEF Creates a new connection configuration.\n# @PRE: Connection name is unique.\n# @POST: Connection is saved to DB.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.post(\"\", response_model=ConnectionSchema, status_code=status.HTTP_201_CREATED)\nasync def create_connection(\n connection: ConnectionCreate, db: Session = Depends(get_db)\n):\n with belief_scope(\"ConnectionsRouter.create_connection\", f\"name={connection.name}\"):\n _ensure_connections_schema(db)\n db_connection = ConnectionConfig(**connection.dict())\n db.add(db_connection)\n db.commit()\n db.refresh(db_connection)\n logger.info(\n f\"[ConnectionsRouter.create_connection][Success] Created connection {db_connection.id}\"\n )\n return db_connection\n\n\n# #endregion create_connection\n" - }, - { - "contract_id": "delete_connection", - "contract_type": "Function", - "file_path": "backend/src/api/routes/connections.py", - "start_line": 111, - "end_line": 139, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "POST": "Connection is removed from DB.", - "PRE": "Connection ID exists.", - "PURPOSE": "Deletes a connection configuration." - }, - "relations": [ - { - "source_id": "delete_connection", - "relation_type": "CALLS", - "target_id": "_ensure_connections_schema", - "target_ref": "_ensure_connections_schema" - }, - { - "source_id": "delete_connection", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "ConnectionConfig" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region delete_connection [C:3] [TYPE Function]\n# @BRIEF Deletes a connection configuration.\n# @PRE: Connection ID exists.\n# @POST: Connection is removed from DB.\n# @RELATION CALLS -> _ensure_connections_schema\n# @RELATION DEPENDS_ON -> ConnectionConfig\n@router.delete(\"/{connection_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_connection(connection_id: str, db: Session = Depends(get_db)):\n with belief_scope(\"ConnectionsRouter.delete_connection\", f\"id={connection_id}\"):\n _ensure_connections_schema(db)\n db_connection = (\n db.query(ConnectionConfig)\n .filter(ConnectionConfig.id == connection_id)\n .first()\n )\n if not db_connection:\n logger.error(\n f\"[ConnectionsRouter.delete_connection][State] Connection {connection_id} not found\"\n )\n raise HTTPException(status_code=404, detail=\"Connection not found\")\n db.delete(db_connection)\n db.commit()\n logger.info(\n f\"[ConnectionsRouter.delete_connection][Success] Deleted connection {connection_id}\"\n )\n return\n\n\n# #endregion delete_connection\n" - }, { "contract_id": "DashboardsApi", "contract_type": "Module", @@ -10316,7 +10087,7 @@ "contract_type": "Module", "file_path": "backend/src/api/routes/datasets.py", "start_line": 1, - "end_line": 402, + "end_line": 681, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -10352,14 +10123,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetsApi [C:5] [TYPE Module] [SEMANTICS fastapi, dataset, api, search, mapping, mapped-fields]\n#\n# @BRIEF API endpoints for the Dataset Hub - listing datasets with mapping progress\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [AppDependencies]\n# @RELATION DEPENDS_ON -> [ResourceService]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n#\n# @PRE SupersetClient is available; env_id is valid.\n# @POST Returns dataset metadata with mapping status.\n# @SIDE_EFFECT Reads from Superset API and task manager.\n# @DATA_CONTRACT Input -> DatasetQuery, Output -> DatasetsResponse, DatasetDetailResponse\n# @INVARIANT: All dataset responses include last_task metadata\n\n\nfrom fastapi import APIRouter, Depends, HTTPException\nfrom pydantic import BaseModel, Field\n\nfrom ...core.logger import belief_scope, logger\nfrom ...core.superset_client import SupersetClient\nfrom ...dependencies import get_config_manager, get_resource_service, get_task_manager, has_permission\n\nrouter = APIRouter(prefix=\"/api/datasets\", tags=[\"Datasets\"])\n\n# #region MappedFields [C:1] [TYPE DataClass]\n# @BRIEF DTO for dataset mapping progress statistics\nclass MappedFields(BaseModel):\n total: int\n mapped: int\n# #endregion MappedFields\n\n# #region LastTask [C:1] [TYPE DataClass]\n# @BRIEF DTO for the most recent task associated with a dataset\nclass LastTask(BaseModel):\n task_id: str | None = None\n status: str | None = Field(None, pattern=\"^RUNNING|SUCCESS|ERROR|WAITING_INPUT$\")\n# #endregion LastTask\n\n# #region DatasetItem [C:1] [TYPE DataClass]\n# @BRIEF Summary DTO for a dataset in the hub listing\nclass DatasetItem(BaseModel):\n id: int\n table_name: str\n schema_name: str = Field(..., alias=\"schema\")\n database: str\n mapped_fields: MappedFields | None = None\n last_task: LastTask | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetItem\n\n# #region LinkedDashboard [C:1] [TYPE DataClass]\n# @BRIEF DTO for a dashboard linked to a dataset\nclass LinkedDashboard(BaseModel):\n id: int\n title: str\n slug: str | None = None\n# #endregion LinkedDashboard\n\n# #region DatasetColumn [C:1] [TYPE DataClass]\n# @BRIEF DTO for a single dataset column's metadata\nclass DatasetColumn(BaseModel):\n id: int\n name: str\n type: str | None = None\n is_dttm: bool = False\n is_active: bool = True\n description: str | None = None\n# #endregion DatasetColumn\n\n# #region DatasetDetailResponse [C:1] [TYPE DataClass]\n# @BRIEF Detailed DTO for a dataset including columns and links\nclass DatasetDetailResponse(BaseModel):\n id: int\n table_name: str | None = None\n schema_name: str | None = Field(None, alias=\"schema\")\n database: str\n description: str | None = None\n columns: list[DatasetColumn]\n column_count: int\n sql: str | None = None\n linked_dashboards: list[LinkedDashboard]\n linked_dashboard_count: int\n is_sqllab_view: bool = False\n created_on: str | None = None\n changed_on: str | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetDetailResponse\n\n# #region DatasetsResponse [C:1] [TYPE DataClass]\n# @BRIEF Paginated response DTO for dataset listings\nclass DatasetsResponse(BaseModel):\n datasets: list[DatasetItem]\n total: int\n page: int\n page_size: int\n total_pages: int\n# #endregion DatasetsResponse\n\n# #region TaskResponse [C:1] [TYPE DataClass]\n# @BRIEF Response DTO containing a task ID for tracking\nclass TaskResponse(BaseModel):\n task_id: str\n# #endregion TaskResponse\n\n# #region get_dataset_ids [C:4] [TYPE Function]\n# @BRIEF Fetch list of all dataset IDs from a specific environment (without pagination)\n# @PRE: env_id must be a valid environment ID\n# @POST: Returns a list of all dataset IDs\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"/ids\")\nasync def get_dataset_ids(\n env_id: str,\n search: str | None = None,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_dataset_ids\", f\"env_id={env_id}, search={search}\"):\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_dataset_ids][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Extract and return just the IDs\n dataset_ids = [d['id'] for d in datasets]\n logger.info(f\"[get_dataset_ids][Coherence:OK] Returning {len(dataset_ids)} dataset IDs\")\n\n return {\"dataset_ids\": dataset_ids}\n\n except Exception as e:\n logger.error(f\"[get_dataset_ids][Coherence:Failed] Failed to fetch dataset IDs: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch dataset IDs: {e!s}\")\n# #endregion get_dataset_ids\n\n# #region get_datasets [C:4] [TYPE Function]\n# @BRIEF Fetch list of datasets from a specific environment with mapping progress\n# @PRE: env_id must be a valid environment ID\n# @PRE: page must be >= 1 if provided\n# @PRE: page_size must be between 1 and 100 if provided\n# @POST: Returns a list of datasets with enhanced metadata and pagination info\n# @POST: Response includes pagination metadata (page, page_size, total, total_pages)\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"\", response_model=DatasetsResponse)\nasync def get_datasets(\n env_id: str,\n search: str | None = None,\n page: int = 1,\n page_size: int = 10,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_datasets\", f\"env_id={env_id}, search={search}, page={page}, page_size={page_size}\"):\n # Validate pagination parameters\n if page < 1:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page: {page}\")\n raise HTTPException(status_code=400, detail=\"Page must be >= 1\")\n if page_size < 1 or page_size > 100:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page_size: {page_size}\")\n raise HTTPException(status_code=400, detail=\"Page size must be between 1 and 100\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_datasets][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Calculate pagination\n total = len(datasets)\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n start_idx = (page - 1) * page_size\n end_idx = start_idx + page_size\n\n # Slice datasets for current page\n paginated_datasets = datasets[start_idx:end_idx]\n\n logger.info(f\"[get_datasets][Coherence:OK] Returning {len(paginated_datasets)} datasets (page {page}/{total_pages}, total: {total})\")\n\n return DatasetsResponse(\n datasets=paginated_datasets,\n total=total,\n page=page,\n page_size=page_size,\n total_pages=total_pages\n )\n\n except Exception as e:\n logger.error(f\"[get_datasets][Coherence:Failed] Failed to fetch datasets: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch datasets: {e!s}\")\n# #endregion get_datasets\n\n# #region MapColumnsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating column mapping\nclass MapColumnsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to map\")\n source_type: str = Field(..., description=\"Source type: 'postgresql' or 'xlsx'\")\n connection_id: str | None = Field(None, description=\"Connection ID for PostgreSQL source\")\n file_data: str | None = Field(None, description=\"File path or data for XLSX source\")\n# #endregion MapColumnsRequest\n\n# #region map_columns [C:4] [TYPE Function]\n# @BRIEF Trigger bulk column mapping for datasets\n# @PRE: User has permission plugin:mapper:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking mapping progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [MapperPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/map-columns\", response_model=TaskResponse)\nasync def map_columns(\n request: MapColumnsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:mapper\", \"EXECUTE\"))\n):\n with belief_scope(\"map_columns\", f\"env={request.env_id}, count={len(request.dataset_ids)}, source={request.source_type}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[map_columns][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate source type\n if request.source_type not in ['postgresql', 'xlsx']:\n logger.error(f\"[map_columns][Coherence:Failed] Invalid source type: {request.source_type}\")\n raise HTTPException(status_code=400, detail=\"Source type must be 'postgresql' or 'xlsx'\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[map_columns][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create mapping task\n task_params = {\n 'env': request.env_id,\n 'dataset_id': request.dataset_ids[0] if request.dataset_ids else None,\n 'source': request.source_type,\n 'connection_id': request.connection_id,\n 'file_data': request.file_data\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='dataset-mapper',\n params=task_params\n )\n\n logger.info(f\"[map_columns][Coherence:OK] Mapping task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[map_columns][Coherence:Failed] Failed to create mapping task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create mapping task: {e!s}\")\n# #endregion map_columns\n\n# #region GenerateDocsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating documentation generation\nclass GenerateDocsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to generate docs for\")\n llm_provider: str = Field(..., description=\"LLM provider to use\")\n options: dict | None = Field(None, description=\"Additional options for documentation generation\")\n# #endregion GenerateDocsRequest\n\n# #region generate_docs [C:4] [TYPE Function]\n# @BRIEF Trigger bulk documentation generation for datasets\n# @PRE: User has permission plugin:llm_analysis:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking documentation generation progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [DocumentationPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/generate-docs\", response_model=TaskResponse)\nasync def generate_docs(\n request: GenerateDocsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:llm_analysis\", \"EXECUTE\"))\n):\n with belief_scope(\"generate_docs\", f\"env={request.env_id}, count={len(request.dataset_ids)}, provider={request.llm_provider}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[generate_docs][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[generate_docs][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create documentation generation task\n task_params = {\n 'environment_id': request.env_id,\n 'dataset_id': str(request.dataset_ids[0]) if request.dataset_ids else None,\n 'provider_id': request.llm_provider,\n 'options': request.options or {}\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='llm_documentation',\n params=task_params\n )\n\n logger.info(f\"[generate_docs][Coherence:OK] Documentation generation task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[generate_docs][Coherence:Failed] Failed to create documentation generation task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create documentation generation task: {e!s}\")\n# #endregion generate_docs\n\n# #region get_dataset_detail [C:4] [TYPE Function]\n# @BRIEF Get detailed dataset information including columns and linked dashboards\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_id is a valid dataset ID\n# @POST: Returns detailed dataset info with columns and linked dashboards\n# @RELATION CALLS -> [SupersetClientGetDatasetDetail]\n@router.get(\"/{dataset_id}\", response_model=DatasetDetailResponse)\nasync def get_dataset_detail(\n env_id: str,\n dataset_id: int,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_dataset_detail\", f\"env_id={env_id}, dataset_id={dataset_id}\"):\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Fetch detailed dataset info using SupersetClient\n client = SupersetClient(env)\n dataset_detail = client.get_dataset_detail(dataset_id)\n\n # Normalize 'database' field: Superset returns an object, model expects a string\n if isinstance(dataset_detail.get(\"database\"), dict):\n db_obj = dataset_detail[\"database\"]\n dataset_detail[\"database\"] = db_obj.get(\"database_name\", str(db_obj.get(\"id\", \"\")))\n\n logger.info(f\"[get_dataset_detail][Coherence:OK] Retrieved dataset {dataset_id} with {dataset_detail['column_count']} columns and {dataset_detail['linked_dashboard_count']} linked dashboards\")\n\n return DatasetDetailResponse(**dataset_detail)\n\n except Exception as e:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Failed to fetch dataset detail: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch dataset detail: {e!s}\")\n# #endregion get_dataset_detail\n\n# #endregion DatasetsApi\n" + "body": "# #region DatasetsApi [C:5] [TYPE Module] [SEMANTICS fastapi, dataset, api, search, mapping, mapped-fields]\n#\n# @BRIEF API endpoints for the Dataset Hub - listing datasets with mapping progress\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [AppDependencies]\n# @RELATION DEPENDS_ON -> [ResourceService]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n#\n# @PRE SupersetClient is available; env_id is valid.\n# @POST Returns dataset metadata with mapping status.\n# @SIDE_EFFECT Reads from Superset API and task manager.\n# @DATA_CONTRACT Input -> DatasetQuery, Output -> DatasetsResponse, DatasetDetailResponse\n# @INVARIANT: All dataset responses include last_task metadata\n\n\nimport re\n\nfrom fastapi import APIRouter, Depends, HTTPException, Query\nfrom pydantic import BaseModel, Field\n\nfrom ...core.logger import belief_scope, logger\nfrom ...core.superset_client import SupersetClient\nfrom ...dependencies import get_config_manager, get_resource_service, get_task_manager, has_permission\n\nrouter = APIRouter(prefix=\"/api/datasets\", tags=[\"Datasets\"])\n\n# #region MappedFields [C:1] [TYPE DataClass]\n# @BRIEF DTO for dataset mapping progress statistics\nclass MappedFields(BaseModel):\n total: int\n mapped: int\n# #endregion MappedFields\n\n# #region LastTask [C:1] [TYPE DataClass]\n# @BRIEF DTO for the most recent task associated with a dataset\nclass LastTask(BaseModel):\n task_id: str | None = None\n status: str | None = Field(None, pattern=\"^RUNNING|SUCCESS|ERROR|WAITING_INPUT$\")\n# #endregion LastTask\n\n# #region DatasetItem [C:1] [TYPE DataClass]\n# @BRIEF Summary DTO for a dataset in the hub listing\nclass DatasetItem(BaseModel):\n id: int\n table_name: str\n schema_name: str = Field(..., alias=\"schema\")\n database: str\n mapped_fields: MappedFields | None = None\n last_task: LastTask | None = None\n metric_count: int = 0\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetItem\n\n# #region LinkedDashboard [C:1] [TYPE DataClass]\n# @BRIEF DTO for a dashboard linked to a dataset\nclass LinkedDashboard(BaseModel):\n id: int\n title: str\n slug: str | None = None\n# #endregion LinkedDashboard\n\n# #region DatasetColumn [C:1] [TYPE DataClass]\n# @BRIEF DTO for a single dataset column's metadata\nclass DatasetColumn(BaseModel):\n id: int\n name: str\n type: str | None = None\n is_dttm: bool = False\n is_active: bool = True\n description: str | None = None\n# #endregion DatasetColumn\n\n# #region MetricItem [C:1] [TYPE DataClass]\n# @BRIEF Pydantic DTO for a dataset metric — carries Superset metric metadata.\n# @RELATION DEPENDS_ON -> [DatasetDetailResponse]\nclass MetricItem(BaseModel):\n id: int\n metric_name: str\n expression: str | None = None\n verbose_name: str | None = None\n description: str | None = None\n metric_type: str | None = None\n# #endregion MetricItem\n\n# #region DatasetDetailResponse [C:2] [TYPE DataClass]\n# @BRIEF Detailed DTO for a dataset including columns, linked dashboards, and metrics.\n# @RELATION DEPENDS_ON -> [MetricItem]\nclass DatasetDetailResponse(BaseModel):\n id: int\n table_name: str | None = None\n schema_name: str | None = Field(None, alias=\"schema\")\n database: str\n description: str | None = None\n columns: list[DatasetColumn]\n column_count: int\n metrics: list[MetricItem] = []\n metric_count: int = 0\n sql: str | None = None\n linked_dashboards: list[LinkedDashboard]\n linked_dashboard_count: int\n is_sqllab_view: bool = False\n created_on: str | None = None\n changed_on: str | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetDetailResponse\n\n# #region StatsCounts [C:1] [TYPE DataClass]\n# @BRIEF Aggregate statistics for the Stats Bar — computed from full dataset list.\nclass StatsCounts(BaseModel):\n total: int\n unmapped_count: int\n mapped_count: int\n linked_count: int\n# #endregion StatsCounts\n\n# #region DatasetsResponse [C:2] [TYPE DataClass]\n# @BRIEF Paginated response DTO for dataset listings with stats.\n# @RELATION DEPENDS_ON -> [StatsCounts]\nclass DatasetsResponse(BaseModel):\n datasets: list[DatasetItem]\n stats: StatsCounts\n total: int\n page: int\n page_size: int\n total_pages: int\n# #endregion DatasetsResponse\n\n# #region TaskResponse [C:1] [TYPE DataClass]\n# @BRIEF Response DTO containing a task ID for tracking\nclass TaskResponse(BaseModel):\n task_id: str\n# #endregion TaskResponse\n\n# #region ColumnDescriptionUpdate [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for inline-edit of a column description.\nclass ColumnDescriptionUpdate(BaseModel):\n description: str\n# #endregion ColumnDescriptionUpdate\n\n# #region MetricDescriptionUpdate [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for inline-edit of a metric description.\nclass MetricDescriptionUpdate(BaseModel):\n description: str\n# #endregion MetricDescriptionUpdate\n\n# #region get_dataset_ids [C:4] [TYPE Function]\n# @BRIEF Fetch list of all dataset IDs from a specific environment (without pagination)\n# @PRE: env_id must be a valid environment ID\n# @POST: Returns a list of all dataset IDs\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"/ids\")\nasync def get_dataset_ids(\n env_id: str,\n search: str | None = None,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_dataset_ids\", f\"env_id={env_id}, search={search}\"):\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_dataset_ids][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Extract and return just the IDs\n dataset_ids = [d['id'] for d in datasets]\n logger.info(f\"[get_dataset_ids][Coherence:OK] Returning {len(dataset_ids)} dataset IDs\")\n\n return {\"dataset_ids\": dataset_ids}\n\n except Exception as e:\n logger.error(f\"[get_dataset_ids][Coherence:Failed] Failed to fetch dataset IDs: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch dataset IDs: {e!s}\")\n# #endregion get_dataset_ids\n\n# #region get_datasets [C:4] [TYPE Function]\n# @BRIEF Fetch list of datasets from a specific environment with mapping progress and stats.\n# @PRE: env_id must be a valid environment ID\n# @PRE: page must be >= 1 if provided\n# @PRE: page_size must be between 1 and 100 if provided\n# @POST: Returns a list of datasets with enhanced metadata, pagination info, and StatsCounts.\n# @POST: Response includes pagination metadata (page, page_size, total, total_pages) and stats object.\n# @RATIONALE Stats counts returned in the same response as datasets to avoid an extra API call for the Stats Bar (FR-022).\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"\", response_model=DatasetsResponse)\nasync def get_datasets(\n env_id: str,\n search: str | None = None,\n filter: str | None = None,\n page: int = 1,\n page_size: int = 10,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_datasets\", f\"env_id={env_id}, search={search}, filter={filter}, page={page}, page_size={page_size}\"):\n # Validate pagination parameters\n if page < 1:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page: {page}\")\n raise HTTPException(status_code=400, detail=\"Page must be >= 1\")\n if page_size < 1 or page_size > 100:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page_size: {page_size}\")\n raise HTTPException(status_code=400, detail=\"Page size must be between 1 and 100\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_datasets][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Compute stats from full list BEFORE filtering/pagination\n total_datasets = len(datasets)\n unmapped = sum(\n 1 for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) == 0\n )\n mapped = sum(\n 1 for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) > 0\n )\n linked = sum(\n 1 for d in datasets\n if d.get(\"linked_dashboard_count\", 0) > 0\n )\n stats = StatsCounts(\n total=total_datasets,\n unmapped_count=unmapped,\n mapped_count=mapped,\n linked_count=linked,\n )\n\n # Apply server-side filter (before pagination) — FR-026\n if filter and filter in (\"unmapped\", \"mapped\", \"linked\"):\n if filter == \"unmapped\":\n datasets = [\n d for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) == 0\n ]\n elif filter == \"mapped\":\n datasets = [\n d for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) > 0\n ]\n elif filter == \"linked\":\n datasets = [\n d for d in datasets\n if d.get(\"linked_dashboard_count\", 0) > 0\n ]\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Calculate pagination\n total = len(datasets)\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n start_idx = (page - 1) * page_size\n end_idx = start_idx + page_size\n\n # Slice datasets for current page\n paginated_datasets = datasets[start_idx:end_idx]\n\n logger.info(f\"[get_datasets][Coherence:OK] Returning {len(paginated_datasets)} datasets (page {page}/{total_pages}, total: {total}, stats: total={stats.total} unmapped={stats.unmapped_count} mapped={stats.mapped_count} linked={stats.linked_count})\")\n\n return DatasetsResponse(\n datasets=paginated_datasets,\n stats=stats,\n total=total,\n page=page,\n page_size=page_size,\n total_pages=total_pages\n )\n\n except Exception as e:\n logger.error(f\"[get_datasets][Coherence:Failed] Failed to fetch datasets: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch datasets: {e!s}\")\n# #endregion get_datasets\n\n# #region MapColumnsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating column mapping\nclass MapColumnsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to map\")\n source_type: str = Field(..., description=\"Source type: 'sqllab' or 'xlsx'\")\n database_id: int | None = Field(None, description=\"Superset database ID for SQL Lab source\")\n sql_query: str | None = Field(None, description=\"Custom SQL query for SQL Lab (optional, defaults to information_schema.columns query)\")\n file_data: str | None = Field(None, description=\"File path or data for XLSX source\")\n# #endregion MapColumnsRequest\n\n# #region map_columns [C:4] [TYPE Function]\n# @BRIEF Trigger bulk column mapping for datasets\n# @PRE: User has permission plugin:mapper:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking mapping progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [MapperPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/map-columns\", response_model=TaskResponse)\nasync def map_columns(\n request: MapColumnsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:mapper\", \"EXECUTE\"))\n):\n with belief_scope(\"map_columns\", f\"env={request.env_id}, count={len(request.dataset_ids)}, source={request.source_type}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[map_columns][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate source type\n if request.source_type not in ['sqllab', 'xlsx']:\n logger.error(f\"[map_columns][Coherence:Failed] Invalid source type: {request.source_type}\")\n raise HTTPException(status_code=400, detail=\"Source type must be 'sqllab' or 'xlsx'\")\n\n # Validate database_id for sqllab source\n if request.source_type == 'sqllab' and not request.database_id:\n raise HTTPException(status_code=400, detail=\"database_id is required for 'sqllab' source type\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[map_columns][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create mapping task\n task_params = {\n 'env': request.env_id,\n 'dataset_id': request.dataset_ids[0] if request.dataset_ids else None,\n 'source': 'sqllab' if request.source_type == 'sqllab' else 'excel',\n 'database_id': request.database_id,\n 'sql_query': request.sql_query,\n 'file_data': request.file_data\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='dataset-mapper',\n params=task_params\n )\n\n logger.info(f\"[map_columns][Coherence:OK] Mapping task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[map_columns][Coherence:Failed] Failed to create mapping task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create mapping task: {e!s}\")\n# #endregion map_columns\n\n# #region GenerateDocsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating documentation generation\nclass GenerateDocsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to generate docs for\")\n llm_provider: str = Field(..., description=\"LLM provider to use\")\n options: dict | None = Field(None, description=\"Additional options for documentation generation\")\n# #endregion GenerateDocsRequest\n\n# #region generate_docs [C:4] [TYPE Function]\n# @BRIEF Trigger bulk documentation generation for datasets\n# @PRE: User has permission plugin:llm_analysis:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking documentation generation progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [DocumentationPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/generate-docs\", response_model=TaskResponse)\nasync def generate_docs(\n request: GenerateDocsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:llm_analysis\", \"EXECUTE\"))\n):\n with belief_scope(\"generate_docs\", f\"env={request.env_id}, count={len(request.dataset_ids)}, provider={request.llm_provider}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[generate_docs][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[generate_docs][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create documentation generation task\n task_params = {\n 'environment_id': request.env_id,\n 'dataset_id': str(request.dataset_ids[0]) if request.dataset_ids else None,\n 'provider_id': request.llm_provider,\n 'options': request.options or {}\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='llm_documentation',\n params=task_params\n )\n\n logger.info(f\"[generate_docs][Coherence:OK] Documentation generation task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[generate_docs][Coherence:Failed] Failed to create documentation generation task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create documentation generation task: {e!s}\")\n# #endregion generate_docs\n\n# #region get_dataset_detail [C:4] [TYPE Function]\n# @BRIEF Get detailed dataset information including columns and linked dashboards\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_id is a valid dataset ID\n# @POST: Returns detailed dataset info with columns and linked dashboards\n# @RELATION CALLS -> [SupersetClientGetDatasetDetail]\n@router.get(\"/{dataset_id}\", response_model=DatasetDetailResponse)\nasync def get_dataset_detail(\n env_id: str,\n dataset_id: int,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_dataset_detail\", f\"env_id={env_id}, dataset_id={dataset_id}\"):\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Fetch detailed dataset info using SupersetClient\n client = SupersetClient(env)\n dataset_detail = client.get_dataset_detail(dataset_id)\n\n # Normalize 'database' field: Superset returns an object, model expects a string\n if isinstance(dataset_detail.get(\"database\"), dict):\n db_obj = dataset_detail[\"database\"]\n dataset_detail[\"database\"] = db_obj.get(\"database_name\", str(db_obj.get(\"id\", \"\")))\n\n logger.info(f\"[get_dataset_detail][Coherence:OK] Retrieved dataset {dataset_id} with {dataset_detail['column_count']} columns and {dataset_detail['linked_dashboard_count']} linked dashboards\")\n\n return DatasetDetailResponse(**dataset_detail)\n\n except Exception as e:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Failed to fetch dataset detail: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch dataset detail: {e!s}\")\n# #endregion get_dataset_detail\n\n# #region _strip_html_tags [C:2] [TYPE Function] [SEMANTICS helper,validation,html]\n# @BRIEF Detect and strip HTML tags from a text string. Uses simple regex <[^>]*>.\n# If HTML is detected, strips tags and logs a warning. Returns cleaned text.\n# @REJECTED Reject-with-400 approach was rejected in favour of silent stripping — more user-friendly\n# and matches the UX expectation that inline-edited descriptions are plain text only.\ndef _strip_html_tags(text: str) -> str:\n if not text:\n return text\n if re.search(r\"<[^>]*>\", text):\n cleaned = re.sub(r\"<[^>]*>\", \"\", text)\n logger.warning(f\"[_strip_html_tags] HTML tags detected and stripped from description\")\n return cleaned\n return text\n# #endregion _strip_html_tags\n\n# #region update_column_description [C:4] [TYPE Endpoint]\n# @BRIEF Save description for a single dataset column. Internal: GET full dataset from Superset, modify one column's description, PUT back.\n# @PRE: dataset_id and column_id must exist in the target environment.\n# @POST: Column description in Superset is updated. Response confirms success.\n# @SIDE_EFFECT: Mutates dataset metadata in upstream Superset instance via PUT.\n# @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.\n# @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).\n# @RELATION CALLS -> [SupersetClient.get_dataset]\n# @RELATION CALLS -> [SupersetClient.update_dataset]\n# @RATIONALE Must perform GET→modify→PUT because Superset has no PATCH for individual columns — only full object PUT with override_columns=false.\n# @REJECTED Direct PUT from frontend — rejected because frontend would need to handle full Superset payload structure.\n@router.put(\"/{dataset_id}/columns/{column_id}/description\")\nasync def update_column_description(\n dataset_id: int,\n column_id: int,\n env_id: str = Query(..., description=\"Environment ID\"),\n body: ColumnDescriptionUpdate = ...,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"WRITE\"))\n):\n with belief_scope(\"update_column_description\", f\"dataset_id={dataset_id}, column_id={column_id}, env_id={env_id}\"):\n # Validate and sanitize description\n description = _strip_html_tags(body.description)\n if len(description) > 2000:\n logger.error(f\"[update_column_description][Coherence:Failed] Description exceeds 2000 chars: {len(description)}\")\n raise HTTPException(status_code=400, detail=\"Description must not exceed 2000 characters\")\n\n # Validate environment\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[update_column_description][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n client = SupersetClient(env)\n\n # GET full dataset\n logger.reason(\"Fetching full dataset from Superset for column description update\",\n extra={\"src\": \"update_column_description\"})\n try:\n response = client.get_dataset(dataset_id)\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Superset GET failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to fetch dataset from Superset: {e!s}\")\n\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n\n if not dataset or not dataset.get(\"id\"):\n logger.error(f\"[update_column_description][Coherence:Failed] Dataset {dataset_id} not found\")\n raise HTTPException(status_code=404, detail=f\"Dataset {dataset_id} not found\")\n\n # Find and modify the target column\n columns = dataset.get(\"columns\", [])\n found = False\n for col in columns:\n if col.get(\"id\") == column_id:\n col[\"description\"] = description\n found = True\n break\n\n if not found:\n logger.error(f\"[update_column_description][Coherence:Failed] Column {column_id} not found in dataset {dataset_id}\")\n raise HTTPException(status_code=404, detail=f\"Column {column_id} not found in dataset {dataset_id}\")\n\n # PUT back with override_columns=false\n put_payload = dataset\n try:\n client.update_dataset(dataset_id, put_payload, override_columns=False)\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Superset PUT failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to update dataset in Superset: {e!s}\")\n\n logger.reflect(\n f\"Updated column {column_id} description for dataset {dataset_id}\",\n extra={\"src\": \"update_column_description\"},\n )\n return {\"success\": True, \"description\": description}\n\n except HTTPException:\n raise\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Unexpected error: {e}\")\n raise HTTPException(status_code=500, detail=f\"Unexpected error: {e!s}\")\n# #endregion update_column_description\n\n# #region update_metric_description [C:4] [TYPE Endpoint]\n# @BRIEF Save description for a single dataset metric. Mirror of update_column_description for metrics.\n# @PRE: dataset_id and metric_id must exist in the target environment.\n# @POST: Metric description in Superset is updated.\n# @SIDE_EFFECT: Mutates dataset metadata in upstream Superset instance via PUT.\n# @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.\n# @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).\n# @RELATION CALLS -> [SupersetClient.get_dataset]\n# @RELATION CALLS -> [SupersetClient.update_dataset]\n@router.put(\"/{dataset_id}/metrics/{metric_id}/description\")\nasync def update_metric_description(\n dataset_id: int,\n metric_id: int,\n env_id: str = Query(..., description=\"Environment ID\"),\n body: MetricDescriptionUpdate = ...,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"WRITE\"))\n):\n with belief_scope(\"update_metric_description\", f\"dataset_id={dataset_id}, metric_id={metric_id}, env_id={env_id}\"):\n # Validate and sanitize description\n description = _strip_html_tags(body.description)\n if len(description) > 2000:\n logger.error(f\"[update_metric_description][Coherence:Failed] Description exceeds 2000 chars: {len(description)}\")\n raise HTTPException(status_code=400, detail=\"Description must not exceed 2000 characters\")\n\n # Validate environment\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[update_metric_description][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n client = SupersetClient(env)\n\n # GET full dataset\n logger.reason(\"Fetching full dataset from Superset for metric description update\",\n extra={\"src\": \"update_metric_description\"})\n try:\n response = client.get_dataset(dataset_id)\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Superset GET failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to fetch dataset from Superset: {e!s}\")\n\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n\n if not dataset or not dataset.get(\"id\"):\n logger.error(f\"[update_metric_description][Coherence:Failed] Dataset {dataset_id} not found\")\n raise HTTPException(status_code=404, detail=f\"Dataset {dataset_id} not found\")\n\n # Find and modify the target metric\n metrics = dataset.get(\"metrics\", [])\n found = False\n for metric in metrics:\n if metric.get(\"id\") == metric_id:\n metric[\"description\"] = description\n found = True\n break\n\n if not found:\n logger.error(f\"[update_metric_description][Coherence:Failed] Metric {metric_id} not found in dataset {dataset_id}\")\n raise HTTPException(status_code=404, detail=f\"Metric {metric_id} not found in dataset {dataset_id}\")\n\n # PUT back with override_columns=false\n try:\n client.update_dataset(dataset_id, dataset, override_columns=False)\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Superset PUT failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to update dataset in Superset: {e!s}\")\n\n logger.reflect(\n f\"Updated metric {metric_id} description for dataset {dataset_id}\",\n extra={\"src\": \"update_metric_description\"},\n )\n return {\"success\": True, \"description\": description}\n\n except HTTPException:\n raise\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Unexpected error: {e}\")\n raise HTTPException(status_code=500, detail=f\"Unexpected error: {e!s}\")\n# #endregion update_metric_description\n\n# #endregion DatasetsApi\n" }, { "contract_id": "MappedFields", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 25, - "end_line": 30, + "start_line": 27, + "end_line": 32, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10430,8 +10201,8 @@ "contract_id": "LastTask", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 32, - "end_line": 37, + "start_line": 34, + "end_line": 39, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10502,8 +10273,8 @@ "contract_id": "DatasetItem", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 39, - "end_line": 51, + "start_line": 41, + "end_line": 54, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10568,14 +10339,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetItem [C:1] [TYPE DataClass]\n# @BRIEF Summary DTO for a dataset in the hub listing\nclass DatasetItem(BaseModel):\n id: int\n table_name: str\n schema_name: str = Field(..., alias=\"schema\")\n database: str\n mapped_fields: MappedFields | None = None\n last_task: LastTask | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetItem\n" + "body": "# #region DatasetItem [C:1] [TYPE DataClass]\n# @BRIEF Summary DTO for a dataset in the hub listing\nclass DatasetItem(BaseModel):\n id: int\n table_name: str\n schema_name: str = Field(..., alias=\"schema\")\n database: str\n mapped_fields: MappedFields | None = None\n last_task: LastTask | None = None\n metric_count: int = 0\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetItem\n" }, { "contract_id": "LinkedDashboard", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 53, - "end_line": 59, + "start_line": 56, + "end_line": 62, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10646,8 +10417,8 @@ "contract_id": "DatasetColumn", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 61, - "end_line": 70, + "start_line": 64, + "end_line": 73, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10715,16 +10486,192 @@ "body": "# #region DatasetColumn [C:1] [TYPE DataClass]\n# @BRIEF DTO for a single dataset column's metadata\nclass DatasetColumn(BaseModel):\n id: int\n name: str\n type: str | None = None\n is_dttm: bool = False\n is_active: bool = True\n description: str | None = None\n# #endregion DatasetColumn\n" }, { - "contract_id": "DatasetDetailResponse", + "contract_id": "MetricItem", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 72, - "end_line": 91, + "start_line": 75, + "end_line": 85, "tier": "TIER_1", "complexity": 1, "metadata": { "COMPLEXITY": 1, - "PURPOSE": "Detailed DTO for a dataset including columns and links" + "PURPOSE": "Pydantic DTO for a dataset metric — carries Superset metric metadata." + }, + "relations": [ + { + "source_id": "MetricItem", + "relation_type": "DEPENDS_ON", + "target_id": "DatasetDetailResponse", + "target_ref": "[DatasetDetailResponse]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MetricItem [C:1] [TYPE DataClass]\n# @BRIEF Pydantic DTO for a dataset metric — carries Superset metric metadata.\n# @RELATION DEPENDS_ON -> [DatasetDetailResponse]\nclass MetricItem(BaseModel):\n id: int\n metric_name: str\n expression: str | None = None\n verbose_name: str | None = None\n description: str | None = None\n metric_type: str | None = None\n# #endregion MetricItem\n" + }, + { + "contract_id": "DatasetDetailResponse", + "contract_type": "DataClass", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 87, + "end_line": 109, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Detailed DTO for a dataset including columns, linked dashboards, and metrics." + }, + "relations": [ + { + "source_id": "DatasetDetailResponse", + "relation_type": "DEPENDS_ON", + "target_id": "MetricItem", + "target_ref": "[MetricItem]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C2", + "detail": { + "actual_complexity": 2, + "contract_type": "DataClass" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'DataClass' at C2", + "detail": { + "actual_complexity": 2, + "contract_type": "DataClass" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'DataClass' at C2", + "detail": { + "actual_complexity": 2, + "contract_type": "DataClass" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region DatasetDetailResponse [C:2] [TYPE DataClass]\n# @BRIEF Detailed DTO for a dataset including columns, linked dashboards, and metrics.\n# @RELATION DEPENDS_ON -> [MetricItem]\nclass DatasetDetailResponse(BaseModel):\n id: int\n table_name: str | None = None\n schema_name: str | None = Field(None, alias=\"schema\")\n database: str\n description: str | None = None\n columns: list[DatasetColumn]\n column_count: int\n metrics: list[MetricItem] = []\n metric_count: int = 0\n sql: str | None = None\n linked_dashboards: list[LinkedDashboard]\n linked_dashboard_count: int\n is_sqllab_view: bool = False\n created_on: str | None = None\n changed_on: str | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetDetailResponse\n" + }, + { + "contract_id": "StatsCounts", + "contract_type": "DataClass", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 111, + "end_line": 118, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Aggregate statistics for the Stats Bar — computed from full dataset list." }, "relations": [], "schema_warnings": [ @@ -10784,21 +10731,28 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetDetailResponse [C:1] [TYPE DataClass]\n# @BRIEF Detailed DTO for a dataset including columns and links\nclass DatasetDetailResponse(BaseModel):\n id: int\n table_name: str | None = None\n schema_name: str | None = Field(None, alias=\"schema\")\n database: str\n description: str | None = None\n columns: list[DatasetColumn]\n column_count: int\n sql: str | None = None\n linked_dashboards: list[LinkedDashboard]\n linked_dashboard_count: int\n is_sqllab_view: bool = False\n created_on: str | None = None\n changed_on: str | None = None\n\n class Config:\n allow_population_by_field_name = True\n# #endregion DatasetDetailResponse\n" + "body": "# #region StatsCounts [C:1] [TYPE DataClass]\n# @BRIEF Aggregate statistics for the Stats Bar — computed from full dataset list.\nclass StatsCounts(BaseModel):\n total: int\n unmapped_count: int\n mapped_count: int\n linked_count: int\n# #endregion StatsCounts\n" }, { "contract_id": "DatasetsResponse", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 93, - "end_line": 101, + "start_line": 120, + "end_line": 130, "tier": "TIER_1", - "complexity": 1, + "complexity": 2, "metadata": { - "COMPLEXITY": 1, - "PURPOSE": "Paginated response DTO for dataset listings" + "COMPLEXITY": 2, + "PURPOSE": "Paginated response DTO for dataset listings with stats." }, - "relations": [], + "relations": [ + { + "source_id": "DatasetsResponse", + "relation_type": "DEPENDS_ON", + "target_id": "StatsCounts", + "target_ref": "[StatsCounts]" + } + ], "schema_warnings": [ { "code": "tag_not_for_contract_type", @@ -10820,9 +10774,9 @@ { "code": "tag_forbidden_by_complexity", "tag": "COMPLEXITY", - "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C1", + "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C2", "detail": { - "actual_complexity": 1, + "actual_complexity": 2, "contract_type": "DataClass" } }, @@ -10847,23 +10801,32 @@ { "code": "tag_forbidden_by_complexity", "tag": "PURPOSE", - "message": "@PURPOSE is forbidden for contract type 'DataClass' at C1", + "message": "@PURPOSE is forbidden for contract type 'DataClass' at C2", "detail": { - "actual_complexity": 1, + "actual_complexity": 2, + "contract_type": "DataClass" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'DataClass' at C2", + "detail": { + "actual_complexity": 2, "contract_type": "DataClass" } } ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetsResponse [C:1] [TYPE DataClass]\n# @BRIEF Paginated response DTO for dataset listings\nclass DatasetsResponse(BaseModel):\n datasets: list[DatasetItem]\n total: int\n page: int\n page_size: int\n total_pages: int\n# #endregion DatasetsResponse\n" + "body": "# #region DatasetsResponse [C:2] [TYPE DataClass]\n# @BRIEF Paginated response DTO for dataset listings with stats.\n# @RELATION DEPENDS_ON -> [StatsCounts]\nclass DatasetsResponse(BaseModel):\n datasets: list[DatasetItem]\n stats: StatsCounts\n total: int\n page: int\n page_size: int\n total_pages: int\n# #endregion DatasetsResponse\n" }, { "contract_id": "TaskResponse", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 103, - "end_line": 107, + "start_line": 132, + "end_line": 136, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -10930,12 +10893,156 @@ "tier_source": "AutoCalculated", "body": "# #region TaskResponse [C:1] [TYPE DataClass]\n# @BRIEF Response DTO containing a task ID for tracking\nclass TaskResponse(BaseModel):\n task_id: str\n# #endregion TaskResponse\n" }, + { + "contract_id": "ColumnDescriptionUpdate", + "contract_type": "DataClass", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 138, + "end_line": 142, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Request DTO for inline-edit of a column description." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ColumnDescriptionUpdate [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for inline-edit of a column description.\nclass ColumnDescriptionUpdate(BaseModel):\n description: str\n# #endregion ColumnDescriptionUpdate\n" + }, + { + "contract_id": "MetricDescriptionUpdate", + "contract_type": "DataClass", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 144, + "end_line": 148, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Request DTO for inline-edit of a metric description." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'DataClass'", + "detail": { + "actual_type": "DataClass", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'DataClass' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "DataClass" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MetricDescriptionUpdate [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for inline-edit of a metric description.\nclass MetricDescriptionUpdate(BaseModel):\n description: str\n# #endregion MetricDescriptionUpdate\n" + }, { "contract_id": "get_dataset_ids", "contract_type": "Function", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 109, - "end_line": 155, + "start_line": 150, + "end_line": 196, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -10961,15 +11068,16 @@ "contract_id": "get_datasets", "contract_type": "Function", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 157, - "end_line": 229, + "start_line": 198, + "end_line": 312, "tier": "TIER_2", "complexity": 4, "metadata": { "COMPLEXITY": 4, - "POST": "Response includes pagination metadata (page, page_size, total, total_pages)", + "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", - "PURPOSE": "Fetch list of datasets from a specific environment with mapping progress" + "PURPOSE": "Fetch list of datasets from a specific environment with mapping progress and stats.", + "RATIONALE": "Stats counts returned in the same response as datasets to avoid an extra API call for the Stats Bar (FR-022)." }, "relations": [ { @@ -10982,14 +11090,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region get_datasets [C:4] [TYPE Function]\n# @BRIEF Fetch list of datasets from a specific environment with mapping progress\n# @PRE: env_id must be a valid environment ID\n# @PRE: page must be >= 1 if provided\n# @PRE: page_size must be between 1 and 100 if provided\n# @POST: Returns a list of datasets with enhanced metadata and pagination info\n# @POST: Response includes pagination metadata (page, page_size, total, total_pages)\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"\", response_model=DatasetsResponse)\nasync def get_datasets(\n env_id: str,\n search: str | None = None,\n page: int = 1,\n page_size: int = 10,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_datasets\", f\"env_id={env_id}, search={search}, page={page}, page_size={page_size}\"):\n # Validate pagination parameters\n if page < 1:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page: {page}\")\n raise HTTPException(status_code=400, detail=\"Page must be >= 1\")\n if page_size < 1 or page_size > 100:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page_size: {page_size}\")\n raise HTTPException(status_code=400, detail=\"Page size must be between 1 and 100\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_datasets][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Calculate pagination\n total = len(datasets)\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n start_idx = (page - 1) * page_size\n end_idx = start_idx + page_size\n\n # Slice datasets for current page\n paginated_datasets = datasets[start_idx:end_idx]\n\n logger.info(f\"[get_datasets][Coherence:OK] Returning {len(paginated_datasets)} datasets (page {page}/{total_pages}, total: {total})\")\n\n return DatasetsResponse(\n datasets=paginated_datasets,\n total=total,\n page=page,\n page_size=page_size,\n total_pages=total_pages\n )\n\n except Exception as e:\n logger.error(f\"[get_datasets][Coherence:Failed] Failed to fetch datasets: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch datasets: {e!s}\")\n# #endregion get_datasets\n" + "body": "# #region get_datasets [C:4] [TYPE Function]\n# @BRIEF Fetch list of datasets from a specific environment with mapping progress and stats.\n# @PRE: env_id must be a valid environment ID\n# @PRE: page must be >= 1 if provided\n# @PRE: page_size must be between 1 and 100 if provided\n# @POST: Returns a list of datasets with enhanced metadata, pagination info, and StatsCounts.\n# @POST: Response includes pagination metadata (page, page_size, total, total_pages) and stats object.\n# @RATIONALE Stats counts returned in the same response as datasets to avoid an extra API call for the Stats Bar (FR-022).\n# @RELATION CALLS -> [get_datasets_with_status]\n@router.get(\"\", response_model=DatasetsResponse)\nasync def get_datasets(\n env_id: str,\n search: str | None = None,\n filter: str | None = None,\n page: int = 1,\n page_size: int = 10,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n resource_service=Depends(get_resource_service),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_datasets\", f\"env_id={env_id}, search={search}, filter={filter}, page={page}, page_size={page_size}\"):\n # Validate pagination parameters\n if page < 1:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page: {page}\")\n raise HTTPException(status_code=400, detail=\"Page must be >= 1\")\n if page_size < 1 or page_size > 100:\n logger.error(f\"[get_datasets][Coherence:Failed] Invalid page_size: {page_size}\")\n raise HTTPException(status_code=400, detail=\"Page size must be between 1 and 100\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_datasets][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Get all tasks for status lookup\n all_tasks = task_manager.get_all_tasks()\n\n # Fetch datasets with status using ResourceService\n datasets = await resource_service.get_datasets_with_status(env, all_tasks)\n\n # Compute stats from full list BEFORE filtering/pagination\n total_datasets = len(datasets)\n unmapped = sum(\n 1 for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) == 0\n )\n mapped = sum(\n 1 for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) > 0\n )\n linked = sum(\n 1 for d in datasets\n if d.get(\"linked_dashboard_count\", 0) > 0\n )\n stats = StatsCounts(\n total=total_datasets,\n unmapped_count=unmapped,\n mapped_count=mapped,\n linked_count=linked,\n )\n\n # Apply server-side filter (before pagination) — FR-026\n if filter and filter in (\"unmapped\", \"mapped\", \"linked\"):\n if filter == \"unmapped\":\n datasets = [\n d for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) == 0\n ]\n elif filter == \"mapped\":\n datasets = [\n d for d in datasets\n if d.get(\"mapped_fields\") and d[\"mapped_fields\"].get(\"mapped\", 0) > 0\n ]\n elif filter == \"linked\":\n datasets = [\n d for d in datasets\n if d.get(\"linked_dashboard_count\", 0) > 0\n ]\n\n # Apply search filter if provided\n if search:\n search_lower = search.lower()\n datasets = [\n d for d in datasets\n if search_lower in d.get('table_name', '').lower()\n ]\n\n # Calculate pagination\n total = len(datasets)\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n start_idx = (page - 1) * page_size\n end_idx = start_idx + page_size\n\n # Slice datasets for current page\n paginated_datasets = datasets[start_idx:end_idx]\n\n logger.info(f\"[get_datasets][Coherence:OK] Returning {len(paginated_datasets)} datasets (page {page}/{total_pages}, total: {total}, stats: total={stats.total} unmapped={stats.unmapped_count} mapped={stats.mapped_count} linked={stats.linked_count})\")\n\n return DatasetsResponse(\n datasets=paginated_datasets,\n stats=stats,\n total=total,\n page=page,\n page_size=page_size,\n total_pages=total_pages\n )\n\n except Exception as e:\n logger.error(f\"[get_datasets][Coherence:Failed] Failed to fetch datasets: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch datasets: {e!s}\")\n# #endregion get_datasets\n" }, { "contract_id": "MapColumnsRequest", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 231, - "end_line": 239, + "start_line": 314, + "end_line": 323, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -11054,14 +11162,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MapColumnsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating column mapping\nclass MapColumnsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to map\")\n source_type: str = Field(..., description=\"Source type: 'postgresql' or 'xlsx'\")\n connection_id: str | None = Field(None, description=\"Connection ID for PostgreSQL source\")\n file_data: str | None = Field(None, description=\"File path or data for XLSX source\")\n# #endregion MapColumnsRequest\n" + "body": "# #region MapColumnsRequest [C:1] [TYPE DataClass]\n# @BRIEF Request DTO for initiating column mapping\nclass MapColumnsRequest(BaseModel):\n env_id: str = Field(..., description=\"Environment ID\")\n dataset_ids: list[int] = Field(..., description=\"List of dataset IDs to map\")\n source_type: str = Field(..., description=\"Source type: 'sqllab' or 'xlsx'\")\n database_id: int | None = Field(None, description=\"Superset database ID for SQL Lab source\")\n sql_query: str | None = Field(None, description=\"Custom SQL query for SQL Lab (optional, defaults to information_schema.columns query)\")\n file_data: str | None = Field(None, description=\"File path or data for XLSX source\")\n# #endregion MapColumnsRequest\n" }, { "contract_id": "map_columns", "contract_type": "Function", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 241, - "end_line": 298, + "start_line": 325, + "end_line": 387, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -11087,14 +11195,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region map_columns [C:4] [TYPE Function]\n# @BRIEF Trigger bulk column mapping for datasets\n# @PRE: User has permission plugin:mapper:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking mapping progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [MapperPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/map-columns\", response_model=TaskResponse)\nasync def map_columns(\n request: MapColumnsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:mapper\", \"EXECUTE\"))\n):\n with belief_scope(\"map_columns\", f\"env={request.env_id}, count={len(request.dataset_ids)}, source={request.source_type}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[map_columns][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate source type\n if request.source_type not in ['postgresql', 'xlsx']:\n logger.error(f\"[map_columns][Coherence:Failed] Invalid source type: {request.source_type}\")\n raise HTTPException(status_code=400, detail=\"Source type must be 'postgresql' or 'xlsx'\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[map_columns][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create mapping task\n task_params = {\n 'env': request.env_id,\n 'dataset_id': request.dataset_ids[0] if request.dataset_ids else None,\n 'source': request.source_type,\n 'connection_id': request.connection_id,\n 'file_data': request.file_data\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='dataset-mapper',\n params=task_params\n )\n\n logger.info(f\"[map_columns][Coherence:OK] Mapping task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[map_columns][Coherence:Failed] Failed to create mapping task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create mapping task: {e!s}\")\n# #endregion map_columns\n" + "body": "# #region map_columns [C:4] [TYPE Function]\n# @BRIEF Trigger bulk column mapping for datasets\n# @PRE: User has permission plugin:mapper:execute\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_ids is a non-empty list\n# @POST: Returns task_id for tracking mapping progress\n# @POST: Task is created and queued for execution\n# @RELATION DISPATCHES -> [MapperPlugin]\n# @RELATION CALLS -> [create_task]\n@router.post(\"/map-columns\", response_model=TaskResponse)\nasync def map_columns(\n request: MapColumnsRequest,\n config_manager=Depends(get_config_manager),\n task_manager=Depends(get_task_manager),\n _ = Depends(has_permission(\"plugin:mapper\", \"EXECUTE\"))\n):\n with belief_scope(\"map_columns\", f\"env={request.env_id}, count={len(request.dataset_ids)}, source={request.source_type}\"):\n # Validate request\n if not request.dataset_ids:\n logger.error(\"[map_columns][Coherence:Failed] No dataset IDs provided\")\n raise HTTPException(status_code=400, detail=\"At least one dataset ID must be provided\")\n\n # Validate source type\n if request.source_type not in ['sqllab', 'xlsx']:\n logger.error(f\"[map_columns][Coherence:Failed] Invalid source type: {request.source_type}\")\n raise HTTPException(status_code=400, detail=\"Source type must be 'sqllab' or 'xlsx'\")\n\n # Validate database_id for sqllab source\n if request.source_type == 'sqllab' and not request.database_id:\n raise HTTPException(status_code=400, detail=\"database_id is required for 'sqllab' source type\")\n\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == request.env_id), None)\n\n if not env:\n logger.error(f\"[map_columns][Coherence:Failed] Environment not found: {request.env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Create mapping task\n task_params = {\n 'env': request.env_id,\n 'dataset_id': request.dataset_ids[0] if request.dataset_ids else None,\n 'source': 'sqllab' if request.source_type == 'sqllab' else 'excel',\n 'database_id': request.database_id,\n 'sql_query': request.sql_query,\n 'file_data': request.file_data\n }\n\n task_obj = await task_manager.create_task(\n plugin_id='dataset-mapper',\n params=task_params\n )\n\n logger.info(f\"[map_columns][Coherence:OK] Mapping task created: {task_obj.id} for {len(request.dataset_ids)} datasets\")\n\n return TaskResponse(task_id=str(task_obj.id))\n\n except Exception as e:\n logger.error(f\"[map_columns][Coherence:Failed] Failed to create mapping task: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to create mapping task: {e!s}\")\n# #endregion map_columns\n" }, { "contract_id": "GenerateDocsRequest", "contract_type": "DataClass", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 300, - "end_line": 307, + "start_line": 389, + "end_line": 396, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -11165,8 +11273,8 @@ "contract_id": "generate_docs", "contract_type": "Function", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 309, - "end_line": 360, + "start_line": 398, + "end_line": 449, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -11198,8 +11306,8 @@ "contract_id": "get_dataset_detail", "contract_type": "Function", "file_path": "backend/src/api/routes/datasets.py", - "start_line": 362, - "end_line": 400, + "start_line": 451, + "end_line": 489, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -11221,6 +11329,482 @@ "tier_source": "AutoCalculated", "body": "# #region get_dataset_detail [C:4] [TYPE Function]\n# @BRIEF Get detailed dataset information including columns and linked dashboards\n# @PRE: env_id is a valid environment ID\n# @PRE: dataset_id is a valid dataset ID\n# @POST: Returns detailed dataset info with columns and linked dashboards\n# @RELATION CALLS -> [SupersetClientGetDatasetDetail]\n@router.get(\"/{dataset_id}\", response_model=DatasetDetailResponse)\nasync def get_dataset_detail(\n env_id: str,\n dataset_id: int,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"READ\"))\n):\n with belief_scope(\"get_dataset_detail\", f\"env_id={env_id}, dataset_id={dataset_id}\"):\n # Validate environment exists\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n # Fetch detailed dataset info using SupersetClient\n client = SupersetClient(env)\n dataset_detail = client.get_dataset_detail(dataset_id)\n\n # Normalize 'database' field: Superset returns an object, model expects a string\n if isinstance(dataset_detail.get(\"database\"), dict):\n db_obj = dataset_detail[\"database\"]\n dataset_detail[\"database\"] = db_obj.get(\"database_name\", str(db_obj.get(\"id\", \"\")))\n\n logger.info(f\"[get_dataset_detail][Coherence:OK] Retrieved dataset {dataset_id} with {dataset_detail['column_count']} columns and {dataset_detail['linked_dashboard_count']} linked dashboards\")\n\n return DatasetDetailResponse(**dataset_detail)\n\n except Exception as e:\n logger.error(f\"[get_dataset_detail][Coherence:Failed] Failed to fetch dataset detail: {e}\")\n raise HTTPException(status_code=503, detail=f\"Failed to fetch dataset detail: {e!s}\")\n# #endregion get_dataset_detail\n" }, + { + "contract_id": "_strip_html_tags", + "contract_type": "Function", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 491, + "end_line": 504, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Detect and strip HTML tags from a text string. Uses simple regex <[^>]*>." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _strip_html_tags [C:2] [TYPE Function] [SEMANTICS helper,validation,html]\n# @BRIEF Detect and strip HTML tags from a text string. Uses simple regex <[^>]*>.\n# If HTML is detected, strips tags and logs a warning. Returns cleaned text.\n# @REJECTED Reject-with-400 approach was rejected in favour of silent stripping — more user-friendly\n# and matches the UX expectation that inline-edited descriptions are plain text only.\ndef _strip_html_tags(text: str) -> str:\n if not text:\n return text\n if re.search(r\"<[^>]*>\", text):\n cleaned = re.sub(r\"<[^>]*>\", \"\", text)\n logger.warning(f\"[_strip_html_tags] HTML tags detected and stripped from description\")\n return cleaned\n return text\n# #endregion _strip_html_tags\n" + }, + { + "contract_id": "update_column_description", + "contract_type": "Endpoint", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 506, + "end_line": 593, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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.", + "PURPOSE": "Save description for a single dataset column. Internal: GET full dataset from Superset, modify one column's description, PUT back.", + "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." + }, + "relations": [ + { + "source_id": "update_column_description", + "relation_type": "CALLS", + "target_id": "SupersetClient.get_dataset", + "target_ref": "[SupersetClient.get_dataset]" + }, + { + "source_id": "update_column_description", + "relation_type": "CALLS", + "target_id": "SupersetClient.update_dataset", + "target_ref": "[SupersetClient.update_dataset]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "ERROR", + "message": "@ERROR is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "ERROR", + "message": "@ERROR is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "POST", + "message": "@POST is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "POST", + "message": "@POST is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PRE", + "message": "@PRE is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PRE", + "message": "@PRE is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "RATIONALE", + "message": "@RATIONALE is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RATIONALE", + "message": "@RATIONALE is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "REJECTED", + "message": "@REJECTED is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "REJECTED", + "message": "@REJECTED is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "SIDE_EFFECT", + "message": "@SIDE_EFFECT is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "SIDE_EFFECT", + "message": "@SIDE_EFFECT is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "unknown_tag", + "tag": "VALIDATION", + "message": "@VALIDATION is not defined in axiom_config.yaml tags", + "detail": null + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region update_column_description [C:4] [TYPE Endpoint]\n# @BRIEF Save description for a single dataset column. Internal: GET full dataset from Superset, modify one column's description, PUT back.\n# @PRE: dataset_id and column_id must exist in the target environment.\n# @POST: Column description in Superset is updated. Response confirms success.\n# @SIDE_EFFECT: Mutates dataset metadata in upstream Superset instance via PUT.\n# @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.\n# @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).\n# @RELATION CALLS -> [SupersetClient.get_dataset]\n# @RELATION CALLS -> [SupersetClient.update_dataset]\n# @RATIONALE Must perform GET→modify→PUT because Superset has no PATCH for individual columns — only full object PUT with override_columns=false.\n# @REJECTED Direct PUT from frontend — rejected because frontend would need to handle full Superset payload structure.\n@router.put(\"/{dataset_id}/columns/{column_id}/description\")\nasync def update_column_description(\n dataset_id: int,\n column_id: int,\n env_id: str = Query(..., description=\"Environment ID\"),\n body: ColumnDescriptionUpdate = ...,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"WRITE\"))\n):\n with belief_scope(\"update_column_description\", f\"dataset_id={dataset_id}, column_id={column_id}, env_id={env_id}\"):\n # Validate and sanitize description\n description = _strip_html_tags(body.description)\n if len(description) > 2000:\n logger.error(f\"[update_column_description][Coherence:Failed] Description exceeds 2000 chars: {len(description)}\")\n raise HTTPException(status_code=400, detail=\"Description must not exceed 2000 characters\")\n\n # Validate environment\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[update_column_description][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n client = SupersetClient(env)\n\n # GET full dataset\n logger.reason(\"Fetching full dataset from Superset for column description update\",\n extra={\"src\": \"update_column_description\"})\n try:\n response = client.get_dataset(dataset_id)\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Superset GET failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to fetch dataset from Superset: {e!s}\")\n\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n\n if not dataset or not dataset.get(\"id\"):\n logger.error(f\"[update_column_description][Coherence:Failed] Dataset {dataset_id} not found\")\n raise HTTPException(status_code=404, detail=f\"Dataset {dataset_id} not found\")\n\n # Find and modify the target column\n columns = dataset.get(\"columns\", [])\n found = False\n for col in columns:\n if col.get(\"id\") == column_id:\n col[\"description\"] = description\n found = True\n break\n\n if not found:\n logger.error(f\"[update_column_description][Coherence:Failed] Column {column_id} not found in dataset {dataset_id}\")\n raise HTTPException(status_code=404, detail=f\"Column {column_id} not found in dataset {dataset_id}\")\n\n # PUT back with override_columns=false\n put_payload = dataset\n try:\n client.update_dataset(dataset_id, put_payload, override_columns=False)\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Superset PUT failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to update dataset in Superset: {e!s}\")\n\n logger.reflect(\n f\"Updated column {column_id} description for dataset {dataset_id}\",\n extra={\"src\": \"update_column_description\"},\n )\n return {\"success\": True, \"description\": description}\n\n except HTTPException:\n raise\n except Exception as e:\n logger.error(f\"[update_column_description][Coherence:Failed] Unexpected error: {e}\")\n raise HTTPException(status_code=500, detail=f\"Unexpected error: {e!s}\")\n# #endregion update_column_description\n" + }, + { + "contract_id": "update_metric_description", + "contract_type": "Endpoint", + "file_path": "backend/src/api/routes/datasets.py", + "start_line": 595, + "end_line": 679, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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.", + "PURPOSE": "Save description for a single dataset metric. Mirror of update_column_description for metrics.", + "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." + }, + "relations": [ + { + "source_id": "update_metric_description", + "relation_type": "CALLS", + "target_id": "SupersetClient.get_dataset", + "target_ref": "[SupersetClient.get_dataset]" + }, + { + "source_id": "update_metric_description", + "relation_type": "CALLS", + "target_id": "SupersetClient.update_dataset", + "target_ref": "[SupersetClient.update_dataset]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "ERROR", + "message": "@ERROR is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "ERROR", + "message": "@ERROR is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "POST", + "message": "@POST is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "POST", + "message": "@POST is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PRE", + "message": "@PRE is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PRE", + "message": "@PRE is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "SIDE_EFFECT", + "message": "@SIDE_EFFECT is not allowed for contract type 'Endpoint'", + "detail": { + "actual_type": "Endpoint", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "SIDE_EFFECT", + "message": "@SIDE_EFFECT is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + }, + { + "code": "unknown_tag", + "tag": "VALIDATION", + "message": "@VALIDATION is not defined in axiom_config.yaml tags", + "detail": null + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'Endpoint' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Endpoint" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region update_metric_description [C:4] [TYPE Endpoint]\n# @BRIEF Save description for a single dataset metric. Mirror of update_column_description for metrics.\n# @PRE: dataset_id and metric_id must exist in the target environment.\n# @POST: Metric description in Superset is updated.\n# @SIDE_EFFECT: Mutates dataset metadata in upstream Superset instance via PUT.\n# @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.\n# @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).\n# @RELATION CALLS -> [SupersetClient.get_dataset]\n# @RELATION CALLS -> [SupersetClient.update_dataset]\n@router.put(\"/{dataset_id}/metrics/{metric_id}/description\")\nasync def update_metric_description(\n dataset_id: int,\n metric_id: int,\n env_id: str = Query(..., description=\"Environment ID\"),\n body: MetricDescriptionUpdate = ...,\n config_manager=Depends(get_config_manager),\n _ = Depends(has_permission(\"plugin:migration\", \"WRITE\"))\n):\n with belief_scope(\"update_metric_description\", f\"dataset_id={dataset_id}, metric_id={metric_id}, env_id={env_id}\"):\n # Validate and sanitize description\n description = _strip_html_tags(body.description)\n if len(description) > 2000:\n logger.error(f\"[update_metric_description][Coherence:Failed] Description exceeds 2000 chars: {len(description)}\")\n raise HTTPException(status_code=400, detail=\"Description must not exceed 2000 characters\")\n\n # Validate environment\n environments = config_manager.get_environments()\n env = next((e for e in environments if e.id == env_id), None)\n if not env:\n logger.error(f\"[update_metric_description][Coherence:Failed] Environment not found: {env_id}\")\n raise HTTPException(status_code=404, detail=\"Environment not found\")\n\n try:\n client = SupersetClient(env)\n\n # GET full dataset\n logger.reason(\"Fetching full dataset from Superset for metric description update\",\n extra={\"src\": \"update_metric_description\"})\n try:\n response = client.get_dataset(dataset_id)\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Superset GET failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to fetch dataset from Superset: {e!s}\")\n\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n\n if not dataset or not dataset.get(\"id\"):\n logger.error(f\"[update_metric_description][Coherence:Failed] Dataset {dataset_id} not found\")\n raise HTTPException(status_code=404, detail=f\"Dataset {dataset_id} not found\")\n\n # Find and modify the target metric\n metrics = dataset.get(\"metrics\", [])\n found = False\n for metric in metrics:\n if metric.get(\"id\") == metric_id:\n metric[\"description\"] = description\n found = True\n break\n\n if not found:\n logger.error(f\"[update_metric_description][Coherence:Failed] Metric {metric_id} not found in dataset {dataset_id}\")\n raise HTTPException(status_code=404, detail=f\"Metric {metric_id} not found in dataset {dataset_id}\")\n\n # PUT back with override_columns=false\n try:\n client.update_dataset(dataset_id, dataset, override_columns=False)\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Superset PUT failed: {e}\")\n raise HTTPException(status_code=502, detail=f\"Failed to update dataset in Superset: {e!s}\")\n\n logger.reflect(\n f\"Updated metric {metric_id} description for dataset {dataset_id}\",\n extra={\"src\": \"update_metric_description\"},\n )\n return {\"success\": True, \"description\": description}\n\n except HTTPException:\n raise\n except Exception as e:\n logger.error(f\"[update_metric_description][Coherence:Failed] Unexpected error: {e}\")\n raise HTTPException(status_code=500, detail=f\"Unexpected error: {e!s}\")\n# #endregion update_metric_description\n" + }, { "contract_id": "EnvironmentsApi", "contract_type": "Module", @@ -14820,39 +15404,6 @@ "tier_source": "AutoCalculated", "body": "# #region TasksRouter [C:3] [TYPE Module] [SEMANTICS fastapi, task, api, search, create-task-request, resolve-task-request]\n# @BRIEF Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks.\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [TaskManager]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n\nfrom typing import Any\n\nfrom fastapi import APIRouter, Depends, HTTPException, Query, status\nfrom pydantic import BaseModel\n\nfrom ...core.config_manager import ConfigManager\nfrom ...core.logger import belief_scope\nfrom ...core.task_manager import Task, TaskManager, TaskStatus\nfrom ...core.task_manager.models import LogFilter, LogStats\nfrom ...dependencies import (\n get_config_manager,\n get_current_user,\n get_task_manager,\n has_permission,\n)\nfrom ...services.llm_prompt_templates import (\n normalize_llm_settings,\n resolve_bound_provider_id,\n)\n\nrouter = APIRouter()\n\nTASK_TYPE_PLUGIN_MAP = {\n \"llm_validation\": [\"llm_dashboard_validation\"],\n \"backup\": [\"superset-backup\"],\n \"migration\": [\"superset-migration\"],\n}\n\n\nclass CreateTaskRequest(BaseModel):\n plugin_id: str\n params: dict[str, Any]\n\n\nclass ResolveTaskRequest(BaseModel):\n resolution_params: dict[str, Any]\n\n\nclass ResumeTaskRequest(BaseModel):\n passwords: dict[str, str]\n\n\n# #region create_task [C:3] [TYPE Function]\n# @BRIEF Create and start a new task for a given plugin.\n# @PRE: plugin_id must exist and params must be valid for that plugin.\n# @POST: A new task is created and started.\n# @RELATION CALLS -> [TaskManager]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n@router.post(\"\", response_model=Task, status_code=status.HTTP_201_CREATED)\nasync def create_task(\n request: CreateTaskRequest,\n task_manager: TaskManager = Depends(get_task_manager),\n current_user=Depends(get_current_user),\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n # Dynamic permission check based on plugin_id\n has_permission(f\"plugin:{request.plugin_id}\", \"EXECUTE\")(current_user)\n with belief_scope(\"create_task\"):\n try:\n # Special handling for LLM tasks to resolve provider config by task binding.\n if request.plugin_id in {\"llm_dashboard_validation\", \"llm_documentation\"}:\n from ...core.database import SessionLocal\n from ...services.llm_provider import LLMProviderService\n\n db = SessionLocal()\n try:\n llm_service = LLMProviderService(db)\n provider_id = request.params.get(\"provider_id\")\n if not provider_id:\n llm_settings = normalize_llm_settings(\n config_manager.get_config().settings.llm\n )\n binding_key = (\n \"dashboard_validation\"\n if request.plugin_id == \"llm_dashboard_validation\"\n else \"documentation\"\n )\n provider_id = resolve_bound_provider_id(\n llm_settings, binding_key\n )\n if provider_id:\n request.params[\"provider_id\"] = provider_id\n if not provider_id:\n providers = llm_service.get_all_providers()\n active_provider = next(\n (p for p in providers if p.is_active), None\n )\n if active_provider:\n provider_id = active_provider.id\n request.params[\"provider_id\"] = provider_id\n\n if provider_id:\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n if (\n request.plugin_id == \"llm_dashboard_validation\"\n and not bool(db_provider.is_multimodal)\n ):\n raise HTTPException(\n status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,\n detail=\"Selected provider model is not multimodal for dashboard validation\",\n )\n finally:\n db.close()\n\n task = await task_manager.create_task(\n plugin_id=request.plugin_id, params=request.params\n )\n return task\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n\n\n# #endregion create_task\n\n\n# #region list_tasks [C:2] [TYPE Function]\n# @BRIEF Retrieve a list of tasks with pagination and optional status filter.\n# @PRE: task_manager must be available.\n# @POST: Returns a list of tasks.\n# @RELATION CALLS -> [TaskManager]\n# @RELATION BINDS_TO -> [TASK_TYPE_PLUGIN_MAP]\n@router.get(\"\", response_model=list[Task])\nasync def list_tasks(\n limit: int = 10,\n offset: int = 0,\n status_filter: TaskStatus | None = Query(None, alias=\"status\"),\n task_type: str | None = Query(\n None, description=\"Task category: llm_validation, backup, migration\"\n ),\n plugin_id: list[str] | None = Query(\n None, description=\"Filter by plugin_id (repeatable query param)\"\n ),\n completed_only: bool = Query(\n False, description=\"Return only completed tasks (SUCCESS/FAILED)\"\n ),\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"READ\")),\n):\n with belief_scope(\"list_tasks\"):\n plugin_filters = list(plugin_id) if plugin_id else []\n if task_type:\n if task_type not in TASK_TYPE_PLUGIN_MAP:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"Unsupported task_type '{task_type}'. Allowed: {', '.join(TASK_TYPE_PLUGIN_MAP.keys())}\",\n )\n plugin_filters.extend(TASK_TYPE_PLUGIN_MAP[task_type])\n\n return task_manager.get_tasks(\n limit=limit,\n offset=offset,\n status=status_filter,\n plugin_ids=plugin_filters or None,\n completed_only=completed_only,\n )\n\n\n# #endregion list_tasks\n\n\n# #region get_task [C:2] [TYPE Function]\n# @BRIEF Retrieve the details of a specific task.\n# @PRE: task_id must exist.\n# @POST: Returns task details or raises 404.\n# @RELATION CALLS -> [TaskManager]\n@router.get(\"/{task_id}\", response_model=Task)\nasync def get_task(\n task_id: str,\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"READ\")),\n):\n with belief_scope(\"get_task\"):\n task = task_manager.get_task(task_id)\n if not task:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND, detail=\"Task not found\"\n )\n return task\n\n\n# #endregion get_task\n\n\n# #region get_task_logs [C:5] [TYPE Function]\n# @BRIEF Retrieve logs for a specific task with optional filtering.\n# @PRE: task_id must exist.\n# @POST: Returns a list of log entries or raises 404.\n# @RELATION CALLS -> [TaskManager]\n# @RELATION DEPENDS_ON -> [LogFilter]\n# @TEST_CONTRACT: TaskLogQueryInput -> List[LogEntry]\n# @TEST_SCENARIO: existing_task_logs_filtered -> Returns filtered logs by level/source/search with pagination.\n# @TEST_FIXTURE: valid_task_with_mixed_logs -> backend/tests/fixtures/task_logs/valid_task_with_mixed_logs.json\n# @TEST_EDGE: missing_task -> Unknown task_id returns 404 Task not found.\n# @TEST_EDGE: invalid_level_type -> Non-string/invalid level query rejected by validation or yields empty result.\n# @TEST_EDGE: pagination_bounds -> offset=0 and limit=1000 remain within API bounds and do not overflow.\n# @TEST_INVARIANT: logs_only_for_existing_task -> VERIFIED_BY: [existing_task_logs_filtered, missing_task]\n@router.get(\"/{task_id}/logs\")\nasync def get_task_logs(\n task_id: str,\n level: str | None = Query(\n None, description=\"Filter by log level (DEBUG, INFO, WARNING, ERROR)\"\n ),\n source: str | None = Query(None, description=\"Filter by source component\"),\n search: str | None = Query(None, description=\"Text search in message\"),\n offset: int = Query(0, ge=0, description=\"Number of logs to skip\"),\n limit: int = Query(\n 100, ge=1, le=1000, description=\"Maximum number of logs to return\"\n ),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"get_task_logs\"):\n task = task_manager.get_task(task_id)\n if not task:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND, detail=\"Task not found\"\n )\n\n log_filter = LogFilter(\n level=level.upper() if level else None,\n source=source,\n search=search,\n offset=offset,\n limit=limit,\n )\n return task_manager.get_task_logs(task_id, log_filter)\n\n\n# #endregion get_task_logs\n\n\n# #region get_task_log_stats [C:2] [TYPE Function]\n# @BRIEF Get statistics about logs for a task (counts by level and source).\n# @PRE: task_id must exist.\n# @POST: Returns log statistics or raises 404.\n# @RELATION CALLS -> [TaskManager]\n# @RELATION DEPENDS_ON -> [LogStats]\n@router.get(\"/{task_id}/logs/stats\", response_model=LogStats)\nasync def get_task_log_stats(\n task_id: str,\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"get_task_log_stats\"):\n task = task_manager.get_task(task_id)\n if not task:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND, detail=\"Task not found\"\n )\n stats_payload = task_manager.get_task_log_stats(task_id)\n if isinstance(stats_payload, LogStats):\n return stats_payload\n if isinstance(stats_payload, dict) and (\n \"total_count\" in stats_payload\n or \"by_level\" in stats_payload\n or \"by_source\" in stats_payload\n ):\n return LogStats(\n total_count=int(stats_payload.get(\"total_count\", 0) or 0),\n by_level=dict(stats_payload.get(\"by_level\") or {}),\n by_source=dict(stats_payload.get(\"by_source\") or {}),\n )\n flat_by_level = (\n dict(stats_payload or {}) if isinstance(stats_payload, dict) else {}\n )\n return LogStats(\n total_count=sum(int(value or 0) for value in flat_by_level.values()),\n by_level={\n str(key): int(value or 0) for key, value in flat_by_level.items()\n },\n by_source={},\n )\n\n\n# #endregion get_task_log_stats\n\n\n# #region get_task_log_sources [C:2] [TYPE Function]\n# @BRIEF Get unique sources for a task's logs.\n# @PRE: task_id must exist.\n# @POST: Returns list of unique source names or raises 404.\n# @RELATION CALLS -> [TaskManager]\n@router.get(\"/{task_id}/logs/sources\", response_model=list[str])\nasync def get_task_log_sources(\n task_id: str,\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"get_task_log_sources\"):\n task = task_manager.get_task(task_id)\n if not task:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND, detail=\"Task not found\"\n )\n return task_manager.get_task_log_sources(task_id)\n\n\n# #endregion get_task_log_sources\n\n\n# #region resolve_task [C:2] [TYPE Function]\n# @BRIEF Resolve a task that is awaiting mapping.\n# @PRE: task must be in AWAITING_MAPPING status.\n# @POST: Task is resolved and resumes execution.\n# @RELATION CALLS -> [TaskManager]\n@router.post(\"/{task_id}/resolve\", response_model=Task)\nasync def resolve_task(\n task_id: str,\n request: ResolveTaskRequest,\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"WRITE\")),\n):\n with belief_scope(\"resolve_task\"):\n try:\n await task_manager.resolve_task(task_id, request.resolution_params)\n return task_manager.get_task(task_id)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n\n\n# #endregion resolve_task\n\n\n# #region resume_task [C:2] [TYPE Function]\n# @BRIEF Resume a task that is awaiting input (e.g., passwords).\n# @PRE: task must be in AWAITING_INPUT status.\n# @POST: Task resumes execution with provided input.\n# @RELATION CALLS -> [TaskManager]\n@router.post(\"/{task_id}/resume\", response_model=Task)\nasync def resume_task(\n task_id: str,\n request: ResumeTaskRequest,\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"WRITE\")),\n):\n with belief_scope(\"resume_task\"):\n try:\n task_manager.resume_task_with_password(task_id, request.passwords)\n return task_manager.get_task(task_id)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n\n\n# #endregion resume_task\n\n\n# #region clear_tasks [C:2] [TYPE Function]\n# @BRIEF Clear tasks matching the status filter.\n# @PRE: task_manager is available.\n# @POST: Tasks are removed from memory/persistence.\n# @RELATION CALLS -> [TaskManager]\n@router.delete(\"\", status_code=status.HTTP_204_NO_CONTENT)\nasync def clear_tasks(\n status: TaskStatus | None = None,\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"WRITE\")),\n):\n with belief_scope(\"clear_tasks\", f\"status={status}\"):\n task_manager.clear_tasks(status)\n return\n\n\n# #endregion clear_tasks\n\n# #endregion TasksRouter\n" }, - { - "contract_id": "list_tasks", - "contract_type": "Function", - "file_path": "backend/src/api/routes/tasks.py", - "start_line": 126, - "end_line": 168, - "tier": "TIER_1", - "complexity": 2, - "metadata": { - "COMPLEXITY": 2, - "POST": "Returns a list of tasks.", - "PRE": "task_manager must be available.", - "PURPOSE": "Retrieve a list of tasks with pagination and optional status filter." - }, - "relations": [ - { - "source_id": "list_tasks", - "relation_type": "CALLS", - "target_id": "TaskManager", - "target_ref": "[TaskManager]" - }, - { - "source_id": "list_tasks", - "relation_type": "BINDS_TO", - "target_id": "TASK_TYPE_PLUGIN_MAP", - "target_ref": "[TASK_TYPE_PLUGIN_MAP]" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region list_tasks [C:2] [TYPE Function]\n# @BRIEF Retrieve a list of tasks with pagination and optional status filter.\n# @PRE: task_manager must be available.\n# @POST: Returns a list of tasks.\n# @RELATION CALLS -> [TaskManager]\n# @RELATION BINDS_TO -> [TASK_TYPE_PLUGIN_MAP]\n@router.get(\"\", response_model=list[Task])\nasync def list_tasks(\n limit: int = 10,\n offset: int = 0,\n status_filter: TaskStatus | None = Query(None, alias=\"status\"),\n task_type: str | None = Query(\n None, description=\"Task category: llm_validation, backup, migration\"\n ),\n plugin_id: list[str] | None = Query(\n None, description=\"Filter by plugin_id (repeatable query param)\"\n ),\n completed_only: bool = Query(\n False, description=\"Return only completed tasks (SUCCESS/FAILED)\"\n ),\n task_manager: TaskManager = Depends(get_task_manager),\n _=Depends(has_permission(\"tasks\", \"READ\")),\n):\n with belief_scope(\"list_tasks\"):\n plugin_filters = list(plugin_id) if plugin_id else []\n if task_type:\n if task_type not in TASK_TYPE_PLUGIN_MAP:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"Unsupported task_type '{task_type}'. Allowed: {', '.join(TASK_TYPE_PLUGIN_MAP.keys())}\",\n )\n plugin_filters.extend(TASK_TYPE_PLUGIN_MAP[task_type])\n\n return task_manager.get_tasks(\n limit=limit,\n offset=offset,\n status=status_filter,\n plugin_ids=plugin_filters or None,\n completed_only=completed_only,\n )\n\n\n# #endregion list_tasks\n" - }, { "contract_id": "resume_task", "contract_type": "Function", @@ -15812,46 +16363,6 @@ "tier_source": "AutoCalculated", "body": "# #region TranslateRunListRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, translate, api, download, search]\n# @BRIEF Translation Run listing, detail, and CSV download routes (cross-job).\n# @LAYER: API\n\n\nfrom fastapi import Depends, HTTPException, Query, status\nfrom sqlalchemy.orm import Session\n\nfrom ....core.config_manager import ConfigManager\nfrom ....core.database import get_db\nfrom ....core.logger import logger\nfrom ....dependencies import get_config_manager, get_current_user, has_permission\nfrom ....plugins.translate.events import TranslationEventLog\nfrom ....plugins.translate.orchestrator import TranslationOrchestrator\nfrom ....schemas.auth import User\nfrom ._router import router\n\n# ============================================================\n# List Runs (cross-job)\n# ============================================================\n\n# #region list_runs [C:4] [TYPE Function]\n# @BRIEF List all runs with cross-job filtering and pagination.\n# @PRE: User has translate.history.view permission.\n# @POST: Returns paginated list of runs.\n@router.get(\"/runs\")\nasync def list_runs(\n job_id: str | None = Query(None),\n run_status: str | None = Query(None),\n trigger_type: str | None = Query(None),\n created_by: str | None = Query(None),\n date_from: str | None = Query(None),\n date_to: str | None = Query(None),\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.history\", \"VIEW\")),\n db: Session = Depends(get_db),\n):\n \"\"\"List all runs with cross-job filtering and pagination.\"\"\"\n logger.reason(f\"list_runs — User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n from ....models.translate import TranslationRun\n query = db.query(TranslationRun)\n\n if job_id:\n query = query.filter(TranslationRun.job_id == job_id)\n if run_status:\n query = query.filter(TranslationRun.status == run_status)\n if trigger_type:\n query = query.filter(TranslationRun.trigger_type == trigger_type)\n if created_by:\n query = query.filter(TranslationRun.created_by == created_by)\n if date_from:\n try:\n from datetime import datetime\n dt_from = datetime.fromisoformat(date_from)\n query = query.filter(TranslationRun.created_at >= dt_from)\n except ValueError:\n logger.debug(\"Could not parse date_from: %s\", date_from)\n if date_to:\n try:\n from datetime import datetime\n dt_to = datetime.fromisoformat(date_to)\n query = query.filter(TranslationRun.created_at <= dt_to)\n except ValueError:\n logger.debug(\"Could not parse date_to: %s\", date_to)\n\n total = query.count()\n runs = (\n query.order_by(TranslationRun.created_at.desc())\n .offset((page - 1) * page_size)\n .limit(page_size)\n .all()\n )\n\n items = []\n for r in runs:\n # Gather per-language statistics from the run's language_stats relationship\n lang_stats = r.language_stats or []\n target_languages = [ls.language_code for ls in lang_stats]\n total_translated = sum((ls.translated_rows or 0) for ls in lang_stats)\n language_stats = {\n ls.language_code: {\n \"total_rows\": ls.total_rows or 0,\n \"translated_rows\": ls.translated_rows or 0,\n \"failed_rows\": ls.failed_rows or 0,\n \"skipped_rows\": ls.skipped_rows or 0,\n \"token_count\": ls.token_count or 0,\n \"estimated_cost\": ls.estimated_cost or 0.0,\n }\n for ls in lang_stats\n }\n\n items.append({\n \"id\": r.id,\n \"job_id\": r.job_id,\n \"status\": r.status,\n \"trigger_type\": r.trigger_type,\n \"started_at\": r.started_at.isoformat() if r.started_at else None,\n \"completed_at\": r.completed_at.isoformat() if r.completed_at else None,\n \"error_message\": r.error_message,\n \"total_records\": r.total_records or 0,\n \"successful_records\": r.successful_records or 0,\n \"failed_records\": r.failed_records or 0,\n \"skipped_records\": r.skipped_records or 0,\n \"insert_status\": r.insert_status,\n \"superset_execution_id\": r.superset_execution_id,\n \"config_hash\": r.config_hash,\n \"dict_snapshot_hash\": r.dict_snapshot_hash,\n \"created_by\": r.created_by,\n \"created_at\": r.created_at.isoformat() if r.created_at else None,\n \"target_languages\": target_languages,\n \"total_translated\": total_translated,\n \"language_stats\": language_stats,\n })\n\n return {\"items\": items, \"total\": total, \"page\": page, \"page_size\": page_size}\n except Exception as e:\n logger.explore(\"list_runs failed\", extra={\"src\": \"translate_routes\", \"error\": str(e)})\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_runs\n\n\n# ============================================================\n# Run Detail\n# ============================================================\n\n# #region get_run_detail [C:4] [TYPE Function]\n# @BRIEF Get detailed run info with config_snapshot, records, events.\n# @PRE: User has translate.history.view permission.\n# @POST: Returns run detail with records and events.\n@router.get(\"/runs/{run_id}/detail\")\nasync def get_run_detail(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.history\", \"VIEW\")),\n db: Session = Depends(get_db),\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n \"\"\"Get detailed run info with config_snapshot, records, events.\"\"\"\n logger.reason(f\"get_run_detail — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n orch = TranslationOrchestrator(db, config_manager, current_user.username)\n status_info = orch.get_run_status(run_id)\n records = orch.get_run_records(run_id, page=1, page_size=50)\n events = TranslationEventLog(db).query_events(run_id=run_id)\n event_summary = TranslationEventLog(db).get_run_event_summary(run_id)\n\n # Get config snapshot from run\n from ....models.translate import TranslationRun\n run = db.query(TranslationRun).filter(TranslationRun.id == run_id).first()\n config_snapshot = run.config_snapshot if run else None\n\n return {\n **status_info,\n \"config_snapshot\": config_snapshot,\n \"config_hash\": run.config_hash if run else None,\n \"records\": records,\n \"events\": events,\n \"event_invariants\": event_summary,\n }\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_run_detail\n\n\n# ============================================================\n# Download Skipped CSV\n# ============================================================\n\n# #region download_skipped_csv [C:4] [TYPE Function]\n# @BRIEF Download a CSV of skipped translation records from a run.\n# @PRE User has translate.job.view permission.\n# @POST Returns CSV file of skipped records.\n# @COMPLEXITY 4\n\n@router.get(\"/runs/{run_id}/skipped.csv\")\nasync def download_skipped_csv(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.job\", \"VIEW\")),\n db: Session = Depends(get_db),\n):\n \"\"\"Download skipped translation records as CSV.\"\"\"\n logger.reason(f\"download_skipped_csv — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n import csv\n import io\n\n from fastapi.responses import StreamingResponse\n\n from ....models.translate import TranslationRecord\n\n records = (\n db.query(TranslationRecord)\n .filter(\n TranslationRecord.run_id == run_id,\n TranslationRecord.status == \"SKIPPED\",\n )\n .all()\n )\n\n output = io.StringIO()\n writer = csv.writer(output)\n writer.writerow([\"id\", \"source_sql\", \"target_sql\", \"source_object_type\",\n \"source_object_id\", \"source_object_name\", \"error_message\"])\n for rec in records:\n writer.writerow([\n rec.id, rec.source_sql, rec.target_sql, rec.source_object_type,\n rec.source_object_id, rec.source_object_name, rec.error_message,\n ])\n\n output.seek(0)\n return StreamingResponse(\n iter([output.getvalue()]),\n media_type=\"text/csv\",\n headers={\"Content-Disposition\": f\"attachment; filename=skipped_{run_id}.csv\"},\n )\n except Exception as e:\n logger.explore(\"download_skipped_csv failed\", extra={\"src\": \"translate_routes\", \"error\": str(e)})\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion download_skipped_csv\n\n# #endregion TranslateRunListRoutesModule\n" }, - { - "contract_id": "list_runs", - "contract_type": "Function", - "file_path": "backend/src/api/routes/translate/_run_list_routes.py", - "start_line": 22, - "end_line": 122, - "tier": "TIER_2", - "complexity": 4, - "metadata": { - "COMPLEXITY": 4, - "POST": "Returns paginated list of runs.", - "PRE": "User has translate.history.view permission.", - "PURPOSE": "List all runs with cross-job filtering and pagination." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region list_runs [C:4] [TYPE Function]\n# @BRIEF List all runs with cross-job filtering and pagination.\n# @PRE: User has translate.history.view permission.\n# @POST: Returns paginated list of runs.\n@router.get(\"/runs\")\nasync def list_runs(\n job_id: str | None = Query(None),\n run_status: str | None = Query(None),\n trigger_type: str | None = Query(None),\n created_by: str | None = Query(None),\n date_from: str | None = Query(None),\n date_to: str | None = Query(None),\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.history\", \"VIEW\")),\n db: Session = Depends(get_db),\n):\n \"\"\"List all runs with cross-job filtering and pagination.\"\"\"\n logger.reason(f\"list_runs — User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n from ....models.translate import TranslationRun\n query = db.query(TranslationRun)\n\n if job_id:\n query = query.filter(TranslationRun.job_id == job_id)\n if run_status:\n query = query.filter(TranslationRun.status == run_status)\n if trigger_type:\n query = query.filter(TranslationRun.trigger_type == trigger_type)\n if created_by:\n query = query.filter(TranslationRun.created_by == created_by)\n if date_from:\n try:\n from datetime import datetime\n dt_from = datetime.fromisoformat(date_from)\n query = query.filter(TranslationRun.created_at >= dt_from)\n except ValueError:\n logger.debug(\"Could not parse date_from: %s\", date_from)\n if date_to:\n try:\n from datetime import datetime\n dt_to = datetime.fromisoformat(date_to)\n query = query.filter(TranslationRun.created_at <= dt_to)\n except ValueError:\n logger.debug(\"Could not parse date_to: %s\", date_to)\n\n total = query.count()\n runs = (\n query.order_by(TranslationRun.created_at.desc())\n .offset((page - 1) * page_size)\n .limit(page_size)\n .all()\n )\n\n items = []\n for r in runs:\n # Gather per-language statistics from the run's language_stats relationship\n lang_stats = r.language_stats or []\n target_languages = [ls.language_code for ls in lang_stats]\n total_translated = sum((ls.translated_rows or 0) for ls in lang_stats)\n language_stats = {\n ls.language_code: {\n \"total_rows\": ls.total_rows or 0,\n \"translated_rows\": ls.translated_rows or 0,\n \"failed_rows\": ls.failed_rows or 0,\n \"skipped_rows\": ls.skipped_rows or 0,\n \"token_count\": ls.token_count or 0,\n \"estimated_cost\": ls.estimated_cost or 0.0,\n }\n for ls in lang_stats\n }\n\n items.append({\n \"id\": r.id,\n \"job_id\": r.job_id,\n \"status\": r.status,\n \"trigger_type\": r.trigger_type,\n \"started_at\": r.started_at.isoformat() if r.started_at else None,\n \"completed_at\": r.completed_at.isoformat() if r.completed_at else None,\n \"error_message\": r.error_message,\n \"total_records\": r.total_records or 0,\n \"successful_records\": r.successful_records or 0,\n \"failed_records\": r.failed_records or 0,\n \"skipped_records\": r.skipped_records or 0,\n \"insert_status\": r.insert_status,\n \"superset_execution_id\": r.superset_execution_id,\n \"config_hash\": r.config_hash,\n \"dict_snapshot_hash\": r.dict_snapshot_hash,\n \"created_by\": r.created_by,\n \"created_at\": r.created_at.isoformat() if r.created_at else None,\n \"target_languages\": target_languages,\n \"total_translated\": total_translated,\n \"language_stats\": language_stats,\n })\n\n return {\"items\": items, \"total\": total, \"page\": page, \"page_size\": page_size}\n except Exception as e:\n logger.explore(\"list_runs failed\", extra={\"src\": \"translate_routes\", \"error\": str(e)})\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_runs\n" - }, - { - "contract_id": "get_run_detail", - "contract_type": "Function", - "file_path": "backend/src/api/routes/translate/_run_list_routes.py", - "start_line": 129, - "end_line": 165, - "tier": "TIER_2", - "complexity": 4, - "metadata": { - "COMPLEXITY": 4, - "POST": "Returns run detail with records and events.", - "PRE": "User has translate.history.view permission.", - "PURPOSE": "Get detailed run info with config_snapshot, records, events." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region get_run_detail [C:4] [TYPE Function]\n# @BRIEF Get detailed run info with config_snapshot, records, events.\n# @PRE: User has translate.history.view permission.\n# @POST: Returns run detail with records and events.\n@router.get(\"/runs/{run_id}/detail\")\nasync def get_run_detail(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.history\", \"VIEW\")),\n db: Session = Depends(get_db),\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n \"\"\"Get detailed run info with config_snapshot, records, events.\"\"\"\n logger.reason(f\"get_run_detail — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n orch = TranslationOrchestrator(db, config_manager, current_user.username)\n status_info = orch.get_run_status(run_id)\n records = orch.get_run_records(run_id, page=1, page_size=50)\n events = TranslationEventLog(db).query_events(run_id=run_id)\n event_summary = TranslationEventLog(db).get_run_event_summary(run_id)\n\n # Get config snapshot from run\n from ....models.translate import TranslationRun\n run = db.query(TranslationRun).filter(TranslationRun.id == run_id).first()\n config_snapshot = run.config_snapshot if run else None\n\n return {\n **status_info,\n \"config_snapshot\": config_snapshot,\n \"config_hash\": run.config_hash if run else None,\n \"records\": records,\n \"events\": events,\n \"event_invariants\": event_summary,\n }\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_run_detail\n" - }, { "contract_id": "download_skipped_csv", "contract_type": "Function", @@ -16251,12 +16762,821 @@ "tier_source": "AutoCalculated", "body": "# #region get_next_executions [C:4] [TYPE Function]\n# @BRIEF Preview next N executions for a job's schedule.\n# @PRE User has translate.schedule.view permission.\n# @POST Returns next execution times.\n# @COMPLEXITY 4\n\n@router.get(\"/jobs/{job_id}/schedule/next-executions\")\nasync def get_next_executions(\n job_id: str,\n n: int = Query(3, ge=1, le=10),\n current_user: User = Depends(get_current_user),\n _ = Depends(has_permission(\"translate.schedule\", \"VIEW\")),\n db: Session = Depends(get_db),\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n \"\"\"Preview next N executions for a job's schedule.\"\"\"\n logger.reason(f\"get_next_executions — Job: {job_id}, User: {current_user.username}\", extra={\"src\": \"translate_routes\"})\n try:\n scheduler = TranslationScheduler(db, config_manager, current_user.username)\n schedule = scheduler.get_schedule(job_id)\n next_times = TranslationScheduler.get_next_executions(\n schedule.cron_expression, schedule.timezone, n=n\n )\n return {\n \"job_id\": job_id,\n \"cron_expression\": schedule.cron_expression,\n \"timezone\": schedule.timezone,\n \"next_executions\": next_times,\n }\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_next_executions\n" }, + { + "contract_id": "ValidationRoutes", + "contract_type": "Module", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 1, + "end_line": 270, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "API", + "PURPOSE": "API routes for validation task management and run history." + }, + "relations": [ + { + "source_id": "ValidationRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "ValidationTaskService", + "target_ref": "[ValidationTaskService]" + }, + { + "source_id": "ValidationRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "ValidationRunService", + "target_ref": "[ValidationRunService]" + }, + { + "source_id": "ValidationRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "TaskManager", + "target_ref": "[TaskManager]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationRoutes [C:3] [TYPE Module] [SEMANTICS fastapi, validation, api, task, run]\n# @BRIEF API routes for validation task management and run history.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [ValidationTaskService]\n# @RELATION DEPENDS_ON -> [ValidationRunService]\n# @RELATION DEPENDS_ON -> [TaskManager]\n\nfrom datetime import date\n\nfrom fastapi import APIRouter, Depends, HTTPException, Query, status\nfrom sqlalchemy.orm import Session\n\nfrom ...core.config_manager import ConfigManager\nfrom ...core.database import get_db\nfrom ...core.logger import logger\nfrom ...core.task_manager import TaskManager\nfrom ...dependencies import get_config_manager, get_current_user, get_task_manager, has_permission\nfrom ...schemas.auth import User\nfrom ...schemas.validation import (\n TriggerRunResponse,\n ValidationRunDetailResponse,\n ValidationRunListResponse,\n ValidationTaskCreate,\n ValidationTaskListResponse,\n ValidationTaskResponse,\n ValidationTaskUpdate,\n)\nfrom ...services.validation_run_service import ValidationRunService\nfrom ...services.validation_service import ValidationTaskService\n\n# #region router [C:1] [TYPE Global]\nrouter = APIRouter(tags=[\"Validation\"])\n# #endregion router\n\n\n# #region _get_task_service [C:1] [TYPE Function]\ndef _get_task_service(\n db: Session = Depends(get_db),\n config_manager: ConfigManager = Depends(get_config_manager),\n current_user: User = Depends(get_current_user),\n) -> ValidationTaskService:\n return ValidationTaskService(db=db, config_manager=config_manager, username=current_user.username)\n# #endregion _get_task_service\n\n\n# #region _get_run_service [C:1] [TYPE Function]\ndef _get_run_service(\n db: Session = Depends(get_db),\n) -> ValidationRunService:\n return ValidationRunService(db=db)\n# #endregion _get_run_service\n\n\n# ============================================================\n# Tasks CRUD\n# ============================================================\n\n\n# #region list_tasks [C:4] [TYPE Function]\n# @RATIONALE Route handler delegates to service with permission check — keeps API layer thin and testable; auth gate happens before any business logic.\n# @REJECTED Business logic in route handler rejected — would duplicate validation logic and make permission checks harder to audit.\n@router.get(\"/tasks\", response_model=ValidationTaskListResponse)\nasync def list_tasks(\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n is_active: bool | None = Query(None),\n environment_id: str | None = Query(None),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"VIEW\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"List all validation tasks with pagination and optional filters.\"\"\"\n logger.reason(f\"list_tasks — User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n total, items = service.list_tasks(is_active=is_active, environment_id=environment_id, page=page, page_size=page_size)\n return ValidationTaskListResponse(items=items, total=total, page=page, page_size=page_size)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_tasks\n\n\n# #region create_task [C:4] [TYPE Function]\n# @RATIONALE Returns 201 with created resource — follows REST conventions for POST resource creation; signals to clients that a new entity was created.\n# @REJECTED Returning 200 with wrapped response rejected — non-standard for POST create; 201 Created signals the correct semantics to HTTP clients and code generators.\n@router.post(\"/tasks\", response_model=ValidationTaskResponse, status_code=status.HTTP_201_CREATED)\nasync def create_task(\n payload: ValidationTaskCreate,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"CREATE\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"Create a new validation task with provider and environment validation.\"\"\"\n logger.reason(f\"create_task — User: {current_user.username}, name: {payload.name}\", extra={\"src\": \"validation_routes\"})\n try:\n return service.create_task(payload)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e))\n# #endregion create_task\n\n\n# #region get_task [C:4] [TYPE Function]\n# @RATIONALE Joins task detail with recent runs in a single endpoint — reduces frontend API calls from 2 to 1, improving page load performance.\n# @REJECTED Separate /tasks/{id}/runs endpoint for recent runs rejected — would require frontend to make 2 sequential API calls, doubling load time on the config page.\n@router.get(\"/tasks/{task_id}\", response_model=dict)\nasync def get_task(\n task_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"VIEW\")),\n task_service: ValidationTaskService = Depends(_get_task_service),\n run_service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"Get a validation task with its recent runs.\"\"\"\n logger.reason(f\"get_task — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n task = task_service.get_task(task_id)\n from ...schemas.validation import ValidationRunResponse\n # Find recent runs via run_service using dashboard matching\n recent = run_service.list_runs(\n dashboard_id=task.dashboard_ids[0] if task.dashboard_ids else None,\n environment_id=task.environment_id,\n page=1,\n page_size=10,\n )\n return {\n \"task\": task.model_dump(),\n \"recent_runs\": [r.model_dump() for r in recent[1]],\n }\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_task\n\n\n# #region update_task [C:4] [TYPE Function]\n# @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.\n# @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.\n@router.put(\"/tasks/{task_id}\", response_model=ValidationTaskResponse)\nasync def update_task(\n task_id: str,\n payload: ValidationTaskUpdate,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"EDIT\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"Update a validation task.\"\"\"\n logger.reason(f\"update_task — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n return service.update_task(task_id, payload)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion update_task\n\n\n# #region delete_task [C:4] [TYPE Function]\n# @RATIONALE DELETE returns 204 No Content per REST convention — minimizes response payload for delete operations; supports optional delete_runs query param for cascade control.\n# @REJECTED Returning deleted resource in response body rejected — unnecessary data transfer; 204 with no body is the REST standard for delete operations.\n@router.delete(\"/tasks/{task_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_task(\n task_id: str,\n delete_runs: bool = Query(False, description=\"Also delete associated validation runs\"),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"DELETE\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"Delete a validation task.\"\"\"\n logger.reason(f\"delete_task — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n service.delete_task(task_id, delete_runs=delete_runs)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion delete_task\n\n\n# ============================================================\n# Run — trigger immediate validation\n# ============================================================\n\n\n# #region trigger_run [C:4] [TYPE Function]\n# @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.\n# @REJECTED Blocking until run completes rejected — LLM-based validation is slow (30-120s); synchronous wait would timeout HTTP requests and create terrible UX.\n@router.post(\"/tasks/{task_id}/run\", response_model=TriggerRunResponse)\nasync def trigger_run(\n task_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"EXECUTE\")),\n service: ValidationTaskService = Depends(_get_task_service),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n \"\"\"Trigger immediate validation for a task.\"\"\"\n logger.reason(f\"trigger_run — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n spawned_task_id = await service.trigger_run(task_id, task_manager)\n return TriggerRunResponse(task_id=task_id, spawned_task_id=spawned_task_id, status=\"PENDING\", message=\"Validation task spawned\")\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e))\n# #endregion trigger_run\n\n\n# ============================================================\n# Runs — history listing and detail\n# ============================================================\n\n\n# #region list_runs [C:4] [TYPE Function]\n# @RATIONALE Exposes 6 query parameters for cross-task run filtering — matches the run service's filter capabilities exactly, enabling flexible history exploration.\n# @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.\n@router.get(\"/runs\", response_model=ValidationRunListResponse)\nasync def list_runs(\n task_id: str | None = Query(None, description=\"Filter by spawned task ID\"),\n dashboard_id: str | None = Query(None, description=\"Filter by dashboard ID\"),\n environment_id: str | None = Query(None, description=\"Filter by environment ID\"),\n status: str | None = Query(None, description=\"Filter by status: PASS, WARN, FAIL, UNKNOWN\"),\n date_from: date | None = Query(None, description=\"Start date (ISO format)\"),\n date_to: date | None = Query(None, description=\"End date (ISO format)\"),\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"VIEW\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"List validation runs with cross-task filtering and pagination.\"\"\"\n logger.reason(f\"list_runs — User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n total, items = service.list_runs(\n task_id=task_id, dashboard_id=dashboard_id, environment_id=environment_id,\n status=status, date_from=date_from, date_to=date_to, page=page, page_size=page_size,\n )\n return ValidationRunListResponse(items=items, total=total, page=page, page_size=page_size)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_runs\n\n\n# #region get_run_detail [C:4] [TYPE Function]\n# @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.\n# @REJECTED Paginated issues endpoint rejected — issues per run are typically < 20 items; pagination overhead is unnecessary for such small collections.\n@router.get(\"/runs/{run_id}\", response_model=ValidationRunDetailResponse)\nasync def get_run_detail(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"VIEW\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"Get detailed validation run info including issues and raw response.\"\"\"\n logger.reason(f\"get_run_detail — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n return service.get_run_detail(run_id)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_run_detail\n\n\n# #region delete_run [C:3] [TYPE Function]\n# @RATIONALE Returns 404 when run not found — explicit error handling rather than silent success; helps frontend distinguish between successful delete and missing resource.\n# @REJECTED Silent success on missing run rejected — would mask bugs in the UI that reference already-deleted runs; explicit 404 helps debugging.\n@router.delete(\"/runs/{run_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_run(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"DELETE\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"Delete a validation run record.\"\"\"\n logger.reason(f\"delete_run — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n if not service.delete_run(run_id):\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=\"Run not found\")\n# #endregion delete_run\n\n\n# #endregion ValidationRoutes\n" + }, + { + "contract_id": "_get_task_service", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 36, + "end_line": 43, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _get_task_service [C:1] [TYPE Function]\ndef _get_task_service(\n db: Session = Depends(get_db),\n config_manager: ConfigManager = Depends(get_config_manager),\n current_user: User = Depends(get_current_user),\n) -> ValidationTaskService:\n return ValidationTaskService(db=db, config_manager=config_manager, username=current_user.username)\n# #endregion _get_task_service\n" + }, + { + "contract_id": "_get_run_service", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 46, + "end_line": 51, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _get_run_service [C:1] [TYPE Function]\ndef _get_run_service(\n db: Session = Depends(get_db),\n) -> ValidationRunService:\n return ValidationRunService(db=db)\n# #endregion _get_run_service\n" + }, + { + "contract_id": "list_tasks", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 59, + "end_line": 79, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region list_tasks [C:4] [TYPE Function]\n# @RATIONALE Route handler delegates to service with permission check — keeps API layer thin and testable; auth gate happens before any business logic.\n# @REJECTED Business logic in route handler rejected — would duplicate validation logic and make permission checks harder to audit.\n@router.get(\"/tasks\", response_model=ValidationTaskListResponse)\nasync def list_tasks(\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n is_active: bool | None = Query(None),\n environment_id: str | None = Query(None),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"VIEW\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"List all validation tasks with pagination and optional filters.\"\"\"\n logger.reason(f\"list_tasks — User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n total, items = service.list_tasks(is_active=is_active, environment_id=environment_id, page=page, page_size=page_size)\n return ValidationTaskListResponse(items=items, total=total, page=page, page_size=page_size)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_tasks\n" + }, + { + "contract_id": "update_task", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 133, + "end_line": 150, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region update_task [C:4] [TYPE Function]\n# @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.\n# @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.\n@router.put(\"/tasks/{task_id}\", response_model=ValidationTaskResponse)\nasync def update_task(\n task_id: str,\n payload: ValidationTaskUpdate,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"EDIT\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"Update a validation task.\"\"\"\n logger.reason(f\"update_task — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n return service.update_task(task_id, payload)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion update_task\n" + }, + { + "contract_id": "delete_task", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 153, + "end_line": 170, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region delete_task [C:4] [TYPE Function]\n# @RATIONALE DELETE returns 204 No Content per REST convention — minimizes response payload for delete operations; supports optional delete_runs query param for cascade control.\n# @REJECTED Returning deleted resource in response body rejected — unnecessary data transfer; 204 with no body is the REST standard for delete operations.\n@router.delete(\"/tasks/{task_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_task(\n task_id: str,\n delete_runs: bool = Query(False, description=\"Also delete associated validation runs\"),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"DELETE\")),\n service: ValidationTaskService = Depends(_get_task_service),\n):\n \"\"\"Delete a validation task.\"\"\"\n logger.reason(f\"delete_task — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n service.delete_task(task_id, delete_runs=delete_runs)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion delete_task\n" + }, + { + "contract_id": "trigger_run", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 178, + "end_line": 196, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region trigger_run [C:4] [TYPE Function]\n# @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.\n# @REJECTED Blocking until run completes rejected — LLM-based validation is slow (30-120s); synchronous wait would timeout HTTP requests and create terrible UX.\n@router.post(\"/tasks/{task_id}/run\", response_model=TriggerRunResponse)\nasync def trigger_run(\n task_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.task\", \"EXECUTE\")),\n service: ValidationTaskService = Depends(_get_task_service),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n \"\"\"Trigger immediate validation for a task.\"\"\"\n logger.reason(f\"trigger_run — Task: {task_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n spawned_task_id = await service.trigger_run(task_id, task_manager)\n return TriggerRunResponse(task_id=task_id, spawned_task_id=spawned_task_id, status=\"PENDING\", message=\"Validation task spawned\")\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e))\n# #endregion trigger_run\n" + }, + { + "contract_id": "list_runs", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 204, + "end_line": 231, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region list_runs [C:4] [TYPE Function]\n# @RATIONALE Exposes 6 query parameters for cross-task run filtering — matches the run service's filter capabilities exactly, enabling flexible history exploration.\n# @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.\n@router.get(\"/runs\", response_model=ValidationRunListResponse)\nasync def list_runs(\n task_id: str | None = Query(None, description=\"Filter by spawned task ID\"),\n dashboard_id: str | None = Query(None, description=\"Filter by dashboard ID\"),\n environment_id: str | None = Query(None, description=\"Filter by environment ID\"),\n status: str | None = Query(None, description=\"Filter by status: PASS, WARN, FAIL, UNKNOWN\"),\n date_from: date | None = Query(None, description=\"Start date (ISO format)\"),\n date_to: date | None = Query(None, description=\"End date (ISO format)\"),\n page: int = Query(1, ge=1),\n page_size: int = Query(20, ge=1, le=100),\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"VIEW\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"List validation runs with cross-task filtering and pagination.\"\"\"\n logger.reason(f\"list_runs — User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n total, items = service.list_runs(\n task_id=task_id, dashboard_id=dashboard_id, environment_id=environment_id,\n status=status, date_from=date_from, date_to=date_to, page=page, page_size=page_size,\n )\n return ValidationRunListResponse(items=items, total=total, page=page, page_size=page_size)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))\n# #endregion list_runs\n" + }, + { + "contract_id": "get_run_detail", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 234, + "end_line": 250, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region get_run_detail [C:4] [TYPE Function]\n# @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.\n# @REJECTED Paginated issues endpoint rejected — issues per run are typically < 20 items; pagination overhead is unnecessary for such small collections.\n@router.get(\"/runs/{run_id}\", response_model=ValidationRunDetailResponse)\nasync def get_run_detail(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"VIEW\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"Get detailed validation run info including issues and raw response.\"\"\"\n logger.reason(f\"get_run_detail — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n try:\n return service.get_run_detail(run_id)\n except ValueError as e:\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))\n# #endregion get_run_detail\n" + }, + { + "contract_id": "delete_run", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation.py", + "start_line": 253, + "end_line": 267, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region delete_run [C:3] [TYPE Function]\n# @RATIONALE Returns 404 when run not found — explicit error handling rather than silent success; helps frontend distinguish between successful delete and missing resource.\n# @REJECTED Silent success on missing run rejected — would mask bugs in the UI that reference already-deleted runs; explicit 404 helps debugging.\n@router.delete(\"/runs/{run_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_run(\n run_id: str,\n current_user: User = Depends(get_current_user),\n _=Depends(has_permission(\"validation.run\", \"DELETE\")),\n service: ValidationRunService = Depends(_get_run_service),\n):\n \"\"\"Delete a validation run record.\"\"\"\n logger.reason(f\"delete_run — Run: {run_id}, User: {current_user.username}\", extra={\"src\": \"validation_routes\"})\n if not service.delete_run(run_id):\n raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=\"Run not found\")\n# #endregion delete_run\n" + }, + { + "contract_id": "ValidationApiTests", + "contract_type": "Module", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 1, + "end_line": 550, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "INVARIANT": "provider_id must reference a multimodal LLM provider for creation", + "LAYER": "API", + "PURPOSE": "Unit tests for validation task CRUD and run history API endpoints.", + "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" + }, + "relations": [ + { + "source_id": "ValidationApiTests", + "relation_type": "BINDS_TO", + "target_id": "ValidationRoutes", + "target_ref": "[ValidationRoutes]" + }, + { + "source_id": "ValidationApiTests", + "relation_type": "DEPENDS_ON", + "target_id": "EXT:FastAPI:TestClient", + "target_ref": "[EXT:FastAPI:TestClient]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "TEST_CONTRACT", + "message": "@TEST_CONTRACT is not allowed for contract type 'Module'", + "detail": { + "actual_type": "Module", + "allowed_types": [ + "Function", + "Block" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "TEST_CONTRACT", + "message": "@TEST_CONTRACT is forbidden for contract type 'Module' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Module" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "TEST_EDGE", + "message": "@TEST_EDGE is not allowed for contract type 'Module'", + "detail": { + "actual_type": "Module", + "allowed_types": [ + "Function", + "Block" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "TEST_EDGE", + "message": "@TEST_EDGE is forbidden for contract type 'Module' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Module" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "TEST_SCENARIO", + "message": "@TEST_SCENARIO is not allowed for contract type 'Module'", + "detail": { + "actual_type": "Module", + "allowed_types": [ + "Function", + "Block" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "TEST_SCENARIO", + "message": "@TEST_SCENARIO is forbidden for contract type 'Module' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Module" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationApiTests [C:3] [TYPE Module] [SEMANTICS validation, api, tests, pagination, crud]\n# @BRIEF Unit tests for validation task CRUD and run history API endpoints.\n# @LAYER: API\n# @RELATION BINDS_TO -> [ValidationRoutes]\n# @RELATION DEPENDS_ON -> [EXT:FastAPI:TestClient]\n# @TEST_CONTRACT: [ValidationTaskCreate|Update|RunRequest] -> [ValidationTaskResponse|RunResponse|TriggerRunResponse]\n# @TEST_SCENARIO: list_tasks -> 200 with paginated tasks; filter by is_active/environment_id\n# @TEST_SCENARIO: create_task -> 201 with valid payload; 422 with invalid provider/environment\n# @TEST_SCENARIO: get_task -> 200 with task+recent_runs; 404 for nonexistent\n# @TEST_SCENARIO: update_task -> 200 with updated fields; 404 for nonexistent\n# @TEST_SCENARIO: delete_task -> 204 on success; 404 for nonexistent\n# @TEST_SCENARIO: trigger_run -> 200 with spawned_task_id; 422 for invalid task\n# @TEST_SCENARIO: list_runs -> 200 with 6 filters + pagination\n# @TEST_SCENARIO: get_run_detail -> 200 with issues/raw_response; 404 for nonexistent\n# @TEST_SCENARIO: delete_run -> 204 on success; 404 for nonexistent\n# @TEST_EDGE: missing_field -> 422 when required field omitted from create payload\n# @TEST_EDGE: invalid_type -> 422 when provider_id is not multimodal\n# @TEST_EDGE: external_fail -> 404/422 when task/run does not exist\n# @TEST_EDGE: delete_task_with_runs -> 204 with delete_runs=true flag\n# @INVARIANT: Every endpoint requires authentication via has_permission\n# @INVARIANT: All list endpoints support pagination (page/page_size) with defaults\n# @INVARIANT: provider_id must reference a multimodal LLM provider for creation\n\n# Set required env vars before ANY app imports — crash-early guard for AuthConfig()\nimport os\nos.environ.setdefault(\"SECRET_KEY\", \"test-secret-key-for-testing\")\nos.environ.setdefault(\"AUTH_DATABASE_URL\", \"sqlite:///:memory:test_auth\")\nos.environ.setdefault(\"DATABASE_URL\", \"sqlite:///:memory:test_main\")\nos.environ.setdefault(\"DEV_MODE\", \"true\")\n\nfrom datetime import datetime, timezone\n\nimport pytest\nfrom unittest.mock import AsyncMock, MagicMock\n\nfrom fastapi.testclient import TestClient\n\nfrom src.app import app\nfrom src.dependencies import (\n get_current_user,\n get_config_manager,\n get_task_manager,\n)\nfrom src.api.routes.validation import _get_task_service, _get_run_service\nfrom src.schemas.validation import (\n ValidationTaskListResponse,\n ValidationTaskResponse,\n ValidationRunListResponse,\n ValidationRunDetailResponse,\n TriggerRunResponse,\n)\nfrom src.models.auth import User\n\n# ── Shared mocks ───────────────────────────────────────────────────────\n\nmock_user = MagicMock(spec=User)\nmock_user.username = \"testuser\"\nmock_user.roles = []\nadmin_role = MagicMock()\nadmin_role.name = \"Admin\"\nadmin_role.permissions = []\nmock_user.roles.append(admin_role)\n\n\ndef _make_now():\n \"\"\"Return a timezone-aware UTC datetime for Pydantic v2.\"\"\"\n return datetime.now(timezone.utc)\n\n\n@pytest.fixture(autouse=True)\ndef mock_all_deps():\n \"\"\"Override service-level FastAPI dependencies with MagicMock stubs.\n\n Permission checking (has_permission) is NOT overridden — mock_user has\n Admin role which passes all permission gates implicitly.\n Fixture resets mock_user.roles before each test to prevent cross-test pollution.\n \"\"\"\n # Reset user state — Admin role passes all permission gates\n mock_user.roles = [admin_role]\n\n mock_task_service = MagicMock()\n mock_run_service = MagicMock()\n mock_task_manager = MagicMock()\n\n app.dependency_overrides[_get_task_service] = lambda: mock_task_service\n app.dependency_overrides[_get_run_service] = lambda: mock_run_service\n app.dependency_overrides[get_config_manager] = lambda: MagicMock()\n app.dependency_overrides[get_task_manager] = lambda: mock_task_manager\n app.dependency_overrides[get_current_user] = lambda: mock_user\n\n yield {\n \"task_service\": mock_task_service,\n \"run_service\": mock_run_service,\n \"task_manager\": mock_task_manager,\n }\n app.dependency_overrides.clear()\n\n\nclient = TestClient(app)\n\n\n# ── Fixtures ────────────────────────────────────────────────────────────\n\ndef _make_task_response(**overrides):\n \"\"\"Build a ValidationTaskResponse for mock returns.\"\"\"\n return ValidationTaskResponse(\n id=overrides.get(\"id\", \"task-1\"),\n name=overrides.get(\"name\", \"Test Task\"),\n environment_id=overrides.get(\"environment_id\", \"env-1\"),\n is_active=overrides.get(\"is_active\", True),\n dashboard_ids=overrides.get(\"dashboard_ids\", [\"dash-1\"]),\n provider_id=overrides.get(\"provider_id\", \"provider-1\"),\n schedule_days=None,\n window_start=None,\n window_end=None,\n notify_owners=True,\n custom_channels=None,\n alert_condition=\"FAIL_ONLY\",\n created_at=overrides.get(\"created_at\", _make_now()),\n updated_at=None,\n last_run_status=None,\n last_run_at=None,\n )\n\n\ndef _make_run_response(**overrides):\n \"\"\"Build a dict representation of a ValidationRunResponse.\"\"\"\n return {\n \"id\": overrides.get(\"id\", \"run-1\"),\n \"task_id\": overrides.get(\"task_id\", \"task-1\"),\n \"dashboard_id\": overrides.get(\"dashboard_id\", \"dash-1\"),\n \"environment_id\": overrides.get(\"environment_id\", \"env-1\"),\n \"status\": overrides.get(\"status\", \"PASS\"),\n \"summary\": overrides.get(\"summary\", \"\"),\n \"timestamp\": overrides.get(\"timestamp\", _make_now()),\n \"screenshot_path\": None,\n \"task_name\": overrides.get(\"task_name\", \"Test Task\"),\n }\n\n\n# ── Task CRUD Tests ────────────────────────────────────────────────────\n\n# #region test_list_tasks_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/tasks returns paginated task list with filters.\ndef test_list_tasks_success(mock_all_deps):\n task = _make_task_response()\n mock_all_deps[\"task_service\"].list_tasks.return_value = (1, [task])\n\n response = client.get(\"/api/validation/tasks\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"items\"][0][\"name\"] == \"Test Task\"\n assert data[\"total\"] == 1\n assert data[\"page\"] == 1\n assert data[\"page_size\"] == 20\n ValidationTaskListResponse(**data)\n\n # environment_id filter\n response = client.get(\"/api/validation/tasks?environment_id=env-1\")\n assert response.status_code == 200\n mock_all_deps[\"task_service\"].list_tasks.assert_called_with(\n is_active=None, environment_id=\"env-1\", page=1, page_size=20\n )\n# #endregion test_list_tasks_success\n\n\n# #region test_list_tasks_pagination [C:2] [TYPE Function]\n# @BRIEF Pagination query params are validated: page >= 1, page_size 1-100.\ndef test_list_tasks_pagination(mock_all_deps):\n response = client.get(\"/api/validation/tasks?page=0\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/tasks?page_size=101\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/tasks?page_size=0\")\n assert response.status_code == 422\n# #endregion test_list_tasks_pagination\n\n\n# #region test_list_tasks_service_error [C:2] [TYPE Function]\n# @BRIEF Service ValueError becomes 400 on list_tasks.\ndef test_list_tasks_service_error(mock_all_deps):\n mock_all_deps[\"task_service\"].list_tasks.side_effect = ValueError(\"Bad filter\")\n response = client.get(\"/api/validation/tasks?environment_id=nonexistent\")\n assert response.status_code == 400\n assert \"Bad filter\" in response.json()[\"detail\"]\n# #endregion test_list_tasks_service_error\n\n\n# #region test_create_task_success [C:2] [TYPE Function]\n# @BRIEF POST /validation/tasks with valid payload returns 201.\ndef test_create_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].create_task.return_value = _make_task_response()\n\n payload = {\n \"name\": \"My Validation Task\",\n \"environment_id\": \"env-1\",\n \"dashboard_ids\": [\"dash-1\"],\n \"provider_id\": \"provider-1\",\n \"notify_owners\": True,\n \"alert_condition\": \"FAIL_ONLY\",\n }\n response = client.post(\"/api/validation/tasks\", json=payload)\n assert response.status_code == 201\n data = response.json()\n assert data[\"name\"] == \"Test Task\"\n assert data[\"id\"] == \"task-1\"\n ValidationTaskResponse(**data)\n mock_all_deps[\"task_service\"].create_task.assert_called_once()\n# #endregion test_create_task_success\n\n\n# #region test_create_task_missing_fields [C:2] [TYPE Function]\n# @BRIEF POST with missing required fields returns 422.\ndef test_create_task_missing_fields(mock_all_deps):\n # Empty payload\n response = client.post(\"/api/validation/tasks\", json={})\n assert response.status_code == 422\n errors = response.json()\n assert \"detail\" in errors\n\n # Missing provider_id\n response = client.post(\"/api/validation/tasks\", json={\n \"name\": \"Test\", \"environment_id\": \"env-1\", \"dashboard_ids\": [\"dash-1\"],\n })\n assert response.status_code == 422\n\n # Missing dashboard_ids\n response = client.post(\"/api/validation/tasks\", json={\n \"name\": \"Test\", \"environment_id\": \"env-1\", \"provider_id\": \"provider-1\",\n })\n assert response.status_code == 422\n# #endregion test_create_task_missing_fields\n\n\n# #region test_create_task_invalid_provider [C:2] [TYPE Function]\n# @BRIEF POST with non-multimodal provider returns 422.\ndef test_create_task_invalid_provider(mock_all_deps):\n mock_all_deps[\"task_service\"].create_task.side_effect = ValueError(\n \"LLM provider 'GPT-3.5' is not multimodal\"\n )\n payload = {\n \"name\": \"Test\", \"environment_id\": \"env-1\",\n \"dashboard_ids\": [\"dash-1\"], \"provider_id\": \"provider-2\",\n }\n response = client.post(\"/api/validation/tasks\", json=payload)\n assert response.status_code == 422\n assert \"not multimodal\" in response.json()[\"detail\"]\n# #endregion test_create_task_invalid_provider\n\n\n# #region test_get_task_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/tasks/{id} returns task with recent_runs.\ndef test_get_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].get_task.return_value = _make_task_response()\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n\n response = client.get(\"/api/validation/tasks/task-1\")\n assert response.status_code == 200\n data = response.json()\n assert \"task\" in data\n assert \"recent_runs\" in data\n assert data[\"task\"][\"name\"] == \"Test Task\"\n mock_all_deps[\"task_service\"].get_task.assert_called_with(\"task-1\")\n# #endregion test_get_task_success\n\n\n# #region test_get_task_not_found [C:2] [TYPE Function]\n# @BRIEF GET for nonexistent task returns 404.\ndef test_get_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].get_task.side_effect = ValueError(\"not found\")\n response = client.get(\"/api/validation/tasks/nonexistent\")\n assert response.status_code == 404\n# #endregion test_get_task_not_found\n\n\n# #region test_update_task_success [C:2] [TYPE Function]\n# @BRIEF PUT /validation/tasks/{id} updates task and returns updated object.\ndef test_update_task_success(mock_all_deps):\n updated = _make_task_response(name=\"Updated Name\", is_active=False)\n mock_all_deps[\"task_service\"].update_task.return_value = updated\n\n payload = {\"name\": \"Updated Name\", \"is_active\": False}\n response = client.put(\"/api/validation/tasks/task-1\", json=payload)\n assert response.status_code == 200\n data = response.json()\n assert data[\"name\"] == \"Updated Name\"\n assert data[\"is_active\"] is False\n ValidationTaskResponse(**data)\n mock_all_deps[\"task_service\"].update_task.assert_called_once()\n# #endregion test_update_task_success\n\n\n# #region test_update_task_not_found [C:2] [TYPE Function]\n# @BRIEF PUT for nonexistent task returns 404.\ndef test_update_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].update_task.side_effect = ValueError(\"not found\")\n payload = {\"name\": \"Nope\"}\n response = client.put(\"/api/validation/tasks/nonexistent\", json=payload)\n assert response.status_code == 404\n# #endregion test_update_task_not_found\n\n\n# #region test_delete_task_success [C:2] [TYPE Function]\n# @BRIEF DELETE /validation/tasks/{id} returns 204.\ndef test_delete_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=False)\n# #endregion test_delete_task_success\n\n\n# #region test_delete_task_not_found [C:2] [TYPE Function]\n# @BRIEF DELETE for nonexistent task returns 404.\ndef test_delete_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.side_effect = ValueError(\"not found\")\n response = client.delete(\"/api/validation/tasks/nonexistent\")\n assert response.status_code == 404\n# #endregion test_delete_task_not_found\n\n\n# #region test_delete_task_with_runs_flag [C:2] [TYPE Function]\n# @BRIEF DELETE with delete_runs=true passes query param to service.\ndef test_delete_task_with_runs_flag(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1?delete_runs=true\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=True)\n# #endregion test_delete_task_with_runs_flag\n\n\n# #region test_trigger_run_success [C:2] [TYPE Function]\n# @BRIEF POST /validation/tasks/{id}/run spawns a validation task.\ndef test_trigger_run_success(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(return_value=\"spawned-1\")\n mock_all_deps[\"task_manager\"].create_task = AsyncMock()\n\n response = client.post(\"/api/validation/tasks/task-1/run\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"task_id\"] == \"task-1\"\n assert data[\"spawned_task_id\"] == \"spawned-1\"\n assert data[\"status\"] == \"PENDING\"\n TriggerRunResponse(**data)\n# #endregion test_trigger_run_success\n\n\n# #region test_trigger_run_not_found [C:2] [TYPE Function]\n# @BRIEF POST for nonexistent task returns 422.\ndef test_trigger_run_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(\n side_effect=ValueError(\"Validation task 'nonexistent' not found\")\n )\n response = client.post(\"/api/validation/tasks/nonexistent/run\")\n assert response.status_code == 422\n assert \"not found\" in response.json()[\"detail\"]\n# #endregion test_trigger_run_not_found\n\n\n# #region test_trigger_run_no_dashboards [C:2] [TYPE Function]\n# @BRIEF Trigger fails with 422 when task has no dashboard IDs.\ndef test_trigger_run_no_dashboards(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(\n side_effect=ValueError(\"has no dashboard IDs configured\")\n )\n response = client.post(\"/api/validation/tasks/task-1/run\")\n assert response.status_code == 422\n assert \"no dashboard IDs\" in response.json()[\"detail\"]\n# #endregion test_trigger_run_no_dashboards\n\n\n# ── Run History Tests ──────────────────────────────────────────────────\n\n# #region test_list_runs_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/runs returns paginated run list.\ndef test_list_runs_success(mock_all_deps):\n run = _make_run_response()\n mock_all_deps[\"run_service\"].list_runs.return_value = (1, [run])\n\n response = client.get(\"/api/validation/runs\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"items\"][0][\"id\"] == \"run-1\"\n assert data[\"total\"] == 1\n ValidationRunListResponse(**data)\n# #endregion test_list_runs_success\n\n\n# #region test_list_runs_filters [C:2] [TYPE Function]\n# @BRIEF All 6 filter query params are accepted and forwarded to service.\ndef test_list_runs_filters(mock_all_deps):\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n\n for query in [\n \"?task_id=task-1\",\n \"?dashboard_id=dash-1\",\n \"?environment_id=env-1\",\n \"?status=PASS\",\n \"?date_from=2026-01-01\",\n \"?date_to=2026-12-31\",\n \"?status=PASS&dashboard_id=dash-1&date_from=2026-01-01\",\n ]:\n response = client.get(f\"/api/validation/runs{query}\")\n assert response.status_code == 200, f\"Filter query failed: {query}\"\n# #endregion test_list_runs_filters\n\n\n# #region test_list_runs_pagination [C:2] [TYPE Function]\n# @BRIEF Pagination boundary checks on runs list.\ndef test_list_runs_pagination(mock_all_deps):\n response = client.get(\"/api/validation/runs?page=0\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/runs?page_size=101\")\n assert response.status_code == 422\n# #endregion test_list_runs_pagination\n\n\n# #region test_list_runs_invalid_status [C:2] [TYPE Function]\n# @BRIEF Status is a free string; any value passes through to service.\ndef test_list_runs_invalid_status(mock_all_deps):\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n response = client.get(\"/api/validation/runs?status=INVALID_STATUS_XYZ\")\n assert response.status_code == 200\n call_kwargs = mock_all_deps[\"run_service\"].list_runs.call_args[1]\n assert call_kwargs.get(\"status\") == \"INVALID_STATUS_XYZ\"\n# #endregion test_list_runs_invalid_status\n\n\n# #region test_get_run_detail_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/runs/{id} returns full detail with issues and raw_response.\ndef test_get_run_detail_success(mock_all_deps):\n mock_all_deps[\"run_service\"].get_run_detail.return_value = ValidationRunDetailResponse(\n id=\"run-1\",\n task_id=\"task-1\",\n dashboard_id=\"dash-1\",\n environment_id=\"env-1\",\n status=\"FAIL\",\n summary=\"Charts failed to render\",\n timestamp=_make_now(),\n screenshot_path=\"/tmp/screenshots/run-1.png\",\n issues=[{\"severity\": \"HIGH\", \"message\": \"Chart timeout\"}],\n raw_response='{\"status\": \"error\"}',\n task_name=\"Test Task\",\n )\n\n response = client.get(\"/api/validation/runs/run-1\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"status\"] == \"FAIL\"\n assert len(data[\"issues\"]) == 1\n assert data[\"raw_response\"] is not None\n ValidationRunDetailResponse(**data)\n# #endregion test_get_run_detail_success\n\n\n# #region test_get_run_detail_not_found [C:2] [TYPE Function]\n# @BRIEF GET for nonexistent run returns 404.\ndef test_get_run_detail_not_found(mock_all_deps):\n mock_all_deps[\"run_service\"].get_run_detail.side_effect = ValueError(\"not found\")\n response = client.get(\"/api/validation/runs/nonexistent\")\n assert response.status_code == 404\n# #endregion test_get_run_detail_not_found\n\n\n# #region test_delete_run_success [C:2] [TYPE Function]\n# @BRIEF DELETE /validation/runs/{id} returns 204.\ndef test_delete_run_success(mock_all_deps):\n mock_all_deps[\"run_service\"].delete_run.return_value = True\n response = client.delete(\"/api/validation/runs/run-1\")\n assert response.status_code == 204\n mock_all_deps[\"run_service\"].delete_run.assert_called_with(\"run-1\")\n# #endregion test_delete_run_success\n\n\n# #region test_delete_run_not_found [C:2] [TYPE Function]\n# @BRIEF DELETE for nonexistent run returns 404.\ndef test_delete_run_not_found(mock_all_deps):\n mock_all_deps[\"run_service\"].delete_run.return_value = False\n response = client.delete(\"/api/validation/runs/nonexistent\")\n assert response.status_code == 404\n# #endregion test_delete_run_not_found\n\n\n# ── Auth / Permission Tests ────────────────────────────────────────────\n\n# #region test_endpoints_require_authentication [C:2] [TYPE Function]\n# @BRIEF Without current_user dependency, all 9 endpoints return 401.\ndef test_endpoints_require_authentication(mock_all_deps):\n app.dependency_overrides.pop(get_current_user, None)\n endpoints = [\n (\"GET\", \"/api/validation/tasks\"),\n (\"POST\", \"/api/validation/tasks\"),\n (\"GET\", \"/api/validation/tasks/task-1\"),\n (\"PUT\", \"/api/validation/tasks/task-1\"),\n (\"DELETE\", \"/api/validation/tasks/task-1\"),\n (\"POST\", \"/api/validation/tasks/task-1/run\"),\n (\"GET\", \"/api/validation/runs\"),\n (\"GET\", \"/api/validation/runs/run-1\"),\n (\"DELETE\", \"/api/validation/runs/run-1\"),\n ]\n for method, path in endpoints:\n response = client.request(method, path)\n assert response.status_code == 401, f\"{method} {path} expected 401 got {response.status_code}\"\n# #endregion test_endpoints_require_authentication\n\n\n# #region test_permission_denied_non_admin [C:2] [TYPE Function]\n# @BRIEF A non-admin user without validation.* permissions receives 403.\ndef test_permission_denied_non_admin(mock_all_deps):\n \"\"\"Remove Admin role so has_permission raises 403.\"\"\"\n mock_user.roles = [] # No Admin, no permissions\n response = client.get(\"/api/validation/tasks\")\n assert response.status_code == 403\n# #endregion test_permission_denied_non_admin\n\n\n# #region test_permission_denied_all_actions [C:2] [TYPE Function]\n# @BRIEF Each action (VIEW, CREATE, EDIT, DELETE, EXECUTE) denied for non-admin.\ndef test_permission_denied_all_actions(mock_all_deps):\n mock_user.roles = []\n action_endpoints = [\n (\"GET\", \"/api/validation/tasks\"),\n (\"POST\", \"/api/validation/tasks\"),\n (\"GET\", \"/api/validation/tasks/task-1\"),\n (\"PUT\", \"/api/validation/tasks/task-1\"),\n (\"DELETE\", \"/api/validation/tasks/task-1\"),\n (\"POST\", \"/api/validation/tasks/task-1/run\"),\n (\"GET\", \"/api/validation/runs\"),\n (\"GET\", \"/api/validation/runs/run-1\"),\n (\"DELETE\", \"/api/validation/runs/run-1\"),\n ]\n for method, path in action_endpoints:\n response = client.request(method, path)\n assert response.status_code == 403, f\"{method} {path} expected 403 got {response.status_code}\"\n# #endregion test_permission_denied_all_actions\n\n\n# #region test_delete_task_runs_default_false [C:2] [TYPE Function]\n# @BRIEF delete_runs query param defaults to False.\ndef test_delete_task_runs_default_false(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=False)\n# #endregion test_delete_task_runs_default_false\n\n# #endregion ValidationApiTests\n" + }, + { + "contract_id": "test_list_tasks_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 143, + "end_line": 164, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET /validation/tasks returns paginated task list with filters." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_tasks_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/tasks returns paginated task list with filters.\ndef test_list_tasks_success(mock_all_deps):\n task = _make_task_response()\n mock_all_deps[\"task_service\"].list_tasks.return_value = (1, [task])\n\n response = client.get(\"/api/validation/tasks\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"items\"][0][\"name\"] == \"Test Task\"\n assert data[\"total\"] == 1\n assert data[\"page\"] == 1\n assert data[\"page_size\"] == 20\n ValidationTaskListResponse(**data)\n\n # environment_id filter\n response = client.get(\"/api/validation/tasks?environment_id=env-1\")\n assert response.status_code == 200\n mock_all_deps[\"task_service\"].list_tasks.assert_called_with(\n is_active=None, environment_id=\"env-1\", page=1, page_size=20\n )\n# #endregion test_list_tasks_success\n" + }, + { + "contract_id": "test_list_tasks_pagination", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 167, + "end_line": 178, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Pagination query params are validated: page >= 1, page_size 1-100." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_tasks_pagination [C:2] [TYPE Function]\n# @BRIEF Pagination query params are validated: page >= 1, page_size 1-100.\ndef test_list_tasks_pagination(mock_all_deps):\n response = client.get(\"/api/validation/tasks?page=0\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/tasks?page_size=101\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/tasks?page_size=0\")\n assert response.status_code == 422\n# #endregion test_list_tasks_pagination\n" + }, + { + "contract_id": "test_list_tasks_service_error", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 181, + "end_line": 188, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Service ValueError becomes 400 on list_tasks." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_tasks_service_error [C:2] [TYPE Function]\n# @BRIEF Service ValueError becomes 400 on list_tasks.\ndef test_list_tasks_service_error(mock_all_deps):\n mock_all_deps[\"task_service\"].list_tasks.side_effect = ValueError(\"Bad filter\")\n response = client.get(\"/api/validation/tasks?environment_id=nonexistent\")\n assert response.status_code == 400\n assert \"Bad filter\" in response.json()[\"detail\"]\n# #endregion test_list_tasks_service_error\n" + }, + { + "contract_id": "test_create_task_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 191, + "end_line": 211, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "POST /validation/tasks with valid payload returns 201." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_create_task_success [C:2] [TYPE Function]\n# @BRIEF POST /validation/tasks with valid payload returns 201.\ndef test_create_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].create_task.return_value = _make_task_response()\n\n payload = {\n \"name\": \"My Validation Task\",\n \"environment_id\": \"env-1\",\n \"dashboard_ids\": [\"dash-1\"],\n \"provider_id\": \"provider-1\",\n \"notify_owners\": True,\n \"alert_condition\": \"FAIL_ONLY\",\n }\n response = client.post(\"/api/validation/tasks\", json=payload)\n assert response.status_code == 201\n data = response.json()\n assert data[\"name\"] == \"Test Task\"\n assert data[\"id\"] == \"task-1\"\n ValidationTaskResponse(**data)\n mock_all_deps[\"task_service\"].create_task.assert_called_once()\n# #endregion test_create_task_success\n" + }, + { + "contract_id": "test_create_task_missing_fields", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 214, + "end_line": 234, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "POST with missing required fields returns 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_create_task_missing_fields [C:2] [TYPE Function]\n# @BRIEF POST with missing required fields returns 422.\ndef test_create_task_missing_fields(mock_all_deps):\n # Empty payload\n response = client.post(\"/api/validation/tasks\", json={})\n assert response.status_code == 422\n errors = response.json()\n assert \"detail\" in errors\n\n # Missing provider_id\n response = client.post(\"/api/validation/tasks\", json={\n \"name\": \"Test\", \"environment_id\": \"env-1\", \"dashboard_ids\": [\"dash-1\"],\n })\n assert response.status_code == 422\n\n # Missing dashboard_ids\n response = client.post(\"/api/validation/tasks\", json={\n \"name\": \"Test\", \"environment_id\": \"env-1\", \"provider_id\": \"provider-1\",\n })\n assert response.status_code == 422\n# #endregion test_create_task_missing_fields\n" + }, + { + "contract_id": "test_create_task_invalid_provider", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 237, + "end_line": 250, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "POST with non-multimodal provider returns 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_create_task_invalid_provider [C:2] [TYPE Function]\n# @BRIEF POST with non-multimodal provider returns 422.\ndef test_create_task_invalid_provider(mock_all_deps):\n mock_all_deps[\"task_service\"].create_task.side_effect = ValueError(\n \"LLM provider 'GPT-3.5' is not multimodal\"\n )\n payload = {\n \"name\": \"Test\", \"environment_id\": \"env-1\",\n \"dashboard_ids\": [\"dash-1\"], \"provider_id\": \"provider-2\",\n }\n response = client.post(\"/api/validation/tasks\", json=payload)\n assert response.status_code == 422\n assert \"not multimodal\" in response.json()[\"detail\"]\n# #endregion test_create_task_invalid_provider\n" + }, + { + "contract_id": "test_get_task_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 253, + "end_line": 266, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET /validation/tasks/{id} returns task with recent_runs." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_get_task_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/tasks/{id} returns task with recent_runs.\ndef test_get_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].get_task.return_value = _make_task_response()\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n\n response = client.get(\"/api/validation/tasks/task-1\")\n assert response.status_code == 200\n data = response.json()\n assert \"task\" in data\n assert \"recent_runs\" in data\n assert data[\"task\"][\"name\"] == \"Test Task\"\n mock_all_deps[\"task_service\"].get_task.assert_called_with(\"task-1\")\n# #endregion test_get_task_success\n" + }, + { + "contract_id": "test_get_task_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 269, + "end_line": 275, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET for nonexistent task returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_get_task_not_found [C:2] [TYPE Function]\n# @BRIEF GET for nonexistent task returns 404.\ndef test_get_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].get_task.side_effect = ValueError(\"not found\")\n response = client.get(\"/api/validation/tasks/nonexistent\")\n assert response.status_code == 404\n# #endregion test_get_task_not_found\n" + }, + { + "contract_id": "test_update_task_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 278, + "end_line": 292, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "PUT /validation/tasks/{id} updates task and returns updated object." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_update_task_success [C:2] [TYPE Function]\n# @BRIEF PUT /validation/tasks/{id} updates task and returns updated object.\ndef test_update_task_success(mock_all_deps):\n updated = _make_task_response(name=\"Updated Name\", is_active=False)\n mock_all_deps[\"task_service\"].update_task.return_value = updated\n\n payload = {\"name\": \"Updated Name\", \"is_active\": False}\n response = client.put(\"/api/validation/tasks/task-1\", json=payload)\n assert response.status_code == 200\n data = response.json()\n assert data[\"name\"] == \"Updated Name\"\n assert data[\"is_active\"] is False\n ValidationTaskResponse(**data)\n mock_all_deps[\"task_service\"].update_task.assert_called_once()\n# #endregion test_update_task_success\n" + }, + { + "contract_id": "test_update_task_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 295, + "end_line": 302, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "PUT for nonexistent task returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_update_task_not_found [C:2] [TYPE Function]\n# @BRIEF PUT for nonexistent task returns 404.\ndef test_update_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].update_task.side_effect = ValueError(\"not found\")\n payload = {\"name\": \"Nope\"}\n response = client.put(\"/api/validation/tasks/nonexistent\", json=payload)\n assert response.status_code == 404\n# #endregion test_update_task_not_found\n" + }, + { + "contract_id": "test_delete_task_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 305, + "end_line": 312, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "DELETE /validation/tasks/{id} returns 204." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_task_success [C:2] [TYPE Function]\n# @BRIEF DELETE /validation/tasks/{id} returns 204.\ndef test_delete_task_success(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=False)\n# #endregion test_delete_task_success\n" + }, + { + "contract_id": "test_delete_task_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 315, + "end_line": 321, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "DELETE for nonexistent task returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_task_not_found [C:2] [TYPE Function]\n# @BRIEF DELETE for nonexistent task returns 404.\ndef test_delete_task_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.side_effect = ValueError(\"not found\")\n response = client.delete(\"/api/validation/tasks/nonexistent\")\n assert response.status_code == 404\n# #endregion test_delete_task_not_found\n" + }, + { + "contract_id": "test_delete_task_with_runs_flag", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 324, + "end_line": 331, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "DELETE with delete_runs=true passes query param to service." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_task_with_runs_flag [C:2] [TYPE Function]\n# @BRIEF DELETE with delete_runs=true passes query param to service.\ndef test_delete_task_with_runs_flag(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1?delete_runs=true\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=True)\n# #endregion test_delete_task_with_runs_flag\n" + }, + { + "contract_id": "test_trigger_run_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 334, + "end_line": 347, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "POST /validation/tasks/{id}/run spawns a validation task." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_run_success [C:2] [TYPE Function]\n# @BRIEF POST /validation/tasks/{id}/run spawns a validation task.\ndef test_trigger_run_success(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(return_value=\"spawned-1\")\n mock_all_deps[\"task_manager\"].create_task = AsyncMock()\n\n response = client.post(\"/api/validation/tasks/task-1/run\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"task_id\"] == \"task-1\"\n assert data[\"spawned_task_id\"] == \"spawned-1\"\n assert data[\"status\"] == \"PENDING\"\n TriggerRunResponse(**data)\n# #endregion test_trigger_run_success\n" + }, + { + "contract_id": "test_trigger_run_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 350, + "end_line": 359, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "POST for nonexistent task returns 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_run_not_found [C:2] [TYPE Function]\n# @BRIEF POST for nonexistent task returns 422.\ndef test_trigger_run_not_found(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(\n side_effect=ValueError(\"Validation task 'nonexistent' not found\")\n )\n response = client.post(\"/api/validation/tasks/nonexistent/run\")\n assert response.status_code == 422\n assert \"not found\" in response.json()[\"detail\"]\n# #endregion test_trigger_run_not_found\n" + }, + { + "contract_id": "test_trigger_run_no_dashboards", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 362, + "end_line": 371, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Trigger fails with 422 when task has no dashboard IDs." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_run_no_dashboards [C:2] [TYPE Function]\n# @BRIEF Trigger fails with 422 when task has no dashboard IDs.\ndef test_trigger_run_no_dashboards(mock_all_deps):\n mock_all_deps[\"task_service\"].trigger_run = AsyncMock(\n side_effect=ValueError(\"has no dashboard IDs configured\")\n )\n response = client.post(\"/api/validation/tasks/task-1/run\")\n assert response.status_code == 422\n assert \"no dashboard IDs\" in response.json()[\"detail\"]\n# #endregion test_trigger_run_no_dashboards\n" + }, + { + "contract_id": "test_list_runs_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 376, + "end_line": 388, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET /validation/runs returns paginated run list." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_runs_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/runs returns paginated run list.\ndef test_list_runs_success(mock_all_deps):\n run = _make_run_response()\n mock_all_deps[\"run_service\"].list_runs.return_value = (1, [run])\n\n response = client.get(\"/api/validation/runs\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"items\"][0][\"id\"] == \"run-1\"\n assert data[\"total\"] == 1\n ValidationRunListResponse(**data)\n# #endregion test_list_runs_success\n" + }, + { + "contract_id": "test_list_runs_filters", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 391, + "end_line": 407, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "All 6 filter query params are accepted and forwarded to service." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_runs_filters [C:2] [TYPE Function]\n# @BRIEF All 6 filter query params are accepted and forwarded to service.\ndef test_list_runs_filters(mock_all_deps):\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n\n for query in [\n \"?task_id=task-1\",\n \"?dashboard_id=dash-1\",\n \"?environment_id=env-1\",\n \"?status=PASS\",\n \"?date_from=2026-01-01\",\n \"?date_to=2026-12-31\",\n \"?status=PASS&dashboard_id=dash-1&date_from=2026-01-01\",\n ]:\n response = client.get(f\"/api/validation/runs{query}\")\n assert response.status_code == 200, f\"Filter query failed: {query}\"\n# #endregion test_list_runs_filters\n" + }, + { + "contract_id": "test_list_runs_pagination", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 410, + "end_line": 418, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Pagination boundary checks on runs list." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_runs_pagination [C:2] [TYPE Function]\n# @BRIEF Pagination boundary checks on runs list.\ndef test_list_runs_pagination(mock_all_deps):\n response = client.get(\"/api/validation/runs?page=0\")\n assert response.status_code == 422\n\n response = client.get(\"/api/validation/runs?page_size=101\")\n assert response.status_code == 422\n# #endregion test_list_runs_pagination\n" + }, + { + "contract_id": "test_list_runs_invalid_status", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 421, + "end_line": 429, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Status is a free string; any value passes through to service." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_list_runs_invalid_status [C:2] [TYPE Function]\n# @BRIEF Status is a free string; any value passes through to service.\ndef test_list_runs_invalid_status(mock_all_deps):\n mock_all_deps[\"run_service\"].list_runs.return_value = (0, [])\n response = client.get(\"/api/validation/runs?status=INVALID_STATUS_XYZ\")\n assert response.status_code == 200\n call_kwargs = mock_all_deps[\"run_service\"].list_runs.call_args[1]\n assert call_kwargs.get(\"status\") == \"INVALID_STATUS_XYZ\"\n# #endregion test_list_runs_invalid_status\n" + }, + { + "contract_id": "test_get_run_detail_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 432, + "end_line": 456, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET /validation/runs/{id} returns full detail with issues and raw_response." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_get_run_detail_success [C:2] [TYPE Function]\n# @BRIEF GET /validation/runs/{id} returns full detail with issues and raw_response.\ndef test_get_run_detail_success(mock_all_deps):\n mock_all_deps[\"run_service\"].get_run_detail.return_value = ValidationRunDetailResponse(\n id=\"run-1\",\n task_id=\"task-1\",\n dashboard_id=\"dash-1\",\n environment_id=\"env-1\",\n status=\"FAIL\",\n summary=\"Charts failed to render\",\n timestamp=_make_now(),\n screenshot_path=\"/tmp/screenshots/run-1.png\",\n issues=[{\"severity\": \"HIGH\", \"message\": \"Chart timeout\"}],\n raw_response='{\"status\": \"error\"}',\n task_name=\"Test Task\",\n )\n\n response = client.get(\"/api/validation/runs/run-1\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"status\"] == \"FAIL\"\n assert len(data[\"issues\"]) == 1\n assert data[\"raw_response\"] is not None\n ValidationRunDetailResponse(**data)\n# #endregion test_get_run_detail_success\n" + }, + { + "contract_id": "test_get_run_detail_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 459, + "end_line": 465, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET for nonexistent run returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_get_run_detail_not_found [C:2] [TYPE Function]\n# @BRIEF GET for nonexistent run returns 404.\ndef test_get_run_detail_not_found(mock_all_deps):\n mock_all_deps[\"run_service\"].get_run_detail.side_effect = ValueError(\"not found\")\n response = client.get(\"/api/validation/runs/nonexistent\")\n assert response.status_code == 404\n# #endregion test_get_run_detail_not_found\n" + }, + { + "contract_id": "test_delete_run_success", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 468, + "end_line": 475, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "DELETE /validation/runs/{id} returns 204." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_run_success [C:2] [TYPE Function]\n# @BRIEF DELETE /validation/runs/{id} returns 204.\ndef test_delete_run_success(mock_all_deps):\n mock_all_deps[\"run_service\"].delete_run.return_value = True\n response = client.delete(\"/api/validation/runs/run-1\")\n assert response.status_code == 204\n mock_all_deps[\"run_service\"].delete_run.assert_called_with(\"run-1\")\n# #endregion test_delete_run_success\n" + }, + { + "contract_id": "test_delete_run_not_found", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 478, + "end_line": 484, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "DELETE for nonexistent run returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_run_not_found [C:2] [TYPE Function]\n# @BRIEF DELETE for nonexistent run returns 404.\ndef test_delete_run_not_found(mock_all_deps):\n mock_all_deps[\"run_service\"].delete_run.return_value = False\n response = client.delete(\"/api/validation/runs/nonexistent\")\n assert response.status_code == 404\n# #endregion test_delete_run_not_found\n" + }, + { + "contract_id": "test_endpoints_require_authentication", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 489, + "end_line": 507, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Without current_user dependency, all 9 endpoints return 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_endpoints_require_authentication [C:2] [TYPE Function]\n# @BRIEF Without current_user dependency, all 9 endpoints return 401.\ndef test_endpoints_require_authentication(mock_all_deps):\n app.dependency_overrides.pop(get_current_user, None)\n endpoints = [\n (\"GET\", \"/api/validation/tasks\"),\n (\"POST\", \"/api/validation/tasks\"),\n (\"GET\", \"/api/validation/tasks/task-1\"),\n (\"PUT\", \"/api/validation/tasks/task-1\"),\n (\"DELETE\", \"/api/validation/tasks/task-1\"),\n (\"POST\", \"/api/validation/tasks/task-1/run\"),\n (\"GET\", \"/api/validation/runs\"),\n (\"GET\", \"/api/validation/runs/run-1\"),\n (\"DELETE\", \"/api/validation/runs/run-1\"),\n ]\n for method, path in endpoints:\n response = client.request(method, path)\n assert response.status_code == 401, f\"{method} {path} expected 401 got {response.status_code}\"\n# #endregion test_endpoints_require_authentication\n" + }, + { + "contract_id": "test_permission_denied_non_admin", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 510, + "end_line": 517, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "A non-admin user without validation.* permissions receives 403." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_permission_denied_non_admin [C:2] [TYPE Function]\n# @BRIEF A non-admin user without validation.* permissions receives 403.\ndef test_permission_denied_non_admin(mock_all_deps):\n \"\"\"Remove Admin role so has_permission raises 403.\"\"\"\n mock_user.roles = [] # No Admin, no permissions\n response = client.get(\"/api/validation/tasks\")\n assert response.status_code == 403\n# #endregion test_permission_denied_non_admin\n" + }, + { + "contract_id": "test_permission_denied_all_actions", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 520, + "end_line": 538, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Each action (VIEW, CREATE, EDIT, DELETE, EXECUTE) denied for non-admin." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_permission_denied_all_actions [C:2] [TYPE Function]\n# @BRIEF Each action (VIEW, CREATE, EDIT, DELETE, EXECUTE) denied for non-admin.\ndef test_permission_denied_all_actions(mock_all_deps):\n mock_user.roles = []\n action_endpoints = [\n (\"GET\", \"/api/validation/tasks\"),\n (\"POST\", \"/api/validation/tasks\"),\n (\"GET\", \"/api/validation/tasks/task-1\"),\n (\"PUT\", \"/api/validation/tasks/task-1\"),\n (\"DELETE\", \"/api/validation/tasks/task-1\"),\n (\"POST\", \"/api/validation/tasks/task-1/run\"),\n (\"GET\", \"/api/validation/runs\"),\n (\"GET\", \"/api/validation/runs/run-1\"),\n (\"DELETE\", \"/api/validation/runs/run-1\"),\n ]\n for method, path in action_endpoints:\n response = client.request(method, path)\n assert response.status_code == 403, f\"{method} {path} expected 403 got {response.status_code}\"\n# #endregion test_permission_denied_all_actions\n" + }, + { + "contract_id": "test_delete_task_runs_default_false", + "contract_type": "Function", + "file_path": "backend/src/api/routes/validation/__tests__/test_validation_api.py", + "start_line": 541, + "end_line": 548, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "delete_runs query param defaults to False." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_delete_task_runs_default_false [C:2] [TYPE Function]\n# @BRIEF delete_runs query param defaults to False.\ndef test_delete_task_runs_default_false(mock_all_deps):\n mock_all_deps[\"task_service\"].delete_task.return_value = None\n response = client.delete(\"/api/validation/tasks/task-1\")\n assert response.status_code == 204\n mock_all_deps[\"task_service\"].delete_task.assert_called_with(\"task-1\", delete_runs=False)\n# #endregion test_delete_task_runs_default_false\n" + }, { "contract_id": "AppModule", "contract_type": "Module", "file_path": "backend/src/app.py", "start_line": 1, - "end_line": 440, + "end_line": 465, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -16281,7 +17601,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region AppModule [C:5] [TYPE Module] [SEMANTICS fastapi, websocket, startup, scheduler, middleware]\n# @BRIEF The main entry point for the FastAPI application.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @INVARIANT All WebSocket connections must be properly cleaned up on disconnect.\n# @PRE Python environment and dependencies installed; configuration database available.\n# @POST FastAPI app instance is created, middleware configured, and routes registered.\n# @SIDE_EFFECT Starts background scheduler and binds network ports for HTTP/WS traffic.\n# @DATA_CONTRACT [HTTP Request | WS Message] -> [HTTP Response | JSON Log Stream]\n# @RATIONALE Duplicate @RELATION and @INVARIANT lines removed from header. Import sorting unified via ruff isort (I) rule across src/ — 139 fixes applied.\n\nimport os\nfrom pathlib import Path\n\n# project_root is used for static files mounting\nproject_root = Path(__file__).resolve().parent.parent.parent\nimport asyncio\n\nfrom fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi.responses import FileResponse\nfrom fastapi.staticfiles import StaticFiles\nfrom starlette.middleware.sessions import SessionMiddleware\n\nfrom .api import auth\nfrom .api.routes import (\n admin,\n assistant,\n clean_release,\n clean_release_v2,\n connections,\n dashboards,\n dataset_review,\n datasets,\n environments,\n git,\n health,\n llm,\n mappings,\n migration,\n plugins,\n profile,\n reports,\n settings,\n storage,\n tasks,\n translate,\n)\nfrom .core.auth.security import get_password_hash\nfrom .core.cot_logger import seed_trace_id\nfrom .core.database import AuthSessionLocal, init_db\nfrom .core.encryption_key import ensure_encryption_key\nfrom .core.logger import belief_scope, logger\nfrom .core.utils.network import NetworkError\nfrom .dependencies import get_scheduler_service, get_task_manager\nfrom .models.auth import Role, User\n\n# #region FastAPI_App [C:3] [TYPE Global] [SEMANTICS app, fastapi, instance, route-registry]\n# @BRIEF Canonical FastAPI application instance for route, middleware, and websocket registration.\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @RELATION BINDS_TO -> [API_Routes]\napp = FastAPI(\n title=\"Superset Tools API\",\n description=\"API for managing Superset automation tools and plugins.\",\n version=\"1.0.0\",\n)\n# #endregion FastAPI_App\n# #region ensure_initial_admin_user [C:3] [TYPE Function]\n# @BRIEF Ensures initial admin user exists when bootstrap env flags are enabled.\n# @RELATION DEPENDS_ON -> AuthRepository\ndef ensure_initial_admin_user() -> None:\n raw_flag = os.getenv(\"INITIAL_ADMIN_CREATE\", \"false\").strip().lower()\n if raw_flag not in {\"1\", \"true\", \"yes\", \"on\"}:\n return\n username = os.getenv(\"INITIAL_ADMIN_USERNAME\", \"\").strip()\n password = os.getenv(\"INITIAL_ADMIN_PASSWORD\", \"\").strip()\n if not username or not password:\n logger.warning(\n \"INITIAL_ADMIN_CREATE is enabled but INITIAL_ADMIN_USERNAME/INITIAL_ADMIN_PASSWORD is missing; skipping bootstrap.\"\n )\n return\n db = AuthSessionLocal()\n try:\n admin_role = db.query(Role).filter(Role.name == \"Admin\").first()\n if not admin_role:\n admin_role = Role(name=\"Admin\", description=\"System Administrator\")\n db.add(admin_role)\n db.commit()\n db.refresh(admin_role)\n existing_user = db.query(User).filter(User.username == username).first()\n if existing_user:\n logger.info(\n \"Initial admin bootstrap skipped: user '%s' already exists.\", username\n )\n return\n new_user = User(\n username=username,\n email=None,\n password_hash=get_password_hash(password),\n auth_source=\"LOCAL\",\n is_active=True,\n )\n new_user.roles.append(admin_role)\n db.add(new_user)\n db.commit()\n logger.info(\n \"Initial admin user '%s' created from environment bootstrap.\", username\n )\n except Exception as exc:\n db.rollback()\n logger.error(\"Failed to bootstrap initial admin user: %s\", exc)\n raise\n finally:\n db.close()\n# #endregion ensure_initial_admin_user\n# #region startup_event [C:3] [TYPE Function]\n# @BRIEF Handles application startup tasks, such as starting the scheduler.\n# @RELATION CALLS -> [AppDependencies]\n# @PRE None.\n# @POST Scheduler is started.\n# Startup event\n@app.on_event(\"startup\")\nasync def startup_event():\n seed_trace_id()\n with belief_scope(\"startup_event\"):\n ensure_encryption_key()\n init_db()\n ensure_initial_admin_user()\n scheduler = get_scheduler_service()\n scheduler.start()\n# #endregion startup_event\n# #region shutdown_event [C:3] [TYPE Function]\n# @BRIEF Handles application shutdown tasks, such as stopping the scheduler.\n# @RELATION CALLS -> [AppDependencies]\n# @PRE None.\n# @POST Scheduler is stopped.\n# Shutdown event\n@app.on_event(\"shutdown\")\nasync def shutdown_event():\n seed_trace_id()\n with belief_scope(\"shutdown_event\"):\n scheduler = get_scheduler_service()\n scheduler.stop()\n# #endregion shutdown_event\n# #region app_middleware [TYPE Block]\n# @BRIEF Configure application-wide middleware (Session, CORS).\n# @RATIONALE CORS allow_origins reads from ALLOWED_ORIGINS env var instead of hardcoded \"*\".\n# Default \"*\" is safe for dev; production must set ALLOWED_ORIGINS to explicit list.\n# @REJECTED Hardcoded allow_origins=[\"*\"] rejected — open CORS allows any origin to access the API,\n# which is a Class 1 security violation in production.\n\n# Configure Session Middleware (required by Authlib for OAuth2 flow)\nfrom .core.auth.config import auth_config\n\napp.add_middleware(SessionMiddleware, secret_key=auth_config.SECRET_KEY)\n# Configure CORS\napp.add_middleware(\n CORSMiddleware,\n allow_origins=os.getenv(\"ALLOWED_ORIGINS\", \"*\").split(\",\"),\n allow_credentials=True,\n allow_methods=[\"*\"],\n allow_headers=[\"*\"],\n)\n# #endregion app_middleware\n# #region network_error_handler [C:1] [TYPE Function]\n# @BRIEF Global exception handler for NetworkError.\n# @PRE request is a FastAPI Request object.\n# @POST Returns 503 HTTP Exception.\n@app.exception_handler(NetworkError)\nasync def network_error_handler(request: Request, exc: NetworkError):\n with belief_scope(\"network_error_handler\"):\n logger.error(f\"Network error: {exc}\")\n return HTTPException(\n status_code=503,\n detail=\"Environment unavailable. Please check if the Superset instance is running.\",\n )\n# #endregion network_error_handler\n# #region log_requests [C:3] [TYPE Function]\n# @BRIEF Middleware to log incoming HTTP requests and their response status.\n# @RELATION DEPENDS_ON -> [LoggerModule]\n# @PRE request is a FastAPI Request object.\n# @POST Logs request and response details.\n@app.middleware(\"http\")\nasync def log_requests(request: Request, call_next):\n with belief_scope(\"log_requests\"):\n # Avoid spamming logs for polling endpoints\n is_polling = request.url.path.endswith(\"/api/tasks\") and request.method == \"GET\"\n if not is_polling:\n logger.info(f\"Incoming request: {request.method} {request.url.path}\")\n try:\n response = await call_next(request)\n if not is_polling:\n logger.info(\n f\"Response status: {response.status_code} for {request.url.path}\"\n )\n return response\n except NetworkError as e:\n logger.error(f\"Network error caught in middleware: {e}\")\n raise HTTPException(\n status_code=503,\n detail=\"Environment unavailable. Please check if the Superset instance is running.\",\n )\n# #endregion log_requests\n# Seed trace_id on every request — MUST be the outermost middleware so trace_id\n# is seeded before log_requests (or any other middleware) runs.\nfrom .core.middleware.trace import TraceContextMiddleware\n\napp.add_middleware(TraceContextMiddleware)\n# #region API_Routes [C:3] [TYPE Block]\n# @BRIEF Register all FastAPI route groups exposed by the application entrypoint.\n# @RELATION DEPENDS_ON -> [FastAPI_App]\n# @RELATION DEPENDS_ON -> [Route_Group_Contracts]\n# @RELATION DEPENDS_ON -> [AuthApi]\n# @RELATION DEPENDS_ON -> [AdminApi]\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ConnectionsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @RELATION DEPENDS_ON -> [CleanReleaseV2Api]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(plugins.router, prefix=\"/api/plugins\", tags=[\"Plugins\"])\napp.include_router(tasks.router, prefix=\"/api/tasks\", tags=[\"Tasks\"])\napp.include_router(settings.router, prefix=\"/api/settings\", tags=[\"Settings\"])\napp.include_router(\n connections.router, prefix=\"/api/settings/connections\", tags=[\"Connections\"]\n)\napp.include_router(environments.router, tags=[\"Environments\"])\napp.include_router(mappings.router, prefix=\"/api/mappings\", tags=[\"Mappings\"])\napp.include_router(migration.router)\napp.include_router(git.router, prefix=\"/api/git\", tags=[\"Git\"])\napp.include_router(llm.router, prefix=\"/api/llm\", tags=[\"LLM\"])\napp.include_router(storage.router, prefix=\"/api/storage\", tags=[\"Storage\"])\napp.include_router(dashboards.router)\napp.include_router(datasets.router)\napp.include_router(reports.router)\napp.include_router(assistant.router, prefix=\"/api/assistant\", tags=[\"Assistant\"])\napp.include_router(clean_release.router)\napp.include_router(clean_release_v2.router)\napp.include_router(profile.router)\napp.include_router(dataset_review.router)\napp.include_router(health.router)\napp.include_router(translate.router)\n# #endregion API_Routes\n# #region api.include_routers [C:1] [TYPE Action] [SEMANTICS routes, registration, api]\n# @BRIEF Registers all API routers with the FastAPI application.\n# @LAYER API\n# #endregion api.include_routers\n# #region websocket_endpoint [C:5] [TYPE Function]\n# @BRIEF Provides a WebSocket endpoint for real-time log streaming of a task with server-side filtering.\n# @RELATION CALLS -> [TaskManagerPackage]\n# @RELATION DEPENDS_ON -> [LoggerModule]\n# @PRE task_id must be a valid task ID.\n# @POST WebSocket connection is managed and logs are streamed until disconnect.\n# @SIDE_EFFECT Subscribes to TaskManager log queue and broadcasts messages over network.\n# @DATA_CONTRACT [task_id: str, source: str, level: str] -> [JSON log entry objects]\n# @INVARIANT Every accepted WebSocket subscription is unsubscribed exactly once even when streaming fails or the client disconnects.\n# @UX_STATE Connecting -> Streaming -> (Disconnected)\n#\n# @TEST_CONTRACT WebSocketLogStreamApi ->\n# {\n# required_fields: {websocket: WebSocket, task_id: str},\n# optional_fields: {source: str, level: str},\n# invariants: [\n# \"Accepts the WebSocket connection\",\n# \"Applies source and level filters correctly to streamed logs\",\n# \"Cleans up subscriptions on disconnect\"\n# ]\n# }\n# @TEST_FIXTURE valid_ws_connection -> {\"task_id\": \"test_1\", \"source\": \"plugin\"}\n# @TEST_EDGE task_not_found_ws -> closes connection or sends error\n# @TEST_EDGE empty_task_logs -> waits for new logs\n# @TEST_INVARIANT consistent_streaming -> verifies: [valid_ws_connection]\n@app.websocket(\"/ws/logs/{task_id}\")\nasync def websocket_endpoint(\n websocket: WebSocket, task_id: str, source: str = None, level: str = None\n):\n \"\"\"\n WebSocket endpoint for real-time log streaming with optional server-side filtering.\n Query Parameters:\n source: Filter logs by source component (e.g., \"plugin\", \"superset_api\")\n level: Filter logs by minimum level (DEBUG, INFO, WARNING, ERROR)\n \"\"\"\n seed_trace_id()\n with belief_scope(\"websocket_endpoint\", f\"task_id={task_id}\"):\n await websocket.accept()\n source_filter = source.lower() if source else None\n level_filter = level.upper() if level else None\n level_hierarchy = {\"DEBUG\": 0, \"INFO\": 1, \"WARNING\": 2, \"ERROR\": 3}\n min_level = level_hierarchy.get(level_filter, 0) if level_filter else 0\n logger.reason(\n \"Accepted WebSocket log stream connection\",\n extra={\n \"task_id\": task_id,\n \"source_filter\": source_filter,\n \"level_filter\": level_filter,\n \"min_level\": min_level,\n },\n )\n task_manager = get_task_manager()\n queue = await task_manager.subscribe_logs(task_id)\n logger.reason(\n \"Subscribed WebSocket client to task log queue\",\n extra={\"task_id\": task_id},\n )\n def matches_filters(log_entry) -> bool:\n \"\"\"Check if log entry matches the filter criteria.\"\"\"\n log_source = getattr(log_entry, \"source\", None)\n if source_filter and str(log_source or \"\").lower() != source_filter:\n return False\n if level_filter:\n log_level = level_hierarchy.get(str(log_entry.level).upper(), 0)\n if log_level < min_level:\n return False\n return True\n try:\n logger.reason(\n \"Starting task log stream replay and live forwarding\",\n extra={\"task_id\": task_id},\n )\n initial_logs = task_manager.get_task_logs(task_id)\n initial_sent = 0\n for log_entry in initial_logs:\n if matches_filters(log_entry):\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n initial_sent += 1\n logger.reflect(\n \"Initial task log replay completed\",\n extra={\n \"task_id\": task_id,\n \"replayed_logs\": initial_sent,\n \"total_available_logs\": len(initial_logs),\n },\n )\n task = task_manager.get_task(task_id)\n if task and task.status == \"AWAITING_INPUT\" and task.input_request:\n synthetic_log = {\n \"timestamp\": task.logs[-1].timestamp.isoformat()\n if task.logs\n else \"2024-01-01T00:00:00\",\n \"level\": \"INFO\",\n \"message\": \"Task paused for user input (Connection Re-established)\",\n \"context\": {\"input_request\": task.input_request},\n }\n await websocket.send_json(synthetic_log)\n logger.reason(\n \"Replayed awaiting-input prompt to restored WebSocket client\",\n extra={\"task_id\": task_id, \"task_status\": task.status},\n )\n while True:\n log_entry = await queue.get()\n if not matches_filters(log_entry):\n continue\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n logger.reflect(\n \"Forwarded task log entry to WebSocket client\",\n extra={\n \"task_id\": task_id,\n \"level\": log_dict.get(\"level\"),\n },\n )\n if (\n \"Task completed successfully\" in log_entry.message\n or \"Task failed\" in log_entry.message\n ):\n logger.reason(\n \"Observed terminal task log entry; delaying to preserve client visibility\",\n extra={\"task_id\": task_id, \"message\": log_entry.message},\n )\n await asyncio.sleep(2)\n except WebSocketDisconnect:\n logger.reason(\n \"WebSocket client disconnected from task log stream\",\n extra={\"task_id\": task_id},\n )\n except Exception as exc:\n logger.explore(\n \"WebSocket log streaming encountered an unexpected failure\",\n extra={\"task_id\": task_id, \"error\": str(exc)},\n )\n raise\n finally:\n task_manager.unsubscribe_logs(task_id, queue)\n logger.reflect(\n \"Released WebSocket log queue subscription\",\n extra={\"task_id\": task_id},\n )\n# #endregion websocket_endpoint\n# #region StaticFiles [C:1] [TYPE Mount] [SEMANTICS static, frontend, spa]\n# @BRIEF Mounts the frontend build directory to serve static assets.\nfrontend_path = project_root / \"frontend\" / \"build\"\nif frontend_path.exists():\n app.mount(\n \"/_app\", StaticFiles(directory=str(frontend_path / \"_app\")), name=\"static\"\n )\n # #region serve_spa [TYPE Function] [C:1]\n # @PURPOSE Serves the SPA frontend for any path not matched by API routes.\n # @PRE frontend_path exists.\n # @POST Returns the requested file or index.html.\n @app.get(\"/{file_path:path}\", include_in_schema=False)\n async def serve_spa(file_path: str):\n with belief_scope(\"serve_spa\"):\n # Only serve SPA for non-API paths\n # API routes are registered separately and should be matched by FastAPI first\n if file_path and (\n file_path.startswith(\"api/\")\n or file_path.startswith(\"/api/\")\n or file_path == \"api\"\n ):\n # This should not happen if API routers are properly registered\n # Return 404 instead of serving HTML\n raise HTTPException(\n status_code=404, detail=f\"API endpoint not found: {file_path}\"\n )\n full_path = frontend_path / file_path\n if file_path and full_path.is_file():\n return FileResponse(str(full_path))\n return FileResponse(str(frontend_path / \"index.html\"))\n # #endregion serve_spa\nelse:\n # #region read_root [TYPE Function] [C:1]\n # @PURPOSE A simple root endpoint to confirm that the API is running when frontend is missing.\n # @PRE None.\n # @POST Returns a JSON message indicating API status.\n @app.get(\"/\")\n async def read_root():\n with belief_scope(\"read_root\"):\n return {\n \"message\": \"Superset Tools API is running (Frontend build not found)\"\n }\n # #endregion read_root\n# #endregion StaticFiles\n# #endregion AppModule\n" + "body": "# #region AppModule [C:5] [TYPE Module] [SEMANTICS fastapi, websocket, startup, scheduler, middleware]\n# @BRIEF The main entry point for the FastAPI application.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @INVARIANT All WebSocket connections must be properly cleaned up on disconnect.\n# @PRE Python environment and dependencies installed; configuration database available.\n# @POST FastAPI app instance is created, middleware configured, and routes registered.\n# @SIDE_EFFECT Starts background scheduler and binds network ports for HTTP/WS traffic.\n# @DATA_CONTRACT [HTTP Request | WS Message] -> [HTTP Response | JSON Log Stream]\n# @RATIONALE Duplicate @RELATION and @INVARIANT lines removed from header. Import sorting unified via ruff isort (I) rule across src/ — 139 fixes applied.\n\nimport os\nfrom pathlib import Path\n\n# project_root is used for static files mounting\nproject_root = Path(__file__).resolve().parent.parent.parent\nimport asyncio\n\nfrom fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi.responses import FileResponse\nfrom fastapi.staticfiles import StaticFiles\nfrom starlette.middleware.sessions import SessionMiddleware\n\nfrom .api import auth\nfrom .api.routes import (\n admin,\n assistant,\n clean_release,\n clean_release_v2,\n dashboards,\n dataset_review,\n datasets,\n environments,\n git,\n health,\n llm,\n mappings,\n migration,\n plugins,\n profile,\n reports,\n settings,\n storage,\n tasks,\n translate,\n validation,\n)\nfrom .core.auth.security import get_password_hash\nfrom .core.cot_logger import seed_trace_id\nfrom .core.database import AuthSessionLocal, init_db\nfrom .core.encryption_key import ensure_encryption_key\nfrom .core.logger import belief_scope, logger\nfrom .core.utils.network import NetworkError\nfrom .dependencies import get_scheduler_service, get_task_manager\nfrom .models.auth import Role, User\n\n# #region FastAPI_App [C:3] [TYPE Global] [SEMANTICS app, fastapi, instance, route-registry]\n# @BRIEF Canonical FastAPI application instance for route, middleware, and websocket registration.\n# @RELATION DEPENDS_ON -> [ApiRoutesModule]\n# @RELATION BINDS_TO -> [API_Routes]\napp = FastAPI(\n title=\"Superset Tools API\",\n description=\"API for managing Superset automation tools and plugins.\",\n version=\"1.0.0\",\n)\n# #endregion FastAPI_App\n# #region ensure_initial_admin_user [C:3] [TYPE Function]\n# @BRIEF Ensures initial admin user exists when bootstrap env flags are enabled.\n# @RELATION DEPENDS_ON -> AuthRepository\ndef ensure_initial_admin_user() -> None:\n raw_flag = os.getenv(\"INITIAL_ADMIN_CREATE\", \"false\").strip().lower()\n if raw_flag not in {\"1\", \"true\", \"yes\", \"on\"}:\n return\n username = os.getenv(\"INITIAL_ADMIN_USERNAME\", \"\").strip()\n password = os.getenv(\"INITIAL_ADMIN_PASSWORD\", \"\").strip()\n if not username or not password:\n logger.warning(\n \"INITIAL_ADMIN_CREATE is enabled but INITIAL_ADMIN_USERNAME/INITIAL_ADMIN_PASSWORD is missing; skipping bootstrap.\"\n )\n return\n db = AuthSessionLocal()\n try:\n admin_role = db.query(Role).filter(Role.name == \"Admin\").first()\n if not admin_role:\n admin_role = Role(name=\"Admin\", description=\"System Administrator\")\n db.add(admin_role)\n db.commit()\n db.refresh(admin_role)\n existing_user = db.query(User).filter(User.username == username).first()\n if existing_user:\n logger.info(\n \"Initial admin bootstrap skipped: user '%s' already exists.\", username\n )\n return\n new_user = User(\n username=username,\n email=None,\n password_hash=get_password_hash(password),\n auth_source=\"LOCAL\",\n is_active=True,\n )\n new_user.roles.append(admin_role)\n db.add(new_user)\n db.commit()\n logger.info(\n \"Initial admin user '%s' created from environment bootstrap.\", username\n )\n except Exception as exc:\n db.rollback()\n logger.error(\"Failed to bootstrap initial admin user: %s\", exc)\n raise\n finally:\n db.close()\n# #endregion ensure_initial_admin_user\n# #region startup_event [C:3] [TYPE Function]\n# @BRIEF Handles application startup tasks, such as starting the scheduler.\n# @RELATION CALLS -> [AppDependencies]\n# @PRE None.\n# @POST Scheduler is started.\n# Startup event\n@app.on_event(\"startup\")\nasync def startup_event():\n seed_trace_id()\n with belief_scope(\"startup_event\"):\n ensure_encryption_key()\n init_db()\n ensure_initial_admin_user()\n scheduler = get_scheduler_service()\n scheduler.start()\n# #endregion startup_event\n# #region shutdown_event [C:3] [TYPE Function]\n# @BRIEF Handles application shutdown tasks, such as stopping the scheduler.\n# @RELATION CALLS -> [AppDependencies]\n# @PRE None.\n# @POST Scheduler is stopped.\n# Shutdown event\n@app.on_event(\"shutdown\")\nasync def shutdown_event():\n seed_trace_id()\n with belief_scope(\"shutdown_event\"):\n scheduler = get_scheduler_service()\n scheduler.stop()\n# #endregion shutdown_event\n# #region app_middleware [TYPE Block]\n# @BRIEF Configure application-wide middleware (Session, CORS).\n# @RATIONALE CORS allow_origins reads from ALLOWED_ORIGINS env var instead of hardcoded \"*\".\n# Default \"*\" is safe for dev; production must set ALLOWED_ORIGINS to explicit list.\n# @REJECTED Hardcoded allow_origins=[\"*\"] rejected — open CORS allows any origin to access the API,\n# which is a Class 1 security violation in production.\n\n# Configure Session Middleware (required by Authlib for OAuth2 flow)\nfrom .core.auth.config import auth_config\n\napp.add_middleware(SessionMiddleware, secret_key=auth_config.SECRET_KEY)\n# Configure CORS\napp.add_middleware(\n CORSMiddleware,\n allow_origins=os.getenv(\"ALLOWED_ORIGINS\", \"*\").split(\",\"),\n allow_credentials=True,\n allow_methods=[\"*\"],\n allow_headers=[\"*\"],\n)\n# #endregion app_middleware\n# #region network_error_handler [C:1] [TYPE Function]\n# @BRIEF Global exception handler for NetworkError.\n# @PRE request is a FastAPI Request object.\n# @POST Returns 503 HTTP Exception.\n@app.exception_handler(NetworkError)\nasync def network_error_handler(request: Request, exc: NetworkError):\n with belief_scope(\"network_error_handler\"):\n logger.error(f\"Network error: {exc}\")\n return HTTPException(\n status_code=503,\n detail=\"Environment unavailable. Please check if the Superset instance is running.\",\n )\n# #endregion network_error_handler\n# #region log_requests [C:3] [TYPE Function]\n# @BRIEF Middleware to log incoming HTTP requests and their response status.\n# @RELATION DEPENDS_ON -> [LoggerModule]\n# @PRE request is a FastAPI Request object.\n# @POST Logs request and response details.\n@app.middleware(\"http\")\nasync def log_requests(request: Request, call_next):\n with belief_scope(\"log_requests\"):\n # Avoid spamming logs for polling endpoints\n is_polling = request.url.path.endswith(\"/api/tasks\") and request.method == \"GET\"\n if not is_polling:\n logger.info(f\"Incoming request: {request.method} {request.url.path}\")\n try:\n response = await call_next(request)\n if not is_polling:\n logger.info(\n f\"Response status: {response.status_code} for {request.url.path}\"\n )\n return response\n except NetworkError as e:\n logger.error(f\"Network error caught in middleware: {e}\")\n raise HTTPException(\n status_code=503,\n detail=\"Environment unavailable. Please check if the Superset instance is running.\",\n )\n# #endregion log_requests\n# Seed trace_id on every request — MUST be the outermost middleware so trace_id\n# is seeded before log_requests (or any other middleware) runs.\nfrom .core.middleware.trace import TraceContextMiddleware\n\napp.add_middleware(TraceContextMiddleware)\n# #region API_Routes [C:3] [TYPE Block]\n# @BRIEF Register all FastAPI route groups exposed by the application entrypoint.\n# @RELATION DEPENDS_ON -> [FastAPI_App]\n# @RELATION DEPENDS_ON -> [Route_Group_Contracts]\n# @RELATION DEPENDS_ON -> [AuthApi]\n# @RELATION DEPENDS_ON -> [AdminApi]\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @RELATION DEPENDS_ON -> [CleanReleaseV2Api]\n# @RELATION DEPENDS_ON -> [ValidationRoutes]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(plugins.router, prefix=\"/api/plugins\", tags=[\"Plugins\"])\napp.include_router(tasks.router, prefix=\"/api/tasks\", tags=[\"Tasks\"])\napp.include_router(settings.router, prefix=\"/api/settings\", tags=[\"Settings\"])\napp.include_router(environments.router, tags=[\"Environments\"])\napp.include_router(mappings.router, prefix=\"/api/mappings\", tags=[\"Mappings\"])\napp.include_router(migration.router)\napp.include_router(git.router, prefix=\"/api/git\", tags=[\"Git\"])\napp.include_router(llm.router, prefix=\"/api/llm\", tags=[\"LLM\"])\napp.include_router(storage.router, prefix=\"/api/storage\", tags=[\"Storage\"])\napp.include_router(dashboards.router)\napp.include_router(datasets.router)\napp.include_router(reports.router)\napp.include_router(assistant.router, prefix=\"/api/assistant\", tags=[\"Assistant\"])\napp.include_router(clean_release.router)\napp.include_router(clean_release_v2.router)\napp.include_router(profile.router)\napp.include_router(dataset_review.router)\napp.include_router(health.router)\napp.include_router(translate.router)\napp.include_router(validation.router, prefix=\"/api/validation\", tags=[\"Validation\"])\n# #endregion API_Routes\n# #region api.include_routers [C:1] [TYPE Action] [SEMANTICS routes, registration, api]\n# @BRIEF Registers all API routers with the FastAPI application.\n# @LAYER API\n# #endregion api.include_routers\n# #region websocket_endpoint [C:5] [TYPE Function]\n# @BRIEF Provides a WebSocket endpoint for real-time log streaming of a task with server-side filtering.\n# @RELATION CALLS -> [TaskManagerPackage]\n# @RELATION DEPENDS_ON -> [LoggerModule]\n# @PRE task_id must be a valid task ID.\n# @POST WebSocket connection is managed and logs are streamed until disconnect.\n# @SIDE_EFFECT Subscribes to TaskManager log queue and broadcasts messages over network.\n# @DATA_CONTRACT [task_id: str, source: str, level: str] -> [JSON log entry objects]\n# @INVARIANT Every accepted WebSocket subscription is unsubscribed exactly once even when streaming fails or the client disconnects.\n# @UX_STATE Connecting -> Streaming -> (Disconnected)\n#\n# @TEST_CONTRACT WebSocketLogStreamApi ->\n# {\n# required_fields: {websocket: WebSocket, task_id: str},\n# optional_fields: {source: str, level: str},\n# invariants: [\n# \"Accepts the WebSocket connection\",\n# \"Applies source and level filters correctly to streamed logs\",\n# \"Cleans up subscriptions on disconnect\"\n# ]\n# }\n# @TEST_FIXTURE valid_ws_connection -> {\"task_id\": \"test_1\", \"source\": \"plugin\"}\n# @TEST_EDGE task_not_found_ws -> closes connection or sends error\n# @TEST_EDGE empty_task_logs -> waits for new logs\n# @TEST_INVARIANT consistent_streaming -> verifies: [valid_ws_connection]\n@app.websocket(\"/ws/logs/{task_id}\")\nasync def websocket_endpoint(\n websocket: WebSocket, task_id: str, source: str = None, level: str = None\n):\n \"\"\"\n WebSocket endpoint for real-time log streaming with optional server-side filtering.\n Query Parameters:\n source: Filter logs by source component (e.g., \"plugin\", \"superset_api\")\n level: Filter logs by minimum level (DEBUG, INFO, WARNING, ERROR)\n \"\"\"\n seed_trace_id()\n with belief_scope(\"websocket_endpoint\", f\"task_id={task_id}\"):\n await websocket.accept()\n source_filter = source.lower() if source else None\n level_filter = level.upper() if level else None\n level_hierarchy = {\"DEBUG\": 0, \"INFO\": 1, \"WARNING\": 2, \"ERROR\": 3}\n min_level = level_hierarchy.get(level_filter, 0) if level_filter else 0\n logger.reason(\n \"Accepted WebSocket log stream connection\",\n extra={\n \"task_id\": task_id,\n \"source_filter\": source_filter,\n \"level_filter\": level_filter,\n \"min_level\": min_level,\n },\n )\n task_manager = get_task_manager()\n queue = await task_manager.subscribe_logs(task_id)\n logger.reason(\n \"Subscribed WebSocket client to task log queue\",\n extra={\"task_id\": task_id},\n )\n def matches_filters(log_entry) -> bool:\n \"\"\"Check if log entry matches the filter criteria.\"\"\"\n log_source = getattr(log_entry, \"source\", None)\n if source_filter and str(log_source or \"\").lower() != source_filter:\n return False\n if level_filter:\n log_level = level_hierarchy.get(str(log_entry.level).upper(), 0)\n if log_level < min_level:\n return False\n return True\n try:\n logger.reason(\n \"Starting task log stream replay and live forwarding\",\n extra={\"task_id\": task_id},\n )\n initial_logs = task_manager.get_task_logs(task_id)\n initial_sent = 0\n for log_entry in initial_logs:\n if matches_filters(log_entry):\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n initial_sent += 1\n logger.reflect(\n \"Initial task log replay completed\",\n extra={\n \"task_id\": task_id,\n \"replayed_logs\": initial_sent,\n \"total_available_logs\": len(initial_logs),\n },\n )\n task = task_manager.get_task(task_id)\n if task and task.status == \"AWAITING_INPUT\" and task.input_request:\n synthetic_log = {\n \"timestamp\": task.logs[-1].timestamp.isoformat()\n if task.logs\n else \"2024-01-01T00:00:00\",\n \"level\": \"INFO\",\n \"message\": \"Task paused for user input (Connection Re-established)\",\n \"context\": {\"input_request\": task.input_request},\n }\n await websocket.send_json(synthetic_log)\n logger.reason(\n \"Replayed awaiting-input prompt to restored WebSocket client\",\n extra={\"task_id\": task_id, \"task_status\": task.status},\n )\n while True:\n log_entry = await queue.get()\n if not matches_filters(log_entry):\n continue\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n logger.reflect(\n \"Forwarded task log entry to WebSocket client\",\n extra={\n \"task_id\": task_id,\n \"level\": log_dict.get(\"level\"),\n },\n )\n if (\n \"Task completed successfully\" in log_entry.message\n or \"Task failed\" in log_entry.message\n ):\n logger.reason(\n \"Observed terminal task log entry; delaying to preserve client visibility\",\n extra={\"task_id\": task_id, \"message\": log_entry.message},\n )\n await asyncio.sleep(2)\n except WebSocketDisconnect:\n logger.reason(\n \"WebSocket client disconnected from task log stream\",\n extra={\"task_id\": task_id},\n )\n except Exception as exc:\n logger.explore(\n \"WebSocket log streaming encountered an unexpected failure\",\n extra={\"task_id\": task_id, \"error\": str(exc)},\n )\n raise\n finally:\n task_manager.unsubscribe_logs(task_id, queue)\n logger.reflect(\n \"Released WebSocket log queue subscription\",\n extra={\"task_id\": task_id},\n )\n# #endregion websocket_endpoint\n# #region dataset_websocket_endpoint [C:4] [TYPE Function]\n# @BRIEF WebSocket endpoint for dataset.updated events — auto-refresh on task completion.\n# @RELATION CALLS -> [TaskManagerPackage]\n# @PRE env_id must reference a known environment.\n# @POST WebSocket streams dataset.updated events until disconnect.\n# @SIDE_EFFECT Subscribes to dataset event queue in task manager lifecycle.\n@app.websocket(\"/ws/datasets/{env_id}\")\nasync def dataset_websocket_endpoint(websocket: WebSocket, env_id: str):\n seed_trace_id()\n with belief_scope(\"dataset_websocket_endpoint\", f\"env_id={env_id}\"):\n await websocket.accept()\n logger.reason(\"Accepted dataset event WebSocket\", extra={\"env_id\": env_id})\n task_manager = get_task_manager()\n queue = await task_manager.subscribe_dataset_events(env_id)\n try:\n while True:\n event = await queue.get()\n await websocket.send_json(event)\n logger.reflect(\"Forwarded dataset.updated event to client\", extra={\"env_id\": env_id})\n except WebSocketDisconnect:\n logger.reason(\"WebSocket client disconnected from dataset events\", extra={\"env_id\": env_id})\n except Exception as exc:\n logger.explore(\"WebSocket dataset streaming failed\", extra={\"env_id\": env_id, \"error\": str(exc)})\n finally:\n task_manager.unsubscribe_dataset_events(env_id, queue)\n logger.reflect(\"Released dataset event subscription\", extra={\"env_id\": env_id})\n# #endregion dataset_websocket_endpoint\n# #region StaticFiles [C:1] [TYPE Mount] [SEMANTICS static, frontend, spa]\n# @BRIEF Mounts the frontend build directory to serve static assets.\nfrontend_path = project_root / \"frontend\" / \"build\"\nif frontend_path.exists():\n app.mount(\n \"/_app\", StaticFiles(directory=str(frontend_path / \"_app\")), name=\"static\"\n )\n # #region serve_spa [TYPE Function] [C:1]\n # @PURPOSE Serves the SPA frontend for any path not matched by API routes.\n # @PRE frontend_path exists.\n # @POST Returns the requested file or index.html.\n @app.get(\"/{file_path:path}\", include_in_schema=False)\n async def serve_spa(file_path: str):\n with belief_scope(\"serve_spa\"):\n # Only serve SPA for non-API paths\n # API routes are registered separately and should be matched by FastAPI first\n if file_path and (\n file_path.startswith(\"api/\")\n or file_path.startswith(\"/api/\")\n or file_path == \"api\"\n ):\n # This should not happen if API routers are properly registered\n # Return 404 instead of serving HTML\n raise HTTPException(\n status_code=404, detail=f\"API endpoint not found: {file_path}\"\n )\n full_path = frontend_path / file_path\n if file_path and full_path.is_file():\n return FileResponse(str(full_path))\n return FileResponse(str(frontend_path / \"index.html\"))\n # #endregion serve_spa\nelse:\n # #region read_root [TYPE Function] [C:1]\n # @PURPOSE A simple root endpoint to confirm that the API is running when frontend is missing.\n # @PRE None.\n # @POST Returns a JSON message indicating API status.\n @app.get(\"/\")\n async def read_root():\n with belief_scope(\"read_root\"):\n return {\n \"message\": \"Superset Tools API is running (Frontend build not found)\"\n }\n # #endregion read_root\n# #endregion StaticFiles\n# #endregion AppModule\n" }, { "contract_id": "FastAPI_App", @@ -16526,7 +17846,7 @@ "contract_type": "Block", "file_path": "backend/src/app.py", "start_line": 209, - "end_line": 247, + "end_line": 245, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -16576,12 +17896,6 @@ "target_id": "SettingsRouter", "target_ref": "[SettingsRouter]" }, - { - "source_id": "API_Routes", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionsRouter", - "target_ref": "[ConnectionsRouter]" - }, { "source_id": "API_Routes", "relation_type": "DEPENDS_ON", @@ -16599,19 +17913,25 @@ "relation_type": "DEPENDS_ON", "target_id": "CleanReleaseV2Api", "target_ref": "[CleanReleaseV2Api]" + }, + { + "source_id": "API_Routes", + "relation_type": "DEPENDS_ON", + "target_id": "ValidationRoutes", + "target_ref": "[ValidationRoutes]" } ], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region API_Routes [C:3] [TYPE Block]\n# @BRIEF Register all FastAPI route groups exposed by the application entrypoint.\n# @RELATION DEPENDS_ON -> [FastAPI_App]\n# @RELATION DEPENDS_ON -> [Route_Group_Contracts]\n# @RELATION DEPENDS_ON -> [AuthApi]\n# @RELATION DEPENDS_ON -> [AdminApi]\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ConnectionsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @RELATION DEPENDS_ON -> [CleanReleaseV2Api]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(plugins.router, prefix=\"/api/plugins\", tags=[\"Plugins\"])\napp.include_router(tasks.router, prefix=\"/api/tasks\", tags=[\"Tasks\"])\napp.include_router(settings.router, prefix=\"/api/settings\", tags=[\"Settings\"])\napp.include_router(\n connections.router, prefix=\"/api/settings/connections\", tags=[\"Connections\"]\n)\napp.include_router(environments.router, tags=[\"Environments\"])\napp.include_router(mappings.router, prefix=\"/api/mappings\", tags=[\"Mappings\"])\napp.include_router(migration.router)\napp.include_router(git.router, prefix=\"/api/git\", tags=[\"Git\"])\napp.include_router(llm.router, prefix=\"/api/llm\", tags=[\"LLM\"])\napp.include_router(storage.router, prefix=\"/api/storage\", tags=[\"Storage\"])\napp.include_router(dashboards.router)\napp.include_router(datasets.router)\napp.include_router(reports.router)\napp.include_router(assistant.router, prefix=\"/api/assistant\", tags=[\"Assistant\"])\napp.include_router(clean_release.router)\napp.include_router(clean_release_v2.router)\napp.include_router(profile.router)\napp.include_router(dataset_review.router)\napp.include_router(health.router)\napp.include_router(translate.router)\n# #endregion API_Routes\n" + "body": "# #region API_Routes [C:3] [TYPE Block]\n# @BRIEF Register all FastAPI route groups exposed by the application entrypoint.\n# @RELATION DEPENDS_ON -> [FastAPI_App]\n# @RELATION DEPENDS_ON -> [Route_Group_Contracts]\n# @RELATION DEPENDS_ON -> [AuthApi]\n# @RELATION DEPENDS_ON -> [AdminApi]\n# @RELATION DEPENDS_ON -> [PluginsRouter]\n# @RELATION DEPENDS_ON -> [TasksRouter]\n# @RELATION DEPENDS_ON -> [SettingsRouter]\n# @RELATION DEPENDS_ON -> [ReportsRouter]\n# @RELATION DEPENDS_ON -> [LlmRoutes]\n# @RELATION DEPENDS_ON -> [CleanReleaseV2Api]\n# @RELATION DEPENDS_ON -> [ValidationRoutes]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(plugins.router, prefix=\"/api/plugins\", tags=[\"Plugins\"])\napp.include_router(tasks.router, prefix=\"/api/tasks\", tags=[\"Tasks\"])\napp.include_router(settings.router, prefix=\"/api/settings\", tags=[\"Settings\"])\napp.include_router(environments.router, tags=[\"Environments\"])\napp.include_router(mappings.router, prefix=\"/api/mappings\", tags=[\"Mappings\"])\napp.include_router(migration.router)\napp.include_router(git.router, prefix=\"/api/git\", tags=[\"Git\"])\napp.include_router(llm.router, prefix=\"/api/llm\", tags=[\"LLM\"])\napp.include_router(storage.router, prefix=\"/api/storage\", tags=[\"Storage\"])\napp.include_router(dashboards.router)\napp.include_router(datasets.router)\napp.include_router(reports.router)\napp.include_router(assistant.router, prefix=\"/api/assistant\", tags=[\"Assistant\"])\napp.include_router(clean_release.router)\napp.include_router(clean_release_v2.router)\napp.include_router(profile.router)\napp.include_router(dataset_review.router)\napp.include_router(health.router)\napp.include_router(translate.router)\napp.include_router(validation.router, prefix=\"/api/validation\", tags=[\"Validation\"])\n# #endregion API_Routes\n" }, { "contract_id": "api.include_routers", "contract_type": "Action", "file_path": "backend/src/app.py", - "start_line": 248, - "end_line": 251, + "start_line": 246, + "end_line": 249, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -16705,8 +18025,8 @@ "contract_id": "websocket_endpoint", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 252, - "end_line": 395, + "start_line": 250, + "end_line": 393, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -16760,12 +18080,40 @@ "tier_source": "AutoCalculated", "body": "# #region websocket_endpoint [C:5] [TYPE Function]\n# @BRIEF Provides a WebSocket endpoint for real-time log streaming of a task with server-side filtering.\n# @RELATION CALLS -> [TaskManagerPackage]\n# @RELATION DEPENDS_ON -> [LoggerModule]\n# @PRE task_id must be a valid task ID.\n# @POST WebSocket connection is managed and logs are streamed until disconnect.\n# @SIDE_EFFECT Subscribes to TaskManager log queue and broadcasts messages over network.\n# @DATA_CONTRACT [task_id: str, source: str, level: str] -> [JSON log entry objects]\n# @INVARIANT Every accepted WebSocket subscription is unsubscribed exactly once even when streaming fails or the client disconnects.\n# @UX_STATE Connecting -> Streaming -> (Disconnected)\n#\n# @TEST_CONTRACT WebSocketLogStreamApi ->\n# {\n# required_fields: {websocket: WebSocket, task_id: str},\n# optional_fields: {source: str, level: str},\n# invariants: [\n# \"Accepts the WebSocket connection\",\n# \"Applies source and level filters correctly to streamed logs\",\n# \"Cleans up subscriptions on disconnect\"\n# ]\n# }\n# @TEST_FIXTURE valid_ws_connection -> {\"task_id\": \"test_1\", \"source\": \"plugin\"}\n# @TEST_EDGE task_not_found_ws -> closes connection or sends error\n# @TEST_EDGE empty_task_logs -> waits for new logs\n# @TEST_INVARIANT consistent_streaming -> verifies: [valid_ws_connection]\n@app.websocket(\"/ws/logs/{task_id}\")\nasync def websocket_endpoint(\n websocket: WebSocket, task_id: str, source: str = None, level: str = None\n):\n \"\"\"\n WebSocket endpoint for real-time log streaming with optional server-side filtering.\n Query Parameters:\n source: Filter logs by source component (e.g., \"plugin\", \"superset_api\")\n level: Filter logs by minimum level (DEBUG, INFO, WARNING, ERROR)\n \"\"\"\n seed_trace_id()\n with belief_scope(\"websocket_endpoint\", f\"task_id={task_id}\"):\n await websocket.accept()\n source_filter = source.lower() if source else None\n level_filter = level.upper() if level else None\n level_hierarchy = {\"DEBUG\": 0, \"INFO\": 1, \"WARNING\": 2, \"ERROR\": 3}\n min_level = level_hierarchy.get(level_filter, 0) if level_filter else 0\n logger.reason(\n \"Accepted WebSocket log stream connection\",\n extra={\n \"task_id\": task_id,\n \"source_filter\": source_filter,\n \"level_filter\": level_filter,\n \"min_level\": min_level,\n },\n )\n task_manager = get_task_manager()\n queue = await task_manager.subscribe_logs(task_id)\n logger.reason(\n \"Subscribed WebSocket client to task log queue\",\n extra={\"task_id\": task_id},\n )\n def matches_filters(log_entry) -> bool:\n \"\"\"Check if log entry matches the filter criteria.\"\"\"\n log_source = getattr(log_entry, \"source\", None)\n if source_filter and str(log_source or \"\").lower() != source_filter:\n return False\n if level_filter:\n log_level = level_hierarchy.get(str(log_entry.level).upper(), 0)\n if log_level < min_level:\n return False\n return True\n try:\n logger.reason(\n \"Starting task log stream replay and live forwarding\",\n extra={\"task_id\": task_id},\n )\n initial_logs = task_manager.get_task_logs(task_id)\n initial_sent = 0\n for log_entry in initial_logs:\n if matches_filters(log_entry):\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n initial_sent += 1\n logger.reflect(\n \"Initial task log replay completed\",\n extra={\n \"task_id\": task_id,\n \"replayed_logs\": initial_sent,\n \"total_available_logs\": len(initial_logs),\n },\n )\n task = task_manager.get_task(task_id)\n if task and task.status == \"AWAITING_INPUT\" and task.input_request:\n synthetic_log = {\n \"timestamp\": task.logs[-1].timestamp.isoformat()\n if task.logs\n else \"2024-01-01T00:00:00\",\n \"level\": \"INFO\",\n \"message\": \"Task paused for user input (Connection Re-established)\",\n \"context\": {\"input_request\": task.input_request},\n }\n await websocket.send_json(synthetic_log)\n logger.reason(\n \"Replayed awaiting-input prompt to restored WebSocket client\",\n extra={\"task_id\": task_id, \"task_status\": task.status},\n )\n while True:\n log_entry = await queue.get()\n if not matches_filters(log_entry):\n continue\n log_dict = log_entry.dict()\n log_dict[\"timestamp\"] = log_dict[\"timestamp\"].isoformat()\n await websocket.send_json(log_dict)\n logger.reflect(\n \"Forwarded task log entry to WebSocket client\",\n extra={\n \"task_id\": task_id,\n \"level\": log_dict.get(\"level\"),\n },\n )\n if (\n \"Task completed successfully\" in log_entry.message\n or \"Task failed\" in log_entry.message\n ):\n logger.reason(\n \"Observed terminal task log entry; delaying to preserve client visibility\",\n extra={\"task_id\": task_id, \"message\": log_entry.message},\n )\n await asyncio.sleep(2)\n except WebSocketDisconnect:\n logger.reason(\n \"WebSocket client disconnected from task log stream\",\n extra={\"task_id\": task_id},\n )\n except Exception as exc:\n logger.explore(\n \"WebSocket log streaming encountered an unexpected failure\",\n extra={\"task_id\": task_id, \"error\": str(exc)},\n )\n raise\n finally:\n task_manager.unsubscribe_logs(task_id, queue)\n logger.reflect(\n \"Released WebSocket log queue subscription\",\n extra={\"task_id\": task_id},\n )\n# #endregion websocket_endpoint\n" }, + { + "contract_id": "dataset_websocket_endpoint", + "contract_type": "Function", + "file_path": "backend/src/app.py", + "start_line": 394, + "end_line": 420, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "POST": "WebSocket streams dataset.updated events until disconnect.", + "PRE": "env_id must reference a known environment.", + "PURPOSE": "WebSocket endpoint for dataset.updated events — auto-refresh on task completion.", + "SIDE_EFFECT": "Subscribes to dataset event queue in task manager lifecycle." + }, + "relations": [ + { + "source_id": "dataset_websocket_endpoint", + "relation_type": "CALLS", + "target_id": "TaskManagerPackage", + "target_ref": "[TaskManagerPackage]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region dataset_websocket_endpoint [C:4] [TYPE Function]\n# @BRIEF WebSocket endpoint for dataset.updated events — auto-refresh on task completion.\n# @RELATION CALLS -> [TaskManagerPackage]\n# @PRE env_id must reference a known environment.\n# @POST WebSocket streams dataset.updated events until disconnect.\n# @SIDE_EFFECT Subscribes to dataset event queue in task manager lifecycle.\n@app.websocket(\"/ws/datasets/{env_id}\")\nasync def dataset_websocket_endpoint(websocket: WebSocket, env_id: str):\n seed_trace_id()\n with belief_scope(\"dataset_websocket_endpoint\", f\"env_id={env_id}\"):\n await websocket.accept()\n logger.reason(\"Accepted dataset event WebSocket\", extra={\"env_id\": env_id})\n task_manager = get_task_manager()\n queue = await task_manager.subscribe_dataset_events(env_id)\n try:\n while True:\n event = await queue.get()\n await websocket.send_json(event)\n logger.reflect(\"Forwarded dataset.updated event to client\", extra={\"env_id\": env_id})\n except WebSocketDisconnect:\n logger.reason(\"WebSocket client disconnected from dataset events\", extra={\"env_id\": env_id})\n except Exception as exc:\n logger.explore(\"WebSocket dataset streaming failed\", extra={\"env_id\": env_id, \"error\": str(exc)})\n finally:\n task_manager.unsubscribe_dataset_events(env_id, queue)\n logger.reflect(\"Released dataset event subscription\", extra={\"env_id\": env_id})\n# #endregion dataset_websocket_endpoint\n" + }, { "contract_id": "StaticFiles", "contract_type": "Mount", "file_path": "backend/src/app.py", - "start_line": 396, - "end_line": 439, + "start_line": 421, + "end_line": 464, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -18399,7 +19747,7 @@ "contract_type": "Module", "file_path": "backend/src/core/auth/config.py", "start_line": 1, - "end_line": 74, + "end_line": 73, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -18420,14 +19768,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region AuthConfigModule [C:2] [TYPE Module] [SEMANTICS pydantic, auth, auth-config, config]\n#\n# @BRIEF Centralized configuration for authentication and authorization.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> pydantic\n#\n# @INVARIANT: All sensitive configuration must be loaded from environment; no hardcoded secrets.\n# @RATIONALE SECRET_KEY and AUTH_DATABASE_URL now crash-early if env vars are missing.\n# Dev fallback for AUTH_DATABASE_URL only when DEV_MODE=true.\n# @REJECTED Default secrets in source code rejected — Class 1 security violation:\n# \"super-secret-key-change-in-production\" and \"postgres:postgres\" exposed\n# secrets in version control.\n\nimport os\n\nfrom pydantic import Field, field_validator\nfrom pydantic_settings import BaseSettings\n\n\n# #region AuthConfig [TYPE Class]\n# @BRIEF Holds authentication-related settings.\n# @PRE: Environment variables may be provided via .env file.\n# @POST: Returns a configuration object with validated settings.\n# @RELATION INHERITS -> pydantic_settings.BaseSettings\nclass AuthConfig(BaseSettings):\n # JWT Settings\n SECRET_KEY: str = Field(default=\"\", env=\"AUTH_SECRET_KEY\")\n ALGORITHM: str = \"HS256\"\n ACCESS_TOKEN_EXPIRE_MINUTES: int = 480\n REFRESH_TOKEN_EXPIRE_DAYS: int = 7\n\n # Database Settings\n AUTH_DATABASE_URL: str = Field(default=\"\", env=\"AUTH_DATABASE_URL\")\n\n # ADFS Settings\n ADFS_CLIENT_ID: str = Field(default=\"\", env=\"ADFS_CLIENT_ID\")\n ADFS_CLIENT_SECRET: str = Field(default=\"\", env=\"ADFS_CLIENT_SECRET\")\n ADFS_METADATA_URL: str = Field(default=\"\", env=\"ADFS_METADATA_URL\")\n\n @field_validator(\"SECRET_KEY\", mode=\"after\")\n @classmethod\n def validate_secret_key(cls, v: str) -> str:\n if v:\n return v\n raise ValueError(\n \"AUTH_SECRET_KEY environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n @field_validator(\"AUTH_DATABASE_URL\", mode=\"after\")\n @classmethod\n def validate_auth_db_url(cls, v: str) -> str:\n if v:\n return v\n is_dev = os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}\n if is_dev:\n return \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\n raise ValueError(\n \"AUTH_DATABASE_URL environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n class Config:\n env_file = \".env\"\n extra = \"ignore\"\n# #endregion AuthConfig\n\n# #region auth_config [TYPE Variable]\n# @BRIEF Singleton instance of AuthConfig.\n# @RELATION DEPENDS_ON -> AuthConfig\nauth_config = AuthConfig()\n# #endregion auth_config\n\n# #endregion AuthConfigModule\n" + "body": "# #region AuthConfigModule [C:2] [TYPE Module] [SEMANTICS pydantic, auth, auth-config, config]\n#\n# @BRIEF Centralized configuration for authentication and authorization.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> pydantic\n#\n# @INVARIANT: All sensitive configuration must be loaded from environment; no hardcoded secrets.\n# @RATIONALE SECRET_KEY and AUTH_DATABASE_URL now crash-early if env vars are missing.\n# Dev fallback for AUTH_DATABASE_URL only when DEV_MODE=true.\n# @REJECTED Default secrets in source code rejected — Class 1 security violation:\n# \"super-secret-key-change-in-production\" and \"postgres:postgres\" exposed\n# secrets in version control.\n\nimport os\n\nfrom pydantic import Field, field_validator\nfrom pydantic_settings import BaseSettings, SettingsConfigDict\n\n\n# #region AuthConfig [TYPE Class]\n# @BRIEF Holds authentication-related settings.\n# @PRE: Environment variables may be provided via .env file.\n# @POST: Returns a configuration object with validated settings.\n# @RELATION INHERITS -> pydantic_settings.BaseSettings\nclass AuthConfig(BaseSettings):\n model_config = SettingsConfigDict(env_file=\".env\", extra=\"ignore\")\n\n # JWT Settings\n SECRET_KEY: str = Field(default=\"\", validation_alias=\"AUTH_SECRET_KEY\")\n ALGORITHM: str = \"HS256\"\n ACCESS_TOKEN_EXPIRE_MINUTES: int = 480\n REFRESH_TOKEN_EXPIRE_DAYS: int = 7\n\n # Database Settings\n AUTH_DATABASE_URL: str = Field(default=\"\", validation_alias=\"AUTH_DATABASE_URL\")\n\n # ADFS Settings\n ADFS_CLIENT_ID: str = Field(default=\"\", validation_alias=\"ADFS_CLIENT_ID\")\n ADFS_CLIENT_SECRET: str = Field(default=\"\", validation_alias=\"ADFS_CLIENT_SECRET\")\n ADFS_METADATA_URL: str = Field(default=\"\", validation_alias=\"ADFS_METADATA_URL\")\n\n @field_validator(\"SECRET_KEY\", mode=\"after\")\n @classmethod\n def validate_secret_key(cls, v: str) -> str:\n if v:\n return v\n raise ValueError(\n \"AUTH_SECRET_KEY environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n @field_validator(\"AUTH_DATABASE_URL\", mode=\"after\")\n @classmethod\n def validate_auth_db_url(cls, v: str) -> str:\n if v:\n return v\n is_dev = os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}\n if is_dev:\n return \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\n raise ValueError(\n \"AUTH_DATABASE_URL environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n# #endregion AuthConfig\n\n# #region auth_config [TYPE Variable]\n# @BRIEF Singleton instance of AuthConfig.\n# @RELATION DEPENDS_ON -> AuthConfig\nauth_config = AuthConfig()\n# #endregion auth_config\n\n# #endregion AuthConfigModule\n" }, { "contract_id": "AuthConfig", "contract_type": "Class", "file_path": "backend/src/core/auth/config.py", "start_line": 20, - "end_line": 66, + "end_line": 65, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -18446,14 +19794,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region AuthConfig [TYPE Class]\n# @BRIEF Holds authentication-related settings.\n# @PRE: Environment variables may be provided via .env file.\n# @POST: Returns a configuration object with validated settings.\n# @RELATION INHERITS -> pydantic_settings.BaseSettings\nclass AuthConfig(BaseSettings):\n # JWT Settings\n SECRET_KEY: str = Field(default=\"\", env=\"AUTH_SECRET_KEY\")\n ALGORITHM: str = \"HS256\"\n ACCESS_TOKEN_EXPIRE_MINUTES: int = 480\n REFRESH_TOKEN_EXPIRE_DAYS: int = 7\n\n # Database Settings\n AUTH_DATABASE_URL: str = Field(default=\"\", env=\"AUTH_DATABASE_URL\")\n\n # ADFS Settings\n ADFS_CLIENT_ID: str = Field(default=\"\", env=\"ADFS_CLIENT_ID\")\n ADFS_CLIENT_SECRET: str = Field(default=\"\", env=\"ADFS_CLIENT_SECRET\")\n ADFS_METADATA_URL: str = Field(default=\"\", env=\"ADFS_METADATA_URL\")\n\n @field_validator(\"SECRET_KEY\", mode=\"after\")\n @classmethod\n def validate_secret_key(cls, v: str) -> str:\n if v:\n return v\n raise ValueError(\n \"AUTH_SECRET_KEY environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n @field_validator(\"AUTH_DATABASE_URL\", mode=\"after\")\n @classmethod\n def validate_auth_db_url(cls, v: str) -> str:\n if v:\n return v\n is_dev = os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}\n if is_dev:\n return \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\n raise ValueError(\n \"AUTH_DATABASE_URL environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n class Config:\n env_file = \".env\"\n extra = \"ignore\"\n# #endregion AuthConfig\n" + "body": "# #region AuthConfig [TYPE Class]\n# @BRIEF Holds authentication-related settings.\n# @PRE: Environment variables may be provided via .env file.\n# @POST: Returns a configuration object with validated settings.\n# @RELATION INHERITS -> pydantic_settings.BaseSettings\nclass AuthConfig(BaseSettings):\n model_config = SettingsConfigDict(env_file=\".env\", extra=\"ignore\")\n\n # JWT Settings\n SECRET_KEY: str = Field(default=\"\", validation_alias=\"AUTH_SECRET_KEY\")\n ALGORITHM: str = \"HS256\"\n ACCESS_TOKEN_EXPIRE_MINUTES: int = 480\n REFRESH_TOKEN_EXPIRE_DAYS: int = 7\n\n # Database Settings\n AUTH_DATABASE_URL: str = Field(default=\"\", validation_alias=\"AUTH_DATABASE_URL\")\n\n # ADFS Settings\n ADFS_CLIENT_ID: str = Field(default=\"\", validation_alias=\"ADFS_CLIENT_ID\")\n ADFS_CLIENT_SECRET: str = Field(default=\"\", validation_alias=\"ADFS_CLIENT_SECRET\")\n ADFS_METADATA_URL: str = Field(default=\"\", validation_alias=\"ADFS_METADATA_URL\")\n\n @field_validator(\"SECRET_KEY\", mode=\"after\")\n @classmethod\n def validate_secret_key(cls, v: str) -> str:\n if v:\n return v\n raise ValueError(\n \"AUTH_SECRET_KEY environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n @field_validator(\"AUTH_DATABASE_URL\", mode=\"after\")\n @classmethod\n def validate_auth_db_url(cls, v: str) -> str:\n if v:\n return v\n is_dev = os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}\n if is_dev:\n return \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\n raise ValueError(\n \"AUTH_DATABASE_URL environment variable is required. \"\n \"Set it in .env or export it before starting the server.\"\n )\n\n# #endregion AuthConfig\n" }, { "contract_id": "auth_config", "contract_type": "Variable", "file_path": "backend/src/core/auth/config.py", - "start_line": 68, - "end_line": 72, + "start_line": 67, + "end_line": 71, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20370,7 +21718,7 @@ "contract_type": "Module", "file_path": "backend/src/core/database.py", "start_line": 1, - "end_line": 765, + "end_line": 740, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -20391,25 +21739,19 @@ "relation_type": "DEPENDS_ON", "target_id": "auth_config", "target_ref": "[auth_config]" - }, - { - "source_id": "DatabaseModule", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "[ConnectionConfig]" } ], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatabaseModule [C:3] [TYPE Module] [SEMANTICS sqlalchemy, connection, session]\n#\n# @BRIEF Configures database connection and session management (PostgreSQL-first).\n# @LAYER: Infrastructure\n# @RELATION DEPENDS_ON -> [MappingModels]\n# @RELATION DEPENDS_ON -> [auth_config]\n# @RELATION DEPENDS_ON -> [ConnectionConfig]\n#\n# @INVARIANT: A single engine instance is used for the entire application.\n\nimport os\nfrom pathlib import Path\n\nfrom sqlalchemy import create_engine, inspect, text\nfrom sqlalchemy.orm import sessionmaker\n\n# Import models to ensure they're registered with Base\nfrom ..models import (\n assistant as _assistant_models, # noqa: F401\n auth as _auth_models, # noqa: F401\n clean_release as _clean_release_models, # noqa: F401\n config as _config_models, # noqa: F401\n connection as _connection_models, # noqa: F401\n dataset_review as _dataset_review_models, # noqa: F401\n llm as _llm_models, # noqa: F401\n profile as _profile_models, # noqa: F401\n task as _task_models, # noqa: F401\n)\nfrom ..models.connection import ConnectionConfig\nfrom ..models.mapping import Base\nfrom .auth.config import auth_config\nfrom .logger import belief_scope, logger\n\n# #region BASE_DIR [C:1] [TYPE Variable]\n# @BRIEF Base directory for the backend.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n# #endregion BASE_DIR\n\n# #region DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the main application database. Read from env; dev fallback only.\n# @RATIONALE DATABASE_URL reads from env (DATABASE_URL or POSTGRES_URL).\n# Crashes at import if unset in production; provides localhost fallback in dev.\n# @REJECTED Hardcoded postgres:postgres@localhost in source code rejected — exposes\n# database credentials in version control (Class 1 security violation).\n_DATABASE_URL = os.getenv(\"DATABASE_URL\") or os.getenv(\"POSTGRES_URL\")\nif _DATABASE_URL:\n DATABASE_URL = _DATABASE_URL\nelif os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}:\n DATABASE_URL = \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\nelse:\n raise RuntimeError(\n \"DATABASE_URL (or POSTGRES_URL) environment variable is required. \"\n \"Set it before starting the server.\"\n )\n# #endregion DATABASE_URL\n\n# #region TASKS_DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the tasks execution database.\n# Defaults to DATABASE_URL to keep task logs in the same PostgreSQL instance.\nTASKS_DATABASE_URL = os.getenv(\"TASKS_DATABASE_URL\", DATABASE_URL)\n# #endregion TASKS_DATABASE_URL\n\n# #region AUTH_DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the authentication database.\nAUTH_DATABASE_URL = os.getenv(\"AUTH_DATABASE_URL\", auth_config.AUTH_DATABASE_URL)\n# #endregion AUTH_DATABASE_URL\n\n\n# #region engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for mappings database.\n# @SIDE_EFFECT: Creates database engine and manages connection pool.\ndef _build_engine(db_url: str):\n with belief_scope(\"_build_engine\"):\n if db_url.startswith(\"sqlite\"):\n return create_engine(db_url, connect_args={\"check_same_thread\": False})\n return create_engine(db_url, pool_pre_ping=True)\n\n\nengine = _build_engine(DATABASE_URL)\n# #endregion engine\n\n# #region tasks_engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for tasks database.\ntasks_engine = _build_engine(TASKS_DATABASE_URL)\n# #endregion tasks_engine\n\n# #region auth_engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for authentication database.\nauth_engine = _build_engine(AUTH_DATABASE_URL)\n# #endregion auth_engine\n\n# #region SessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the main mappings database.\n# @PRE: engine is initialized.\nSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)\n# #endregion SessionLocal\n\n# #region TasksSessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the tasks execution database.\n# @PRE: tasks_engine is initialized.\nTasksSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=tasks_engine)\n# #endregion TasksSessionLocal\n\n# #region AuthSessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the authentication database.\n# @PRE: auth_engine is initialized.\nAuthSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=auth_engine)\n# #endregion AuthSessionLocal\n\n\n# #region _ensure_user_dashboard_preferences_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for user_dashboard_preferences table.\n# @PRE: bind_engine points to application database where profile table is stored.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_user_dashboard_preferences_columns(bind_engine):\n with belief_scope(\"_ensure_user_dashboard_preferences_columns\"):\n table_name = \"user_dashboard_preferences\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"git_username\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN git_username VARCHAR\"\n )\n if \"git_email\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN git_email VARCHAR\"\n )\n if \"git_personal_access_token_encrypted\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN git_personal_access_token_encrypted VARCHAR\"\n )\n if \"start_page\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN start_page VARCHAR NOT NULL DEFAULT 'dashboards'\"\n )\n if \"auto_open_task_drawer\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN auto_open_task_drawer BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n if \"dashboards_table_density\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN dashboards_table_density VARCHAR NOT NULL DEFAULT 'comfortable'\"\n )\n if \"show_only_slug_dashboards\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN show_only_slug_dashboards BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"Profile preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_user_dashboard_preferences_columns\n\n\n# #region _ensure_user_dashboard_preferences_health_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for user_dashboard_preferences table (health fields).\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_user_dashboard_preferences_health_columns(bind_engine):\n with belief_scope(\"_ensure_user_dashboard_preferences_health_columns\"):\n table_name = \"user_dashboard_preferences\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"telegram_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN telegram_id VARCHAR\"\n )\n if \"email_address\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN email_address VARCHAR\"\n )\n if \"notify_on_fail\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN notify_on_fail BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"Profile health preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_user_dashboard_preferences_health_columns\n\n\n# #region _ensure_llm_validation_results_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for llm_validation_results table.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_llm_validation_results_columns(bind_engine):\n with belief_scope(\"_ensure_llm_validation_results_columns\"):\n table_name = \"llm_validation_results\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"task_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE llm_validation_results ADD COLUMN task_id VARCHAR\"\n )\n if \"environment_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE llm_validation_results ADD COLUMN environment_id VARCHAR\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"ValidationRecord additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_llm_validation_results_columns\n\n\n# #region _ensure_git_server_configs_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for git_server_configs table.\n# @PRE: bind_engine points to application database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_git_server_configs_columns(bind_engine):\n with belief_scope(\"_ensure_git_server_configs_columns\"):\n table_name = \"git_server_configs\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"default_branch\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE git_server_configs ADD COLUMN default_branch VARCHAR NOT NULL DEFAULT 'main'\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"GitServerConfig preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_git_server_configs_columns\n\n\n# #region _ensure_auth_users_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for auth users table.\n# @PRE: bind_engine points to authentication database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [auth_engine]\ndef _ensure_auth_users_columns(bind_engine):\n with belief_scope(\"_ensure_auth_users_columns\"):\n table_name = \"users\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"full_name\" not in existing_columns:\n alter_statements.append(\"ALTER TABLE users ADD COLUMN full_name VARCHAR\")\n if \"is_ad_user\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE users ADD COLUMN is_ad_user BOOLEAN NOT NULL DEFAULT FALSE\"\n )\n\n if not alter_statements:\n logger.reason(\n \"Auth users schema already up to date\",\n extra={\"table\": table_name, \"columns\": sorted(existing_columns)},\n )\n return\n\n logger.reason(\n \"Applying additive auth users schema migration\",\n extra={\"table\": table_name, \"statements\": alter_statements},\n )\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n logger.reason(\n \"Auth users schema migration completed\",\n extra={\n \"table\": table_name,\n \"added_columns\": [\n stmt.split(\" ADD COLUMN \", 1)[1].split()[0]\n for stmt in alter_statements\n ],\n },\n )\n except Exception as migration_error:\n logger.explore(\n \"Auth users additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion _ensure_auth_users_columns\n\n\n# #region ensure_connection_configs_table [C:3] [TYPE Function]\n# @BRIEF Ensures the external connection registry table exists in the main database.\n# @PRE: bind_engine points to the application database.\n# @POST: connection_configs table exists without dropping existing data.\n# @RELATION DEPENDS_ON -> [ConnectionConfig]\ndef ensure_connection_configs_table(bind_engine):\n with belief_scope(\"ensure_connection_configs_table\"):\n try:\n ConnectionConfig.__table__.create(bind=bind_engine, checkfirst=True)\n except Exception as migration_error:\n logger.explore(\n \"ConnectionConfig table ensure failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion ensure_connection_configs_table\n\n\n# #region _ensure_filter_source_enum_values [C:3] [TYPE Function]\n# @BRIEF Adds missing FilterSource enum values to the PostgreSQL native filtersource type.\n# @PRE: bind_engine points to application database with imported_filters table.\n# @POST: New enum values are available without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_filter_source_enum_values(bind_engine):\n with belief_scope(\"_ensure_filter_source_enum_values\"):\n try:\n with bind_engine.connect() as connection:\n # Check if the native enum type exists\n result = connection.execute(\n text(\n \"SELECT t.typname FROM pg_type t \"\n \"JOIN pg_namespace n ON t.typnamespace = n.oid \"\n \"WHERE t.typname = 'filtersource' AND n.nspname = 'public'\"\n )\n )\n if result.fetchone() is None:\n logger.reason(\n \"filtersource enum type does not exist yet; skipping migration\"\n )\n return\n\n # Get existing enum values\n result = connection.execute(\n text(\n \"SELECT e.enumlabel FROM pg_enum e \"\n \"JOIN pg_type t ON e.enumtypid = t.oid \"\n \"WHERE t.typname = 'filtersource' \"\n \"ORDER BY e.enumsortorder\"\n )\n )\n existing_values = {row[0] for row in result.fetchall()}\n\n required_values = [\"SUPERSET_PERMALINK\", \"SUPERSET_NATIVE_FILTERS_KEY\"]\n missing_values = [\n v for v in required_values if v not in existing_values\n ]\n\n if not missing_values:\n logger.reason(\n \"filtersource enum already up to date\",\n extra={\"existing\": sorted(existing_values)},\n )\n return\n\n logger.reason(\n \"Adding missing values to filtersource enum\",\n extra={\"missing\": missing_values},\n )\n for value in missing_values:\n connection.execute(\n text(\n f\"ALTER TYPE filtersource ADD VALUE IF NOT EXISTS '{value}'\"\n )\n )\n connection.commit()\n logger.reason(\n \"filtersource enum migration completed\",\n extra={\"added\": missing_values},\n )\n except Exception as migration_error:\n logger.explore(\n \"FilterSource enum additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_filter_source_enum_values\n\n\n# #region _ensure_dataset_review_session_columns [C:4] [TYPE Function]\n# @BRIEF Apply additive schema upgrades for dataset review persistence required by optimistic-lock and recovery metadata semantics.\n# @PRE: bind_engine points to the application database where dataset review tables are stored.\n# @POST: Missing additive columns across legacy dataset review tables are created without removing existing data.\n# @SIDE_EFFECT: Executes ALTER TABLE statements against dataset review tables in the application database.\n# @RELATION DEPENDS_ON -> [DatasetReviewSession]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\ndef _ensure_translation_jobs_columns(bind_engine):\n with belief_scope(\"_ensure_translation_jobs_columns\"):\n table_name = \"translation_jobs\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n if \"environment_id\" not in existing_columns:\n try:\n with bind_engine.begin() as connection:\n connection.execute(\n text(\n \"ALTER TABLE translation_jobs \"\n \"ADD COLUMN environment_id VARCHAR\"\n )\n )\n logger.reflect(\n \"Added environment_id column to translation_jobs\",\n )\n except Exception as migration_error:\n logger.explore(\n \"Failed to add environment_id to translation_jobs\",\n extra={\"error\": str(migration_error)},\n )\n raise\n\n if \"target_database_id\" not in existing_columns:\n try:\n with bind_engine.begin() as connection:\n connection.execute(\n text(\n \"ALTER TABLE translation_jobs \"\n \"ADD COLUMN target_database_id VARCHAR\"\n )\n )\n logger.reflect(\n \"Added target_database_id column to translation_jobs\",\n )\n except Exception as migration_error:\n logger.explore(\n \"Failed to add target_database_id to translation_jobs\",\n extra={\"error\": str(migration_error)},\n )\n\n\ndef _ensure_dataset_review_session_columns(bind_engine):\n with belief_scope(\"_ensure_dataset_review_session_columns\"):\n inspector = inspect(bind_engine)\n existing_tables = set(inspector.get_table_names())\n migration_plan = {\n \"dataset_review_sessions\": [\n (\n \"version\",\n \"ALTER TABLE dataset_review_sessions \"\n \"ADD COLUMN version INTEGER NOT NULL DEFAULT 0\",\n )\n ],\n \"imported_filters\": [\n (\n \"raw_value_masked\",\n \"ALTER TABLE imported_filters \"\n \"ADD COLUMN raw_value_masked BOOLEAN NOT NULL DEFAULT FALSE\",\n )\n ],\n }\n\n for table_name, planned_columns in migration_plan.items():\n if table_name not in existing_tables:\n logger.reason(\n \"Dataset review table does not exist yet; skipping additive schema migration\",\n extra={\"table\": table_name},\n )\n continue\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n alter_statements = [\n statement\n for column_name, statement in planned_columns\n if column_name not in existing_columns\n ]\n\n if not alter_statements:\n logger.reason(\n \"Dataset review table schema already up to date\",\n extra={\"table\": table_name, \"columns\": sorted(existing_columns)},\n )\n continue\n\n logger.reason(\n \"Applying additive dataset review schema migration\",\n extra={\"table\": table_name, \"statements\": alter_statements},\n )\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n logger.reflect(\n \"Dataset review additive schema migration completed\",\n extra={\n \"table\": table_name,\n \"added_columns\": [\n stmt.split(\" ADD COLUMN \", 1)[1].split()[0]\n for stmt in alter_statements\n ],\n },\n )\n except Exception as migration_error:\n logger.explore(\n \"Dataset review additive schema migration failed\",\n extra={\"table\": table_name, \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion _ensure_dataset_review_session_columns\n\n\n# #region _ensure_translation_schedules_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for translation_schedules table.\n# @PRE: bind_engine points to application database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_translation_schedules_columns(bind_engine):\n with belief_scope(\"_ensure_translation_schedules_columns\"):\n table_name = \"translation_schedules\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"execution_mode\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE translation_schedules \"\n \"ADD COLUMN execution_mode VARCHAR NOT NULL DEFAULT 'full'\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"TranslationSchedule additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_translation_schedules_columns\n\n\n# #region _ensure_dictionary_entries_columns [C:3] [TYPE Function]\n# @BRIEF Additive migration for dictionary_entries origin tracking columns.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_dictionary_entries_columns(bind_engine):\n with belief_scope(\"_ensure_dictionary_entries_columns\"):\n table_name = \"dictionary_entries\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"origin_run_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_run_id VARCHAR\"\n )\n if \"origin_row_key\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_row_key VARCHAR\"\n )\n if \"origin_user_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_user_id VARCHAR\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"DictionaryEntry additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_dictionary_entries_columns\n\n\n# #region init_db [C:3] [TYPE Function]\n# @BRIEF Initializes the database by creating all tables.\n# @PRE: engine, tasks_engine and auth_engine are initialized.\n# @POST: Database tables created in all databases.\n# @SIDE_EFFECT: Creates physical database files if they don't exist.\n# @RELATION CALLS -> [ensure_connection_configs_table]\n# @RELATION CALLS -> [_ensure_filter_source_enum_values]\n# @RELATION CALLS -> [_ensure_dataset_review_session_columns]\n# @RELATION CALLS -> [_ensure_dictionary_entries_columns]\ndef init_db():\n with belief_scope(\"init_db\"):\n Base.metadata.create_all(bind=engine)\n Base.metadata.create_all(bind=tasks_engine)\n Base.metadata.create_all(bind=auth_engine)\n _ensure_user_dashboard_preferences_columns(engine)\n _ensure_llm_validation_results_columns(engine)\n _ensure_user_dashboard_preferences_health_columns(engine)\n _ensure_git_server_configs_columns(engine)\n _ensure_auth_users_columns(auth_engine)\n ensure_connection_configs_table(engine)\n _ensure_filter_source_enum_values(engine)\n _ensure_dataset_review_session_columns(engine)\n _ensure_translation_jobs_columns(engine)\n _ensure_translation_schedules_columns(engine)\n _ensure_dictionary_entries_columns(engine)\n\n\n# #endregion init_db\n\n\n# #region get_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting a database session.\n# @PRE: SessionLocal is initialized.\n# @POST: Session is closed after use.\n# @RELATION DEPENDS_ON -> [SessionLocal]\ndef get_db():\n with belief_scope(\"get_db\"):\n db = SessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_db\n\n\n# #region get_tasks_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting a tasks database session.\n# @PRE: TasksSessionLocal is initialized.\n# @POST: Session is closed after use.\n# @RELATION DEPENDS_ON -> [TasksSessionLocal]\ndef get_tasks_db():\n with belief_scope(\"get_tasks_db\"):\n db = TasksSessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_tasks_db\n\n\n# #region get_auth_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting an authentication database session.\n# @PRE: AuthSessionLocal is initialized.\n# @POST: Session is closed after use.\n# @DATA_CONTRACT: None -> Output[sqlalchemy.orm.Session]\n# @RELATION DEPENDS_ON -> [AuthSessionLocal]\ndef get_auth_db():\n with belief_scope(\"get_auth_db\"):\n db = AuthSessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_auth_db\n\n# #endregion DatabaseModule\n" + "body": "# #region DatabaseModule [C:3] [TYPE Module] [SEMANTICS sqlalchemy, connection, session]\n#\n# @BRIEF Configures database connection and session management (PostgreSQL-first).\n# @LAYER: Infrastructure\n# @RELATION DEPENDS_ON -> [MappingModels]\n# @RELATION DEPENDS_ON -> [auth_config]\n#\n# @INVARIANT: A single engine instance is used for the entire application.\n\nimport os\nfrom pathlib import Path\n\nfrom sqlalchemy import create_engine, inspect, text\nfrom sqlalchemy.orm import sessionmaker\n\n# Import models to ensure they're registered with Base\nfrom ..models import (\n assistant as _assistant_models, # noqa: F401\n auth as _auth_models, # noqa: F401\n clean_release as _clean_release_models, # noqa: F401\n config as _config_models, # noqa: F401\n dataset_review as _dataset_review_models, # noqa: F401\n llm as _llm_models, # noqa: F401\n profile as _profile_models, # noqa: F401\n task as _task_models, # noqa: F401\n)\nfrom ..models.mapping import Base\nfrom .auth.config import auth_config\nfrom .logger import belief_scope, logger\n\n# #region BASE_DIR [C:1] [TYPE Variable]\n# @BRIEF Base directory for the backend.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n# #endregion BASE_DIR\n\n# #region DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the main application database. Read from env; dev fallback only.\n# @RATIONALE DATABASE_URL reads from env (DATABASE_URL or POSTGRES_URL).\n# Crashes at import if unset in production; provides localhost fallback in dev.\n# @REJECTED Hardcoded postgres:postgres@localhost in source code rejected — exposes\n# database credentials in version control (Class 1 security violation).\n_DATABASE_URL = os.getenv(\"DATABASE_URL\") or os.getenv(\"POSTGRES_URL\")\nif _DATABASE_URL:\n DATABASE_URL = _DATABASE_URL\nelif os.getenv(\"DEV_MODE\", \"\").strip().lower() in {\"1\", \"true\", \"yes\"}:\n DATABASE_URL = \"postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools\"\nelse:\n raise RuntimeError(\n \"DATABASE_URL (or POSTGRES_URL) environment variable is required. \"\n \"Set it before starting the server.\"\n )\n# #endregion DATABASE_URL\n\n# #region TASKS_DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the tasks execution database.\n# Defaults to DATABASE_URL to keep task logs in the same PostgreSQL instance.\nTASKS_DATABASE_URL = os.getenv(\"TASKS_DATABASE_URL\", DATABASE_URL)\n# #endregion TASKS_DATABASE_URL\n\n# #region AUTH_DATABASE_URL [C:1] [TYPE Constant]\n# @BRIEF URL for the authentication database.\nAUTH_DATABASE_URL = os.getenv(\"AUTH_DATABASE_URL\", auth_config.AUTH_DATABASE_URL)\n# #endregion AUTH_DATABASE_URL\n\n\n# #region engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for mappings database.\n# @SIDE_EFFECT: Creates database engine and manages connection pool.\ndef _build_engine(db_url: str):\n with belief_scope(\"_build_engine\"):\n if db_url.startswith(\"sqlite\"):\n return create_engine(db_url, connect_args={\"check_same_thread\": False})\n return create_engine(db_url, pool_pre_ping=True)\n\n\nengine = _build_engine(DATABASE_URL)\n# #endregion engine\n\n# #region tasks_engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for tasks database.\ntasks_engine = _build_engine(TASKS_DATABASE_URL)\n# #endregion tasks_engine\n\n# #region auth_engine [C:1] [TYPE Variable]\n# @BRIEF SQLAlchemy engine for authentication database.\nauth_engine = _build_engine(AUTH_DATABASE_URL)\n# #endregion auth_engine\n\n# #region SessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the main mappings database.\n# @PRE: engine is initialized.\nSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)\n# #endregion SessionLocal\n\n# #region TasksSessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the tasks execution database.\n# @PRE: tasks_engine is initialized.\nTasksSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=tasks_engine)\n# #endregion TasksSessionLocal\n\n# #region AuthSessionLocal [C:1] [TYPE Class]\n# @BRIEF A session factory for the authentication database.\n# @PRE: auth_engine is initialized.\nAuthSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=auth_engine)\n# #endregion AuthSessionLocal\n\n\n# #region _ensure_user_dashboard_preferences_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for user_dashboard_preferences table.\n# @PRE: bind_engine points to application database where profile table is stored.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_user_dashboard_preferences_columns(bind_engine):\n with belief_scope(\"_ensure_user_dashboard_preferences_columns\"):\n table_name = \"user_dashboard_preferences\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"git_username\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN git_username VARCHAR\"\n )\n if \"git_email\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN git_email VARCHAR\"\n )\n if \"git_personal_access_token_encrypted\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN git_personal_access_token_encrypted VARCHAR\"\n )\n if \"start_page\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN start_page VARCHAR NOT NULL DEFAULT 'dashboards'\"\n )\n if \"auto_open_task_drawer\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN auto_open_task_drawer BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n if \"dashboards_table_density\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN dashboards_table_density VARCHAR NOT NULL DEFAULT 'comfortable'\"\n )\n if \"show_only_slug_dashboards\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences \"\n \"ADD COLUMN show_only_slug_dashboards BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"Profile preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_user_dashboard_preferences_columns\n\n\n# #region _ensure_user_dashboard_preferences_health_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for user_dashboard_preferences table (health fields).\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_user_dashboard_preferences_health_columns(bind_engine):\n with belief_scope(\"_ensure_user_dashboard_preferences_health_columns\"):\n table_name = \"user_dashboard_preferences\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"telegram_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN telegram_id VARCHAR\"\n )\n if \"email_address\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN email_address VARCHAR\"\n )\n if \"notify_on_fail\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE user_dashboard_preferences ADD COLUMN notify_on_fail BOOLEAN NOT NULL DEFAULT TRUE\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"Profile health preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_user_dashboard_preferences_health_columns\n\n\n# #region _ensure_llm_validation_results_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for llm_validation_results table.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_llm_validation_results_columns(bind_engine):\n with belief_scope(\"_ensure_llm_validation_results_columns\"):\n table_name = \"llm_validation_results\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"task_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE llm_validation_results ADD COLUMN task_id VARCHAR\"\n )\n if \"environment_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE llm_validation_results ADD COLUMN environment_id VARCHAR\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"ValidationRecord additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_llm_validation_results_columns\n\n\n# #region _ensure_git_server_configs_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for git_server_configs table.\n# @PRE: bind_engine points to application database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_git_server_configs_columns(bind_engine):\n with belief_scope(\"_ensure_git_server_configs_columns\"):\n table_name = \"git_server_configs\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"default_branch\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE git_server_configs ADD COLUMN default_branch VARCHAR NOT NULL DEFAULT 'main'\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"GitServerConfig preference additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_git_server_configs_columns\n\n\n# #region _ensure_auth_users_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for auth users table.\n# @PRE: bind_engine points to authentication database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [auth_engine]\ndef _ensure_auth_users_columns(bind_engine):\n with belief_scope(\"_ensure_auth_users_columns\"):\n table_name = \"users\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"full_name\" not in existing_columns:\n alter_statements.append(\"ALTER TABLE users ADD COLUMN full_name VARCHAR\")\n if \"is_ad_user\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE users ADD COLUMN is_ad_user BOOLEAN NOT NULL DEFAULT FALSE\"\n )\n\n if not alter_statements:\n logger.reason(\n \"Auth users schema already up to date\",\n extra={\"table\": table_name, \"columns\": sorted(existing_columns)},\n )\n return\n\n logger.reason(\n \"Applying additive auth users schema migration\",\n extra={\"table\": table_name, \"statements\": alter_statements},\n )\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n logger.reason(\n \"Auth users schema migration completed\",\n extra={\n \"table\": table_name,\n \"added_columns\": [\n stmt.split(\" ADD COLUMN \", 1)[1].split()[0]\n for stmt in alter_statements\n ],\n },\n )\n except Exception as migration_error:\n logger.explore(\n \"Auth users additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion _ensure_auth_users_columns\n\n\n# #region _ensure_filter_source_enum_values [C:3] [TYPE Function]\n# @BRIEF Adds missing FilterSource enum values to the PostgreSQL native filtersource type.\n# @PRE: bind_engine points to application database with imported_filters table.\n# @POST: New enum values are available without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_filter_source_enum_values(bind_engine):\n with belief_scope(\"_ensure_filter_source_enum_values\"):\n try:\n with bind_engine.connect() as connection:\n # Check if the native enum type exists\n result = connection.execute(\n text(\n \"SELECT t.typname FROM pg_type t \"\n \"JOIN pg_namespace n ON t.typnamespace = n.oid \"\n \"WHERE t.typname = 'filtersource' AND n.nspname = 'public'\"\n )\n )\n if result.fetchone() is None:\n logger.reason(\n \"filtersource enum type does not exist yet; skipping migration\"\n )\n return\n\n # Get existing enum values\n result = connection.execute(\n text(\n \"SELECT e.enumlabel FROM pg_enum e \"\n \"JOIN pg_type t ON e.enumtypid = t.oid \"\n \"WHERE t.typname = 'filtersource' \"\n \"ORDER BY e.enumsortorder\"\n )\n )\n existing_values = {row[0] for row in result.fetchall()}\n\n required_values = [\"SUPERSET_PERMALINK\", \"SUPERSET_NATIVE_FILTERS_KEY\"]\n missing_values = [\n v for v in required_values if v not in existing_values\n ]\n\n if not missing_values:\n logger.reason(\n \"filtersource enum already up to date\",\n extra={\"existing\": sorted(existing_values)},\n )\n return\n\n logger.reason(\n \"Adding missing values to filtersource enum\",\n extra={\"missing\": missing_values},\n )\n for value in missing_values:\n connection.execute(\n text(\n f\"ALTER TYPE filtersource ADD VALUE IF NOT EXISTS '{value}'\"\n )\n )\n connection.commit()\n logger.reason(\n \"filtersource enum migration completed\",\n extra={\"added\": missing_values},\n )\n except Exception as migration_error:\n logger.explore(\n \"FilterSource enum additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_filter_source_enum_values\n\n\n# #region _ensure_dataset_review_session_columns [C:4] [TYPE Function]\n# @BRIEF Apply additive schema upgrades for dataset review persistence required by optimistic-lock and recovery metadata semantics.\n# @PRE: bind_engine points to the application database where dataset review tables are stored.\n# @POST: Missing additive columns across legacy dataset review tables are created without removing existing data.\n# @SIDE_EFFECT: Executes ALTER TABLE statements against dataset review tables in the application database.\n# @RELATION DEPENDS_ON -> [DatasetReviewSession]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\ndef _ensure_translation_jobs_columns(bind_engine):\n with belief_scope(\"_ensure_translation_jobs_columns\"):\n table_name = \"translation_jobs\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n if \"environment_id\" not in existing_columns:\n try:\n with bind_engine.begin() as connection:\n connection.execute(\n text(\n \"ALTER TABLE translation_jobs \"\n \"ADD COLUMN environment_id VARCHAR\"\n )\n )\n logger.reflect(\n \"Added environment_id column to translation_jobs\",\n )\n except Exception as migration_error:\n logger.explore(\n \"Failed to add environment_id to translation_jobs\",\n extra={\"error\": str(migration_error)},\n )\n raise\n\n if \"target_database_id\" not in existing_columns:\n try:\n with bind_engine.begin() as connection:\n connection.execute(\n text(\n \"ALTER TABLE translation_jobs \"\n \"ADD COLUMN target_database_id VARCHAR\"\n )\n )\n logger.reflect(\n \"Added target_database_id column to translation_jobs\",\n )\n except Exception as migration_error:\n logger.explore(\n \"Failed to add target_database_id to translation_jobs\",\n extra={\"error\": str(migration_error)},\n )\n\n\ndef _ensure_dataset_review_session_columns(bind_engine):\n with belief_scope(\"_ensure_dataset_review_session_columns\"):\n inspector = inspect(bind_engine)\n existing_tables = set(inspector.get_table_names())\n migration_plan = {\n \"dataset_review_sessions\": [\n (\n \"version\",\n \"ALTER TABLE dataset_review_sessions \"\n \"ADD COLUMN version INTEGER NOT NULL DEFAULT 0\",\n )\n ],\n \"imported_filters\": [\n (\n \"raw_value_masked\",\n \"ALTER TABLE imported_filters \"\n \"ADD COLUMN raw_value_masked BOOLEAN NOT NULL DEFAULT FALSE\",\n )\n ],\n }\n\n for table_name, planned_columns in migration_plan.items():\n if table_name not in existing_tables:\n logger.reason(\n \"Dataset review table does not exist yet; skipping additive schema migration\",\n extra={\"table\": table_name},\n )\n continue\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n alter_statements = [\n statement\n for column_name, statement in planned_columns\n if column_name not in existing_columns\n ]\n\n if not alter_statements:\n logger.reason(\n \"Dataset review table schema already up to date\",\n extra={\"table\": table_name, \"columns\": sorted(existing_columns)},\n )\n continue\n\n logger.reason(\n \"Applying additive dataset review schema migration\",\n extra={\"table\": table_name, \"statements\": alter_statements},\n )\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n logger.reflect(\n \"Dataset review additive schema migration completed\",\n extra={\n \"table\": table_name,\n \"added_columns\": [\n stmt.split(\" ADD COLUMN \", 1)[1].split()[0]\n for stmt in alter_statements\n ],\n },\n )\n except Exception as migration_error:\n logger.explore(\n \"Dataset review additive schema migration failed\",\n extra={\"table\": table_name, \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion _ensure_dataset_review_session_columns\n\n\n# #region _ensure_translation_schedules_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for translation_schedules table.\n# @PRE: bind_engine points to application database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_translation_schedules_columns(bind_engine):\n with belief_scope(\"_ensure_translation_schedules_columns\"):\n table_name = \"translation_schedules\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"execution_mode\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE translation_schedules \"\n \"ADD COLUMN execution_mode VARCHAR NOT NULL DEFAULT 'full'\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"TranslationSchedule additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_translation_schedules_columns\n\n\n# #region _ensure_dictionary_entries_columns [C:3] [TYPE Function]\n# @BRIEF Additive migration for dictionary_entries origin tracking columns.\n# @RELATION DEPENDS_ON -> [engine]\ndef _ensure_dictionary_entries_columns(bind_engine):\n with belief_scope(\"_ensure_dictionary_entries_columns\"):\n table_name = \"dictionary_entries\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"origin_run_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_run_id VARCHAR\"\n )\n if \"origin_row_key\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_row_key VARCHAR\"\n )\n if \"origin_user_id\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE dictionary_entries \"\n \"ADD COLUMN origin_user_id VARCHAR\"\n )\n\n if not alter_statements:\n return\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n except Exception as migration_error:\n logger.explore(\n \"DictionaryEntry additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n\n\n# #endregion _ensure_dictionary_entries_columns\n\n\n# #region init_db [C:3] [TYPE Function]\n# @BRIEF Initializes the database by creating all tables.\n# @PRE: engine, tasks_engine and auth_engine are initialized.\n# @POST: Database tables created in all databases.\n# @SIDE_EFFECT: Creates physical database files if they don't exist.\n# @RELATION CALLS -> [_ensure_filter_source_enum_values]\n# @RELATION CALLS -> [_ensure_dataset_review_session_columns]\n# @RELATION CALLS -> [_ensure_dictionary_entries_columns]\ndef init_db():\n with belief_scope(\"init_db\"):\n Base.metadata.create_all(bind=engine)\n Base.metadata.create_all(bind=tasks_engine)\n Base.metadata.create_all(bind=auth_engine)\n _ensure_user_dashboard_preferences_columns(engine)\n _ensure_llm_validation_results_columns(engine)\n _ensure_user_dashboard_preferences_health_columns(engine)\n _ensure_git_server_configs_columns(engine)\n _ensure_auth_users_columns(auth_engine)\n _ensure_filter_source_enum_values(engine)\n _ensure_dataset_review_session_columns(engine)\n _ensure_translation_jobs_columns(engine)\n _ensure_translation_schedules_columns(engine)\n _ensure_dictionary_entries_columns(engine)\n\n\n# #endregion init_db\n\n\n# #region get_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting a database session.\n# @PRE: SessionLocal is initialized.\n# @POST: Session is closed after use.\n# @RELATION DEPENDS_ON -> [SessionLocal]\ndef get_db():\n with belief_scope(\"get_db\"):\n db = SessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_db\n\n\n# #region get_tasks_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting a tasks database session.\n# @PRE: TasksSessionLocal is initialized.\n# @POST: Session is closed after use.\n# @RELATION DEPENDS_ON -> [TasksSessionLocal]\ndef get_tasks_db():\n with belief_scope(\"get_tasks_db\"):\n db = TasksSessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_tasks_db\n\n\n# #region get_auth_db [C:3] [TYPE Function]\n# @BRIEF Dependency for getting an authentication database session.\n# @PRE: AuthSessionLocal is initialized.\n# @POST: Session is closed after use.\n# @DATA_CONTRACT: None -> Output[sqlalchemy.orm.Session]\n# @RELATION DEPENDS_ON -> [AuthSessionLocal]\ndef get_auth_db():\n with belief_scope(\"get_auth_db\"):\n db = AuthSessionLocal()\n try:\n yield db\n finally:\n db.close()\n\n\n# #endregion get_auth_db\n\n# #endregion DatabaseModule\n" }, { "contract_id": "BASE_DIR", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 34, - "end_line": 37, + "start_line": 31, + "end_line": 34, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20480,8 +21822,8 @@ "contract_id": "DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 39, - "end_line": 55, + "start_line": 36, + "end_line": 52, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20580,8 +21922,8 @@ "contract_id": "TASKS_DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 57, - "end_line": 61, + "start_line": 54, + "end_line": 58, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20652,8 +21994,8 @@ "contract_id": "AUTH_DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 63, - "end_line": 66, + "start_line": 60, + "end_line": 63, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20724,8 +22066,8 @@ "contract_id": "engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 69, - "end_line": 80, + "start_line": 66, + "end_line": 77, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20821,8 +22163,8 @@ "contract_id": "tasks_engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 82, - "end_line": 85, + "start_line": 79, + "end_line": 82, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20893,8 +22235,8 @@ "contract_id": "auth_engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 87, - "end_line": 90, + "start_line": 84, + "end_line": 87, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20965,8 +22307,8 @@ "contract_id": "SessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 92, - "end_line": 96, + "start_line": 89, + "end_line": 93, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20984,8 +22326,8 @@ "contract_id": "TasksSessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 98, - "end_line": 102, + "start_line": 95, + "end_line": 99, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21003,8 +22345,8 @@ "contract_id": "AuthSessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 104, - "end_line": 108, + "start_line": 101, + "end_line": 105, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21022,8 +22364,8 @@ "contract_id": "_ensure_user_dashboard_preferences_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 111, - "end_line": 177, + "start_line": 108, + "end_line": 174, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21049,8 +22391,8 @@ "contract_id": "_ensure_user_dashboard_preferences_health_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 180, - "end_line": 223, + "start_line": 177, + "end_line": 220, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21074,8 +22416,8 @@ "contract_id": "_ensure_llm_validation_results_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 226, - "end_line": 265, + "start_line": 223, + "end_line": 262, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21099,8 +22441,8 @@ "contract_id": "_ensure_git_server_configs_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 268, - "end_line": 305, + "start_line": 265, + "end_line": 302, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21126,8 +22468,8 @@ "contract_id": "_ensure_auth_users_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 308, - "end_line": 367, + "start_line": 305, + "end_line": 364, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21149,39 +22491,12 @@ "tier_source": "AutoCalculated", "body": "# #region _ensure_auth_users_columns [C:3] [TYPE Function]\n# @BRIEF Applies additive schema upgrades for auth users table.\n# @PRE: bind_engine points to authentication database.\n# @POST: Missing columns are added without data loss.\n# @RELATION DEPENDS_ON -> [auth_engine]\ndef _ensure_auth_users_columns(bind_engine):\n with belief_scope(\"_ensure_auth_users_columns\"):\n table_name = \"users\"\n inspector = inspect(bind_engine)\n if table_name not in inspector.get_table_names():\n return\n\n existing_columns = {\n str(column.get(\"name\") or \"\").strip()\n for column in inspector.get_columns(table_name)\n }\n\n alter_statements = []\n if \"full_name\" not in existing_columns:\n alter_statements.append(\"ALTER TABLE users ADD COLUMN full_name VARCHAR\")\n if \"is_ad_user\" not in existing_columns:\n alter_statements.append(\n \"ALTER TABLE users ADD COLUMN is_ad_user BOOLEAN NOT NULL DEFAULT FALSE\"\n )\n\n if not alter_statements:\n logger.reason(\n \"Auth users schema already up to date\",\n extra={\"table\": table_name, \"columns\": sorted(existing_columns)},\n )\n return\n\n logger.reason(\n \"Applying additive auth users schema migration\",\n extra={\"table\": table_name, \"statements\": alter_statements},\n )\n\n try:\n with bind_engine.begin() as connection:\n for statement in alter_statements:\n connection.execute(text(statement))\n logger.reason(\n \"Auth users schema migration completed\",\n extra={\n \"table\": table_name,\n \"added_columns\": [\n stmt.split(\" ADD COLUMN \", 1)[1].split()[0]\n for stmt in alter_statements\n ],\n },\n )\n except Exception as migration_error:\n logger.explore(\n \"Auth users additive migration failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion _ensure_auth_users_columns\n" }, - { - "contract_id": "ensure_connection_configs_table", - "contract_type": "Function", - "file_path": "backend/src/core/database.py", - "start_line": 370, - "end_line": 387, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "POST": "connection_configs table exists without dropping existing data.", - "PRE": "bind_engine points to the application database.", - "PURPOSE": "Ensures the external connection registry table exists in the main database." - }, - "relations": [ - { - "source_id": "ensure_connection_configs_table", - "relation_type": "DEPENDS_ON", - "target_id": "ConnectionConfig", - "target_ref": "[ConnectionConfig]" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ensure_connection_configs_table [C:3] [TYPE Function]\n# @BRIEF Ensures the external connection registry table exists in the main database.\n# @PRE: bind_engine points to the application database.\n# @POST: connection_configs table exists without dropping existing data.\n# @RELATION DEPENDS_ON -> [ConnectionConfig]\ndef ensure_connection_configs_table(bind_engine):\n with belief_scope(\"ensure_connection_configs_table\"):\n try:\n ConnectionConfig.__table__.create(bind=bind_engine, checkfirst=True)\n except Exception as migration_error:\n logger.explore(\n \"ConnectionConfig table ensure failed\",\n extra={\"src\": \"database\", \"error\": str(migration_error)},\n )\n raise\n\n\n# #endregion ensure_connection_configs_table\n" - }, { "contract_id": "_ensure_filter_source_enum_values", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 390, - "end_line": 458, + "start_line": 367, + "end_line": 435, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21207,8 +22522,8 @@ "contract_id": "_ensure_dataset_review_session_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 461, - "end_line": 591, + "start_line": 438, + "end_line": 568, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -21241,8 +22556,8 @@ "contract_id": "_ensure_translation_schedules_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 594, - "end_line": 632, + "start_line": 571, + "end_line": 609, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21268,8 +22583,8 @@ "contract_id": "_ensure_dictionary_entries_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 635, - "end_line": 681, + "start_line": 612, + "end_line": 658, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21293,8 +22608,8 @@ "contract_id": "init_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 684, - "end_line": 711, + "start_line": 661, + "end_line": 686, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21305,12 +22620,6 @@ "SIDE_EFFECT": "Creates physical database files if they don't exist." }, "relations": [ - { - "source_id": "init_db", - "relation_type": "CALLS", - "target_id": "ensure_connection_configs_table", - "target_ref": "[ensure_connection_configs_table]" - }, { "source_id": "init_db", "relation_type": "CALLS", @@ -21333,14 +22642,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region init_db [C:3] [TYPE Function]\n# @BRIEF Initializes the database by creating all tables.\n# @PRE: engine, tasks_engine and auth_engine are initialized.\n# @POST: Database tables created in all databases.\n# @SIDE_EFFECT: Creates physical database files if they don't exist.\n# @RELATION CALLS -> [ensure_connection_configs_table]\n# @RELATION CALLS -> [_ensure_filter_source_enum_values]\n# @RELATION CALLS -> [_ensure_dataset_review_session_columns]\n# @RELATION CALLS -> [_ensure_dictionary_entries_columns]\ndef init_db():\n with belief_scope(\"init_db\"):\n Base.metadata.create_all(bind=engine)\n Base.metadata.create_all(bind=tasks_engine)\n Base.metadata.create_all(bind=auth_engine)\n _ensure_user_dashboard_preferences_columns(engine)\n _ensure_llm_validation_results_columns(engine)\n _ensure_user_dashboard_preferences_health_columns(engine)\n _ensure_git_server_configs_columns(engine)\n _ensure_auth_users_columns(auth_engine)\n ensure_connection_configs_table(engine)\n _ensure_filter_source_enum_values(engine)\n _ensure_dataset_review_session_columns(engine)\n _ensure_translation_jobs_columns(engine)\n _ensure_translation_schedules_columns(engine)\n _ensure_dictionary_entries_columns(engine)\n\n\n# #endregion init_db\n" + "body": "# #region init_db [C:3] [TYPE Function]\n# @BRIEF Initializes the database by creating all tables.\n# @PRE: engine, tasks_engine and auth_engine are initialized.\n# @POST: Database tables created in all databases.\n# @SIDE_EFFECT: Creates physical database files if they don't exist.\n# @RELATION CALLS -> [_ensure_filter_source_enum_values]\n# @RELATION CALLS -> [_ensure_dataset_review_session_columns]\n# @RELATION CALLS -> [_ensure_dictionary_entries_columns]\ndef init_db():\n with belief_scope(\"init_db\"):\n Base.metadata.create_all(bind=engine)\n Base.metadata.create_all(bind=tasks_engine)\n Base.metadata.create_all(bind=auth_engine)\n _ensure_user_dashboard_preferences_columns(engine)\n _ensure_llm_validation_results_columns(engine)\n _ensure_user_dashboard_preferences_health_columns(engine)\n _ensure_git_server_configs_columns(engine)\n _ensure_auth_users_columns(auth_engine)\n _ensure_filter_source_enum_values(engine)\n _ensure_dataset_review_session_columns(engine)\n _ensure_translation_jobs_columns(engine)\n _ensure_translation_schedules_columns(engine)\n _ensure_dictionary_entries_columns(engine)\n\n\n# #endregion init_db\n" }, { "contract_id": "get_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 714, - "end_line": 728, + "start_line": 689, + "end_line": 703, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21366,8 +22675,8 @@ "contract_id": "get_tasks_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 731, - "end_line": 745, + "start_line": 706, + "end_line": 720, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21393,8 +22702,8 @@ "contract_id": "get_auth_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 748, - "end_line": 763, + "start_line": 723, + "end_line": 738, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -24971,7 +26280,7 @@ "contract_type": "Module", "file_path": "backend/src/core/superset_client/_datasets.py", "start_line": 1, - "end_line": 186, + "end_line": 205, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -25009,7 +26318,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SupersetDatasetsMixin [C:3] [TYPE Module] [SEMANTICS dataset, superset, search, superset-datasets-mixin]\n# @LAYER: Infra\n# @BRIEF Dataset domain mixin for SupersetClient — list, get, detail, update.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\nimport json\nfrom typing import Any, cast\n\nfrom ..logger import belief_scope, logger as app_logger\n\napp_logger = cast(Any, app_logger)\n# #region SupersetDatasetsMixin [C:3] [TYPE Class]\n# @BRIEF Mixin providing basic dataset CRUD operations (list, get, detail, update).\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\nclass SupersetDatasetsMixin:\n # #region SupersetClientGetDatasets [TYPE Function] [C:3]\n # @PURPOSE: Получает полный список датасетов, автоматически обрабатывая пагинацию.\n # @RELATION: CALLS -> [SupersetClientFetchAllPages]\n def get_datasets(self, query: dict | None = None) -> tuple[int, list[dict]]:\n with belief_scope(\"get_datasets\"):\n app_logger.info(\"[get_datasets][Enter] Fetching datasets.\")\n validated_query = self._validate_query_params(query)\n paginated_data = self._fetch_all_pages(\n endpoint=\"/dataset/\",\n pagination_options={\n \"base_query\": validated_query,\n \"results_field\": \"result\",\n },\n )\n total_count = len(paginated_data)\n app_logger.reflect(f\"Found {total_count} datasets.\", extra={\"src\": \"get_datasets\"})\n return total_count, paginated_data\n # #endregion SupersetClientGetDatasets\n # #region SupersetClientGetDatasetsSummary [TYPE Function] [C:3]\n # @PURPOSE: Fetches dataset metadata optimized for the Dataset Hub grid.\n # @RELATION: CALLS -> [SupersetClientGetDatasets]\n def get_datasets_summary(self) -> list[dict]:\n with belief_scope(\"SupersetClient.get_datasets_summary\"):\n query = {\"columns\": [\"id\", \"table_name\", \"schema\", \"database\"]}\n _, datasets = self.get_datasets(query=query)\n result = []\n for ds in datasets:\n result.append(\n {\n \"id\": ds.get(\"id\"),\n \"table_name\": ds.get(\"table_name\"),\n \"schema\": ds.get(\"schema\"),\n \"database\": ds.get(\"database\", {}).get(\n \"database_name\", \"Unknown\"\n ),\n }\n )\n return result\n # #endregion SupersetClientGetDatasetsSummary\n # #region SupersetClientGetDatasetDetail [TYPE Function] [C:3]\n # @PURPOSE: Fetches detailed dataset information including columns and linked dashboards.\n # @RELATION: CALLS -> [SupersetClientGetDataset]\n # @RELATION: CALLS -> [APIClient]\n def get_dataset_detail(self, dataset_id: int) -> dict:\n with belief_scope(\"SupersetClient.get_dataset_detail\", f\"id={dataset_id}\"):\n def as_bool(value, default=False):\n if value is None:\n return default\n if isinstance(value, bool):\n return value\n if isinstance(value, str):\n return value.strip().lower() in (\"1\", \"true\", \"yes\", \"y\", \"on\")\n return bool(value)\n response = self.get_dataset(dataset_id)\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n columns = dataset.get(\"columns\", [])\n column_info = []\n for col in columns:\n col_id = col.get(\"id\")\n if col_id is None:\n continue\n column_info.append(\n {\n \"id\": int(col_id),\n \"name\": col.get(\"column_name\"),\n \"type\": col.get(\"type\"),\n \"is_dttm\": as_bool(col.get(\"is_dttm\"), default=False),\n \"is_active\": as_bool(col.get(\"is_active\"), default=True),\n \"description\": col.get(\"description\", \"\"),\n }\n )\n linked_dashboards = []\n try:\n related_objects = self.network.request(\n method=\"GET\", endpoint=f\"/dataset/{dataset_id}/related_objects\"\n )\n if isinstance(related_objects, dict):\n if \"dashboards\" in related_objects:\n dashboards_data = related_objects[\"dashboards\"]\n elif \"result\" in related_objects and isinstance(\n related_objects[\"result\"], dict\n ):\n dashboards_data = related_objects[\"result\"].get(\"dashboards\", [])\n else:\n dashboards_data = []\n for dash in dashboards_data:\n if isinstance(dash, dict):\n dash_id = dash.get(\"id\")\n if dash_id is None:\n continue\n linked_dashboards.append(\n {\n \"id\": int(dash_id),\n \"title\": dash.get(\"dashboard_title\")\n or dash.get(\"title\", f\"Dashboard {dash_id}\"),\n \"slug\": dash.get(\"slug\"),\n }\n )\n else:\n try:\n dash_id = int(dash)\n except (TypeError, ValueError):\n continue\n linked_dashboards.append(\n {\"id\": dash_id, \"title\": f\"Dashboard {dash_id}\", \"slug\": None}\n )\n except Exception as e:\n app_logger.warning(\n f\"[get_dataset_detail][Warning] Failed to fetch related dashboards: {e}\"\n )\n linked_dashboards = []\n database_obj = dataset.get(\"database\")\n database_dict = database_obj if isinstance(database_obj, dict) else {}\n sql = dataset.get(\"sql\", \"\")\n result = {\n \"id\": dataset.get(\"id\"),\n \"table_name\": dataset.get(\"table_name\"),\n \"schema\": dataset.get(\"schema\"),\n \"database\": database_dict,\n \"database_id\": dataset.get(\"database_id\", database_dict.get(\"id\")),\n \"database_backend\": database_dict.get(\"backend\") or database_dict.get(\"engine\") or \"\",\n \"description\": dataset.get(\"description\", \"\"),\n \"columns\": column_info,\n \"column_count\": len(column_info),\n \"sql\": sql,\n \"linked_dashboards\": linked_dashboards,\n \"linked_dashboard_count\": len(linked_dashboards),\n \"is_sqllab_view\": as_bool(dataset.get(\"is_sqllab_view\"), default=False),\n \"created_on\": dataset.get(\"created_on\"),\n \"changed_on\": dataset.get(\"changed_on\"),\n }\n app_logger.reflect(\n f\"Got dataset {dataset_id} with {len(column_info)} columns and {len(linked_dashboards)} linked dashboards\",\n extra={\"src\": \"get_dataset_detail\"},\n )\n return result\n # #endregion SupersetClientGetDatasetDetail\n # #region SupersetClientGetDataset [TYPE Function] [C:3]\n # @PURPOSE: Получает информацию о конкретном датасете по его ID.\n # @RELATION: CALLS -> [APIClient]\n def get_dataset(self, dataset_id: int) -> dict:\n with belief_scope(\"SupersetClient.get_dataset\", f\"id={dataset_id}\"):\n app_logger.info(\"[get_dataset][Enter] Fetching dataset %s.\", dataset_id)\n response = self.network.request(\n method=\"GET\", endpoint=f\"/dataset/{dataset_id}\"\n )\n response = cast(dict, response)\n app_logger.reflect(f\"Got dataset {dataset_id}.\", extra={\"src\": \"get_dataset\"})\n return response\n # #endregion SupersetClientGetDataset\n # #region SupersetClientUpdateDataset [TYPE Function] [C:3]\n # @PURPOSE: Обновляет данные датасета по его ID.\n # @SIDE_EFFECT: Modifies resource in upstream Superset environment.\n # @RELATION: CALLS -> [APIClient]\n def update_dataset(self, dataset_id: int, data: dict) -> dict:\n with belief_scope(\"SupersetClient.update_dataset\", f\"id={dataset_id}\"):\n app_logger.info(\"[update_dataset][Enter] Updating dataset %s.\", dataset_id)\n response = self.network.request(\n method=\"PUT\",\n endpoint=f\"/dataset/{dataset_id}\",\n data=json.dumps(data),\n headers={\"Content-Type\": \"application/json\"},\n )\n response = cast(dict, response)\n app_logger.reflect(f\"Updated dataset {dataset_id}.\", extra={\"src\": \"update_dataset\"})\n return response\n # #endregion SupersetClientUpdateDataset\n# #endregion SupersetDatasetsMixin\n# #endregion SupersetDatasetsMixin\n" + "body": "# #region SupersetDatasetsMixin [C:3] [TYPE Module] [SEMANTICS dataset, superset, search, superset-datasets-mixin]\n# @LAYER: Infra\n# @BRIEF Dataset domain mixin for SupersetClient — list, get, detail, update.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\nimport json\nfrom typing import Any, cast\n\nfrom ..logger import belief_scope, logger as app_logger\n\napp_logger = cast(Any, app_logger)\n# #region SupersetDatasetsMixin [C:3] [TYPE Class]\n# @BRIEF Mixin providing basic dataset CRUD operations (list, get, detail, update).\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\nclass SupersetDatasetsMixin:\n # #region SupersetClientGetDatasets [TYPE Function] [C:3]\n # @PURPOSE: Получает полный список датасетов, автоматически обрабатывая пагинацию.\n # @RELATION: CALLS -> [SupersetClientFetchAllPages]\n def get_datasets(self, query: dict | None = None) -> tuple[int, list[dict]]:\n with belief_scope(\"get_datasets\"):\n app_logger.info(\"[get_datasets][Enter] Fetching datasets.\")\n validated_query = self._validate_query_params(query)\n paginated_data = self._fetch_all_pages(\n endpoint=\"/dataset/\",\n pagination_options={\n \"base_query\": validated_query,\n \"results_field\": \"result\",\n },\n )\n total_count = len(paginated_data)\n app_logger.reflect(f\"Found {total_count} datasets.\", extra={\"src\": \"get_datasets\"})\n return total_count, paginated_data\n # #endregion SupersetClientGetDatasets\n # #region SupersetClientGetDatasetsSummary [TYPE Function] [C:3]\n # @PURPOSE: Fetches dataset metadata optimized for the Dataset Hub grid.\n # @RELATION: CALLS -> [SupersetClientGetDatasets]\n def get_datasets_summary(self) -> list[dict]:\n with belief_scope(\"SupersetClient.get_datasets_summary\"):\n query = {\"columns\": [\"id\", \"table_name\", \"schema\", \"database\"]}\n _, datasets = self.get_datasets(query=query)\n result = []\n for ds in datasets:\n result.append(\n {\n \"id\": ds.get(\"id\"),\n \"table_name\": ds.get(\"table_name\"),\n \"schema\": ds.get(\"schema\"),\n \"database\": ds.get(\"database\", {}).get(\n \"database_name\", \"Unknown\"\n ),\n }\n )\n return result\n # #endregion SupersetClientGetDatasetsSummary\n # #region SupersetClientGetDatasetDetail [TYPE Function] [C:3]\n # @PURPOSE: Fetches detailed dataset information including columns and linked dashboards.\n # @RELATION: CALLS -> [SupersetClientGetDataset]\n # @RELATION: CALLS -> [APIClient]\n def get_dataset_detail(self, dataset_id: int) -> dict:\n with belief_scope(\"SupersetClient.get_dataset_detail\", f\"id={dataset_id}\"):\n def as_bool(value, default=False):\n if value is None:\n return default\n if isinstance(value, bool):\n return value\n if isinstance(value, str):\n return value.strip().lower() in (\"1\", \"true\", \"yes\", \"y\", \"on\")\n return bool(value)\n response = self.get_dataset(dataset_id)\n if isinstance(response, dict) and \"result\" in response:\n dataset = response[\"result\"]\n else:\n dataset = response\n columns = dataset.get(\"columns\", [])\n column_info = []\n for col in columns:\n col_id = col.get(\"id\")\n if col_id is None:\n continue\n column_info.append(\n {\n \"id\": int(col_id),\n \"name\": col.get(\"column_name\"),\n \"type\": col.get(\"type\"),\n \"is_dttm\": as_bool(col.get(\"is_dttm\"), default=False),\n \"is_active\": as_bool(col.get(\"is_active\"), default=True),\n \"description\": col.get(\"description\", \"\"),\n }\n )\n metrics = dataset.get(\"metrics\", [])\n metric_info = []\n for metric in metrics:\n metric_id = metric.get(\"id\")\n if metric_id is None:\n continue\n metric_info.append(\n {\n \"id\": int(metric_id),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\", \"\"),\n \"metric_type\": metric.get(\"metric_type\"),\n }\n )\n linked_dashboards = []\n try:\n related_objects = self.network.request(\n method=\"GET\", endpoint=f\"/dataset/{dataset_id}/related_objects\"\n )\n if isinstance(related_objects, dict):\n if \"dashboards\" in related_objects:\n dashboards_data = related_objects[\"dashboards\"]\n elif \"result\" in related_objects and isinstance(\n related_objects[\"result\"], dict\n ):\n dashboards_data = related_objects[\"result\"].get(\"dashboards\", [])\n else:\n dashboards_data = []\n for dash in dashboards_data:\n if isinstance(dash, dict):\n dash_id = dash.get(\"id\")\n if dash_id is None:\n continue\n linked_dashboards.append(\n {\n \"id\": int(dash_id),\n \"title\": dash.get(\"dashboard_title\")\n or dash.get(\"title\", f\"Dashboard {dash_id}\"),\n \"slug\": dash.get(\"slug\"),\n }\n )\n else:\n try:\n dash_id = int(dash)\n except (TypeError, ValueError):\n continue\n linked_dashboards.append(\n {\"id\": dash_id, \"title\": f\"Dashboard {dash_id}\", \"slug\": None}\n )\n except Exception as e:\n app_logger.warning(\n f\"[get_dataset_detail][Warning] Failed to fetch related dashboards: {e}\"\n )\n linked_dashboards = []\n database_obj = dataset.get(\"database\")\n database_dict = database_obj if isinstance(database_obj, dict) else {}\n sql = dataset.get(\"sql\", \"\")\n result = {\n \"id\": dataset.get(\"id\"),\n \"table_name\": dataset.get(\"table_name\"),\n \"schema\": dataset.get(\"schema\"),\n \"database\": database_dict,\n \"database_id\": dataset.get(\"database_id\", database_dict.get(\"id\")),\n \"database_backend\": database_dict.get(\"backend\") or database_dict.get(\"engine\") or \"\",\n \"description\": dataset.get(\"description\", \"\"),\n \"columns\": column_info,\n \"column_count\": len(column_info),\n \"metrics\": metric_info,\n \"metric_count\": len(metric_info),\n \"sql\": sql,\n \"linked_dashboards\": linked_dashboards,\n \"linked_dashboard_count\": len(linked_dashboards),\n \"is_sqllab_view\": as_bool(dataset.get(\"is_sqllab_view\"), default=False),\n \"created_on\": dataset.get(\"created_on\"),\n \"changed_on\": dataset.get(\"changed_on\"),\n }\n app_logger.reflect(\n f\"Got dataset {dataset_id} with {len(column_info)} columns, {len(metric_info)} metrics, and {len(linked_dashboards)} linked dashboards\",\n extra={\"src\": \"get_dataset_detail\"},\n )\n return result\n # #endregion SupersetClientGetDatasetDetail\n # #region SupersetClientGetDataset [TYPE Function] [C:3]\n # @PURPOSE: Получает информацию о конкретном датасете по его ID.\n # @RELATION: CALLS -> [APIClient]\n def get_dataset(self, dataset_id: int) -> dict:\n with belief_scope(\"SupersetClient.get_dataset\", f\"id={dataset_id}\"):\n app_logger.info(\"[get_dataset][Enter] Fetching dataset %s.\", dataset_id)\n response = self.network.request(\n method=\"GET\", endpoint=f\"/dataset/{dataset_id}\"\n )\n response = cast(dict, response)\n app_logger.reflect(f\"Got dataset {dataset_id}.\", extra={\"src\": \"get_dataset\"})\n return response\n # #endregion SupersetClientGetDataset\n # #region SupersetClientUpdateDataset [TYPE Function] [C:3]\n # @PURPOSE: Обновляет данные датасета по его ID.\n # @SIDE_EFFECT: Modifies resource in upstream Superset environment.\n # @RELATION: CALLS -> [APIClient]\n def update_dataset(self, dataset_id: int, data: dict, override_columns: bool = False) -> dict:\n with belief_scope(\"SupersetClient.update_dataset\", f\"id={dataset_id}\"):\n app_logger.info(\"[update_dataset][Enter] Updating dataset %s.\", dataset_id)\n endpoint = f\"/dataset/{dataset_id}?override_columns={'true' if override_columns else 'false'}\"\n response = self.network.request(\n method=\"PUT\",\n endpoint=endpoint,\n data=json.dumps(data),\n headers={\"Content-Type\": \"application/json\"},\n )\n response = cast(dict, response)\n app_logger.reflect(f\"Updated dataset {dataset_id}.\", extra={\"src\": \"update_dataset\"})\n return response\n # #endregion SupersetClientUpdateDataset\n# #endregion SupersetDatasetsMixin\n# #endregion SupersetDatasetsMixin\n" }, { "contract_id": "SupersetDatasetsPreviewMixin", @@ -26421,7 +27730,7 @@ "contract_type": "Module", "file_path": "backend/src/core/task_manager/lifecycle.py", "start_line": 1, - "end_line": 313, + "end_line": 352, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -26432,14 +27741,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region JobLifecycleModule [C:5] [TYPE Module] [SEMANTICS task,lifecycle,state,machine,execution]\n# @BRIEF Task creation, execution, pause/resume, and completion transitions for plugin-backed\n# jobs — extracted from the monolithic TaskManager.\n# @LAYER Core\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RATIONALE Extracted from TaskManager to satisfy INV_7. JobLifecycle encodes the task state\n# machine with plugin execution, context injection, backward-compatible plugin\n# dispatch, and input/mapping pause/resume transitions.\n# @REJECTED Keeping lifecycle/execution logic inside TaskManager was rejected — it mixes\n# async execution orchestration with passive registry and log buffering concerns,\n# violating single-responsibility and INV_7.\n# @PRE Requested plugin ids resolve to executable plugins; task state transitions target known\n# TaskStatus values.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @SIDE_EFFECT Schedules async execution, pauses on input/mapping requests, mutates persisted\n# task lifecycle markers.\n# @INVARIANT A task cannot be resumed from a waiting state unless a matching future exists or\n# a new wait future is created.\n\nimport asyncio\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import UTC, datetime\nimport inspect\nfrom typing import Any\n\nfrom ..cot_logger import seed_trace_id\nfrom ..logger import belief_scope, logger\nfrom .context import TaskContext\nfrom .graph import TaskGraph\nfrom .models import Task, TaskStatus\n\n\n# #region JobLifecycle [C:5] [TYPE Class] [SEMANTICS task,lifecycle,execution,state,machine]\n# @BRIEF Encodes task creation, execution, pause/resume, and completion transitions for\n# plugin-backed jobs.\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @PRE plugin_loader resolves plugin ids; graph and event_bus are initialized.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @RATIONALE Extracted as standalone lifecycle state machine to isolate async execution\n# orchestration (plugin dispatch, context injection, pause/resume futures) from\n# passive registry and log buffering concerns.\n# @REJECTED Keeping execution logic inside TaskManager was rejected — it mixed async task\n# orchestration with synchronous registry operations and background threading,\n# violating single-responsibility and making the 708-line module unmaintainable.\nclass JobLifecycle:\n \"\"\"Task state machine: creation, execution, pause/resume, completion.\"\"\"\n\n # #region __init__ [TYPE Function]\n # @BRIEF Initialize with dependencies.\n def __init__(\n self,\n plugin_loader: Any,\n graph: TaskGraph,\n event_bus: Any,\n persistence_service: Any,\n executor: ThreadPoolExecutor,\n loop: asyncio.AbstractEventLoop,\n ):\n self.plugin_loader = plugin_loader\n self.graph = graph\n self.event_bus = event_bus\n self.persistence_service = persistence_service\n self.executor = executor\n self.loop = loop\n # #endregion __init__\n\n # #region create_task [C:4] [TYPE Function] [SEMANTICS task,create,persist,schedule]\n # @BRIEF Creates and queues a new task for execution.\n # @PRE Plugin with plugin_id exists. Params are valid dict.\n # @POST Task is created, added to registry, and scheduled for execution.\n # @RAISES ValueError if plugin not found or params invalid.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None,\n add_log_callback=None,\n ) -> Task:\n with belief_scope(\"JobLifecycle.create_task\", f\"plugin_id={plugin_id}\"):\n if not self.plugin_loader.has_plugin(plugin_id):\n logger.error(f\"Plugin with ID '{plugin_id}' not found.\")\n raise ValueError(f\"Plugin with ID '{plugin_id}' not found.\")\n self.plugin_loader.get_plugin(plugin_id)\n if not isinstance(params, dict):\n logger.error(\"Task parameters must be a dictionary.\")\n raise ValueError(\"Task parameters must be a dictionary.\")\n logger.reason(\"Creating task node and scheduling execution\")\n task = Task(plugin_id=plugin_id, params=params, user_id=user_id)\n self.graph.add_task(task)\n self.persistence_service.persist_task(task)\n logger.info(f\"Task {task.id} created and scheduled for execution\")\n self.loop.create_task(\n self._run_task(task.id, add_log_callback=add_log_callback)\n )\n logger.reflect(\n \"Task creation persisted and execution scheduled\",\n extra={\"task_id\": task.id, \"plugin_id\": plugin_id},\n )\n return task\n # #endregion create_task\n\n # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # #endregion _run_task\n\n # #region resolve_task [C:3] [TYPE Function] [SEMANTICS task,resolve,mapping,resume]\n # @BRIEF Resumes a task that is awaiting mapping.\n # @PRE Task exists and is in AWAITING_MAPPING state.\n # @POST Task status updated to RUNNING, params updated, execution resumed.\n # @RAISES ValueError if task not found or not awaiting mapping.\n async def resolve_task(\n self, task_id: str, resolution_params: dict[str, Any],\n ) -> None:\n with belief_scope(\"JobLifecycle.resolve_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task or task.status != TaskStatus.AWAITING_MAPPING:\n raise ValueError(\"Task is not awaiting mapping.\")\n task.params.update(resolution_params)\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n self.graph.resolve_future(task_id, True)\n # #endregion resolve_task\n\n # #region wait_for_resolution [C:3] [TYPE Function] [SEMANTICS task,wait,mapping,future]\n # @BRIEF Pauses execution and waits for a resolution signal.\n # @PRE Task exists.\n # @POST Execution pauses until future is set.\n async def wait_for_resolution(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_resolution\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n task.status = TaskStatus.AWAITING_MAPPING\n self.persistence_service.persist_task(task)\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [C:3] [TYPE Function] [SEMANTICS task,wait,input,future]\n # @BRIEF Pauses execution and waits for user input.\n # @PRE Task exists.\n # @POST Execution pauses until future is set via resume_task_with_password.\n async def wait_for_input(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_input\n\n # #region await_input [C:3] [TYPE Function] [SEMANTICS task,input,pause,state]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n # @PRE Task exists and is in RUNNING state.\n # @POST Task status changed to AWAITING_INPUT, input_request set, persisted.\n # @RAISES ValueError if task not found or not RUNNING.\n def await_input(\n self, task_id: str, input_request: dict[str, Any],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\"JobLifecycle.await_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.RUNNING:\n raise ValueError(\n f\"Task {task_id} is not RUNNING (current: {task.status})\"\n )\n task.status = TaskStatus.AWAITING_INPUT\n task.input_required = True\n task.input_request = input_request\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task paused for user input\",\n metadata={\"input_request\": input_request},\n )\n # #endregion await_input\n\n # #region resume_task_with_password [C:3] [TYPE Function] [SEMANTICS task,resume,password,input]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n # @PRE Task exists and is in AWAITING_INPUT state.\n # @POST Task status changed to RUNNING, passwords injected, task resumed.\n # @RAISES ValueError if task not found, not awaiting input, or passwords invalid.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\n \"JobLifecycle.resume_task_with_password\", f\"task_id={task_id}\"\n ):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.AWAITING_INPUT:\n raise ValueError(\n f\"Task {task_id} is not AWAITING_INPUT (current: {task.status})\"\n )\n if not isinstance(passwords, dict) or not passwords:\n raise ValueError(\"Passwords must be a non-empty dictionary\")\n task.params[\"passwords\"] = passwords\n task.input_required = False\n task.input_request = None\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task resumed with passwords\",\n metadata={\"databases\": list(passwords.keys())},\n )\n self.graph.resolve_future(task_id, True)\n # #endregion resume_task_with_password\n# #endregion JobLifecycle\n# #endregion JobLifecycleModule\n" + "body": "# #region JobLifecycleModule [C:5] [TYPE Module] [SEMANTICS task,lifecycle,state,machine,execution]\n# @BRIEF Task creation, execution, pause/resume, and completion transitions for plugin-backed\n# jobs — extracted from the monolithic TaskManager.\n# @LAYER Core\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RATIONALE Extracted from TaskManager to satisfy INV_7. JobLifecycle encodes the task state\n# machine with plugin execution, context injection, backward-compatible plugin\n# dispatch, and input/mapping pause/resume transitions.\n# @REJECTED Keeping lifecycle/execution logic inside TaskManager was rejected — it mixes\n# async execution orchestration with passive registry and log buffering concerns,\n# violating single-responsibility and INV_7.\n# @PRE Requested plugin ids resolve to executable plugins; task state transitions target known\n# TaskStatus values.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @SIDE_EFFECT Schedules async execution, pauses on input/mapping requests, mutates persisted\n# task lifecycle markers.\n# @INVARIANT A task cannot be resumed from a waiting state unless a matching future exists or\n# a new wait future is created.\n\nimport asyncio\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import UTC, datetime\nimport inspect\nfrom typing import Any\n\nfrom ..cot_logger import seed_trace_id\nfrom ..logger import belief_scope, logger\nfrom .context import TaskContext\nfrom .graph import TaskGraph\nfrom .models import Task, TaskStatus\n\n\n# #region JobLifecycle [C:5] [TYPE Class] [SEMANTICS task,lifecycle,execution,state,machine]\n# @BRIEF Encodes task creation, execution, pause/resume, and completion transitions for\n# plugin-backed jobs.\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @PRE plugin_loader resolves plugin ids; graph and event_bus are initialized.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @RATIONALE Extracted as standalone lifecycle state machine to isolate async execution\n# orchestration (plugin dispatch, context injection, pause/resume futures) from\n# passive registry and log buffering concerns.\n# @REJECTED Keeping execution logic inside TaskManager was rejected — it mixed async task\n# orchestration with synchronous registry operations and background threading,\n# violating single-responsibility and making the 708-line module unmaintainable.\nclass JobLifecycle:\n \"\"\"Task state machine: creation, execution, pause/resume, completion.\"\"\"\n\n # #region __init__ [TYPE Function]\n # @BRIEF Initialize with dependencies.\n def __init__(\n self,\n plugin_loader: Any,\n graph: TaskGraph,\n event_bus: Any,\n persistence_service: Any,\n executor: ThreadPoolExecutor,\n loop: asyncio.AbstractEventLoop,\n ):\n self.plugin_loader = plugin_loader\n self.graph = graph\n self.event_bus = event_bus\n self.persistence_service = persistence_service\n self.executor = executor\n self.loop = loop\n self._dataset_subscribers: dict[str, list[asyncio.Queue]] = {}\n # #endregion __init__\n\n # #region create_task [C:4] [TYPE Function] [SEMANTICS task,create,persist,schedule]\n # @BRIEF Creates and queues a new task for execution.\n # @PRE Plugin with plugin_id exists. Params are valid dict.\n # @POST Task is created, added to registry, and scheduled for execution.\n # @RAISES ValueError if plugin not found or params invalid.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None,\n add_log_callback=None,\n ) -> Task:\n with belief_scope(\"JobLifecycle.create_task\", f\"plugin_id={plugin_id}\"):\n if not self.plugin_loader.has_plugin(plugin_id):\n logger.error(f\"Plugin with ID '{plugin_id}' not found.\")\n raise ValueError(f\"Plugin with ID '{plugin_id}' not found.\")\n self.plugin_loader.get_plugin(plugin_id)\n if not isinstance(params, dict):\n logger.error(\"Task parameters must be a dictionary.\")\n raise ValueError(\"Task parameters must be a dictionary.\")\n logger.reason(\"Creating task node and scheduling execution\")\n task = Task(plugin_id=plugin_id, params=params, user_id=user_id)\n self.graph.add_task(task)\n self.persistence_service.persist_task(task)\n logger.info(f\"Task {task.id} created and scheduled for execution\")\n self.loop.create_task(\n self._run_task(task.id, add_log_callback=add_log_callback)\n )\n logger.reflect(\n \"Task creation persisted and execution scheduled\",\n extra={\"task_id\": task.id, \"plugin_id\": plugin_id},\n )\n return task\n # #endregion create_task\n\n # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # Broadcast dataset.updated for mapping and documentation tasks (FR-024, R4)\n if task.plugin_id in (\"dataset-mapper\", \"llm_documentation\"):\n dataset_ids = task.params.get(\"dataset_ids\") or [task.params.get(\"dataset_id\")]\n env_id = task.params.get(\"env\") or task.params.get(\"environment_id\", \"\")\n if dataset_ids and env_id:\n self._broadcast_dataset_updated(env_id, dataset_ids)\n # #endregion _run_task\n\n # #region resolve_task [C:3] [TYPE Function] [SEMANTICS task,resolve,mapping,resume]\n # @BRIEF Resumes a task that is awaiting mapping.\n # @PRE Task exists and is in AWAITING_MAPPING state.\n # @POST Task status updated to RUNNING, params updated, execution resumed.\n # @RAISES ValueError if task not found or not awaiting mapping.\n async def resolve_task(\n self, task_id: str, resolution_params: dict[str, Any],\n ) -> None:\n with belief_scope(\"JobLifecycle.resolve_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task or task.status != TaskStatus.AWAITING_MAPPING:\n raise ValueError(\"Task is not awaiting mapping.\")\n task.params.update(resolution_params)\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n self.graph.resolve_future(task_id, True)\n # #endregion resolve_task\n\n # #region wait_for_resolution [C:3] [TYPE Function] [SEMANTICS task,wait,mapping,future]\n # @BRIEF Pauses execution and waits for a resolution signal.\n # @PRE Task exists.\n # @POST Execution pauses until future is set.\n async def wait_for_resolution(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_resolution\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n task.status = TaskStatus.AWAITING_MAPPING\n self.persistence_service.persist_task(task)\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [C:3] [TYPE Function] [SEMANTICS task,wait,input,future]\n # @BRIEF Pauses execution and waits for user input.\n # @PRE Task exists.\n # @POST Execution pauses until future is set via resume_task_with_password.\n async def wait_for_input(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_input\n\n # #region await_input [C:3] [TYPE Function] [SEMANTICS task,input,pause,state]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n # @PRE Task exists and is in RUNNING state.\n # @POST Task status changed to AWAITING_INPUT, input_request set, persisted.\n # @RAISES ValueError if task not found or not RUNNING.\n def await_input(\n self, task_id: str, input_request: dict[str, Any],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\"JobLifecycle.await_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.RUNNING:\n raise ValueError(\n f\"Task {task_id} is not RUNNING (current: {task.status})\"\n )\n task.status = TaskStatus.AWAITING_INPUT\n task.input_required = True\n task.input_request = input_request\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task paused for user input\",\n metadata={\"input_request\": input_request},\n )\n # #endregion await_input\n\n # #region resume_task_with_password [C:3] [TYPE Function] [SEMANTICS task,resume,password,input]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n # @PRE Task exists and is in AWAITING_INPUT state.\n # @POST Task status changed to RUNNING, passwords injected, task resumed.\n # @RAISES ValueError if task not found, not awaiting input, or passwords invalid.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\n \"JobLifecycle.resume_task_with_password\", f\"task_id={task_id}\"\n ):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.AWAITING_INPUT:\n raise ValueError(\n f\"Task {task_id} is not AWAITING_INPUT (current: {task.status})\"\n )\n if not isinstance(passwords, dict) or not passwords:\n raise ValueError(\"Passwords must be a non-empty dictionary\")\n task.params[\"passwords\"] = passwords\n task.input_required = False\n task.input_request = None\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task resumed with passwords\",\n metadata={\"databases\": list(passwords.keys())},\n )\n self.graph.resolve_future(task_id, True)\n # #endregion resume_task_with_password\n\n # #region subscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,subscribe,events,websocket]\n # @BRIEF Subscribe to dataset.updated events for a specific environment.\n async def subscribe_dataset_events(self, env_id: str) -> asyncio.Queue:\n queue = asyncio.Queue()\n if env_id not in self._dataset_subscribers:\n self._dataset_subscribers[env_id] = []\n self._dataset_subscribers[env_id].append(queue)\n return queue\n # #endregion subscribe_dataset_events\n\n # #region unsubscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,unsubscribe,events]\n # @BRIEF Unsubscribe from dataset.updated events for a specific environment.\n def unsubscribe_dataset_events(self, env_id: str, queue: asyncio.Queue):\n if env_id in self._dataset_subscribers:\n if queue in self._dataset_subscribers[env_id]:\n self._dataset_subscribers[env_id].remove(queue)\n if not self._dataset_subscribers[env_id]:\n del self._dataset_subscribers[env_id]\n # #endregion unsubscribe_dataset_events\n\n # #region _broadcast_dataset_updated [C:3] [TYPE Function] [SEMANTICS dataset,broadcast,event,websocket]\n # @BRIEF Broadcast dataset.updated event to all subscribers for a given environment.\n def _broadcast_dataset_updated(self, env_id: str, dataset_ids: list[int]):\n event = {\"type\": \"dataset.updated\", \"payload\": {\"env_id\": env_id, \"dataset_ids\": dataset_ids}}\n if env_id in self._dataset_subscribers:\n for queue in self._dataset_subscribers[env_id]:\n try:\n self.loop.call_soon_threadsafe(queue.put_nowait, event)\n except Exception:\n pass\n # #endregion _broadcast_dataset_updated\n# #endregion JobLifecycle\n# #endregion JobLifecycleModule\n" }, { "contract_id": "JobLifecycle", "contract_type": "Class", "file_path": "backend/src/core/task_manager/lifecycle.py", "start_line": 38, - "end_line": 312, + "end_line": 351, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -26450,14 +27759,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region JobLifecycle [C:5] [TYPE Class] [SEMANTICS task,lifecycle,execution,state,machine]\n# @BRIEF Encodes task creation, execution, pause/resume, and completion transitions for\n# plugin-backed jobs.\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @PRE plugin_loader resolves plugin ids; graph and event_bus are initialized.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @RATIONALE Extracted as standalone lifecycle state machine to isolate async execution\n# orchestration (plugin dispatch, context injection, pause/resume futures) from\n# passive registry and log buffering concerns.\n# @REJECTED Keeping execution logic inside TaskManager was rejected — it mixed async task\n# orchestration with synchronous registry operations and background threading,\n# violating single-responsibility and making the 708-line module unmaintainable.\nclass JobLifecycle:\n \"\"\"Task state machine: creation, execution, pause/resume, completion.\"\"\"\n\n # #region __init__ [TYPE Function]\n # @BRIEF Initialize with dependencies.\n def __init__(\n self,\n plugin_loader: Any,\n graph: TaskGraph,\n event_bus: Any,\n persistence_service: Any,\n executor: ThreadPoolExecutor,\n loop: asyncio.AbstractEventLoop,\n ):\n self.plugin_loader = plugin_loader\n self.graph = graph\n self.event_bus = event_bus\n self.persistence_service = persistence_service\n self.executor = executor\n self.loop = loop\n # #endregion __init__\n\n # #region create_task [C:4] [TYPE Function] [SEMANTICS task,create,persist,schedule]\n # @BRIEF Creates and queues a new task for execution.\n # @PRE Plugin with plugin_id exists. Params are valid dict.\n # @POST Task is created, added to registry, and scheduled for execution.\n # @RAISES ValueError if plugin not found or params invalid.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None,\n add_log_callback=None,\n ) -> Task:\n with belief_scope(\"JobLifecycle.create_task\", f\"plugin_id={plugin_id}\"):\n if not self.plugin_loader.has_plugin(plugin_id):\n logger.error(f\"Plugin with ID '{plugin_id}' not found.\")\n raise ValueError(f\"Plugin with ID '{plugin_id}' not found.\")\n self.plugin_loader.get_plugin(plugin_id)\n if not isinstance(params, dict):\n logger.error(\"Task parameters must be a dictionary.\")\n raise ValueError(\"Task parameters must be a dictionary.\")\n logger.reason(\"Creating task node and scheduling execution\")\n task = Task(plugin_id=plugin_id, params=params, user_id=user_id)\n self.graph.add_task(task)\n self.persistence_service.persist_task(task)\n logger.info(f\"Task {task.id} created and scheduled for execution\")\n self.loop.create_task(\n self._run_task(task.id, add_log_callback=add_log_callback)\n )\n logger.reflect(\n \"Task creation persisted and execution scheduled\",\n extra={\"task_id\": task.id, \"plugin_id\": plugin_id},\n )\n return task\n # #endregion create_task\n\n # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # #endregion _run_task\n\n # #region resolve_task [C:3] [TYPE Function] [SEMANTICS task,resolve,mapping,resume]\n # @BRIEF Resumes a task that is awaiting mapping.\n # @PRE Task exists and is in AWAITING_MAPPING state.\n # @POST Task status updated to RUNNING, params updated, execution resumed.\n # @RAISES ValueError if task not found or not awaiting mapping.\n async def resolve_task(\n self, task_id: str, resolution_params: dict[str, Any],\n ) -> None:\n with belief_scope(\"JobLifecycle.resolve_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task or task.status != TaskStatus.AWAITING_MAPPING:\n raise ValueError(\"Task is not awaiting mapping.\")\n task.params.update(resolution_params)\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n self.graph.resolve_future(task_id, True)\n # #endregion resolve_task\n\n # #region wait_for_resolution [C:3] [TYPE Function] [SEMANTICS task,wait,mapping,future]\n # @BRIEF Pauses execution and waits for a resolution signal.\n # @PRE Task exists.\n # @POST Execution pauses until future is set.\n async def wait_for_resolution(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_resolution\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n task.status = TaskStatus.AWAITING_MAPPING\n self.persistence_service.persist_task(task)\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [C:3] [TYPE Function] [SEMANTICS task,wait,input,future]\n # @BRIEF Pauses execution and waits for user input.\n # @PRE Task exists.\n # @POST Execution pauses until future is set via resume_task_with_password.\n async def wait_for_input(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_input\n\n # #region await_input [C:3] [TYPE Function] [SEMANTICS task,input,pause,state]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n # @PRE Task exists and is in RUNNING state.\n # @POST Task status changed to AWAITING_INPUT, input_request set, persisted.\n # @RAISES ValueError if task not found or not RUNNING.\n def await_input(\n self, task_id: str, input_request: dict[str, Any],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\"JobLifecycle.await_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.RUNNING:\n raise ValueError(\n f\"Task {task_id} is not RUNNING (current: {task.status})\"\n )\n task.status = TaskStatus.AWAITING_INPUT\n task.input_required = True\n task.input_request = input_request\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task paused for user input\",\n metadata={\"input_request\": input_request},\n )\n # #endregion await_input\n\n # #region resume_task_with_password [C:3] [TYPE Function] [SEMANTICS task,resume,password,input]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n # @PRE Task exists and is in AWAITING_INPUT state.\n # @POST Task status changed to RUNNING, passwords injected, task resumed.\n # @RAISES ValueError if task not found, not awaiting input, or passwords invalid.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\n \"JobLifecycle.resume_task_with_password\", f\"task_id={task_id}\"\n ):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.AWAITING_INPUT:\n raise ValueError(\n f\"Task {task_id} is not AWAITING_INPUT (current: {task.status})\"\n )\n if not isinstance(passwords, dict) or not passwords:\n raise ValueError(\"Passwords must be a non-empty dictionary\")\n task.params[\"passwords\"] = passwords\n task.input_required = False\n task.input_request = None\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task resumed with passwords\",\n metadata={\"databases\": list(passwords.keys())},\n )\n self.graph.resolve_future(task_id, True)\n # #endregion resume_task_with_password\n# #endregion JobLifecycle\n" + "body": "# #region JobLifecycle [C:5] [TYPE Class] [SEMANTICS task,lifecycle,execution,state,machine]\n# @BRIEF Encodes task creation, execution, pause/resume, and completion transitions for\n# plugin-backed jobs.\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @PRE plugin_loader resolves plugin ids; graph and event_bus are initialized.\n# @POST Every scheduled task transitions through a valid lifecycle path ending in persisted\n# terminal or waiting state.\n# @RATIONALE Extracted as standalone lifecycle state machine to isolate async execution\n# orchestration (plugin dispatch, context injection, pause/resume futures) from\n# passive registry and log buffering concerns.\n# @REJECTED Keeping execution logic inside TaskManager was rejected — it mixed async task\n# orchestration with synchronous registry operations and background threading,\n# violating single-responsibility and making the 708-line module unmaintainable.\nclass JobLifecycle:\n \"\"\"Task state machine: creation, execution, pause/resume, completion.\"\"\"\n\n # #region __init__ [TYPE Function]\n # @BRIEF Initialize with dependencies.\n def __init__(\n self,\n plugin_loader: Any,\n graph: TaskGraph,\n event_bus: Any,\n persistence_service: Any,\n executor: ThreadPoolExecutor,\n loop: asyncio.AbstractEventLoop,\n ):\n self.plugin_loader = plugin_loader\n self.graph = graph\n self.event_bus = event_bus\n self.persistence_service = persistence_service\n self.executor = executor\n self.loop = loop\n self._dataset_subscribers: dict[str, list[asyncio.Queue]] = {}\n # #endregion __init__\n\n # #region create_task [C:4] [TYPE Function] [SEMANTICS task,create,persist,schedule]\n # @BRIEF Creates and queues a new task for execution.\n # @PRE Plugin with plugin_id exists. Params are valid dict.\n # @POST Task is created, added to registry, and scheduled for execution.\n # @RAISES ValueError if plugin not found or params invalid.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None,\n add_log_callback=None,\n ) -> Task:\n with belief_scope(\"JobLifecycle.create_task\", f\"plugin_id={plugin_id}\"):\n if not self.plugin_loader.has_plugin(plugin_id):\n logger.error(f\"Plugin with ID '{plugin_id}' not found.\")\n raise ValueError(f\"Plugin with ID '{plugin_id}' not found.\")\n self.plugin_loader.get_plugin(plugin_id)\n if not isinstance(params, dict):\n logger.error(\"Task parameters must be a dictionary.\")\n raise ValueError(\"Task parameters must be a dictionary.\")\n logger.reason(\"Creating task node and scheduling execution\")\n task = Task(plugin_id=plugin_id, params=params, user_id=user_id)\n self.graph.add_task(task)\n self.persistence_service.persist_task(task)\n logger.info(f\"Task {task.id} created and scheduled for execution\")\n self.loop.create_task(\n self._run_task(task.id, add_log_callback=add_log_callback)\n )\n logger.reflect(\n \"Task creation persisted and execution scheduled\",\n extra={\"task_id\": task.id, \"plugin_id\": plugin_id},\n )\n return task\n # #endregion create_task\n\n # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # Broadcast dataset.updated for mapping and documentation tasks (FR-024, R4)\n if task.plugin_id in (\"dataset-mapper\", \"llm_documentation\"):\n dataset_ids = task.params.get(\"dataset_ids\") or [task.params.get(\"dataset_id\")]\n env_id = task.params.get(\"env\") or task.params.get(\"environment_id\", \"\")\n if dataset_ids and env_id:\n self._broadcast_dataset_updated(env_id, dataset_ids)\n # #endregion _run_task\n\n # #region resolve_task [C:3] [TYPE Function] [SEMANTICS task,resolve,mapping,resume]\n # @BRIEF Resumes a task that is awaiting mapping.\n # @PRE Task exists and is in AWAITING_MAPPING state.\n # @POST Task status updated to RUNNING, params updated, execution resumed.\n # @RAISES ValueError if task not found or not awaiting mapping.\n async def resolve_task(\n self, task_id: str, resolution_params: dict[str, Any],\n ) -> None:\n with belief_scope(\"JobLifecycle.resolve_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task or task.status != TaskStatus.AWAITING_MAPPING:\n raise ValueError(\"Task is not awaiting mapping.\")\n task.params.update(resolution_params)\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n self.graph.resolve_future(task_id, True)\n # #endregion resolve_task\n\n # #region wait_for_resolution [C:3] [TYPE Function] [SEMANTICS task,wait,mapping,future]\n # @BRIEF Pauses execution and waits for a resolution signal.\n # @PRE Task exists.\n # @POST Execution pauses until future is set.\n async def wait_for_resolution(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_resolution\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n task.status = TaskStatus.AWAITING_MAPPING\n self.persistence_service.persist_task(task)\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [C:3] [TYPE Function] [SEMANTICS task,wait,input,future]\n # @BRIEF Pauses execution and waits for user input.\n # @PRE Task exists.\n # @POST Execution pauses until future is set via resume_task_with_password.\n async def wait_for_input(self, task_id: str) -> None:\n with belief_scope(\"JobLifecycle.wait_for_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n return\n future = self.loop.create_future()\n self.graph.create_future(task_id, future)\n try:\n await future\n finally:\n self.graph.remove_future(task_id)\n # #endregion wait_for_input\n\n # #region await_input [C:3] [TYPE Function] [SEMANTICS task,input,pause,state]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n # @PRE Task exists and is in RUNNING state.\n # @POST Task status changed to AWAITING_INPUT, input_request set, persisted.\n # @RAISES ValueError if task not found or not RUNNING.\n def await_input(\n self, task_id: str, input_request: dict[str, Any],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\"JobLifecycle.await_input\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.RUNNING:\n raise ValueError(\n f\"Task {task_id} is not RUNNING (current: {task.status})\"\n )\n task.status = TaskStatus.AWAITING_INPUT\n task.input_required = True\n task.input_request = input_request\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task paused for user input\",\n metadata={\"input_request\": input_request},\n )\n # #endregion await_input\n\n # #region resume_task_with_password [C:3] [TYPE Function] [SEMANTICS task,resume,password,input]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n # @PRE Task exists and is in AWAITING_INPUT state.\n # @POST Task status changed to RUNNING, passwords injected, task resumed.\n # @RAISES ValueError if task not found, not awaiting input, or passwords invalid.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\n \"JobLifecycle.resume_task_with_password\", f\"task_id={task_id}\"\n ):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.AWAITING_INPUT:\n raise ValueError(\n f\"Task {task_id} is not AWAITING_INPUT (current: {task.status})\"\n )\n if not isinstance(passwords, dict) or not passwords:\n raise ValueError(\"Passwords must be a non-empty dictionary\")\n task.params[\"passwords\"] = passwords\n task.input_required = False\n task.input_request = None\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task resumed with passwords\",\n metadata={\"databases\": list(passwords.keys())},\n )\n self.graph.resolve_future(task_id, True)\n # #endregion resume_task_with_password\n\n # #region subscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,subscribe,events,websocket]\n # @BRIEF Subscribe to dataset.updated events for a specific environment.\n async def subscribe_dataset_events(self, env_id: str) -> asyncio.Queue:\n queue = asyncio.Queue()\n if env_id not in self._dataset_subscribers:\n self._dataset_subscribers[env_id] = []\n self._dataset_subscribers[env_id].append(queue)\n return queue\n # #endregion subscribe_dataset_events\n\n # #region unsubscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,unsubscribe,events]\n # @BRIEF Unsubscribe from dataset.updated events for a specific environment.\n def unsubscribe_dataset_events(self, env_id: str, queue: asyncio.Queue):\n if env_id in self._dataset_subscribers:\n if queue in self._dataset_subscribers[env_id]:\n self._dataset_subscribers[env_id].remove(queue)\n if not self._dataset_subscribers[env_id]:\n del self._dataset_subscribers[env_id]\n # #endregion unsubscribe_dataset_events\n\n # #region _broadcast_dataset_updated [C:3] [TYPE Function] [SEMANTICS dataset,broadcast,event,websocket]\n # @BRIEF Broadcast dataset.updated event to all subscribers for a given environment.\n def _broadcast_dataset_updated(self, env_id: str, dataset_ids: list[int]):\n event = {\"type\": \"dataset.updated\", \"payload\": {\"env_id\": env_id, \"dataset_ids\": dataset_ids}}\n if env_id in self._dataset_subscribers:\n for queue in self._dataset_subscribers[env_id]:\n try:\n self.loop.call_soon_threadsafe(queue.put_nowait, event)\n except Exception:\n pass\n # #endregion _broadcast_dataset_updated\n# #endregion JobLifecycle\n" }, { "contract_id": "create_task", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 76, - "end_line": 106, + "start_line": 77, + "end_line": 107, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -26477,8 +27786,8 @@ "contract_id": "_run_task", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 108, - "end_line": 193, + "start_line": 109, + "end_line": 200, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -26492,14 +27801,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # #endregion _run_task\n" + "body": " # #region _run_task [C:4] [TYPE Function] [SEMANTICS task,execute,context,dispatch]\n # @BRIEF Internal method to execute a task with TaskContext support.\n # @PRE Task exists in registry.\n # @POST Task is executed, status updated to SUCCESS or FAILED.\n # @SIDE_EFFECT Executes plugin code, updates task status and persistence, emits logs.\n async def _run_task(self, task_id: str, add_log_callback=None):\n seed_trace_id()\n with belief_scope(\"JobLifecycle._run_task\", f\"task_id={task_id}\"):\n task = self.graph.get_task(task_id)\n if task is None:\n logger.error(f\"Task {task_id} not found in registry\")\n return\n plugin = self.plugin_loader.get_plugin(task.plugin_id)\n logger.reason(\n \"Transitioning task to running state\",\n extra={\"task_id\": task_id, \"plugin_id\": task.plugin_id},\n )\n logger.info(\n f\"Starting execution of task {task_id} for plugin '{plugin.name}'\"\n )\n task.status = TaskStatus.RUNNING\n task.started_at = datetime.utcnow()\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task started for plugin '{plugin.name}'\",\n source=\"system\",\n )\n try:\n params = {**task.params, \"_task_id\": task_id}\n sig = inspect.signature(plugin.execute)\n accepts_context = \"context\" in sig.parameters\n if accepts_context:\n # Create TaskContext for new-style plugins\n context = TaskContext(\n task_id=task_id,\n add_log_fn=add_log_callback,\n params=params,\n default_source=\"plugin\",\n background_tasks=None,\n )\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params, context=context)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor,\n lambda: plugin.execute(params, context=context),\n )\n else:\n if asyncio.iscoroutinefunction(plugin.execute):\n task.result = await plugin.execute(params)\n else:\n task.result = await self.loop.run_in_executor(\n self.executor, plugin.execute, params\n )\n logger.info(f\"Task {task_id} completed successfully\")\n task.status = TaskStatus.SUCCESS\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n f\"Task completed successfully for plugin '{plugin.name}'\",\n source=\"system\",\n )\n except Exception as e:\n logger.error(f\"Task {task_id} failed: {e}\")\n task.status = TaskStatus.FAILED\n if add_log_callback:\n add_log_callback(\n task_id, \"ERROR\",\n f\"Task failed: {e}\",\n source=\"system\",\n metadata={\"error_type\": type(e).__name__},\n )\n finally:\n task.finished_at = datetime.utcnow()\n self.event_bus.flush_task_logs(task_id)\n self.persistence_service.persist_task(task)\n logger.info(\n f\"Task {task_id} execution finished with status: {task.status}\"\n )\n logger.reflect(\n \"Task lifecycle reached persisted terminal state\",\n extra={\"task_id\": task_id, \"status\": str(task.status)},\n )\n # Broadcast dataset.updated for mapping and documentation tasks (FR-024, R4)\n if task.plugin_id in (\"dataset-mapper\", \"llm_documentation\"):\n dataset_ids = task.params.get(\"dataset_ids\") or [task.params.get(\"dataset_id\")]\n env_id = task.params.get(\"env\") or task.params.get(\"environment_id\", \"\")\n if dataset_ids and env_id:\n self._broadcast_dataset_updated(env_id, dataset_ids)\n # #endregion _run_task\n" }, { "contract_id": "resolve_task", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 195, - "end_line": 211, + "start_line": 202, + "end_line": 218, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26519,8 +27828,8 @@ "contract_id": "wait_for_resolution", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 213, - "end_line": 230, + "start_line": 220, + "end_line": 237, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26539,8 +27848,8 @@ "contract_id": "wait_for_input", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 232, - "end_line": 247, + "start_line": 239, + "end_line": 254, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26559,8 +27868,8 @@ "contract_id": "await_input", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 249, - "end_line": 276, + "start_line": 256, + "end_line": 283, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26580,8 +27889,8 @@ "contract_id": "resume_task_with_password", "contract_type": "Function", "file_path": "backend/src/core/task_manager/lifecycle.py", - "start_line": 278, - "end_line": 311, + "start_line": 285, + "end_line": 318, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26597,12 +27906,66 @@ "tier_source": "AutoCalculated", "body": " # #region resume_task_with_password [C:3] [TYPE Function] [SEMANTICS task,resume,password,input]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n # @PRE Task exists and is in AWAITING_INPUT state.\n # @POST Task status changed to RUNNING, passwords injected, task resumed.\n # @RAISES ValueError if task not found, not awaiting input, or passwords invalid.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str],\n add_log_callback=None,\n ) -> None:\n with belief_scope(\n \"JobLifecycle.resume_task_with_password\", f\"task_id={task_id}\"\n ):\n task = self.graph.get_task(task_id)\n if not task:\n raise ValueError(f\"Task {task_id} not found\")\n if task.status != TaskStatus.AWAITING_INPUT:\n raise ValueError(\n f\"Task {task_id} is not AWAITING_INPUT (current: {task.status})\"\n )\n if not isinstance(passwords, dict) or not passwords:\n raise ValueError(\"Passwords must be a non-empty dictionary\")\n task.params[\"passwords\"] = passwords\n task.input_required = False\n task.input_request = None\n task.status = TaskStatus.RUNNING\n self.persistence_service.persist_task(task)\n if add_log_callback:\n add_log_callback(\n task_id, \"INFO\",\n \"Task resumed with passwords\",\n metadata={\"databases\": list(passwords.keys())},\n )\n self.graph.resolve_future(task_id, True)\n # #endregion resume_task_with_password\n" }, + { + "contract_id": "subscribe_dataset_events", + "contract_type": "Function", + "file_path": "backend/src/core/task_manager/lifecycle.py", + "start_line": 320, + "end_line": 328, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Subscribe to dataset.updated events for a specific environment." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region subscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,subscribe,events,websocket]\n # @BRIEF Subscribe to dataset.updated events for a specific environment.\n async def subscribe_dataset_events(self, env_id: str) -> asyncio.Queue:\n queue = asyncio.Queue()\n if env_id not in self._dataset_subscribers:\n self._dataset_subscribers[env_id] = []\n self._dataset_subscribers[env_id].append(queue)\n return queue\n # #endregion subscribe_dataset_events\n" + }, + { + "contract_id": "unsubscribe_dataset_events", + "contract_type": "Function", + "file_path": "backend/src/core/task_manager/lifecycle.py", + "start_line": 330, + "end_line": 338, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Unsubscribe from dataset.updated events for a specific environment." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region unsubscribe_dataset_events [C:2] [TYPE Function] [SEMANTICS dataset,unsubscribe,events]\n # @BRIEF Unsubscribe from dataset.updated events for a specific environment.\n def unsubscribe_dataset_events(self, env_id: str, queue: asyncio.Queue):\n if env_id in self._dataset_subscribers:\n if queue in self._dataset_subscribers[env_id]:\n self._dataset_subscribers[env_id].remove(queue)\n if not self._dataset_subscribers[env_id]:\n del self._dataset_subscribers[env_id]\n # #endregion unsubscribe_dataset_events\n" + }, + { + "contract_id": "_broadcast_dataset_updated", + "contract_type": "Function", + "file_path": "backend/src/core/task_manager/lifecycle.py", + "start_line": 340, + "end_line": 350, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Broadcast dataset.updated event to all subscribers for a given environment." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _broadcast_dataset_updated [C:3] [TYPE Function] [SEMANTICS dataset,broadcast,event,websocket]\n # @BRIEF Broadcast dataset.updated event to all subscribers for a given environment.\n def _broadcast_dataset_updated(self, env_id: str, dataset_ids: list[int]):\n event = {\"type\": \"dataset.updated\", \"payload\": {\"env_id\": env_id, \"dataset_ids\": dataset_ids}}\n if env_id in self._dataset_subscribers:\n for queue in self._dataset_subscribers[env_id]:\n try:\n self.loop.call_soon_threadsafe(queue.put_nowait, event)\n except Exception:\n pass\n # #endregion _broadcast_dataset_updated\n" + }, { "contract_id": "TaskManagerModule", "contract_type": "Module", "file_path": "backend/src/core/task_manager/manager.py", "start_line": 1, - "end_line": 322, + "end_line": 336, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -26613,14 +27976,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TaskManagerModule [C:5] [TYPE Module] [SEMANTICS task, schedule, execution, task-manager]\n# @BRIEF Thin facade composing TaskGraph (registry), EventBus (log/pub-sub), and JobLifecycle\n# (state machine) into a single TaskManager interface for backward compatibility.\n# @LAYER: Core\n# @PRE: Plugin loader and database sessions are initialized.\n# @POST: Orchestrates task execution and persistence.\n# @SIDE_EFFECT: Spawns worker threads and flushes logs to DB.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Model[Task, LogEntry]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @INVARIANT: Task IDs are unique.\n# @TEST_CONTRACT: TaskManagerRuntime -> {\n# required_fields: {plugin_loader: PluginLoader},\n# optional_fields: {},\n# invariants: [\"Must use belief_scope for logging\"]\n# }\n# @TEST_FIXTURE: valid_module -> {\"manager_initialized\": true}\n# @TEST_EDGE: missing_required_field -> {\"plugin_loader\": null}\n# @TEST_EDGE: empty_response -> {\"tasks\": []}\n# @TEST_EDGE: invalid_type -> {\"plugin_loader\": \"string_instead_of_object\"}\n# @TEST_EDGE: external_failure -> {\"db_unavailable\": true}\n# @TEST_INVARIANT: logger_compliance -> verifies: [valid_module]\n# @RATIONALE Decomposed from 708-line monolithic module into four focused modules (TaskGraph,\n# EventBus, JobLifecycle, and this facade) to satisfy INV_7. TaskManager now delegates\n# to sub-services while preserving the public API contract.\n# @REJECTED Keeping all five concerns (registry, lifecycle, log buffer, subscriptions, execution)\n# in one module was rejected — it violated INV_7 (708 lines vs 400 max), mixed threading\n# with async execution, and created an unmaintainable god class.\n\nimport asyncio\nfrom concurrent.futures import ThreadPoolExecutor\nimport threading\nfrom typing import Any\n\nfrom ..logger import belief_scope, logger\nfrom .event_bus import EventBus\nfrom .graph import TaskGraph\nfrom .lifecycle import JobLifecycle\nfrom .models import LogFilter, LogStats, Task, TaskStatus\nfrom .persistence import TaskLogPersistenceService, TaskPersistenceService\n\n\n# #region TaskManager [C:5] [TYPE Class] [SEMANTICS task, manager, lifecycle, execution, state]\n# @BRIEF Facade composing TaskGraph, EventBus, and JobLifecycle into a single interface.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @PRE: Plugin loader resolves plugin ids and persistence services are available.\n# @POST: In-memory task graph, lifecycle scheduler, and log event bus stay consistent with\n# persisted task state.\n# @INVARIANT: Task IDs are unique within the registry.\n# @INVARIANT: Each task has exactly one status at any time.\n# @INVARIANT: Log entries are never deleted after being added to a task.\n# @SIDE_EFFECT: Spawns worker threads, flushes logs to database, and mutates task states.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Output[Task]\n# @RATIONALE Thin facade — all delegating methods are under 15 lines. Actual business logic\n# (registry CRUD, log buffering, lifecycle state machine) lives in extracted modules.\n# @REJECTED Keeping all five concerns in one class was rejected — it violated INV_7 (708-line\n# manager.py) and made the god class impossible to test or maintain independently.\nclass TaskManager:\n \"\"\"\n Facade composing TaskGraph (registry), EventBus (log/pub-sub), and\n JobLifecycle (state machine) into a single TaskManager interface.\n \"\"\"\n\n # #region __init__ [TYPE Function] [C:5]\n # @BRIEF Initialize sub-services, create add_log callback, start background flusher.\n # @PRE: plugin_loader is initialized.\n # @POST: TaskManager is ready to accept tasks.\n # @SIDE_EFFECT: Starts background flusher thread and loads persisted task state into memory.\n def __init__(self, plugin_loader):\n with belief_scope(\"TaskManager.__init__\"):\n logger.reason(\"Initializing task manager runtime services\")\n self.plugin_loader = plugin_loader\n self.executor = ThreadPoolExecutor(max_workers=5)\n self.persistence_service = TaskPersistenceService()\n self.log_persistence_service = TaskLogPersistenceService()\n\n try:\n self.loop = asyncio.get_running_loop()\n except RuntimeError:\n self.loop = asyncio.get_event_loop()\n\n # Create sub-services\n self.graph = TaskGraph(self.persistence_service)\n self.event_bus = EventBus(self.log_persistence_service, self.loop)\n\n # Create add_log callback that lifecycle and plugins use\n self._add_log = self._make_add_log_callback()\n\n self.lifecycle = JobLifecycle(\n plugin_loader=self.plugin_loader,\n graph=self.graph,\n event_bus=self.event_bus,\n persistence_service=self.persistence_service,\n executor=self.executor,\n loop=self.loop,\n )\n\n # Load persisted tasks on startup\n self.graph.load_persisted_tasks()\n\n # Backward-compatible property aliases for tests\n self.tasks = self.graph.tasks\n self.task_futures = self.graph.task_futures\n self.subscribers = self.event_bus.subscribers\n self._log_buffer = self.event_bus._log_buffer\n self._log_buffer_lock = self.event_bus._log_buffer_lock\n self._flusher_stop_event = self.event_bus._flusher_stop_event\n self._flusher_thread = self.event_bus._flusher_thread\n\n logger.reflect(\n \"Task manager runtime initialized\",\n extra={\"task_count\": len(self.tasks)},\n )\n # #endregion __init__\n\n # #region _make_add_log_callback [C:2] [TYPE Function]\n # @BRIEF Create a closure for adding logs that looks up the task and delegates to EventBus.\n def _make_add_log_callback(self):\n def _add_log(task_id, level, message, source=\"system\", metadata=None, context=None):\n task = self.graph.get_task(task_id)\n if not task:\n return\n self.event_bus.add_log(\n task_id, level, message, source, metadata, context,\n task_logs_list=task.logs,\n )\n return _add_log\n # #endregion _make_add_log_callback\n\n # ── Deprecated legacy aliases (delegate to EventBus) ──\n\n # #region _flusher_loop [C:3] [TYPE Function] [SEMANTICS flush,background,thread]\n # @BRIEF Legacy alias delegating to EventBus._flusher_loop.\n def _flusher_loop(self):\n self.event_bus._flusher_loop()\n # #endregion _flusher_loop\n\n # #region _flush_logs [C:3] [TYPE Function] [SEMANTICS flush,batch,persistence]\n # @BRIEF Legacy alias delegating to EventBus._flush_logs.\n def _flush_logs(self):\n self.event_bus._flush_logs()\n # #endregion _flush_logs\n\n # #region _flush_task_logs [C:3] [TYPE Function] [SEMANTICS flush,single,persistence]\n # @BRIEF Legacy alias delegating to EventBus.flush_task_logs.\n def _flush_task_logs(self, task_id: str):\n self.event_bus.flush_task_logs(task_id)\n # #endregion _flush_task_logs\n\n # ── Task CRUD delegates to TaskGraph ──\n\n # #region get_task [TYPE Function] [C:2]\n # @BRIEF Retrieves a task by its ID.\n def get_task(self, task_id: str) -> Task | None:\n return self.graph.get_task(task_id)\n # #endregion get_task\n\n # #region get_all_tasks [TYPE Function] [C:1]\n # @BRIEF Retrieves all registered tasks.\n def get_all_tasks(self) -> list[Task]:\n return self.graph.get_all_tasks()\n # #endregion get_all_tasks\n\n # #region get_tasks [TYPE Function] [C:3]\n # @BRIEF Retrieves tasks with pagination and optional status filter.\n def get_tasks(\n self,\n limit: int = 10,\n offset: int = 0,\n status: TaskStatus | None = None,\n plugin_ids: list[str] | None = None,\n completed_only: bool = False,\n ) -> list[Task]:\n return self.graph.get_tasks(limit, offset, status, plugin_ids, completed_only)\n # #endregion get_tasks\n\n # #region load_persisted_tasks [TYPE Function] [C:2]\n # @BRIEF Load persisted tasks using persistence service.\n def load_persisted_tasks(self) -> None:\n self.graph.load_persisted_tasks(limit=100)\n # #endregion load_persisted_tasks\n\n # #region clear_tasks [TYPE Function] [C:4]\n # @BRIEF Clears tasks based on status filter (also deletes associated logs).\n # @SIDE_EFFECT Removes tasks from registry and persistence; cancels futures.\n def clear_tasks(self, status: TaskStatus | None = None) -> int:\n with belief_scope(\"TaskManager.clear_tasks\"):\n tasks_to_remove = []\n for task_id, task in list(self.tasks.items()):\n should_remove = False\n if status:\n if task.status == status:\n should_remove = True\n else:\n if task.status not in [\n TaskStatus.RUNNING,\n TaskStatus.AWAITING_INPUT,\n TaskStatus.AWAITING_MAPPING,\n ]:\n should_remove = True\n if should_remove:\n tasks_to_remove.append(task_id)\n\n # Delete logs first, then remove tasks\n if tasks_to_remove:\n self.event_bus.delete_logs_for_tasks(tasks_to_remove)\n removed = self.graph.remove_tasks(tasks_to_remove)\n logger.info(f\"Cleared {removed} tasks.\")\n return removed\n # #endregion clear_tasks\n\n # ── Log delegates to EventBus ──\n\n # #region get_task_logs [TYPE Function] [C:3]\n # @BRIEF Retrieves logs for a specific task (from memory or persistence).\n def get_task_logs(\n self, task_id: str, log_filter: LogFilter | None = None\n ) -> list:\n task = self.graph.get_task(task_id)\n task_status = task.status if task else None\n task_logs = task.logs if task else []\n return self.event_bus.get_task_logs(\n task_id, log_filter, task_status=task_status, task_logs=task_logs\n )\n # #endregion get_task_logs\n\n # #region get_task_log_stats [TYPE Function] [C:2]\n # @BRIEF Get statistics about logs for a task.\n def get_task_log_stats(self, task_id: str) -> LogStats:\n return self.event_bus.get_task_log_stats(task_id)\n # #endregion get_task_log_stats\n\n # #region get_task_log_sources [TYPE Function] [C:2]\n # @BRIEF Get unique sources for a task's logs.\n def get_task_log_sources(self, task_id: str) -> list[str]:\n return self.event_bus.get_task_log_sources(task_id)\n # #endregion get_task_log_sources\n\n # ── Subscription delegates to EventBus ──\n\n # #region subscribe_logs [TYPE Function] [C:2]\n # @BRIEF Subscribes to real-time logs for a task.\n async def subscribe_logs(self, task_id: str) -> asyncio.Queue:\n return await self.event_bus.subscribe_logs(task_id)\n # #endregion subscribe_logs\n\n # #region unsubscribe_logs [TYPE Function] [C:2]\n # @BRIEF Unsubscribes from real-time logs for a task.\n def unsubscribe_logs(self, task_id: str, queue: asyncio.Queue):\n self.event_bus.unsubscribe_logs(task_id, queue)\n # #endregion unsubscribe_logs\n\n # ── Lifecycle delegates to JobLifecycle ──\n\n # #region create_task [TYPE Function] [C:4]\n # @BRIEF Creates and queues a new task for execution.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None\n ) -> Task:\n return await self.lifecycle.create_task(\n plugin_id, params, user_id,\n add_log_callback=self._add_log,\n )\n # #endregion create_task\n\n # #region _run_task [TYPE Function] [C:4]\n # @BRIEF Internal method to execute a task with TaskContext support (delegates to lifecycle).\n async def _run_task(self, task_id: str):\n await self.lifecycle._run_task(task_id, add_log_callback=self._add_log)\n # #endregion _run_task\n\n # #region resolve_task [TYPE Function] [C:3]\n # @BRIEF Resumes a task that is awaiting mapping.\n async def resolve_task(self, task_id: str, resolution_params: dict[str, Any]):\n await self.lifecycle.resolve_task(task_id, resolution_params)\n # #endregion resolve_task\n\n # #region wait_for_resolution [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for a resolution signal.\n async def wait_for_resolution(self, task_id: str):\n await self.lifecycle.wait_for_resolution(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for user input.\n async def wait_for_input(self, task_id: str):\n await self.lifecycle.wait_for_input(task_id)\n # #endregion wait_for_input\n\n # #region await_input [TYPE Function] [C:3]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n def await_input(self, task_id: str, input_request: dict[str, Any]) -> None:\n self.lifecycle.await_input(\n task_id, input_request,\n add_log_callback=self._add_log,\n )\n # #endregion await_input\n\n # #region resume_task_with_password [TYPE Function] [C:3]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str]\n ) -> None:\n self.lifecycle.resume_task_with_password(\n task_id, passwords,\n add_log_callback=self._add_log,\n )\n # #endregion resume_task_with_password\n# #endregion TaskManager\n# #endregion TaskManagerModule\n" + "body": "# #region TaskManagerModule [C:5] [TYPE Module] [SEMANTICS task, schedule, execution, task-manager]\n# @BRIEF Thin facade composing TaskGraph (registry), EventBus (log/pub-sub), and JobLifecycle\n# (state machine) into a single TaskManager interface for backward compatibility.\n# @LAYER: Core\n# @PRE: Plugin loader and database sessions are initialized.\n# @POST: Orchestrates task execution and persistence.\n# @SIDE_EFFECT: Spawns worker threads and flushes logs to DB.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Model[Task, LogEntry]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @INVARIANT: Task IDs are unique.\n# @TEST_CONTRACT: TaskManagerRuntime -> {\n# required_fields: {plugin_loader: PluginLoader},\n# optional_fields: {},\n# invariants: [\"Must use belief_scope for logging\"]\n# }\n# @TEST_FIXTURE: valid_module -> {\"manager_initialized\": true}\n# @TEST_EDGE: missing_required_field -> {\"plugin_loader\": null}\n# @TEST_EDGE: empty_response -> {\"tasks\": []}\n# @TEST_EDGE: invalid_type -> {\"plugin_loader\": \"string_instead_of_object\"}\n# @TEST_EDGE: external_failure -> {\"db_unavailable\": true}\n# @TEST_INVARIANT: logger_compliance -> verifies: [valid_module]\n# @RATIONALE Decomposed from 708-line monolithic module into four focused modules (TaskGraph,\n# EventBus, JobLifecycle, and this facade) to satisfy INV_7. TaskManager now delegates\n# to sub-services while preserving the public API contract.\n# @REJECTED Keeping all five concerns (registry, lifecycle, log buffer, subscriptions, execution)\n# in one module was rejected — it violated INV_7 (708 lines vs 400 max), mixed threading\n# with async execution, and created an unmaintainable god class.\n\nimport asyncio\nfrom concurrent.futures import ThreadPoolExecutor\nimport threading\nfrom typing import Any\n\nfrom ..logger import belief_scope, logger\nfrom .event_bus import EventBus\nfrom .graph import TaskGraph\nfrom .lifecycle import JobLifecycle\nfrom .models import LogFilter, LogStats, Task, TaskStatus\nfrom .persistence import TaskLogPersistenceService, TaskPersistenceService\n\n\n# #region TaskManager [C:5] [TYPE Class] [SEMANTICS task, manager, lifecycle, execution, state]\n# @BRIEF Facade composing TaskGraph, EventBus, and JobLifecycle into a single interface.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @PRE: Plugin loader resolves plugin ids and persistence services are available.\n# @POST: In-memory task graph, lifecycle scheduler, and log event bus stay consistent with\n# persisted task state.\n# @INVARIANT: Task IDs are unique within the registry.\n# @INVARIANT: Each task has exactly one status at any time.\n# @INVARIANT: Log entries are never deleted after being added to a task.\n# @SIDE_EFFECT: Spawns worker threads, flushes logs to database, and mutates task states.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Output[Task]\n# @RATIONALE Thin facade — all delegating methods are under 15 lines. Actual business logic\n# (registry CRUD, log buffering, lifecycle state machine) lives in extracted modules.\n# @REJECTED Keeping all five concerns in one class was rejected — it violated INV_7 (708-line\n# manager.py) and made the god class impossible to test or maintain independently.\nclass TaskManager:\n \"\"\"\n Facade composing TaskGraph (registry), EventBus (log/pub-sub), and\n JobLifecycle (state machine) into a single TaskManager interface.\n \"\"\"\n\n # #region __init__ [TYPE Function] [C:5]\n # @BRIEF Initialize sub-services, create add_log callback, start background flusher.\n # @PRE: plugin_loader is initialized.\n # @POST: TaskManager is ready to accept tasks.\n # @SIDE_EFFECT: Starts background flusher thread and loads persisted task state into memory.\n def __init__(self, plugin_loader):\n with belief_scope(\"TaskManager.__init__\"):\n logger.reason(\"Initializing task manager runtime services\")\n self.plugin_loader = plugin_loader\n self.executor = ThreadPoolExecutor(max_workers=5)\n self.persistence_service = TaskPersistenceService()\n self.log_persistence_service = TaskLogPersistenceService()\n\n try:\n self.loop = asyncio.get_running_loop()\n except RuntimeError:\n self.loop = asyncio.get_event_loop()\n\n # Create sub-services\n self.graph = TaskGraph(self.persistence_service)\n self.event_bus = EventBus(self.log_persistence_service, self.loop)\n\n # Create add_log callback that lifecycle and plugins use\n self._add_log = self._make_add_log_callback()\n\n self.lifecycle = JobLifecycle(\n plugin_loader=self.plugin_loader,\n graph=self.graph,\n event_bus=self.event_bus,\n persistence_service=self.persistence_service,\n executor=self.executor,\n loop=self.loop,\n )\n\n # Load persisted tasks on startup\n self.graph.load_persisted_tasks()\n\n # Backward-compatible property aliases for tests\n self.tasks = self.graph.tasks\n self.task_futures = self.graph.task_futures\n self.subscribers = self.event_bus.subscribers\n self._log_buffer = self.event_bus._log_buffer\n self._log_buffer_lock = self.event_bus._log_buffer_lock\n self._flusher_stop_event = self.event_bus._flusher_stop_event\n self._flusher_thread = self.event_bus._flusher_thread\n\n logger.reflect(\n \"Task manager runtime initialized\",\n extra={\"task_count\": len(self.tasks)},\n )\n # #endregion __init__\n\n # #region _make_add_log_callback [C:2] [TYPE Function]\n # @BRIEF Create a closure for adding logs that looks up the task and delegates to EventBus.\n def _make_add_log_callback(self):\n def _add_log(task_id, level, message, source=\"system\", metadata=None, context=None):\n task = self.graph.get_task(task_id)\n if not task:\n return\n self.event_bus.add_log(\n task_id, level, message, source, metadata, context,\n task_logs_list=task.logs,\n )\n return _add_log\n # #endregion _make_add_log_callback\n\n # ── Deprecated legacy aliases (delegate to EventBus) ──\n\n # #region _flusher_loop [C:3] [TYPE Function] [SEMANTICS flush,background,thread]\n # @BRIEF Legacy alias delegating to EventBus._flusher_loop.\n def _flusher_loop(self):\n self.event_bus._flusher_loop()\n # #endregion _flusher_loop\n\n # #region _flush_logs [C:3] [TYPE Function] [SEMANTICS flush,batch,persistence]\n # @BRIEF Legacy alias delegating to EventBus._flush_logs.\n def _flush_logs(self):\n self.event_bus._flush_logs()\n # #endregion _flush_logs\n\n # #region _flush_task_logs [C:3] [TYPE Function] [SEMANTICS flush,single,persistence]\n # @BRIEF Legacy alias delegating to EventBus.flush_task_logs.\n def _flush_task_logs(self, task_id: str):\n self.event_bus.flush_task_logs(task_id)\n # #endregion _flush_task_logs\n\n # ── Task CRUD delegates to TaskGraph ──\n\n # #region get_task [TYPE Function] [C:2]\n # @BRIEF Retrieves a task by its ID.\n def get_task(self, task_id: str) -> Task | None:\n return self.graph.get_task(task_id)\n # #endregion get_task\n\n # #region get_all_tasks [TYPE Function] [C:1]\n # @BRIEF Retrieves all registered tasks.\n def get_all_tasks(self) -> list[Task]:\n return self.graph.get_all_tasks()\n # #endregion get_all_tasks\n\n # #region get_tasks [TYPE Function] [C:3]\n # @BRIEF Retrieves tasks with pagination and optional status filter.\n def get_tasks(\n self,\n limit: int = 10,\n offset: int = 0,\n status: TaskStatus | None = None,\n plugin_ids: list[str] | None = None,\n completed_only: bool = False,\n ) -> list[Task]:\n return self.graph.get_tasks(limit, offset, status, plugin_ids, completed_only)\n # #endregion get_tasks\n\n # #region load_persisted_tasks [TYPE Function] [C:2]\n # @BRIEF Load persisted tasks using persistence service.\n def load_persisted_tasks(self) -> None:\n self.graph.load_persisted_tasks(limit=100)\n # #endregion load_persisted_tasks\n\n # #region clear_tasks [TYPE Function] [C:4]\n # @BRIEF Clears tasks based on status filter (also deletes associated logs).\n # @SIDE_EFFECT Removes tasks from registry and persistence; cancels futures.\n def clear_tasks(self, status: TaskStatus | None = None) -> int:\n with belief_scope(\"TaskManager.clear_tasks\"):\n tasks_to_remove = []\n for task_id, task in list(self.tasks.items()):\n should_remove = False\n if status:\n if task.status == status:\n should_remove = True\n else:\n if task.status not in [\n TaskStatus.RUNNING,\n TaskStatus.AWAITING_INPUT,\n TaskStatus.AWAITING_MAPPING,\n ]:\n should_remove = True\n if should_remove:\n tasks_to_remove.append(task_id)\n\n # Delete logs first, then remove tasks\n if tasks_to_remove:\n self.event_bus.delete_logs_for_tasks(tasks_to_remove)\n removed = self.graph.remove_tasks(tasks_to_remove)\n logger.info(f\"Cleared {removed} tasks.\")\n return removed\n # #endregion clear_tasks\n\n # ── Log delegates to EventBus ──\n\n # #region get_task_logs [TYPE Function] [C:3]\n # @BRIEF Retrieves logs for a specific task (from memory or persistence).\n def get_task_logs(\n self, task_id: str, log_filter: LogFilter | None = None\n ) -> list:\n task = self.graph.get_task(task_id)\n task_status = task.status if task else None\n task_logs = task.logs if task else []\n return self.event_bus.get_task_logs(\n task_id, log_filter, task_status=task_status, task_logs=task_logs\n )\n # #endregion get_task_logs\n\n # #region get_task_log_stats [TYPE Function] [C:2]\n # @BRIEF Get statistics about logs for a task.\n def get_task_log_stats(self, task_id: str) -> LogStats:\n return self.event_bus.get_task_log_stats(task_id)\n # #endregion get_task_log_stats\n\n # #region get_task_log_sources [TYPE Function] [C:2]\n # @BRIEF Get unique sources for a task's logs.\n def get_task_log_sources(self, task_id: str) -> list[str]:\n return self.event_bus.get_task_log_sources(task_id)\n # #endregion get_task_log_sources\n\n # ── Subscription delegates to EventBus ──\n\n # #region subscribe_logs [TYPE Function] [C:2]\n # @BRIEF Subscribes to real-time logs for a task.\n async def subscribe_logs(self, task_id: str) -> asyncio.Queue:\n return await self.event_bus.subscribe_logs(task_id)\n # #endregion subscribe_logs\n\n # #region unsubscribe_logs [TYPE Function] [C:2]\n # @BRIEF Unsubscribes from real-time logs for a task.\n def unsubscribe_logs(self, task_id: str, queue: asyncio.Queue):\n self.event_bus.unsubscribe_logs(task_id, queue)\n # #endregion unsubscribe_logs\n\n # ── Lifecycle delegates to JobLifecycle ──\n\n # #region create_task [TYPE Function] [C:4]\n # @BRIEF Creates and queues a new task for execution.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None\n ) -> Task:\n return await self.lifecycle.create_task(\n plugin_id, params, user_id,\n add_log_callback=self._add_log,\n )\n # #endregion create_task\n\n # #region _run_task [TYPE Function] [C:4]\n # @BRIEF Internal method to execute a task with TaskContext support (delegates to lifecycle).\n async def _run_task(self, task_id: str):\n await self.lifecycle._run_task(task_id, add_log_callback=self._add_log)\n # #endregion _run_task\n\n # #region resolve_task [TYPE Function] [C:3]\n # @BRIEF Resumes a task that is awaiting mapping.\n async def resolve_task(self, task_id: str, resolution_params: dict[str, Any]):\n await self.lifecycle.resolve_task(task_id, resolution_params)\n # #endregion resolve_task\n\n # #region wait_for_resolution [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for a resolution signal.\n async def wait_for_resolution(self, task_id: str):\n await self.lifecycle.wait_for_resolution(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for user input.\n async def wait_for_input(self, task_id: str):\n await self.lifecycle.wait_for_input(task_id)\n # #endregion wait_for_input\n\n # #region await_input [TYPE Function] [C:3]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n def await_input(self, task_id: str, input_request: dict[str, Any]) -> None:\n self.lifecycle.await_input(\n task_id, input_request,\n add_log_callback=self._add_log,\n )\n # #endregion await_input\n\n # #region resume_task_with_password [TYPE Function] [C:3]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str]\n ) -> None:\n self.lifecycle.resume_task_with_password(\n task_id, passwords,\n add_log_callback=self._add_log,\n )\n # #endregion resume_task_with_password\n\n # ── Dataset event delegates to JobLifecycle ──\n\n # #region subscribe_dataset_events [TYPE Function] [C:2]\n # @BRIEF Subscribe to dataset.updated events for an environment.\n async def subscribe_dataset_events(self, env_id: str) -> asyncio.Queue:\n return await self.lifecycle.subscribe_dataset_events(env_id)\n # #endregion subscribe_dataset_events\n\n # #region unsubscribe_dataset_events [TYPE Function] [C:2]\n # @BRIEF Unsubscribe from dataset.updated events.\n def unsubscribe_dataset_events(self, env_id: str, queue: asyncio.Queue):\n self.lifecycle.unsubscribe_dataset_events(env_id, queue)\n # #endregion unsubscribe_dataset_events\n# #endregion TaskManager\n# #endregion TaskManagerModule\n" }, { "contract_id": "TaskManager", "contract_type": "Class", "file_path": "backend/src/core/task_manager/manager.py", "start_line": 48, - "end_line": 321, + "end_line": 335, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -26700,7 +28063,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TaskManager [C:5] [TYPE Class] [SEMANTICS task, manager, lifecycle, execution, state]\n# @BRIEF Facade composing TaskGraph, EventBus, and JobLifecycle into a single interface.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @PRE: Plugin loader resolves plugin ids and persistence services are available.\n# @POST: In-memory task graph, lifecycle scheduler, and log event bus stay consistent with\n# persisted task state.\n# @INVARIANT: Task IDs are unique within the registry.\n# @INVARIANT: Each task has exactly one status at any time.\n# @INVARIANT: Log entries are never deleted after being added to a task.\n# @SIDE_EFFECT: Spawns worker threads, flushes logs to database, and mutates task states.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Output[Task]\n# @RATIONALE Thin facade — all delegating methods are under 15 lines. Actual business logic\n# (registry CRUD, log buffering, lifecycle state machine) lives in extracted modules.\n# @REJECTED Keeping all five concerns in one class was rejected — it violated INV_7 (708-line\n# manager.py) and made the god class impossible to test or maintain independently.\nclass TaskManager:\n \"\"\"\n Facade composing TaskGraph (registry), EventBus (log/pub-sub), and\n JobLifecycle (state machine) into a single TaskManager interface.\n \"\"\"\n\n # #region __init__ [TYPE Function] [C:5]\n # @BRIEF Initialize sub-services, create add_log callback, start background flusher.\n # @PRE: plugin_loader is initialized.\n # @POST: TaskManager is ready to accept tasks.\n # @SIDE_EFFECT: Starts background flusher thread and loads persisted task state into memory.\n def __init__(self, plugin_loader):\n with belief_scope(\"TaskManager.__init__\"):\n logger.reason(\"Initializing task manager runtime services\")\n self.plugin_loader = plugin_loader\n self.executor = ThreadPoolExecutor(max_workers=5)\n self.persistence_service = TaskPersistenceService()\n self.log_persistence_service = TaskLogPersistenceService()\n\n try:\n self.loop = asyncio.get_running_loop()\n except RuntimeError:\n self.loop = asyncio.get_event_loop()\n\n # Create sub-services\n self.graph = TaskGraph(self.persistence_service)\n self.event_bus = EventBus(self.log_persistence_service, self.loop)\n\n # Create add_log callback that lifecycle and plugins use\n self._add_log = self._make_add_log_callback()\n\n self.lifecycle = JobLifecycle(\n plugin_loader=self.plugin_loader,\n graph=self.graph,\n event_bus=self.event_bus,\n persistence_service=self.persistence_service,\n executor=self.executor,\n loop=self.loop,\n )\n\n # Load persisted tasks on startup\n self.graph.load_persisted_tasks()\n\n # Backward-compatible property aliases for tests\n self.tasks = self.graph.tasks\n self.task_futures = self.graph.task_futures\n self.subscribers = self.event_bus.subscribers\n self._log_buffer = self.event_bus._log_buffer\n self._log_buffer_lock = self.event_bus._log_buffer_lock\n self._flusher_stop_event = self.event_bus._flusher_stop_event\n self._flusher_thread = self.event_bus._flusher_thread\n\n logger.reflect(\n \"Task manager runtime initialized\",\n extra={\"task_count\": len(self.tasks)},\n )\n # #endregion __init__\n\n # #region _make_add_log_callback [C:2] [TYPE Function]\n # @BRIEF Create a closure for adding logs that looks up the task and delegates to EventBus.\n def _make_add_log_callback(self):\n def _add_log(task_id, level, message, source=\"system\", metadata=None, context=None):\n task = self.graph.get_task(task_id)\n if not task:\n return\n self.event_bus.add_log(\n task_id, level, message, source, metadata, context,\n task_logs_list=task.logs,\n )\n return _add_log\n # #endregion _make_add_log_callback\n\n # ── Deprecated legacy aliases (delegate to EventBus) ──\n\n # #region _flusher_loop [C:3] [TYPE Function] [SEMANTICS flush,background,thread]\n # @BRIEF Legacy alias delegating to EventBus._flusher_loop.\n def _flusher_loop(self):\n self.event_bus._flusher_loop()\n # #endregion _flusher_loop\n\n # #region _flush_logs [C:3] [TYPE Function] [SEMANTICS flush,batch,persistence]\n # @BRIEF Legacy alias delegating to EventBus._flush_logs.\n def _flush_logs(self):\n self.event_bus._flush_logs()\n # #endregion _flush_logs\n\n # #region _flush_task_logs [C:3] [TYPE Function] [SEMANTICS flush,single,persistence]\n # @BRIEF Legacy alias delegating to EventBus.flush_task_logs.\n def _flush_task_logs(self, task_id: str):\n self.event_bus.flush_task_logs(task_id)\n # #endregion _flush_task_logs\n\n # ── Task CRUD delegates to TaskGraph ──\n\n # #region get_task [TYPE Function] [C:2]\n # @BRIEF Retrieves a task by its ID.\n def get_task(self, task_id: str) -> Task | None:\n return self.graph.get_task(task_id)\n # #endregion get_task\n\n # #region get_all_tasks [TYPE Function] [C:1]\n # @BRIEF Retrieves all registered tasks.\n def get_all_tasks(self) -> list[Task]:\n return self.graph.get_all_tasks()\n # #endregion get_all_tasks\n\n # #region get_tasks [TYPE Function] [C:3]\n # @BRIEF Retrieves tasks with pagination and optional status filter.\n def get_tasks(\n self,\n limit: int = 10,\n offset: int = 0,\n status: TaskStatus | None = None,\n plugin_ids: list[str] | None = None,\n completed_only: bool = False,\n ) -> list[Task]:\n return self.graph.get_tasks(limit, offset, status, plugin_ids, completed_only)\n # #endregion get_tasks\n\n # #region load_persisted_tasks [TYPE Function] [C:2]\n # @BRIEF Load persisted tasks using persistence service.\n def load_persisted_tasks(self) -> None:\n self.graph.load_persisted_tasks(limit=100)\n # #endregion load_persisted_tasks\n\n # #region clear_tasks [TYPE Function] [C:4]\n # @BRIEF Clears tasks based on status filter (also deletes associated logs).\n # @SIDE_EFFECT Removes tasks from registry and persistence; cancels futures.\n def clear_tasks(self, status: TaskStatus | None = None) -> int:\n with belief_scope(\"TaskManager.clear_tasks\"):\n tasks_to_remove = []\n for task_id, task in list(self.tasks.items()):\n should_remove = False\n if status:\n if task.status == status:\n should_remove = True\n else:\n if task.status not in [\n TaskStatus.RUNNING,\n TaskStatus.AWAITING_INPUT,\n TaskStatus.AWAITING_MAPPING,\n ]:\n should_remove = True\n if should_remove:\n tasks_to_remove.append(task_id)\n\n # Delete logs first, then remove tasks\n if tasks_to_remove:\n self.event_bus.delete_logs_for_tasks(tasks_to_remove)\n removed = self.graph.remove_tasks(tasks_to_remove)\n logger.info(f\"Cleared {removed} tasks.\")\n return removed\n # #endregion clear_tasks\n\n # ── Log delegates to EventBus ──\n\n # #region get_task_logs [TYPE Function] [C:3]\n # @BRIEF Retrieves logs for a specific task (from memory or persistence).\n def get_task_logs(\n self, task_id: str, log_filter: LogFilter | None = None\n ) -> list:\n task = self.graph.get_task(task_id)\n task_status = task.status if task else None\n task_logs = task.logs if task else []\n return self.event_bus.get_task_logs(\n task_id, log_filter, task_status=task_status, task_logs=task_logs\n )\n # #endregion get_task_logs\n\n # #region get_task_log_stats [TYPE Function] [C:2]\n # @BRIEF Get statistics about logs for a task.\n def get_task_log_stats(self, task_id: str) -> LogStats:\n return self.event_bus.get_task_log_stats(task_id)\n # #endregion get_task_log_stats\n\n # #region get_task_log_sources [TYPE Function] [C:2]\n # @BRIEF Get unique sources for a task's logs.\n def get_task_log_sources(self, task_id: str) -> list[str]:\n return self.event_bus.get_task_log_sources(task_id)\n # #endregion get_task_log_sources\n\n # ── Subscription delegates to EventBus ──\n\n # #region subscribe_logs [TYPE Function] [C:2]\n # @BRIEF Subscribes to real-time logs for a task.\n async def subscribe_logs(self, task_id: str) -> asyncio.Queue:\n return await self.event_bus.subscribe_logs(task_id)\n # #endregion subscribe_logs\n\n # #region unsubscribe_logs [TYPE Function] [C:2]\n # @BRIEF Unsubscribes from real-time logs for a task.\n def unsubscribe_logs(self, task_id: str, queue: asyncio.Queue):\n self.event_bus.unsubscribe_logs(task_id, queue)\n # #endregion unsubscribe_logs\n\n # ── Lifecycle delegates to JobLifecycle ──\n\n # #region create_task [TYPE Function] [C:4]\n # @BRIEF Creates and queues a new task for execution.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None\n ) -> Task:\n return await self.lifecycle.create_task(\n plugin_id, params, user_id,\n add_log_callback=self._add_log,\n )\n # #endregion create_task\n\n # #region _run_task [TYPE Function] [C:4]\n # @BRIEF Internal method to execute a task with TaskContext support (delegates to lifecycle).\n async def _run_task(self, task_id: str):\n await self.lifecycle._run_task(task_id, add_log_callback=self._add_log)\n # #endregion _run_task\n\n # #region resolve_task [TYPE Function] [C:3]\n # @BRIEF Resumes a task that is awaiting mapping.\n async def resolve_task(self, task_id: str, resolution_params: dict[str, Any]):\n await self.lifecycle.resolve_task(task_id, resolution_params)\n # #endregion resolve_task\n\n # #region wait_for_resolution [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for a resolution signal.\n async def wait_for_resolution(self, task_id: str):\n await self.lifecycle.wait_for_resolution(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for user input.\n async def wait_for_input(self, task_id: str):\n await self.lifecycle.wait_for_input(task_id)\n # #endregion wait_for_input\n\n # #region await_input [TYPE Function] [C:3]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n def await_input(self, task_id: str, input_request: dict[str, Any]) -> None:\n self.lifecycle.await_input(\n task_id, input_request,\n add_log_callback=self._add_log,\n )\n # #endregion await_input\n\n # #region resume_task_with_password [TYPE Function] [C:3]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str]\n ) -> None:\n self.lifecycle.resume_task_with_password(\n task_id, passwords,\n add_log_callback=self._add_log,\n )\n # #endregion resume_task_with_password\n# #endregion TaskManager\n" + "body": "# #region TaskManager [C:5] [TYPE Class] [SEMANTICS task, manager, lifecycle, execution, state]\n# @BRIEF Facade composing TaskGraph, EventBus, and JobLifecycle into a single interface.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> [TaskPersistenceService]\n# @RELATION DEPENDS_ON -> [TaskLogPersistenceService]\n# @RELATION DEPENDS_ON -> [PluginLoader]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @RELATION DEPENDS_ON -> [TaskGraph]\n# @RELATION DEPENDS_ON -> [JobLifecycle]\n# @RELATION DEPENDS_ON -> [EventBus]\n# @PRE: Plugin loader resolves plugin ids and persistence services are available.\n# @POST: In-memory task graph, lifecycle scheduler, and log event bus stay consistent with\n# persisted task state.\n# @INVARIANT: Task IDs are unique within the registry.\n# @INVARIANT: Each task has exactly one status at any time.\n# @INVARIANT: Log entries are never deleted after being added to a task.\n# @SIDE_EFFECT: Spawns worker threads, flushes logs to database, and mutates task states.\n# @DATA_CONTRACT: Input[plugin_id, params] -> Output[Task]\n# @RATIONALE Thin facade — all delegating methods are under 15 lines. Actual business logic\n# (registry CRUD, log buffering, lifecycle state machine) lives in extracted modules.\n# @REJECTED Keeping all five concerns in one class was rejected — it violated INV_7 (708-line\n# manager.py) and made the god class impossible to test or maintain independently.\nclass TaskManager:\n \"\"\"\n Facade composing TaskGraph (registry), EventBus (log/pub-sub), and\n JobLifecycle (state machine) into a single TaskManager interface.\n \"\"\"\n\n # #region __init__ [TYPE Function] [C:5]\n # @BRIEF Initialize sub-services, create add_log callback, start background flusher.\n # @PRE: plugin_loader is initialized.\n # @POST: TaskManager is ready to accept tasks.\n # @SIDE_EFFECT: Starts background flusher thread and loads persisted task state into memory.\n def __init__(self, plugin_loader):\n with belief_scope(\"TaskManager.__init__\"):\n logger.reason(\"Initializing task manager runtime services\")\n self.plugin_loader = plugin_loader\n self.executor = ThreadPoolExecutor(max_workers=5)\n self.persistence_service = TaskPersistenceService()\n self.log_persistence_service = TaskLogPersistenceService()\n\n try:\n self.loop = asyncio.get_running_loop()\n except RuntimeError:\n self.loop = asyncio.get_event_loop()\n\n # Create sub-services\n self.graph = TaskGraph(self.persistence_service)\n self.event_bus = EventBus(self.log_persistence_service, self.loop)\n\n # Create add_log callback that lifecycle and plugins use\n self._add_log = self._make_add_log_callback()\n\n self.lifecycle = JobLifecycle(\n plugin_loader=self.plugin_loader,\n graph=self.graph,\n event_bus=self.event_bus,\n persistence_service=self.persistence_service,\n executor=self.executor,\n loop=self.loop,\n )\n\n # Load persisted tasks on startup\n self.graph.load_persisted_tasks()\n\n # Backward-compatible property aliases for tests\n self.tasks = self.graph.tasks\n self.task_futures = self.graph.task_futures\n self.subscribers = self.event_bus.subscribers\n self._log_buffer = self.event_bus._log_buffer\n self._log_buffer_lock = self.event_bus._log_buffer_lock\n self._flusher_stop_event = self.event_bus._flusher_stop_event\n self._flusher_thread = self.event_bus._flusher_thread\n\n logger.reflect(\n \"Task manager runtime initialized\",\n extra={\"task_count\": len(self.tasks)},\n )\n # #endregion __init__\n\n # #region _make_add_log_callback [C:2] [TYPE Function]\n # @BRIEF Create a closure for adding logs that looks up the task and delegates to EventBus.\n def _make_add_log_callback(self):\n def _add_log(task_id, level, message, source=\"system\", metadata=None, context=None):\n task = self.graph.get_task(task_id)\n if not task:\n return\n self.event_bus.add_log(\n task_id, level, message, source, metadata, context,\n task_logs_list=task.logs,\n )\n return _add_log\n # #endregion _make_add_log_callback\n\n # ── Deprecated legacy aliases (delegate to EventBus) ──\n\n # #region _flusher_loop [C:3] [TYPE Function] [SEMANTICS flush,background,thread]\n # @BRIEF Legacy alias delegating to EventBus._flusher_loop.\n def _flusher_loop(self):\n self.event_bus._flusher_loop()\n # #endregion _flusher_loop\n\n # #region _flush_logs [C:3] [TYPE Function] [SEMANTICS flush,batch,persistence]\n # @BRIEF Legacy alias delegating to EventBus._flush_logs.\n def _flush_logs(self):\n self.event_bus._flush_logs()\n # #endregion _flush_logs\n\n # #region _flush_task_logs [C:3] [TYPE Function] [SEMANTICS flush,single,persistence]\n # @BRIEF Legacy alias delegating to EventBus.flush_task_logs.\n def _flush_task_logs(self, task_id: str):\n self.event_bus.flush_task_logs(task_id)\n # #endregion _flush_task_logs\n\n # ── Task CRUD delegates to TaskGraph ──\n\n # #region get_task [TYPE Function] [C:2]\n # @BRIEF Retrieves a task by its ID.\n def get_task(self, task_id: str) -> Task | None:\n return self.graph.get_task(task_id)\n # #endregion get_task\n\n # #region get_all_tasks [TYPE Function] [C:1]\n # @BRIEF Retrieves all registered tasks.\n def get_all_tasks(self) -> list[Task]:\n return self.graph.get_all_tasks()\n # #endregion get_all_tasks\n\n # #region get_tasks [TYPE Function] [C:3]\n # @BRIEF Retrieves tasks with pagination and optional status filter.\n def get_tasks(\n self,\n limit: int = 10,\n offset: int = 0,\n status: TaskStatus | None = None,\n plugin_ids: list[str] | None = None,\n completed_only: bool = False,\n ) -> list[Task]:\n return self.graph.get_tasks(limit, offset, status, plugin_ids, completed_only)\n # #endregion get_tasks\n\n # #region load_persisted_tasks [TYPE Function] [C:2]\n # @BRIEF Load persisted tasks using persistence service.\n def load_persisted_tasks(self) -> None:\n self.graph.load_persisted_tasks(limit=100)\n # #endregion load_persisted_tasks\n\n # #region clear_tasks [TYPE Function] [C:4]\n # @BRIEF Clears tasks based on status filter (also deletes associated logs).\n # @SIDE_EFFECT Removes tasks from registry and persistence; cancels futures.\n def clear_tasks(self, status: TaskStatus | None = None) -> int:\n with belief_scope(\"TaskManager.clear_tasks\"):\n tasks_to_remove = []\n for task_id, task in list(self.tasks.items()):\n should_remove = False\n if status:\n if task.status == status:\n should_remove = True\n else:\n if task.status not in [\n TaskStatus.RUNNING,\n TaskStatus.AWAITING_INPUT,\n TaskStatus.AWAITING_MAPPING,\n ]:\n should_remove = True\n if should_remove:\n tasks_to_remove.append(task_id)\n\n # Delete logs first, then remove tasks\n if tasks_to_remove:\n self.event_bus.delete_logs_for_tasks(tasks_to_remove)\n removed = self.graph.remove_tasks(tasks_to_remove)\n logger.info(f\"Cleared {removed} tasks.\")\n return removed\n # #endregion clear_tasks\n\n # ── Log delegates to EventBus ──\n\n # #region get_task_logs [TYPE Function] [C:3]\n # @BRIEF Retrieves logs for a specific task (from memory or persistence).\n def get_task_logs(\n self, task_id: str, log_filter: LogFilter | None = None\n ) -> list:\n task = self.graph.get_task(task_id)\n task_status = task.status if task else None\n task_logs = task.logs if task else []\n return self.event_bus.get_task_logs(\n task_id, log_filter, task_status=task_status, task_logs=task_logs\n )\n # #endregion get_task_logs\n\n # #region get_task_log_stats [TYPE Function] [C:2]\n # @BRIEF Get statistics about logs for a task.\n def get_task_log_stats(self, task_id: str) -> LogStats:\n return self.event_bus.get_task_log_stats(task_id)\n # #endregion get_task_log_stats\n\n # #region get_task_log_sources [TYPE Function] [C:2]\n # @BRIEF Get unique sources for a task's logs.\n def get_task_log_sources(self, task_id: str) -> list[str]:\n return self.event_bus.get_task_log_sources(task_id)\n # #endregion get_task_log_sources\n\n # ── Subscription delegates to EventBus ──\n\n # #region subscribe_logs [TYPE Function] [C:2]\n # @BRIEF Subscribes to real-time logs for a task.\n async def subscribe_logs(self, task_id: str) -> asyncio.Queue:\n return await self.event_bus.subscribe_logs(task_id)\n # #endregion subscribe_logs\n\n # #region unsubscribe_logs [TYPE Function] [C:2]\n # @BRIEF Unsubscribes from real-time logs for a task.\n def unsubscribe_logs(self, task_id: str, queue: asyncio.Queue):\n self.event_bus.unsubscribe_logs(task_id, queue)\n # #endregion unsubscribe_logs\n\n # ── Lifecycle delegates to JobLifecycle ──\n\n # #region create_task [TYPE Function] [C:4]\n # @BRIEF Creates and queues a new task for execution.\n async def create_task(\n self, plugin_id: str, params: dict[str, Any], user_id: str | None = None\n ) -> Task:\n return await self.lifecycle.create_task(\n plugin_id, params, user_id,\n add_log_callback=self._add_log,\n )\n # #endregion create_task\n\n # #region _run_task [TYPE Function] [C:4]\n # @BRIEF Internal method to execute a task with TaskContext support (delegates to lifecycle).\n async def _run_task(self, task_id: str):\n await self.lifecycle._run_task(task_id, add_log_callback=self._add_log)\n # #endregion _run_task\n\n # #region resolve_task [TYPE Function] [C:3]\n # @BRIEF Resumes a task that is awaiting mapping.\n async def resolve_task(self, task_id: str, resolution_params: dict[str, Any]):\n await self.lifecycle.resolve_task(task_id, resolution_params)\n # #endregion resolve_task\n\n # #region wait_for_resolution [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for a resolution signal.\n async def wait_for_resolution(self, task_id: str):\n await self.lifecycle.wait_for_resolution(task_id)\n # #endregion wait_for_resolution\n\n # #region wait_for_input [TYPE Function] [C:3]\n # @BRIEF Pauses execution and waits for user input.\n async def wait_for_input(self, task_id: str):\n await self.lifecycle.wait_for_input(task_id)\n # #endregion wait_for_input\n\n # #region await_input [TYPE Function] [C:3]\n # @BRIEF Transition a task to AWAITING_INPUT state with input request.\n def await_input(self, task_id: str, input_request: dict[str, Any]) -> None:\n self.lifecycle.await_input(\n task_id, input_request,\n add_log_callback=self._add_log,\n )\n # #endregion await_input\n\n # #region resume_task_with_password [TYPE Function] [C:3]\n # @BRIEF Resume a task that is awaiting input with provided passwords.\n def resume_task_with_password(\n self, task_id: str, passwords: dict[str, str]\n ) -> None:\n self.lifecycle.resume_task_with_password(\n task_id, passwords,\n add_log_callback=self._add_log,\n )\n # #endregion resume_task_with_password\n\n # ── Dataset event delegates to JobLifecycle ──\n\n # #region subscribe_dataset_events [TYPE Function] [C:2]\n # @BRIEF Subscribe to dataset.updated events for an environment.\n async def subscribe_dataset_events(self, env_id: str) -> asyncio.Queue:\n return await self.lifecycle.subscribe_dataset_events(env_id)\n # #endregion subscribe_dataset_events\n\n # #region unsubscribe_dataset_events [TYPE Function] [C:2]\n # @BRIEF Unsubscribe from dataset.updated events.\n def unsubscribe_dataset_events(self, env_id: str, queue: asyncio.Queue):\n self.lifecycle.unsubscribe_dataset_events(env_id, queue)\n # #endregion unsubscribe_dataset_events\n# #endregion TaskManager\n" }, { "contract_id": "_make_add_log_callback", @@ -27668,96 +29031,53 @@ "contract_type": "Module", "file_path": "backend/src/core/utils/dataset_mapper.py", "start_line": 1, - "end_line": 225, + "end_line": 238, "tier": "TIER_1", "complexity": 1, "metadata": { - "LAYER": "Domain", - "PUBLIC_API": "DatasetMapper", - "PURPOSE": "Этот модуль отвечает за обновление метаданных (verbose_map) в датасетах Superset, извлекая их из PostgreSQL или XLSX-файлов." + "PURPOSE": "Этот модуль отвечает за обновление метаданных (verbose_name) в датасетах Superset," }, - "relations": [ - { - "source_id": "DatasetMapperModule", - "relation_type": "DEPENDS_ON", - "target_id": "backend.core.superset_client", - "target_ref": "backend.core.superset_client" - }, - { - "source_id": "DatasetMapperModule", - "relation_type": "DEPENDS_ON", - "target_id": "pandas", - "target_ref": "pandas" - }, - { - "source_id": "DatasetMapperModule", - "relation_type": "DEPENDS_ON", - "target_id": "psycopg2", - "target_ref": "psycopg2" - } - ], + "relations": [], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetMapperModule [TYPE Module] [SEMANTICS dataset, superset, dataset-mapper]\n#\n# @BRIEF Этот модуль отвечает за обновление метаданных (verbose_map) в датасетах Superset, извлекая их из PostgreSQL или XLSX-файлов.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> backend.core.superset_client\n# @RELATION DEPENDS_ON -> pandas\n# @RELATION DEPENDS_ON -> psycopg2\n# @PUBLIC_API: DatasetMapper\nfrom typing import Any\n\nimport pandas as pd # type: ignore\nimport psycopg2 # type: ignore\n\nfrom ..logger import belief_scope, logger as app_logger\n\n\n# #region DatasetMapper [TYPE Class]\n# @BRIEF Класс для меппинга и обновления verbose_map в датасетах Superset.\nclass DatasetMapper:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the mapper.\n # @POST: Объект DatasetMapper инициализирован.\n def __init__(self):\n pass\n # #endregion __init__\n # #region get_postgres_comments [TYPE Function]\n # @PURPOSE: Извлекает комментарии к колонкам из системного каталога PostgreSQL.\n # @PRE: db_config должен содержать валидные параметры подключения (host, port, user, password, dbname).\n # @PRE: table_name и table_schema должны быть строками.\n # @POST: Возвращается словарь, где ключи - имена колонок, значения - комментарии из БД.\n # @THROW: Exception - При ошибках подключения или выполнения запроса к БД.\n # @PARAM: db_config (Dict) - Конфигурация для подключения к БД.\n # @PARAM: table_name (str) - Имя таблицы.\n # @PARAM: table_schema (str) - Схема таблицы.\n # @RETURN: Dict[str, str] - Словарь с комментариями к колонкам.\n def get_postgres_comments(self, db_config: dict, table_name: str, table_schema: str) -> dict[str, str]:\n with belief_scope(\"Fetch comments from PostgreSQL\"):\n app_logger.info(\"[get_postgres_comments][Enter] Fetching comments from PostgreSQL for %s.%s.\", table_schema, table_name)\n query = f\"\"\"\n SELECT \n cols.column_name,\n CASE \n WHEN pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ) LIKE '%|%' THEN \n split_part(\n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ), \n '|', \n 1\n )\n ELSE \n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n )\n END AS column_comment\n FROM \n information_schema.columns cols \n WHERE cols.table_catalog = '{db_config.get('dbname')}' AND cols.table_name = '{table_name}' AND cols.table_schema = '{table_schema}';\n \"\"\"\n comments = {}\n try:\n with psycopg2.connect(**db_config) as conn, conn.cursor() as cursor:\n cursor.execute(query)\n for row in cursor.fetchall():\n if row[1]:\n comments[row[0]] = row[1]\n app_logger.info(\"[get_postgres_comments][Success] Fetched %d comments.\", len(comments))\n except Exception as e:\n app_logger.error(\"[get_postgres_comments][Failure] %s\", e, exc_info=True)\n raise\n return comments\n # #endregion get_postgres_comments\n # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает меппинги 'column_name' -> 'column_comment' из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с меппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с меппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения меппинга и обновления verbose_map датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_postgres_comments\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('postgres', 'excel', 'both').\n # @PARAM: postgres_config (Optional[Dict]) - Конфигурация для подключения к PostgreSQL.\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n # @PARAM: table_name (Optional[str]) - Имя таблицы в PostgreSQL.\n # @PARAM: table_schema (Optional[str]) - Схема таблицы в PostgreSQL.\n def run_mapping(self, superset_client: Any, dataset_id: int, source: str, postgres_config: dict | None = None, excel_path: str | None = None, table_name: str | None = None, table_schema: str | None = None):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source in ['postgres', 'both']:\n assert postgres_config and table_name and table_schema, \"Postgres config is required.\"\n mappings.update(self.get_postgres_comments(postgres_config, table_name, table_schema))\n if source in ['excel', 'both']:\n assert excel_path, \"Excel path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n if source not in ['postgres', 'excel', 'both']:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n# #endregion DatasetMapper\n# #endregion DatasetMapperModule\n" + "body": "# #region DatasetMapperModule [TYPE Module] [SEMANTICS dataset, superset, dataset-mapper, sqllab]\n#\n# @BRIEF Этот модуль отвечает за обновление метаданных (verbose_name) в датасетах Superset,\n# извлекая их из Superset SQL Lab (любая БД, подключённая к Superset) или XLSX-файлов.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> backend.core.superset_client\n# @RELATION DEPENDS_ON -> pandas\n# @PUBLIC_API: DatasetMapper\nfrom typing import Any\n\nimport pandas as pd # type: ignore\n\nfrom ..logger import belief_scope, logger as app_logger\n\n\n# #region DatasetMapper [TYPE Class]\n# @BRIEF Класс для маппинга и обновления verbose_name в датасетах Superset.\nclass DatasetMapper:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the mapper.\n # @POST: Объект DatasetMapper инициализирован.\n def __init__(self):\n pass\n # #endregion __init__\n\n # #region get_sqllab_mappings [TYPE Function]\n # @PURPOSE: Извлекает маппинги column_name -> verbose_name через SQL Lab Superset.\n # @PRE: sqllab_executor должен быть инициализирован с database_id.\n # @PRE: dataset_id должен существовать в Superset.\n # @POST: Возвращается словарь column_name -> verbose_name из результатов SQL-запроса.\n # Если sql_query не указан, строится запрос к information_schema.columns.\n # @PARAM: client (SupersetClient) - Авторизованный клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета (для получения table_name/schema).\n # @PARAM: sqllab_executor (SupersetSqlLabExecutor) - Исполнитель SQL Lab.\n # @PARAM: database_id (int) - ID базы данных в Superset.\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (должен вернуть column_name + verbose_name).\n # @RETURN: Dict[str, str] - Словарь column_name -> verbose_name.\n def get_sqllab_mappings(\n self,\n client: Any,\n dataset_id: int,\n sqllab_executor: Any,\n database_id: int,\n sql_query: str | None = None,\n ) -> dict[str, str]:\n with belief_scope(\"Fetch mappings via SQL Lab\"):\n # Получаем датасет из Superset, чтобы узнать table_name и schema\n dataset_response = client.get_dataset(dataset_id)\n dataset_data = dataset_response.get(\"result\", dataset_response)\n table_name = dataset_data.get(\"table_name\")\n table_schema = dataset_data.get(\"schema\") or \"public\"\n database_name = dataset_data.get(\"database\", {}).get(\"database_name\", \"\")\n\n app_logger.info(\n \"[get_sqllab_mappings] Dataset %d: %s.%s (db: %s)\",\n dataset_id, table_schema, table_name, database_name\n )\n\n # Если SQL-запрос не указан, строим дефолтный для information_schema\n if not sql_query:\n sql_query = (\n \"SELECT column_name, pg_catalog.col_description(\\n\"\n \" (quote_ident(table_schema) || '.' || quote_ident(table_name))::regclass::oid,\\n\"\n \" ordinal_position\\n\"\n \") AS verbose_name\\n\"\n f\"FROM information_schema.columns\\n\"\n f\"WHERE table_schema = '{table_schema}' AND table_name = '{table_name}';\\n\"\n )\n app_logger.info(\"[get_sqllab_mappings] Using default information_schema query for %s.%s\", table_schema, table_name)\n else:\n app_logger.info(\"[get_sqllab_mappings] Using custom SQL query\")\n\n # Выполняем запрос через SQL Lab\n app_logger.info(\"[get_sqllab_mappings] Executing SQL Lab query on database %d...\", database_id)\n result = sqllab_executor.execute_and_poll(sql_query, database_id)\n rows = result.get(\"results\") or result.get(\"data\") or result.get(\"result\", [])\n app_logger.info(\"[get_sqllab_mappings] SQL Lab returned %d rows\", len(rows))\n\n mappings: dict[str, str] = {}\n for row in rows:\n col_name = row.get(\"column_name\")\n verbose_name = row.get(\"verbose_name\")\n if col_name and verbose_name:\n mappings[col_name] = str(verbose_name)\n\n app_logger.info(\"[get_sqllab_mappings] Extracted %d mappings\", len(mappings))\n return mappings\n # #endregion get_sqllab_mappings\n\n # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает маппинги column_name -> verbose_name из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с маппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с маппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n\n # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения маппинга и обновления verbose_name датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_sqllab_mappings\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('sqllab' или 'excel').\n # @PARAM: sqllab_executor (Optional[Any]) - Исполнитель SQL Lab (для sqllab source).\n # @PARAM: database_id (Optional[int]) - ID базы данных Superset (для sqllab source).\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (для sqllab source).\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n def run_mapping(\n self,\n superset_client: Any,\n dataset_id: int,\n source: str,\n sqllab_executor: Any = None,\n database_id: int | None = None,\n sql_query: str | None = None,\n excel_path: str | None = None,\n ):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source == \"sqllab\":\n assert sqllab_executor and database_id, \"sqllab_executor and database_id are required for sqllab source.\"\n mappings.update(self.get_sqllab_mappings(superset_client, dataset_id, sqllab_executor, database_id, sql_query))\n elif source == \"excel\":\n assert excel_path, \"excel_path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n else:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n# #endregion DatasetMapper\n# #endregion DatasetMapperModule\n" }, { "contract_id": "DatasetMapper", "contract_type": "Class", "file_path": "backend/src/core/utils/dataset_mapper.py", - "start_line": 17, - "end_line": 224, + "start_line": 16, + "end_line": 237, "tier": "TIER_1", "complexity": 1, "metadata": { - "PURPOSE": "Класс для меппинга и обновления verbose_map в датасетах Superset." + "PURPOSE": "Класс для маппинга и обновления verbose_name в датасетах Superset." }, "relations": [], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetMapper [TYPE Class]\n# @BRIEF Класс для меппинга и обновления verbose_map в датасетах Superset.\nclass DatasetMapper:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the mapper.\n # @POST: Объект DatasetMapper инициализирован.\n def __init__(self):\n pass\n # #endregion __init__\n # #region get_postgres_comments [TYPE Function]\n # @PURPOSE: Извлекает комментарии к колонкам из системного каталога PostgreSQL.\n # @PRE: db_config должен содержать валидные параметры подключения (host, port, user, password, dbname).\n # @PRE: table_name и table_schema должны быть строками.\n # @POST: Возвращается словарь, где ключи - имена колонок, значения - комментарии из БД.\n # @THROW: Exception - При ошибках подключения или выполнения запроса к БД.\n # @PARAM: db_config (Dict) - Конфигурация для подключения к БД.\n # @PARAM: table_name (str) - Имя таблицы.\n # @PARAM: table_schema (str) - Схема таблицы.\n # @RETURN: Dict[str, str] - Словарь с комментариями к колонкам.\n def get_postgres_comments(self, db_config: dict, table_name: str, table_schema: str) -> dict[str, str]:\n with belief_scope(\"Fetch comments from PostgreSQL\"):\n app_logger.info(\"[get_postgres_comments][Enter] Fetching comments from PostgreSQL for %s.%s.\", table_schema, table_name)\n query = f\"\"\"\n SELECT \n cols.column_name,\n CASE \n WHEN pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ) LIKE '%|%' THEN \n split_part(\n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ), \n '|', \n 1\n )\n ELSE \n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n )\n END AS column_comment\n FROM \n information_schema.columns cols \n WHERE cols.table_catalog = '{db_config.get('dbname')}' AND cols.table_name = '{table_name}' AND cols.table_schema = '{table_schema}';\n \"\"\"\n comments = {}\n try:\n with psycopg2.connect(**db_config) as conn, conn.cursor() as cursor:\n cursor.execute(query)\n for row in cursor.fetchall():\n if row[1]:\n comments[row[0]] = row[1]\n app_logger.info(\"[get_postgres_comments][Success] Fetched %d comments.\", len(comments))\n except Exception as e:\n app_logger.error(\"[get_postgres_comments][Failure] %s\", e, exc_info=True)\n raise\n return comments\n # #endregion get_postgres_comments\n # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает меппинги 'column_name' -> 'column_comment' из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с меппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с меппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения меппинга и обновления verbose_map датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_postgres_comments\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('postgres', 'excel', 'both').\n # @PARAM: postgres_config (Optional[Dict]) - Конфигурация для подключения к PostgreSQL.\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n # @PARAM: table_name (Optional[str]) - Имя таблицы в PostgreSQL.\n # @PARAM: table_schema (Optional[str]) - Схема таблицы в PostgreSQL.\n def run_mapping(self, superset_client: Any, dataset_id: int, source: str, postgres_config: dict | None = None, excel_path: str | None = None, table_name: str | None = None, table_schema: str | None = None):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source in ['postgres', 'both']:\n assert postgres_config and table_name and table_schema, \"Postgres config is required.\"\n mappings.update(self.get_postgres_comments(postgres_config, table_name, table_schema))\n if source in ['excel', 'both']:\n assert excel_path, \"Excel path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n if source not in ['postgres', 'excel', 'both']:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n# #endregion DatasetMapper\n" + "body": "# #region DatasetMapper [TYPE Class]\n# @BRIEF Класс для маппинга и обновления verbose_name в датасетах Superset.\nclass DatasetMapper:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the mapper.\n # @POST: Объект DatasetMapper инициализирован.\n def __init__(self):\n pass\n # #endregion __init__\n\n # #region get_sqllab_mappings [TYPE Function]\n # @PURPOSE: Извлекает маппинги column_name -> verbose_name через SQL Lab Superset.\n # @PRE: sqllab_executor должен быть инициализирован с database_id.\n # @PRE: dataset_id должен существовать в Superset.\n # @POST: Возвращается словарь column_name -> verbose_name из результатов SQL-запроса.\n # Если sql_query не указан, строится запрос к information_schema.columns.\n # @PARAM: client (SupersetClient) - Авторизованный клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета (для получения table_name/schema).\n # @PARAM: sqllab_executor (SupersetSqlLabExecutor) - Исполнитель SQL Lab.\n # @PARAM: database_id (int) - ID базы данных в Superset.\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (должен вернуть column_name + verbose_name).\n # @RETURN: Dict[str, str] - Словарь column_name -> verbose_name.\n def get_sqllab_mappings(\n self,\n client: Any,\n dataset_id: int,\n sqllab_executor: Any,\n database_id: int,\n sql_query: str | None = None,\n ) -> dict[str, str]:\n with belief_scope(\"Fetch mappings via SQL Lab\"):\n # Получаем датасет из Superset, чтобы узнать table_name и schema\n dataset_response = client.get_dataset(dataset_id)\n dataset_data = dataset_response.get(\"result\", dataset_response)\n table_name = dataset_data.get(\"table_name\")\n table_schema = dataset_data.get(\"schema\") or \"public\"\n database_name = dataset_data.get(\"database\", {}).get(\"database_name\", \"\")\n\n app_logger.info(\n \"[get_sqllab_mappings] Dataset %d: %s.%s (db: %s)\",\n dataset_id, table_schema, table_name, database_name\n )\n\n # Если SQL-запрос не указан, строим дефолтный для information_schema\n if not sql_query:\n sql_query = (\n \"SELECT column_name, pg_catalog.col_description(\\n\"\n \" (quote_ident(table_schema) || '.' || quote_ident(table_name))::regclass::oid,\\n\"\n \" ordinal_position\\n\"\n \") AS verbose_name\\n\"\n f\"FROM information_schema.columns\\n\"\n f\"WHERE table_schema = '{table_schema}' AND table_name = '{table_name}';\\n\"\n )\n app_logger.info(\"[get_sqllab_mappings] Using default information_schema query for %s.%s\", table_schema, table_name)\n else:\n app_logger.info(\"[get_sqllab_mappings] Using custom SQL query\")\n\n # Выполняем запрос через SQL Lab\n app_logger.info(\"[get_sqllab_mappings] Executing SQL Lab query on database %d...\", database_id)\n result = sqllab_executor.execute_and_poll(sql_query, database_id)\n rows = result.get(\"results\") or result.get(\"data\") or result.get(\"result\", [])\n app_logger.info(\"[get_sqllab_mappings] SQL Lab returned %d rows\", len(rows))\n\n mappings: dict[str, str] = {}\n for row in rows:\n col_name = row.get(\"column_name\")\n verbose_name = row.get(\"verbose_name\")\n if col_name and verbose_name:\n mappings[col_name] = str(verbose_name)\n\n app_logger.info(\"[get_sqllab_mappings] Extracted %d mappings\", len(mappings))\n return mappings\n # #endregion get_sqllab_mappings\n\n # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает маппинги column_name -> verbose_name из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с маппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с маппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n\n # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения маппинга и обновления verbose_name датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_sqllab_mappings\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('sqllab' или 'excel').\n # @PARAM: sqllab_executor (Optional[Any]) - Исполнитель SQL Lab (для sqllab source).\n # @PARAM: database_id (Optional[int]) - ID базы данных Superset (для sqllab source).\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (для sqllab source).\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n def run_mapping(\n self,\n superset_client: Any,\n dataset_id: int,\n source: str,\n sqllab_executor: Any = None,\n database_id: int | None = None,\n sql_query: str | None = None,\n excel_path: str | None = None,\n ):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source == \"sqllab\":\n assert sqllab_executor and database_id, \"sqllab_executor and database_id are required for sqllab source.\"\n mappings.update(self.get_sqllab_mappings(superset_client, dataset_id, sqllab_executor, database_id, sql_query))\n elif source == \"excel\":\n assert excel_path, \"excel_path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n else:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n# #endregion DatasetMapper\n" }, { - "contract_id": "get_postgres_comments", + "contract_id": "get_sqllab_mappings", "contract_type": "Function", "file_path": "backend/src/core/utils/dataset_mapper.py", "start_line": 26, - "end_line": 89, + "end_line": 88, "tier": "TIER_1", "complexity": 1, "metadata": { - "PARAM": "table_schema (str) - Схема таблицы.", - "POST": "Возвращается словарь, где ключи - имена колонок, значения - комментарии из БД.", - "PRE": "table_name и table_schema должны быть строками.", - "PURPOSE": "Извлекает комментарии к колонкам из системного каталога PostgreSQL.", - "RETURN": "Dict[str, str] - Словарь с комментариями к колонкам.", - "THROW": "Exception - При ошибках подключения или выполнения запроса к БД." + "POST": "Возвращается словарь column_name -> verbose_name из результатов SQL-запроса.", + "PRE": "dataset_id должен существовать в Superset.", + "PURPOSE": "Извлекает маппинги column_name -> verbose_name через SQL Lab Superset." }, "relations": [], - "schema_warnings": [ - { - "code": "unknown_tag", - "tag": "PARAM", - "message": "@PARAM is not defined in axiom_config.yaml tags", - "detail": null - }, - { - "code": "unknown_tag", - "tag": "RETURN", - "message": "@RETURN is not defined in axiom_config.yaml tags", - "detail": null - }, - { - "code": "unknown_tag", - "tag": "THROW", - "message": "@THROW is not defined in axiom_config.yaml tags", - "detail": null - } - ], + "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region get_postgres_comments [TYPE Function]\n # @PURPOSE: Извлекает комментарии к колонкам из системного каталога PostgreSQL.\n # @PRE: db_config должен содержать валидные параметры подключения (host, port, user, password, dbname).\n # @PRE: table_name и table_schema должны быть строками.\n # @POST: Возвращается словарь, где ключи - имена колонок, значения - комментарии из БД.\n # @THROW: Exception - При ошибках подключения или выполнения запроса к БД.\n # @PARAM: db_config (Dict) - Конфигурация для подключения к БД.\n # @PARAM: table_name (str) - Имя таблицы.\n # @PARAM: table_schema (str) - Схема таблицы.\n # @RETURN: Dict[str, str] - Словарь с комментариями к колонкам.\n def get_postgres_comments(self, db_config: dict, table_name: str, table_schema: str) -> dict[str, str]:\n with belief_scope(\"Fetch comments from PostgreSQL\"):\n app_logger.info(\"[get_postgres_comments][Enter] Fetching comments from PostgreSQL for %s.%s.\", table_schema, table_name)\n query = f\"\"\"\n SELECT \n cols.column_name,\n CASE \n WHEN pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ) LIKE '%|%' THEN \n split_part(\n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n ), \n '|', \n 1\n )\n ELSE \n pg_catalog.col_description(\n (SELECT c.oid \n FROM pg_catalog.pg_class c \n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n WHERE c.relname = cols.table_name \n AND n.nspname = cols.table_schema),\n cols.ordinal_position::int\n )\n END AS column_comment\n FROM \n information_schema.columns cols \n WHERE cols.table_catalog = '{db_config.get('dbname')}' AND cols.table_name = '{table_name}' AND cols.table_schema = '{table_schema}';\n \"\"\"\n comments = {}\n try:\n with psycopg2.connect(**db_config) as conn, conn.cursor() as cursor:\n cursor.execute(query)\n for row in cursor.fetchall():\n if row[1]:\n comments[row[0]] = row[1]\n app_logger.info(\"[get_postgres_comments][Success] Fetched %d comments.\", len(comments))\n except Exception as e:\n app_logger.error(\"[get_postgres_comments][Failure] %s\", e, exc_info=True)\n raise\n return comments\n # #endregion get_postgres_comments\n" + "body": " # #region get_sqllab_mappings [TYPE Function]\n # @PURPOSE: Извлекает маппинги column_name -> verbose_name через SQL Lab Superset.\n # @PRE: sqllab_executor должен быть инициализирован с database_id.\n # @PRE: dataset_id должен существовать в Superset.\n # @POST: Возвращается словарь column_name -> verbose_name из результатов SQL-запроса.\n # Если sql_query не указан, строится запрос к information_schema.columns.\n # @PARAM: client (SupersetClient) - Авторизованный клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета (для получения table_name/schema).\n # @PARAM: sqllab_executor (SupersetSqlLabExecutor) - Исполнитель SQL Lab.\n # @PARAM: database_id (int) - ID базы данных в Superset.\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (должен вернуть column_name + verbose_name).\n # @RETURN: Dict[str, str] - Словарь column_name -> verbose_name.\n def get_sqllab_mappings(\n self,\n client: Any,\n dataset_id: int,\n sqllab_executor: Any,\n database_id: int,\n sql_query: str | None = None,\n ) -> dict[str, str]:\n with belief_scope(\"Fetch mappings via SQL Lab\"):\n # Получаем датасет из Superset, чтобы узнать table_name и schema\n dataset_response = client.get_dataset(dataset_id)\n dataset_data = dataset_response.get(\"result\", dataset_response)\n table_name = dataset_data.get(\"table_name\")\n table_schema = dataset_data.get(\"schema\") or \"public\"\n database_name = dataset_data.get(\"database\", {}).get(\"database_name\", \"\")\n\n app_logger.info(\n \"[get_sqllab_mappings] Dataset %d: %s.%s (db: %s)\",\n dataset_id, table_schema, table_name, database_name\n )\n\n # Если SQL-запрос не указан, строим дефолтный для information_schema\n if not sql_query:\n sql_query = (\n \"SELECT column_name, pg_catalog.col_description(\\n\"\n \" (quote_ident(table_schema) || '.' || quote_ident(table_name))::regclass::oid,\\n\"\n \" ordinal_position\\n\"\n \") AS verbose_name\\n\"\n f\"FROM information_schema.columns\\n\"\n f\"WHERE table_schema = '{table_schema}' AND table_name = '{table_name}';\\n\"\n )\n app_logger.info(\"[get_sqllab_mappings] Using default information_schema query for %s.%s\", table_schema, table_name)\n else:\n app_logger.info(\"[get_sqllab_mappings] Using custom SQL query\")\n\n # Выполняем запрос через SQL Lab\n app_logger.info(\"[get_sqllab_mappings] Executing SQL Lab query on database %d...\", database_id)\n result = sqllab_executor.execute_and_poll(sql_query, database_id)\n rows = result.get(\"results\") or result.get(\"data\") or result.get(\"result\", [])\n app_logger.info(\"[get_sqllab_mappings] SQL Lab returned %d rows\", len(rows))\n\n mappings: dict[str, str] = {}\n for row in rows:\n col_name = row.get(\"column_name\")\n verbose_name = row.get(\"verbose_name\")\n if col_name and verbose_name:\n mappings[col_name] = str(verbose_name)\n\n app_logger.info(\"[get_sqllab_mappings] Extracted %d mappings\", len(mappings))\n return mappings\n # #endregion get_sqllab_mappings\n" }, { "contract_id": "load_excel_mappings", @@ -27769,10 +29089,10 @@ "complexity": 1, "metadata": { "PARAM": "file_path (str) - Путь к XLSX файлу.", - "POST": "Возвращается словарь с меппингами из файла.", + "POST": "Возвращается словарь с маппингами из файла.", "PRE": "file_path должен указывать на существующий XLSX файл.", - "PURPOSE": "Загружает меппинги 'column_name' -> 'column_comment' из XLSX файла.", - "RETURN": "Dict[str, str] - Словарь с меппингами.", + "PURPOSE": "Загружает маппинги column_name -> verbose_name из XLSX файла.", + "RETURN": "Dict[str, str] - Словарь с маппингами.", "THROW": "Exception - При ошибках чтения файла или парсинга." }, "relations": [], @@ -27798,28 +29118,28 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает меппинги 'column_name' -> 'column_comment' из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с меппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с меппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n" + "body": " # #region load_excel_mappings [TYPE Function]\n # @PURPOSE: Загружает маппинги column_name -> verbose_name из XLSX файла.\n # @PRE: file_path должен указывать на существующий XLSX файл.\n # @POST: Возвращается словарь с маппингами из файла.\n # @THROW: Exception - При ошибках чтения файла или парсинга.\n # @PARAM: file_path (str) - Путь к XLSX файлу.\n # @RETURN: Dict[str, str] - Словарь с маппингами.\n def load_excel_mappings(self, file_path: str) -> dict[str, str]:\n with belief_scope(\"Load mappings from Excel\"):\n app_logger.info(\"[load_excel_mappings][Enter] Loading mappings from %s.\", file_path)\n try:\n df = pd.read_excel(file_path)\n mappings = df.set_index('column_name')['verbose_name'].to_dict()\n app_logger.info(\"[load_excel_mappings][Success] Loaded %d mappings.\", len(mappings))\n return mappings\n except Exception as e:\n app_logger.error(\"[load_excel_mappings][Failure] %s\", e, exc_info=True)\n raise\n # #endregion load_excel_mappings\n" }, { "contract_id": "run_mapping", "contract_type": "Function", "file_path": "backend/src/core/utils/dataset_mapper.py", - "start_line": 109, - "end_line": 223, + "start_line": 110, + "end_line": 236, "tier": "TIER_1", "complexity": 1, "metadata": { - "PARAM": "table_schema (Optional[str]) - Схема таблицы в PostgreSQL.", + "PARAM": "excel_path (Optional[str]) - Путь к XLSX файлу.", "POST": "Если найдены изменения, датасет в Superset обновлен через API.", "PRE": "dataset_id должен быть существующим ID в Superset.", - "PURPOSE": "Основная функция для выполнения меппинга и обновления verbose_map датасета в Superset." + "PURPOSE": "Основная функция для выполнения маппинга и обновления verbose_name датасета в Superset." }, "relations": [ { "source_id": "run_mapping", "relation_type": "CALLS", - "target_id": "self.get_postgres_comments", - "target_ref": "self.get_postgres_comments" + "target_id": "self.get_sqllab_mappings", + "target_ref": "self.get_sqllab_mappings" }, { "source_id": "run_mapping", @@ -27850,7 +29170,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения меппинга и обновления verbose_map датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_postgres_comments\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('postgres', 'excel', 'both').\n # @PARAM: postgres_config (Optional[Dict]) - Конфигурация для подключения к PostgreSQL.\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n # @PARAM: table_name (Optional[str]) - Имя таблицы в PostgreSQL.\n # @PARAM: table_schema (Optional[str]) - Схема таблицы в PostgreSQL.\n def run_mapping(self, superset_client: Any, dataset_id: int, source: str, postgres_config: dict | None = None, excel_path: str | None = None, table_name: str | None = None, table_schema: str | None = None):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source in ['postgres', 'both']:\n assert postgres_config and table_name and table_schema, \"Postgres config is required.\"\n mappings.update(self.get_postgres_comments(postgres_config, table_name, table_schema))\n if source in ['excel', 'both']:\n assert excel_path, \"Excel path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n if source not in ['postgres', 'excel', 'both']:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n" + "body": " # #region run_mapping [TYPE Function]\n # @PURPOSE: Основная функция для выполнения маппинга и обновления verbose_name датасета в Superset.\n # @PRE: superset_client должен быть авторизован.\n # @PRE: dataset_id должен быть существующим ID в Superset.\n # @POST: Если найдены изменения, датасет в Superset обновлен через API.\n # @RELATION: CALLS -> self.get_sqllab_mappings\n # @RELATION: CALLS -> self.load_excel_mappings\n # @RELATION: CALLS -> superset_client.get_dataset\n # @RELATION: CALLS -> superset_client.update_dataset\n # @PARAM: superset_client (Any) - Клиент Superset.\n # @PARAM: dataset_id (int) - ID датасета для обновления.\n # @PARAM: source (str) - Источник данных ('sqllab' или 'excel').\n # @PARAM: sqllab_executor (Optional[Any]) - Исполнитель SQL Lab (для sqllab source).\n # @PARAM: database_id (Optional[int]) - ID базы данных Superset (для sqllab source).\n # @PARAM: sql_query (Optional[str]) - Произвольный SQL-запрос (для sqllab source).\n # @PARAM: excel_path (Optional[str]) - Путь к XLSX файлу.\n def run_mapping(\n self,\n superset_client: Any,\n dataset_id: int,\n source: str,\n sqllab_executor: Any = None,\n database_id: int | None = None,\n sql_query: str | None = None,\n excel_path: str | None = None,\n ):\n with belief_scope(f\"Run dataset mapping for ID {dataset_id}\"):\n app_logger.info(\"[run_mapping][Enter] Starting dataset mapping for ID %d from source '%s'.\", dataset_id, source)\n mappings: dict[str, str] = {}\n\n try:\n if source == \"sqllab\":\n assert sqllab_executor and database_id, \"sqllab_executor and database_id are required for sqllab source.\"\n mappings.update(self.get_sqllab_mappings(superset_client, dataset_id, sqllab_executor, database_id, sql_query))\n elif source == \"excel\":\n assert excel_path, \"excel_path is required.\"\n mappings.update(self.load_excel_mappings(excel_path))\n else:\n app_logger.error(\"[run_mapping][Failure] Invalid source: %s.\", source)\n return\n\n dataset_response = superset_client.get_dataset(dataset_id)\n dataset_data = dataset_response['result']\n\n original_columns = dataset_data.get('columns', [])\n updated_columns = []\n changes_made = False\n for column in original_columns:\n col_name = column.get('column_name')\n\n new_column = {\n \"column_name\": col_name,\n \"id\": column.get(\"id\"),\n \"advanced_data_type\": column.get(\"advanced_data_type\"),\n \"description\": column.get(\"description\"),\n \"expression\": column.get(\"expression\"),\n \"extra\": column.get(\"extra\"),\n \"filterable\": column.get(\"filterable\"),\n \"groupby\": column.get(\"groupby\"),\n \"is_active\": column.get(\"is_active\"),\n \"is_dttm\": column.get(\"is_dttm\"),\n \"python_date_format\": column.get(\"python_date_format\"),\n \"type\": column.get(\"type\"),\n \"uuid\": column.get(\"uuid\"),\n \"verbose_name\": column.get(\"verbose_name\"),\n }\n\n new_column = {k: v for k, v in new_column.items() if v is not None}\n if col_name in mappings:\n mapping_value = mappings[col_name]\n if isinstance(mapping_value, str) and new_column.get('verbose_name') != mapping_value:\n new_column['verbose_name'] = mapping_value\n changes_made = True\n\n updated_columns.append(new_column)\n\n updated_metrics = []\n for metric in dataset_data.get(\"metrics\", []):\n new_metric = {\n \"id\": metric.get(\"id\"),\n \"metric_name\": metric.get(\"metric_name\"),\n \"expression\": metric.get(\"expression\"),\n \"verbose_name\": metric.get(\"verbose_name\"),\n \"description\": metric.get(\"description\"),\n \"d3format\": metric.get(\"d3format\"),\n \"currency\": metric.get(\"currency\"),\n \"extra\": metric.get(\"extra\"),\n \"warning_text\": metric.get(\"warning_text\"),\n \"metric_type\": metric.get(\"metric_type\"),\n \"uuid\": metric.get(\"uuid\"),\n }\n updated_metrics.append({k: v for k, v in new_metric.items() if v is not None})\n\n if changes_made:\n payload_for_update = {\n \"database_id\": dataset_data.get(\"database\", {}).get(\"id\"),\n \"table_name\": dataset_data.get(\"table_name\"),\n \"schema\": dataset_data.get(\"schema\"),\n \"columns\": updated_columns,\n \"owners\": [owner[\"id\"] for owner in dataset_data.get(\"owners\", [])],\n \"metrics\": updated_metrics,\n \"extra\": dataset_data.get(\"extra\"),\n \"description\": dataset_data.get(\"description\"),\n \"sql\": dataset_data.get(\"sql\"),\n \"cache_timeout\": dataset_data.get(\"cache_timeout\"),\n \"catalog\": dataset_data.get(\"catalog\"),\n \"default_endpoint\": dataset_data.get(\"default_endpoint\"),\n \"external_url\": dataset_data.get(\"external_url\"),\n \"fetch_values_predicate\": dataset_data.get(\"fetch_values_predicate\"),\n \"filter_select_enabled\": dataset_data.get(\"filter_select_enabled\"),\n \"is_managed_externally\": dataset_data.get(\"is_managed_externally\"),\n \"is_sqllab_view\": dataset_data.get(\"is_sqllab_view\"),\n \"main_dttm_col\": dataset_data.get(\"main_dttm_col\"),\n \"normalize_columns\": dataset_data.get(\"normalize_columns\"),\n \"offset\": dataset_data.get(\"offset\"),\n \"template_params\": dataset_data.get(\"template_params\"),\n }\n\n payload_for_update = {k: v for k, v in payload_for_update.items() if v is not None}\n superset_client.update_dataset(dataset_id, payload_for_update)\n app_logger.info(\"[run_mapping][Success] Dataset %d columns' verbose_name updated.\", dataset_id)\n else:\n app_logger.info(\"[run_mapping][State] No changes in columns' verbose_name, skipping update.\")\n except (AssertionError, FileNotFoundError, Exception) as e:\n app_logger.error(\"[run_mapping][Failure] %s\", e, exc_info=True)\n return\n # #endregion run_mapping\n" }, { "contract_id": "FileIO", @@ -31556,51 +32876,6 @@ "tier_source": "AutoCalculated", "body": "# #region NotificationConfig [TYPE Class]\n# @BRIEF Stores persisted provider-level notification configuration and encrypted credentials metadata.\n# @PRE: SQLAlchemy declarative Base is initialized and uuid generation is available at instance creation time.\n# @POST: ORM table 'notification_configs' exposes id, type, name, credentials, is_active, created_at, updated_at fields with declared constraints/defaults.\n# @SIDE_EFFECT: Registers ORM mapping metadata during module import; may generate UUID values for new entity instances.\n# @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.\nclass NotificationConfig(Base):\n __tablename__ = \"notification_configs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n type = Column(String, nullable=False) # SMTP, SLACK, TELEGRAM\n name = Column(String, nullable=False)\n credentials = Column(JSON, nullable=False) # Encrypted connection details\n is_active = Column(Boolean, default=True)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion NotificationConfig\n" }, - { - "contract_id": "ConnectionModels", - "contract_type": "Module", - "file_path": "backend/src/models/connection.py", - "start_line": 1, - "end_line": 34, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "COMPLEXITY": 1, - "INVARIANT": "All primary keys are UUID strings.", - "LAYER": "Domain", - "PURPOSE": "Defines the database schema for external database connection configurations." - }, - "relations": [ - { - "source_id": "ConnectionModels", - "relation_type": "DEPENDS_ON", - "target_id": "sqlalchemy", - "target_ref": "sqlalchemy" - } - ], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ConnectionModels [C:1] [TYPE Module] [SEMANTICS sqlalchemy, connection, model, schema, connection-config]\n#\n# @BRIEF Defines the database schema for external database connection configurations.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> sqlalchemy\n#\n# @INVARIANT: All primary keys are UUID strings.\n\nimport uuid\n\nfrom sqlalchemy import Column, DateTime, Integer, String\nfrom sqlalchemy.sql import func\n\nfrom .mapping import Base\n\n\n# #region ConnectionConfig [C:1] [TYPE Class]\n# @BRIEF Stores credentials for external databases used for column mapping.\nclass ConnectionConfig(Base):\n __tablename__ = \"connection_configs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n name = Column(String, nullable=False)\n type = Column(String, nullable=False) # e.g., \"postgres\"\n host = Column(String, nullable=True)\n port = Column(Integer, nullable=True)\n database = Column(String, nullable=True)\n username = Column(String, nullable=True)\n password = Column(String, nullable=True) # Encrypted/Obfuscated password\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ConnectionConfig\n\n# #endregion ConnectionModels\n" - }, - { - "contract_id": "ConnectionConfig", - "contract_type": "Class", - "file_path": "backend/src/models/connection.py", - "start_line": 17, - "end_line": 32, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "COMPLEXITY": 1, - "PURPOSE": "Stores credentials for external databases used for column mapping." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "# #region ConnectionConfig [C:1] [TYPE Class]\n# @BRIEF Stores credentials for external databases used for column mapping.\nclass ConnectionConfig(Base):\n __tablename__ = \"connection_configs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n name = Column(String, nullable=False)\n type = Column(String, nullable=False) # e.g., \"postgres\"\n host = Column(String, nullable=True)\n port = Column(Integer, nullable=True)\n database = Column(String, nullable=True)\n username = Column(String, nullable=True)\n password = Column(String, nullable=True) # Encrypted/Obfuscated password\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ConnectionConfig\n" - }, { "contract_id": "DashboardModels", "contract_type": "Module", @@ -33952,7 +35227,7 @@ "contract_type": "Module", "file_path": "backend/src/models/llm.py", "start_line": 1, - "end_line": 70, + "end_line": 73, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -33991,31 +35266,38 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region LlmModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, llm, model, schema, validate, provider]\n# @BRIEF SQLAlchemy models for LLM provider configuration and validation results.\n# @LAYER: Domain\n# @RELATION INHERITS_FROM -> MappingModels:Base\n\nfrom datetime import datetime\nimport uuid\n\nfrom sqlalchemy import JSON, Boolean, Column, DateTime, String, Text, Time\n\nfrom .mapping import Base\n\n\ndef generate_uuid():\n return str(uuid.uuid4())\n\n# #region ValidationPolicy [TYPE Class]\n# @BRIEF Defines a scheduled rule for validating a group of dashboards within an execution window.\nclass ValidationPolicy(Base):\n __tablename__ = \"validation_policies\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n environment_id = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n dashboard_ids = Column(JSON, nullable=False) # Array of dashboard IDs\n schedule_days = Column(JSON, nullable=False) # Array of integers (0-6)\n window_start = Column(Time, nullable=False)\n window_end = Column(Time, nullable=False)\n notify_owners = Column(Boolean, default=True)\n custom_channels = Column(JSON, nullable=True) # List of external channels\n alert_condition = Column(String, default=\"FAIL_ONLY\") # FAIL_ONLY, WARN_AND_FAIL, ALWAYS\n created_at = Column(DateTime, default=datetime.utcnow)\n updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)\n# #endregion ValidationPolicy\n\n# #region LLMProvider [TYPE Class]\n# @BRIEF SQLAlchemy model for LLM provider configuration.\nclass LLMProvider(Base):\n __tablename__ = \"llm_providers\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n provider_type = Column(String, nullable=False) # openai, openrouter, kilo\n name = Column(String, nullable=False)\n base_url = Column(String, nullable=False)\n api_key = Column(String, nullable=False) # Should be encrypted\n default_model = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n is_multimodal = Column(Boolean, default=False)\n created_at = Column(DateTime, default=datetime.utcnow)\n# #endregion LLMProvider\n\n# #region ValidationRecord [TYPE Class]\n# @BRIEF SQLAlchemy model for dashboard validation history.\nclass ValidationRecord(Base):\n __tablename__ = \"llm_validation_results\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n task_id = Column(String, nullable=True, index=True) # Reference to TaskRecord\n dashboard_id = Column(String, nullable=False, index=True)\n environment_id = Column(String, nullable=True, index=True)\n timestamp = Column(DateTime, default=datetime.utcnow)\n status = Column(String, nullable=False) # PASS, WARN, FAIL, UNKNOWN\n screenshot_path = Column(String, nullable=True)\n issues = Column(JSON, nullable=False)\n summary = Column(Text, nullable=False)\n raw_response = Column(Text, nullable=True)\n# #endregion ValidationRecord\n\n# #endregion LlmModels\n" + "body": "# #region LlmModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, llm, model, schema, validate, provider]\n# @BRIEF SQLAlchemy models for LLM provider configuration and validation results.\n# @LAYER: Domain\n# @RELATION INHERITS_FROM -> MappingModels:Base\n\nfrom datetime import datetime\nimport uuid\n\nfrom sqlalchemy import JSON, Boolean, Column, DateTime, String, Text, Time\n\nfrom .mapping import Base\n\n\ndef generate_uuid():\n return str(uuid.uuid4())\n\n# #region ValidationPolicy [TYPE Class]\n# @BRIEF Defines a scheduled rule for validating a group of dashboards within an execution window.\n# @RELATION DEPENDS_ON -> [LLMProvider]\nclass ValidationPolicy(Base):\n __tablename__ = \"validation_policies\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n environment_id = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n dashboard_ids = Column(JSON, nullable=False) # Array of dashboard IDs\n provider_id = Column(String, nullable=True) # Reference to LLMProvider.id\n schedule_days = Column(JSON, nullable=False) # Array of integers (0-6)\n window_start = Column(Time, nullable=False)\n window_end = Column(Time, nullable=False)\n notify_owners = Column(Boolean, default=True)\n custom_channels = Column(JSON, nullable=True) # List of external channels\n alert_condition = Column(String, default=\"FAIL_ONLY\") # FAIL_ONLY, WARN_AND_FAIL, ALWAYS\n created_at = Column(DateTime, default=datetime.utcnow)\n updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)\n# #endregion ValidationPolicy\n\n# #region LLMProvider [TYPE Class]\n# @BRIEF SQLAlchemy model for LLM provider configuration.\nclass LLMProvider(Base):\n __tablename__ = \"llm_providers\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n provider_type = Column(String, nullable=False) # openai, openrouter, kilo\n name = Column(String, nullable=False)\n base_url = Column(String, nullable=False)\n api_key = Column(String, nullable=False) # Should be encrypted\n default_model = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n is_multimodal = Column(Boolean, default=False)\n created_at = Column(DateTime, default=datetime.utcnow)\n# #endregion LLMProvider\n\n# #region ValidationRecord [TYPE Class]\n# @BRIEF SQLAlchemy model for dashboard validation history.\nclass ValidationRecord(Base):\n __tablename__ = \"llm_validation_results\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n task_id = Column(String, nullable=True, index=True) # Reference to TaskRecord\n policy_id = Column(String, nullable=True, index=True) # Reference to ValidationPolicy.id\n dashboard_id = Column(String, nullable=False, index=True)\n environment_id = Column(String, nullable=True, index=True)\n timestamp = Column(DateTime, default=datetime.utcnow)\n status = Column(String, nullable=False) # PASS, WARN, FAIL, UNKNOWN\n screenshot_path = Column(String, nullable=True)\n issues = Column(JSON, nullable=False)\n summary = Column(Text, nullable=False)\n raw_response = Column(Text, nullable=True)\n# #endregion ValidationRecord\n\n# #endregion LlmModels\n" }, { "contract_id": "ValidationPolicy", "contract_type": "Class", "file_path": "backend/src/models/llm.py", "start_line": 17, - "end_line": 35, + "end_line": 37, "tier": "TIER_1", "complexity": 1, "metadata": { "PURPOSE": "Defines a scheduled rule for validating a group of dashboards within an execution window." }, - "relations": [], + "relations": [ + { + "source_id": "ValidationPolicy", + "relation_type": "DEPENDS_ON", + "target_id": "LLMProvider", + "target_ref": "[LLMProvider]" + } + ], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ValidationPolicy [TYPE Class]\n# @BRIEF Defines a scheduled rule for validating a group of dashboards within an execution window.\nclass ValidationPolicy(Base):\n __tablename__ = \"validation_policies\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n environment_id = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n dashboard_ids = Column(JSON, nullable=False) # Array of dashboard IDs\n schedule_days = Column(JSON, nullable=False) # Array of integers (0-6)\n window_start = Column(Time, nullable=False)\n window_end = Column(Time, nullable=False)\n notify_owners = Column(Boolean, default=True)\n custom_channels = Column(JSON, nullable=True) # List of external channels\n alert_condition = Column(String, default=\"FAIL_ONLY\") # FAIL_ONLY, WARN_AND_FAIL, ALWAYS\n created_at = Column(DateTime, default=datetime.utcnow)\n updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)\n# #endregion ValidationPolicy\n" + "body": "# #region ValidationPolicy [TYPE Class]\n# @BRIEF Defines a scheduled rule for validating a group of dashboards within an execution window.\n# @RELATION DEPENDS_ON -> [LLMProvider]\nclass ValidationPolicy(Base):\n __tablename__ = \"validation_policies\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n environment_id = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n dashboard_ids = Column(JSON, nullable=False) # Array of dashboard IDs\n provider_id = Column(String, nullable=True) # Reference to LLMProvider.id\n schedule_days = Column(JSON, nullable=False) # Array of integers (0-6)\n window_start = Column(Time, nullable=False)\n window_end = Column(Time, nullable=False)\n notify_owners = Column(Boolean, default=True)\n custom_channels = Column(JSON, nullable=True) # List of external channels\n alert_condition = Column(String, default=\"FAIL_ONLY\") # FAIL_ONLY, WARN_AND_FAIL, ALWAYS\n created_at = Column(DateTime, default=datetime.utcnow)\n updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)\n# #endregion ValidationPolicy\n" }, { "contract_id": "LLMProvider", "contract_type": "Class", "file_path": "backend/src/models/llm.py", - "start_line": 37, - "end_line": 51, + "start_line": 39, + "end_line": 53, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -34031,8 +35313,8 @@ "contract_id": "ValidationRecord", "contract_type": "Class", "file_path": "backend/src/models/llm.py", - "start_line": 53, - "end_line": 68, + "start_line": 55, + "end_line": 71, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -34042,7 +35324,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ValidationRecord [TYPE Class]\n# @BRIEF SQLAlchemy model for dashboard validation history.\nclass ValidationRecord(Base):\n __tablename__ = \"llm_validation_results\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n task_id = Column(String, nullable=True, index=True) # Reference to TaskRecord\n dashboard_id = Column(String, nullable=False, index=True)\n environment_id = Column(String, nullable=True, index=True)\n timestamp = Column(DateTime, default=datetime.utcnow)\n status = Column(String, nullable=False) # PASS, WARN, FAIL, UNKNOWN\n screenshot_path = Column(String, nullable=True)\n issues = Column(JSON, nullable=False)\n summary = Column(Text, nullable=False)\n raw_response = Column(Text, nullable=True)\n# #endregion ValidationRecord\n" + "body": "# #region ValidationRecord [TYPE Class]\n# @BRIEF SQLAlchemy model for dashboard validation history.\nclass ValidationRecord(Base):\n __tablename__ = \"llm_validation_results\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n task_id = Column(String, nullable=True, index=True) # Reference to TaskRecord\n policy_id = Column(String, nullable=True, index=True) # Reference to ValidationPolicy.id\n dashboard_id = Column(String, nullable=False, index=True)\n environment_id = Column(String, nullable=True, index=True)\n timestamp = Column(DateTime, default=datetime.utcnow)\n status = Column(String, nullable=False) # PASS, WARN, FAIL, UNKNOWN\n screenshot_path = Column(String, nullable=True)\n issues = Column(JSON, nullable=False)\n summary = Column(Text, nullable=False)\n raw_response = Column(Text, nullable=True)\n# #endregion ValidationRecord\n" }, { "contract_id": "MappingModels", @@ -35472,7 +36754,7 @@ "contract_type": "Module", "file_path": "backend/src/plugins/llm_analysis/plugin.py", "start_line": 1, - "end_line": 482, + "end_line": 483, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -35517,7 +36799,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region LLMAnalysisPlugin [C:5] [TYPE Module] [SEMANTICS llm, analysis, dashboard, validation, documentation]\n# @BRIEF Implements DashboardValidationPlugin and DocumentationPlugin.\n# @LAYER: Plugin\n# @RELATION INHERITS -> [PluginBase]\n# @RELATION CALLS -> [ScreenshotService]\n# @RELATION CALLS -> [LLMClient]\n# @RELATION CALLS -> [LLMProviderService]\n# @RELATION USES -> TaskContext\n# @INVARIANT: All LLM interactions must be executed as asynchronous tasks.\n# @DATA_CONTRACT: AnalysisRequest -> AnalysisResult\n\nfrom datetime import datetime, timedelta\nimport json\nimport os\nfrom typing import Any\n\nfrom ...core.database import SessionLocal\nfrom ...core.logger import belief_scope, logger\nfrom ...core.plugin_base import PluginBase\nfrom ...core.superset_client import SupersetClient\nfrom ...core.task_manager.context import TaskContext\nfrom ...models.llm import ValidationPolicy, ValidationRecord\nfrom ...services.llm_prompt_templates import (\n DEFAULT_LLM_PROMPTS,\n normalize_llm_settings,\n render_prompt,\n)\nfrom ...services.llm_provider import LLMProviderService\nfrom ...services.notifications.service import NotificationService\nfrom .models import DetectedIssue, LLMProviderType, ValidationResult, ValidationStatus\nfrom .service import LLMClient, ScreenshotService\n\n\n# #region _is_masked_or_invalid_api_key [TYPE Function]\n# @BRIEF Guards against placeholder or malformed API keys in runtime.\n# @PRE: value may be None.\n# @POST: Returns True when value cannot be used for authenticated provider calls.\ndef _is_masked_or_invalid_api_key(value: str | None) -> bool:\n key = (value or \"\").strip()\n if not key:\n return True\n if key in {\"********\", \"EMPTY_OR_NONE\"}:\n return True\n # Most provider tokens are significantly longer; short values are almost always placeholders.\n return len(key) < 16\n# #endregion _is_masked_or_invalid_api_key\n\n# #region _json_safe_value [TYPE Function]\n# @BRIEF Recursively normalize payload values for JSON serialization.\n# @PRE: value may be nested dict/list with datetime values.\n# @POST: datetime values are converted to ISO strings.\ndef _json_safe_value(value: Any):\n if isinstance(value, datetime):\n return value.isoformat()\n if isinstance(value, dict):\n return {k: _json_safe_value(v) for k, v in value.items()}\n if isinstance(value, list):\n return [_json_safe_value(v) for v in value]\n return value\n# #endregion _json_safe_value\n\n# #region DashboardValidationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dashboard health analysis using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DashboardValidationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_dashboard_validation\"\n\n @property\n def name(self) -> str:\n return \"Dashboard LLM Validation\"\n\n @property\n def description(self) -> str:\n return \"Automated dashboard health analysis using multimodal LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dashboard_id\": {\"type\": \"string\", \"title\": \"Dashboard ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dashboard_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DashboardValidationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dashboard validation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Validation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dashboard_id, environment_id, and provider_id.\n # @POST: Returns a dictionary with validation results and persists them to the database.\n # @SIDE_EFFECT: Captures a screenshot, calls LLM API, and writes to the database.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n validation_started_at = datetime.utcnow()\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n screenshot_log = log.with_source(\"screenshot\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dashboard_id_raw = params.get(\"dashboard_id\")\n dashboard_id = str(dashboard_id_raw) if dashboard_id_raw is not None else None\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n llm_log.debug(f\" Is Active: {db_provider.is_active}\")\n llm_log.debug(f\" Is Multimodal: {db_provider.is_multimodal}\")\n if not bool(db_provider.is_multimodal):\n raise ValueError(\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Capture Screenshot\n screenshot_service = ScreenshotService(env)\n\n storage_root = config_mgr.get_config().settings.storage.root_path\n screenshots_dir = os.path.join(storage_root, \"screenshots\")\n os.makedirs(screenshots_dir, exist_ok=True)\n\n filename = f\"{dashboard_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png\"\n screenshot_path = os.path.join(screenshots_dir, filename)\n\n screenshot_started_at = datetime.utcnow()\n screenshot_log.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n await screenshot_service.capture_dashboard(dashboard_id, screenshot_path)\n screenshot_log.debug(f\"Screenshot saved to: {screenshot_path}\")\n screenshot_finished_at = datetime.utcnow()\n\n # 4. Fetch Logs (from Environment /api/v1/log/)\n logs = []\n logs_fetch_started_at = datetime.utcnow()\n try:\n client = SupersetClient(env)\n\n # Calculate time window (last 24 hours)\n start_time = (datetime.now() - timedelta(hours=24)).isoformat()\n\n # Construct filter for logs\n # Note: We filter by dashboard_id matching the object\n query_params = {\n \"filters\": [\n {\"col\": \"dashboard_id\", \"opr\": \"eq\", \"value\": dashboard_id},\n {\"col\": \"dttm\", \"opr\": \"gt\", \"value\": start_time}\n ],\n \"order_column\": \"dttm\",\n \"order_direction\": \"desc\",\n \"page\": 0,\n \"page_size\": 100\n }\n\n superset_log.debug(f\"Fetching logs for dashboard {dashboard_id}\")\n response = client.network.request(\n method=\"GET\",\n endpoint=\"/log/\",\n params={\"q\": json.dumps(query_params)}\n )\n\n if isinstance(response, dict) and \"result\" in response:\n for item in response[\"result\"]:\n action = item.get(\"action\", \"unknown\")\n dttm = item.get(\"dttm\", \"\")\n details = item.get(\"json\", \"\")\n logs.append(f\"[{dttm}] {action}: {details}\")\n\n if not logs:\n logs = [\"No recent logs found for this dashboard.\"]\n superset_log.debug(\"No recent logs found for this dashboard\")\n\n except Exception as e:\n superset_log.warning(f\"Failed to fetch logs from environment: {e}\")\n logs = [f\"Error fetching remote logs: {e!s}\"]\n logs_fetch_finished_at = datetime.utcnow()\n\n # 5. Analyze with LLM\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_log.info(f\"Analyzing dashboard {dashboard_id} with LLM\")\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n dashboard_prompt = llm_settings[\"prompts\"].get(\n \"dashboard_validation_prompt\",\n DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n )\n llm_call_started_at = datetime.utcnow()\n analysis = await llm_client.analyze_dashboard(\n screenshot_path,\n logs,\n prompt_template=dashboard_prompt,\n )\n llm_call_finished_at = datetime.utcnow()\n\n # Log analysis summary to task logs for better visibility\n llm_log.info(f\"[ANALYSIS_SUMMARY] Status: {analysis['status']}\")\n llm_log.info(f\"[ANALYSIS_SUMMARY] Summary: {analysis['summary']}\")\n if analysis.get(\"issues\"):\n for i, issue in enumerate(analysis[\"issues\"]):\n llm_log.info(f\"[ANALYSIS_ISSUE][{i+1}] {issue.get('severity')}: {issue.get('message')} (Location: {issue.get('location', 'N/A')})\")\n\n # 6. Persist Result\n validation_result = ValidationResult(\n dashboard_id=dashboard_id,\n status=ValidationStatus(analysis[\"status\"]),\n summary=analysis[\"summary\"],\n issues=[DetectedIssue(**issue) for issue in analysis[\"issues\"]],\n screenshot_path=screenshot_path,\n raw_response=str(analysis)\n )\n validation_finished_at = datetime.utcnow()\n\n result_payload = _json_safe_value(validation_result.dict())\n result_payload[\"screenshot_paths\"] = [screenshot_path]\n result_payload[\"logs_sent_to_llm\"] = logs\n result_payload[\"logs_sent_count\"] = len(logs)\n result_payload[\"prompt_template\"] = dashboard_prompt\n result_payload[\"provider\"] = {\n \"id\": db_provider.id,\n \"name\": db_provider.name,\n \"type\": db_provider.provider_type,\n \"base_url\": db_provider.base_url,\n \"model\": db_provider.default_model,\n }\n result_payload[\"environment_id\"] = env_id\n result_payload[\"timings\"] = {\n \"validation_started_at\": validation_started_at.isoformat(),\n \"validation_finished_at\": validation_finished_at.isoformat(),\n \"validation_duration_ms\": int((validation_finished_at - validation_started_at).total_seconds() * 1000),\n \"screenshot_started_at\": screenshot_started_at.isoformat(),\n \"screenshot_finished_at\": screenshot_finished_at.isoformat(),\n \"screenshot_duration_ms\": int((screenshot_finished_at - screenshot_started_at).total_seconds() * 1000),\n \"logs_fetch_started_at\": logs_fetch_started_at.isoformat(),\n \"logs_fetch_finished_at\": logs_fetch_finished_at.isoformat(),\n \"logs_fetch_duration_ms\": int((logs_fetch_finished_at - logs_fetch_started_at).total_seconds() * 1000),\n \"llm_call_started_at\": llm_call_started_at.isoformat(),\n \"llm_call_finished_at\": llm_call_finished_at.isoformat(),\n \"llm_call_duration_ms\": int((llm_call_finished_at - llm_call_started_at).total_seconds() * 1000),\n }\n\n db_record = ValidationRecord(\n task_id=context.task_id if context else None,\n dashboard_id=validation_result.dashboard_id,\n environment_id=env_id,\n status=validation_result.status.value,\n summary=validation_result.summary,\n issues=[issue.dict() for issue in validation_result.issues],\n screenshot_path=validation_result.screenshot_path,\n raw_response=json.dumps(result_payload, ensure_ascii=False)\n )\n db.add(db_record)\n db.commit()\n\n # 7. Notification on failure (US1 / FR-015)\n try:\n policy_id = params.get(\"policy_id\")\n policy = None\n if policy_id:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n\n notification_service = NotificationService(db, config_mgr)\n await notification_service.dispatch_report(\n record=db_record,\n policy=policy,\n background_tasks=getattr(context, \"background_tasks\", None) if context else None\n )\n except Exception as e:\n log.error(f\"Failed to dispatch notifications: {e}\")\n\n # Final log to ensure all analysis is visible in task logs\n log.info(f\"Validation completed for dashboard {dashboard_id}. Status: {validation_result.status.value}\")\n\n return result_payload\n\n finally:\n db.close()\n # endregion DashboardValidationPlugin.execute\n# #endregion DashboardValidationPlugin\n\n# #region DocumentationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dataset documentation using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DocumentationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_documentation\"\n\n @property\n def name(self) -> str:\n return \"Dataset LLM Documentation\"\n\n @property\n def description(self) -> str:\n return \"Automated dataset and column documentation using LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dataset_id\": {\"type\": \"string\", \"title\": \"Dataset ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dataset_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DocumentationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dataset documentation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Documentation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dataset_id, environment_id, and provider_id.\n # @POST: Returns generated documentation and updates the dataset in Superset.\n # @SIDE_EFFECT: Calls LLM API and updates dataset metadata in Superset.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dataset_id = params.get(\"dataset_id\")\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Fetch Metadata (US2 / T024)\n from ...core.superset_client import SupersetClient\n client = SupersetClient(env)\n\n superset_log.debug(f\"Fetching dataset {dataset_id}\")\n dataset = client.get_dataset(int(dataset_id))\n\n # Extract columns and existing descriptions\n columns_data = []\n for col in dataset.get(\"columns\", []):\n columns_data.append({\n \"name\": col.get(\"column_name\"),\n \"type\": col.get(\"type\"),\n \"description\": col.get(\"description\")\n })\n superset_log.debug(f\"Extracted {len(columns_data)} columns from dataset\")\n\n # 4. Construct Prompt & Analyze (US2 / T025)\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n documentation_prompt = llm_settings[\"prompts\"].get(\n \"documentation_prompt\",\n DEFAULT_LLM_PROMPTS[\"documentation_prompt\"],\n )\n prompt = render_prompt(\n documentation_prompt,\n {\n \"dataset_name\": dataset.get(\"table_name\") or \"\",\n \"columns_json\": json.dumps(columns_data, ensure_ascii=False),\n },\n )\n\n # Using a generic chat completion for text-only US2\n llm_log.info(f\"Generating documentation for dataset {dataset_id}\")\n doc_result = await llm_client.get_json_completion([{\"role\": \"user\", \"content\": prompt}])\n\n # 5. Update Metadata (US2 / T026)\n update_payload = {\n \"description\": doc_result[\"dataset_description\"],\n \"columns\": []\n }\n\n # Map generated descriptions back to column IDs\n for col_doc in doc_result[\"column_descriptions\"]:\n for col in dataset.get(\"columns\", []):\n if col.get(\"column_name\") == col_doc[\"name\"]:\n update_payload[\"columns\"].append({\n \"id\": col.get(\"id\"),\n \"description\": col_doc[\"description\"]\n })\n\n superset_log.info(f\"Updating dataset {dataset_id} with generated documentation\")\n client.update_dataset(int(dataset_id), update_payload)\n\n log.info(f\"Documentation completed for dataset {dataset_id}\")\n\n return doc_result\n\n finally:\n db.close()\n # endregion DocumentationPlugin.execute\n# #endregion DocumentationPlugin\n\n# #endregion LLMAnalysisPlugin\n" + "body": "# #region LLMAnalysisPlugin [C:5] [TYPE Module] [SEMANTICS llm, analysis, dashboard, validation, documentation]\n# @BRIEF Implements DashboardValidationPlugin and DocumentationPlugin.\n# @LAYER: Plugin\n# @RELATION INHERITS -> [PluginBase]\n# @RELATION CALLS -> [ScreenshotService]\n# @RELATION CALLS -> [LLMClient]\n# @RELATION CALLS -> [LLMProviderService]\n# @RELATION USES -> TaskContext\n# @INVARIANT: All LLM interactions must be executed as asynchronous tasks.\n# @DATA_CONTRACT: AnalysisRequest -> AnalysisResult\n\nfrom datetime import datetime, timedelta\nimport json\nimport os\nfrom typing import Any\n\nfrom ...core.database import SessionLocal\nfrom ...core.logger import belief_scope, logger\nfrom ...core.plugin_base import PluginBase\nfrom ...core.superset_client import SupersetClient\nfrom ...core.task_manager.context import TaskContext\nfrom ...models.llm import ValidationPolicy, ValidationRecord\nfrom ...services.llm_prompt_templates import (\n DEFAULT_LLM_PROMPTS,\n normalize_llm_settings,\n render_prompt,\n)\nfrom ...services.llm_provider import LLMProviderService\nfrom ...services.notifications.service import NotificationService\nfrom .models import DetectedIssue, LLMProviderType, ValidationResult, ValidationStatus\nfrom .service import LLMClient, ScreenshotService\n\n\n# #region _is_masked_or_invalid_api_key [TYPE Function]\n# @BRIEF Guards against placeholder or malformed API keys in runtime.\n# @PRE: value may be None.\n# @POST: Returns True when value cannot be used for authenticated provider calls.\ndef _is_masked_or_invalid_api_key(value: str | None) -> bool:\n key = (value or \"\").strip()\n if not key:\n return True\n if key in {\"********\", \"EMPTY_OR_NONE\"}:\n return True\n # Most provider tokens are significantly longer; short values are almost always placeholders.\n return len(key) < 16\n# #endregion _is_masked_or_invalid_api_key\n\n# #region _json_safe_value [TYPE Function]\n# @BRIEF Recursively normalize payload values for JSON serialization.\n# @PRE: value may be nested dict/list with datetime values.\n# @POST: datetime values are converted to ISO strings.\ndef _json_safe_value(value: Any):\n if isinstance(value, datetime):\n return value.isoformat()\n if isinstance(value, dict):\n return {k: _json_safe_value(v) for k, v in value.items()}\n if isinstance(value, list):\n return [_json_safe_value(v) for v in value]\n return value\n# #endregion _json_safe_value\n\n# #region DashboardValidationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dashboard health analysis using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DashboardValidationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_dashboard_validation\"\n\n @property\n def name(self) -> str:\n return \"Dashboard LLM Validation\"\n\n @property\n def description(self) -> str:\n return \"Automated dashboard health analysis using multimodal LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dashboard_id\": {\"type\": \"string\", \"title\": \"Dashboard ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dashboard_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DashboardValidationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dashboard validation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Validation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dashboard_id, environment_id, and provider_id.\n # @POST: Returns a dictionary with validation results and persists them to the database.\n # @SIDE_EFFECT: Captures a screenshot, calls LLM API, and writes to the database.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n validation_started_at = datetime.utcnow()\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n screenshot_log = log.with_source(\"screenshot\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dashboard_id_raw = params.get(\"dashboard_id\")\n dashboard_id = str(dashboard_id_raw) if dashboard_id_raw is not None else None\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n llm_log.debug(f\" Is Active: {db_provider.is_active}\")\n llm_log.debug(f\" Is Multimodal: {db_provider.is_multimodal}\")\n if not bool(db_provider.is_multimodal):\n raise ValueError(\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Capture Screenshot\n screenshot_service = ScreenshotService(env)\n\n storage_root = config_mgr.get_config().settings.storage.root_path\n screenshots_dir = os.path.join(storage_root, \"screenshots\")\n os.makedirs(screenshots_dir, exist_ok=True)\n\n filename = f\"{dashboard_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png\"\n screenshot_path = os.path.join(screenshots_dir, filename)\n\n screenshot_started_at = datetime.utcnow()\n screenshot_log.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n await screenshot_service.capture_dashboard(dashboard_id, screenshot_path)\n screenshot_log.debug(f\"Screenshot saved to: {screenshot_path}\")\n screenshot_finished_at = datetime.utcnow()\n\n # 4. Fetch Logs (from Environment /api/v1/log/)\n logs = []\n logs_fetch_started_at = datetime.utcnow()\n try:\n client = SupersetClient(env)\n\n # Calculate time window (last 24 hours)\n start_time = (datetime.now() - timedelta(hours=24)).isoformat()\n\n # Construct filter for logs\n # Note: We filter by dashboard_id matching the object\n query_params = {\n \"filters\": [\n {\"col\": \"dashboard_id\", \"opr\": \"eq\", \"value\": dashboard_id},\n {\"col\": \"dttm\", \"opr\": \"gt\", \"value\": start_time}\n ],\n \"order_column\": \"dttm\",\n \"order_direction\": \"desc\",\n \"page\": 0,\n \"page_size\": 100\n }\n\n superset_log.debug(f\"Fetching logs for dashboard {dashboard_id}\")\n response = client.network.request(\n method=\"GET\",\n endpoint=\"/log/\",\n params={\"q\": json.dumps(query_params)}\n )\n\n if isinstance(response, dict) and \"result\" in response:\n for item in response[\"result\"]:\n action = item.get(\"action\", \"unknown\")\n dttm = item.get(\"dttm\", \"\")\n details = item.get(\"json\", \"\")\n logs.append(f\"[{dttm}] {action}: {details}\")\n\n if not logs:\n logs = [\"No recent logs found for this dashboard.\"]\n superset_log.debug(\"No recent logs found for this dashboard\")\n\n except Exception as e:\n superset_log.warning(f\"Failed to fetch logs from environment: {e}\")\n logs = [f\"Error fetching remote logs: {e!s}\"]\n logs_fetch_finished_at = datetime.utcnow()\n\n # 5. Analyze with LLM\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_log.info(f\"Analyzing dashboard {dashboard_id} with LLM\")\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n dashboard_prompt = llm_settings[\"prompts\"].get(\n \"dashboard_validation_prompt\",\n DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n )\n llm_call_started_at = datetime.utcnow()\n analysis = await llm_client.analyze_dashboard(\n screenshot_path,\n logs,\n prompt_template=dashboard_prompt,\n )\n llm_call_finished_at = datetime.utcnow()\n\n # Log analysis summary to task logs for better visibility\n llm_log.info(f\"[ANALYSIS_SUMMARY] Status: {analysis['status']}\")\n llm_log.info(f\"[ANALYSIS_SUMMARY] Summary: {analysis['summary']}\")\n if analysis.get(\"issues\"):\n for i, issue in enumerate(analysis[\"issues\"]):\n llm_log.info(f\"[ANALYSIS_ISSUE][{i+1}] {issue.get('severity')}: {issue.get('message')} (Location: {issue.get('location', 'N/A')})\")\n\n # 6. Persist Result\n validation_result = ValidationResult(\n dashboard_id=dashboard_id,\n status=ValidationStatus(analysis[\"status\"]),\n summary=analysis[\"summary\"],\n issues=[DetectedIssue(**issue) for issue in analysis[\"issues\"]],\n screenshot_path=screenshot_path,\n raw_response=str(analysis)\n )\n validation_finished_at = datetime.utcnow()\n\n result_payload = _json_safe_value(validation_result.dict())\n result_payload[\"screenshot_paths\"] = [screenshot_path]\n result_payload[\"logs_sent_to_llm\"] = logs\n result_payload[\"logs_sent_count\"] = len(logs)\n result_payload[\"prompt_template\"] = dashboard_prompt\n result_payload[\"provider\"] = {\n \"id\": db_provider.id,\n \"name\": db_provider.name,\n \"type\": db_provider.provider_type,\n \"base_url\": db_provider.base_url,\n \"model\": db_provider.default_model,\n }\n result_payload[\"environment_id\"] = env_id\n result_payload[\"timings\"] = {\n \"validation_started_at\": validation_started_at.isoformat(),\n \"validation_finished_at\": validation_finished_at.isoformat(),\n \"validation_duration_ms\": int((validation_finished_at - validation_started_at).total_seconds() * 1000),\n \"screenshot_started_at\": screenshot_started_at.isoformat(),\n \"screenshot_finished_at\": screenshot_finished_at.isoformat(),\n \"screenshot_duration_ms\": int((screenshot_finished_at - screenshot_started_at).total_seconds() * 1000),\n \"logs_fetch_started_at\": logs_fetch_started_at.isoformat(),\n \"logs_fetch_finished_at\": logs_fetch_finished_at.isoformat(),\n \"logs_fetch_duration_ms\": int((logs_fetch_finished_at - logs_fetch_started_at).total_seconds() * 1000),\n \"llm_call_started_at\": llm_call_started_at.isoformat(),\n \"llm_call_finished_at\": llm_call_finished_at.isoformat(),\n \"llm_call_duration_ms\": int((llm_call_finished_at - llm_call_started_at).total_seconds() * 1000),\n }\n\n db_record = ValidationRecord(\n task_id=context.task_id if context else None,\n policy_id=params.get(\"policy_id\"),\n dashboard_id=validation_result.dashboard_id,\n environment_id=env_id,\n status=validation_result.status.value,\n summary=validation_result.summary,\n issues=[issue.dict() for issue in validation_result.issues],\n screenshot_path=validation_result.screenshot_path,\n raw_response=json.dumps(result_payload, ensure_ascii=False)\n )\n db.add(db_record)\n db.commit()\n\n # 7. Notification on failure (US1 / FR-015)\n try:\n policy_id = params.get(\"policy_id\")\n policy = None\n if policy_id:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n\n notification_service = NotificationService(db, config_mgr)\n await notification_service.dispatch_report(\n record=db_record,\n policy=policy,\n background_tasks=getattr(context, \"background_tasks\", None) if context else None\n )\n except Exception as e:\n log.error(f\"Failed to dispatch notifications: {e}\")\n\n # Final log to ensure all analysis is visible in task logs\n log.info(f\"Validation completed for dashboard {dashboard_id}. Status: {validation_result.status.value}\")\n\n return result_payload\n\n finally:\n db.close()\n # endregion DashboardValidationPlugin.execute\n# #endregion DashboardValidationPlugin\n\n# #region DocumentationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dataset documentation using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DocumentationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_documentation\"\n\n @property\n def name(self) -> str:\n return \"Dataset LLM Documentation\"\n\n @property\n def description(self) -> str:\n return \"Automated dataset and column documentation using LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dataset_id\": {\"type\": \"string\", \"title\": \"Dataset ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dataset_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DocumentationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dataset documentation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Documentation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dataset_id, environment_id, and provider_id.\n # @POST: Returns generated documentation and updates the dataset in Superset.\n # @SIDE_EFFECT: Calls LLM API and updates dataset metadata in Superset.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dataset_id = params.get(\"dataset_id\")\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Fetch Metadata (US2 / T024)\n from ...core.superset_client import SupersetClient\n client = SupersetClient(env)\n\n superset_log.debug(f\"Fetching dataset {dataset_id}\")\n dataset = client.get_dataset(int(dataset_id))\n\n # Extract columns and existing descriptions\n columns_data = []\n for col in dataset.get(\"columns\", []):\n columns_data.append({\n \"name\": col.get(\"column_name\"),\n \"type\": col.get(\"type\"),\n \"description\": col.get(\"description\")\n })\n superset_log.debug(f\"Extracted {len(columns_data)} columns from dataset\")\n\n # 4. Construct Prompt & Analyze (US2 / T025)\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n documentation_prompt = llm_settings[\"prompts\"].get(\n \"documentation_prompt\",\n DEFAULT_LLM_PROMPTS[\"documentation_prompt\"],\n )\n prompt = render_prompt(\n documentation_prompt,\n {\n \"dataset_name\": dataset.get(\"table_name\") or \"\",\n \"columns_json\": json.dumps(columns_data, ensure_ascii=False),\n },\n )\n\n # Using a generic chat completion for text-only US2\n llm_log.info(f\"Generating documentation for dataset {dataset_id}\")\n doc_result = await llm_client.get_json_completion([{\"role\": \"user\", \"content\": prompt}])\n\n # 5. Update Metadata (US2 / T026)\n update_payload = {\n \"description\": doc_result[\"dataset_description\"],\n \"columns\": []\n }\n\n # Map generated descriptions back to column IDs\n for col_doc in doc_result[\"column_descriptions\"]:\n for col in dataset.get(\"columns\", []):\n if col.get(\"column_name\") == col_doc[\"name\"]:\n update_payload[\"columns\"].append({\n \"id\": col.get(\"id\"),\n \"description\": col_doc[\"description\"]\n })\n\n superset_log.info(f\"Updating dataset {dataset_id} with generated documentation\")\n client.update_dataset(int(dataset_id), update_payload)\n\n log.info(f\"Documentation completed for dataset {dataset_id}\")\n\n return doc_result\n\n finally:\n db.close()\n # endregion DocumentationPlugin.execute\n# #endregion DocumentationPlugin\n\n# #endregion LLMAnalysisPlugin\n" }, { "contract_id": "_is_masked_or_invalid_api_key", @@ -35562,7 +36844,7 @@ "contract_type": "Class", "file_path": "backend/src/plugins/llm_analysis/plugin.py", "start_line": 62, - "end_line": 324, + "end_line": 325, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -35579,14 +36861,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DashboardValidationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dashboard health analysis using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DashboardValidationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_dashboard_validation\"\n\n @property\n def name(self) -> str:\n return \"Dashboard LLM Validation\"\n\n @property\n def description(self) -> str:\n return \"Automated dashboard health analysis using multimodal LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dashboard_id\": {\"type\": \"string\", \"title\": \"Dashboard ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dashboard_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DashboardValidationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dashboard validation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Validation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dashboard_id, environment_id, and provider_id.\n # @POST: Returns a dictionary with validation results and persists them to the database.\n # @SIDE_EFFECT: Captures a screenshot, calls LLM API, and writes to the database.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n validation_started_at = datetime.utcnow()\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n screenshot_log = log.with_source(\"screenshot\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dashboard_id_raw = params.get(\"dashboard_id\")\n dashboard_id = str(dashboard_id_raw) if dashboard_id_raw is not None else None\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n llm_log.debug(f\" Is Active: {db_provider.is_active}\")\n llm_log.debug(f\" Is Multimodal: {db_provider.is_multimodal}\")\n if not bool(db_provider.is_multimodal):\n raise ValueError(\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Capture Screenshot\n screenshot_service = ScreenshotService(env)\n\n storage_root = config_mgr.get_config().settings.storage.root_path\n screenshots_dir = os.path.join(storage_root, \"screenshots\")\n os.makedirs(screenshots_dir, exist_ok=True)\n\n filename = f\"{dashboard_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png\"\n screenshot_path = os.path.join(screenshots_dir, filename)\n\n screenshot_started_at = datetime.utcnow()\n screenshot_log.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n await screenshot_service.capture_dashboard(dashboard_id, screenshot_path)\n screenshot_log.debug(f\"Screenshot saved to: {screenshot_path}\")\n screenshot_finished_at = datetime.utcnow()\n\n # 4. Fetch Logs (from Environment /api/v1/log/)\n logs = []\n logs_fetch_started_at = datetime.utcnow()\n try:\n client = SupersetClient(env)\n\n # Calculate time window (last 24 hours)\n start_time = (datetime.now() - timedelta(hours=24)).isoformat()\n\n # Construct filter for logs\n # Note: We filter by dashboard_id matching the object\n query_params = {\n \"filters\": [\n {\"col\": \"dashboard_id\", \"opr\": \"eq\", \"value\": dashboard_id},\n {\"col\": \"dttm\", \"opr\": \"gt\", \"value\": start_time}\n ],\n \"order_column\": \"dttm\",\n \"order_direction\": \"desc\",\n \"page\": 0,\n \"page_size\": 100\n }\n\n superset_log.debug(f\"Fetching logs for dashboard {dashboard_id}\")\n response = client.network.request(\n method=\"GET\",\n endpoint=\"/log/\",\n params={\"q\": json.dumps(query_params)}\n )\n\n if isinstance(response, dict) and \"result\" in response:\n for item in response[\"result\"]:\n action = item.get(\"action\", \"unknown\")\n dttm = item.get(\"dttm\", \"\")\n details = item.get(\"json\", \"\")\n logs.append(f\"[{dttm}] {action}: {details}\")\n\n if not logs:\n logs = [\"No recent logs found for this dashboard.\"]\n superset_log.debug(\"No recent logs found for this dashboard\")\n\n except Exception as e:\n superset_log.warning(f\"Failed to fetch logs from environment: {e}\")\n logs = [f\"Error fetching remote logs: {e!s}\"]\n logs_fetch_finished_at = datetime.utcnow()\n\n # 5. Analyze with LLM\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_log.info(f\"Analyzing dashboard {dashboard_id} with LLM\")\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n dashboard_prompt = llm_settings[\"prompts\"].get(\n \"dashboard_validation_prompt\",\n DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n )\n llm_call_started_at = datetime.utcnow()\n analysis = await llm_client.analyze_dashboard(\n screenshot_path,\n logs,\n prompt_template=dashboard_prompt,\n )\n llm_call_finished_at = datetime.utcnow()\n\n # Log analysis summary to task logs for better visibility\n llm_log.info(f\"[ANALYSIS_SUMMARY] Status: {analysis['status']}\")\n llm_log.info(f\"[ANALYSIS_SUMMARY] Summary: {analysis['summary']}\")\n if analysis.get(\"issues\"):\n for i, issue in enumerate(analysis[\"issues\"]):\n llm_log.info(f\"[ANALYSIS_ISSUE][{i+1}] {issue.get('severity')}: {issue.get('message')} (Location: {issue.get('location', 'N/A')})\")\n\n # 6. Persist Result\n validation_result = ValidationResult(\n dashboard_id=dashboard_id,\n status=ValidationStatus(analysis[\"status\"]),\n summary=analysis[\"summary\"],\n issues=[DetectedIssue(**issue) for issue in analysis[\"issues\"]],\n screenshot_path=screenshot_path,\n raw_response=str(analysis)\n )\n validation_finished_at = datetime.utcnow()\n\n result_payload = _json_safe_value(validation_result.dict())\n result_payload[\"screenshot_paths\"] = [screenshot_path]\n result_payload[\"logs_sent_to_llm\"] = logs\n result_payload[\"logs_sent_count\"] = len(logs)\n result_payload[\"prompt_template\"] = dashboard_prompt\n result_payload[\"provider\"] = {\n \"id\": db_provider.id,\n \"name\": db_provider.name,\n \"type\": db_provider.provider_type,\n \"base_url\": db_provider.base_url,\n \"model\": db_provider.default_model,\n }\n result_payload[\"environment_id\"] = env_id\n result_payload[\"timings\"] = {\n \"validation_started_at\": validation_started_at.isoformat(),\n \"validation_finished_at\": validation_finished_at.isoformat(),\n \"validation_duration_ms\": int((validation_finished_at - validation_started_at).total_seconds() * 1000),\n \"screenshot_started_at\": screenshot_started_at.isoformat(),\n \"screenshot_finished_at\": screenshot_finished_at.isoformat(),\n \"screenshot_duration_ms\": int((screenshot_finished_at - screenshot_started_at).total_seconds() * 1000),\n \"logs_fetch_started_at\": logs_fetch_started_at.isoformat(),\n \"logs_fetch_finished_at\": logs_fetch_finished_at.isoformat(),\n \"logs_fetch_duration_ms\": int((logs_fetch_finished_at - logs_fetch_started_at).total_seconds() * 1000),\n \"llm_call_started_at\": llm_call_started_at.isoformat(),\n \"llm_call_finished_at\": llm_call_finished_at.isoformat(),\n \"llm_call_duration_ms\": int((llm_call_finished_at - llm_call_started_at).total_seconds() * 1000),\n }\n\n db_record = ValidationRecord(\n task_id=context.task_id if context else None,\n dashboard_id=validation_result.dashboard_id,\n environment_id=env_id,\n status=validation_result.status.value,\n summary=validation_result.summary,\n issues=[issue.dict() for issue in validation_result.issues],\n screenshot_path=validation_result.screenshot_path,\n raw_response=json.dumps(result_payload, ensure_ascii=False)\n )\n db.add(db_record)\n db.commit()\n\n # 7. Notification on failure (US1 / FR-015)\n try:\n policy_id = params.get(\"policy_id\")\n policy = None\n if policy_id:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n\n notification_service = NotificationService(db, config_mgr)\n await notification_service.dispatch_report(\n record=db_record,\n policy=policy,\n background_tasks=getattr(context, \"background_tasks\", None) if context else None\n )\n except Exception as e:\n log.error(f\"Failed to dispatch notifications: {e}\")\n\n # Final log to ensure all analysis is visible in task logs\n log.info(f\"Validation completed for dashboard {dashboard_id}. Status: {validation_result.status.value}\")\n\n return result_payload\n\n finally:\n db.close()\n # endregion DashboardValidationPlugin.execute\n# #endregion DashboardValidationPlugin\n" + "body": "# #region DashboardValidationPlugin [TYPE Class]\n# @BRIEF Plugin for automated dashboard health analysis using LLMs.\n# @RELATION IMPLEMENTS -> backend.src.core.plugin_base.PluginBase\nclass DashboardValidationPlugin(PluginBase):\n @property\n def id(self) -> str:\n return \"llm_dashboard_validation\"\n\n @property\n def name(self) -> str:\n return \"Dashboard LLM Validation\"\n\n @property\n def description(self) -> str:\n return \"Automated dashboard health analysis using multimodal LLMs.\"\n\n @property\n def version(self) -> str:\n return \"1.0.0\"\n\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"dashboard_id\": {\"type\": \"string\", \"title\": \"Dashboard ID\"},\n \"environment_id\": {\"type\": \"string\", \"title\": \"Environment ID\"},\n \"provider_id\": {\"type\": \"string\", \"title\": \"LLM Provider ID\"}\n },\n \"required\": [\"dashboard_id\", \"environment_id\", \"provider_id\"]\n }\n\n # region DashboardValidationPlugin.execute [TYPE Function]\n # @PURPOSE: Executes the dashboard validation task with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Validation parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: params contains dashboard_id, environment_id, and provider_id.\n # @POST: Returns a dictionary with validation results and persists them to the database.\n # @SIDE_EFFECT: Captures a screenshot, calls LLM API, and writes to the database.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None):\n with belief_scope(\"execute\", f\"plugin_id={self.id}\"):\n validation_started_at = datetime.utcnow()\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n llm_log = log.with_source(\"llm\") if context else log\n screenshot_log = log.with_source(\"screenshot\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing {self.name} with params: {params}\")\n\n dashboard_id_raw = params.get(\"dashboard_id\")\n dashboard_id = str(dashboard_id_raw) if dashboard_id_raw is not None else None\n env_id = params.get(\"environment_id\")\n provider_id = params.get(\"provider_id\")\n\n db = SessionLocal()\n try:\n # 1. Get Environment\n from ...dependencies import get_config_manager\n config_mgr = get_config_manager()\n env = config_mgr.get_environment(env_id)\n if not env:\n log.error(f\"Environment {env_id} not found\")\n raise ValueError(f\"Environment {env_id} not found\")\n\n # 2. Get LLM Provider\n llm_service = LLMProviderService(db)\n db_provider = llm_service.get_provider(provider_id)\n if not db_provider:\n log.error(f\"LLM Provider {provider_id} not found\")\n raise ValueError(f\"LLM Provider {provider_id} not found\")\n\n llm_log.debug(\"Retrieved provider config:\")\n llm_log.debug(f\" Provider ID: {db_provider.id}\")\n llm_log.debug(f\" Provider Name: {db_provider.name}\")\n llm_log.debug(f\" Provider Type: {db_provider.provider_type}\")\n llm_log.debug(f\" Base URL: {db_provider.base_url}\")\n llm_log.debug(f\" Default Model: {db_provider.default_model}\")\n llm_log.debug(f\" Is Active: {db_provider.is_active}\")\n llm_log.debug(f\" Is Multimodal: {db_provider.is_multimodal}\")\n if not bool(db_provider.is_multimodal):\n raise ValueError(\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n\n api_key = llm_service.get_decrypted_api_key(provider_id)\n llm_log.debug(f\"API Key decrypted (first 8 chars): {api_key[:8] if api_key and len(api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n\n # Check if API key was successfully decrypted\n if _is_masked_or_invalid_api_key(api_key):\n raise ValueError(\n f\"Invalid API key for provider {provider_id}. \"\n \"Please open LLM provider settings and save a real API key (not masked placeholder).\"\n )\n\n # 3. Capture Screenshot\n screenshot_service = ScreenshotService(env)\n\n storage_root = config_mgr.get_config().settings.storage.root_path\n screenshots_dir = os.path.join(storage_root, \"screenshots\")\n os.makedirs(screenshots_dir, exist_ok=True)\n\n filename = f\"{dashboard_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png\"\n screenshot_path = os.path.join(screenshots_dir, filename)\n\n screenshot_started_at = datetime.utcnow()\n screenshot_log.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n await screenshot_service.capture_dashboard(dashboard_id, screenshot_path)\n screenshot_log.debug(f\"Screenshot saved to: {screenshot_path}\")\n screenshot_finished_at = datetime.utcnow()\n\n # 4. Fetch Logs (from Environment /api/v1/log/)\n logs = []\n logs_fetch_started_at = datetime.utcnow()\n try:\n client = SupersetClient(env)\n\n # Calculate time window (last 24 hours)\n start_time = (datetime.now() - timedelta(hours=24)).isoformat()\n\n # Construct filter for logs\n # Note: We filter by dashboard_id matching the object\n query_params = {\n \"filters\": [\n {\"col\": \"dashboard_id\", \"opr\": \"eq\", \"value\": dashboard_id},\n {\"col\": \"dttm\", \"opr\": \"gt\", \"value\": start_time}\n ],\n \"order_column\": \"dttm\",\n \"order_direction\": \"desc\",\n \"page\": 0,\n \"page_size\": 100\n }\n\n superset_log.debug(f\"Fetching logs for dashboard {dashboard_id}\")\n response = client.network.request(\n method=\"GET\",\n endpoint=\"/log/\",\n params={\"q\": json.dumps(query_params)}\n )\n\n if isinstance(response, dict) and \"result\" in response:\n for item in response[\"result\"]:\n action = item.get(\"action\", \"unknown\")\n dttm = item.get(\"dttm\", \"\")\n details = item.get(\"json\", \"\")\n logs.append(f\"[{dttm}] {action}: {details}\")\n\n if not logs:\n logs = [\"No recent logs found for this dashboard.\"]\n superset_log.debug(\"No recent logs found for this dashboard\")\n\n except Exception as e:\n superset_log.warning(f\"Failed to fetch logs from environment: {e}\")\n logs = [f\"Error fetching remote logs: {e!s}\"]\n logs_fetch_finished_at = datetime.utcnow()\n\n # 5. Analyze with LLM\n llm_client = LLMClient(\n provider_type=LLMProviderType(db_provider.provider_type),\n api_key=api_key,\n base_url=db_provider.base_url,\n default_model=db_provider.default_model\n )\n\n llm_log.info(f\"Analyzing dashboard {dashboard_id} with LLM\")\n llm_settings = normalize_llm_settings(config_mgr.get_config().settings.llm)\n dashboard_prompt = llm_settings[\"prompts\"].get(\n \"dashboard_validation_prompt\",\n DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n )\n llm_call_started_at = datetime.utcnow()\n analysis = await llm_client.analyze_dashboard(\n screenshot_path,\n logs,\n prompt_template=dashboard_prompt,\n )\n llm_call_finished_at = datetime.utcnow()\n\n # Log analysis summary to task logs for better visibility\n llm_log.info(f\"[ANALYSIS_SUMMARY] Status: {analysis['status']}\")\n llm_log.info(f\"[ANALYSIS_SUMMARY] Summary: {analysis['summary']}\")\n if analysis.get(\"issues\"):\n for i, issue in enumerate(analysis[\"issues\"]):\n llm_log.info(f\"[ANALYSIS_ISSUE][{i+1}] {issue.get('severity')}: {issue.get('message')} (Location: {issue.get('location', 'N/A')})\")\n\n # 6. Persist Result\n validation_result = ValidationResult(\n dashboard_id=dashboard_id,\n status=ValidationStatus(analysis[\"status\"]),\n summary=analysis[\"summary\"],\n issues=[DetectedIssue(**issue) for issue in analysis[\"issues\"]],\n screenshot_path=screenshot_path,\n raw_response=str(analysis)\n )\n validation_finished_at = datetime.utcnow()\n\n result_payload = _json_safe_value(validation_result.dict())\n result_payload[\"screenshot_paths\"] = [screenshot_path]\n result_payload[\"logs_sent_to_llm\"] = logs\n result_payload[\"logs_sent_count\"] = len(logs)\n result_payload[\"prompt_template\"] = dashboard_prompt\n result_payload[\"provider\"] = {\n \"id\": db_provider.id,\n \"name\": db_provider.name,\n \"type\": db_provider.provider_type,\n \"base_url\": db_provider.base_url,\n \"model\": db_provider.default_model,\n }\n result_payload[\"environment_id\"] = env_id\n result_payload[\"timings\"] = {\n \"validation_started_at\": validation_started_at.isoformat(),\n \"validation_finished_at\": validation_finished_at.isoformat(),\n \"validation_duration_ms\": int((validation_finished_at - validation_started_at).total_seconds() * 1000),\n \"screenshot_started_at\": screenshot_started_at.isoformat(),\n \"screenshot_finished_at\": screenshot_finished_at.isoformat(),\n \"screenshot_duration_ms\": int((screenshot_finished_at - screenshot_started_at).total_seconds() * 1000),\n \"logs_fetch_started_at\": logs_fetch_started_at.isoformat(),\n \"logs_fetch_finished_at\": logs_fetch_finished_at.isoformat(),\n \"logs_fetch_duration_ms\": int((logs_fetch_finished_at - logs_fetch_started_at).total_seconds() * 1000),\n \"llm_call_started_at\": llm_call_started_at.isoformat(),\n \"llm_call_finished_at\": llm_call_finished_at.isoformat(),\n \"llm_call_duration_ms\": int((llm_call_finished_at - llm_call_started_at).total_seconds() * 1000),\n }\n\n db_record = ValidationRecord(\n task_id=context.task_id if context else None,\n policy_id=params.get(\"policy_id\"),\n dashboard_id=validation_result.dashboard_id,\n environment_id=env_id,\n status=validation_result.status.value,\n summary=validation_result.summary,\n issues=[issue.dict() for issue in validation_result.issues],\n screenshot_path=validation_result.screenshot_path,\n raw_response=json.dumps(result_payload, ensure_ascii=False)\n )\n db.add(db_record)\n db.commit()\n\n # 7. Notification on failure (US1 / FR-015)\n try:\n policy_id = params.get(\"policy_id\")\n policy = None\n if policy_id:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n\n notification_service = NotificationService(db, config_mgr)\n await notification_service.dispatch_report(\n record=db_record,\n policy=policy,\n background_tasks=getattr(context, \"background_tasks\", None) if context else None\n )\n except Exception as e:\n log.error(f\"Failed to dispatch notifications: {e}\")\n\n # Final log to ensure all analysis is visible in task logs\n log.info(f\"Validation completed for dashboard {dashboard_id}. Status: {validation_result.status.value}\")\n\n return result_payload\n\n finally:\n db.close()\n # endregion DashboardValidationPlugin.execute\n# #endregion DashboardValidationPlugin\n" }, { "contract_id": "DocumentationPlugin", "contract_type": "Class", "file_path": "backend/src/plugins/llm_analysis/plugin.py", - "start_line": 326, - "end_line": 480, + "start_line": 327, + "end_line": 481, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -35671,7 +36953,7 @@ "contract_type": "Module", "file_path": "backend/src/plugins/llm_analysis/service.py", "start_line": 1, - "end_line": 990, + "end_line": 1095, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -35705,14 +36987,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region LLMAnalysisService [C:5] [TYPE Module] [SEMANTICS llm, screenshot, playwright, openai, tenacity]\n# @BRIEF Services for LLM interaction and dashboard screenshots.\n# @LAYER Plugin\n# @RELATION DEPENDS_ON -> tenacity\n# @RELATION DEPENDS_ON -> tenacity\n# @RELATION DEPENDS_ON -> tenacity\n# @INVARIANT Screenshots must be 1920px width and capture full page height.\n# @DATA_CONTRACT DashboardSpec -> Screenshot + Analysis\n# @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.\n\nimport asyncio\nimport base64\nimport io\nimport json\nimport os\nfrom typing import Any\nfrom urllib.parse import urlsplit\n\nimport httpx\nfrom openai import AsyncOpenAI, AuthenticationError as OpenAIAuthenticationError, RateLimitError\nfrom PIL import Image\nfrom playwright.async_api import async_playwright\nfrom tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential\n\nfrom ...core.config_models import Environment\nfrom ...core.logger import belief_scope, logger\nfrom ...services.llm_prompt_templates import DEFAULT_LLM_PROMPTS, render_prompt\nfrom .models import LLMProviderType\n\n# Timeout constants (milliseconds unless noted)\nPLAYWRIGHT_NAVIGATION_TIMEOUT_MS = 30000\nPLAYWRIGHT_WAIT_TIMEOUT_MS = 10000\nPLAYWRIGHT_SHORT_TIMEOUT_MS = 5000\nHTTP_REQUEST_TIMEOUT_MS = 60000\nSCREENSHOT_SERVICE_TIMEOUT_MS = 120000\nLLM_HTTP_TIMEOUT_S = 120 # seconds (httpx client timeout)\nDEFAULT_USER_AGENT = \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\"\n\n# #region ScreenshotService [TYPE Class]\n# @BRIEF Handles capturing screenshots of Superset dashboards.\nclass ScreenshotService:\n # region ScreenshotService.__init__ [TYPE Function]\n # @PURPOSE Initializes the ScreenshotService with environment configuration.\n # @PRE env is a valid Environment object.\n def __init__(self, env: Environment):\n self.env = env\n # endregion ScreenshotService.__init__\n\n # region ScreenshotService._find_first_visible_locator [TYPE Function]\n # @PURPOSE Resolve the first visible locator from multiple Playwright locator strategies.\n # @PRE candidates is a non-empty list of locator-like objects.\n # @POST Returns a locator ready for interaction or None when nothing matches.\n async def _find_first_visible_locator(self, candidates) -> Any:\n for locator in candidates:\n try:\n match_count = await locator.count()\n for index in range(match_count):\n candidate = locator.nth(index)\n if await candidate.is_visible():\n return candidate\n except Exception:\n continue\n return None\n # endregion ScreenshotService._find_first_visible_locator\n\n # region ScreenshotService._iter_login_roots [TYPE Function]\n # @PURPOSE Enumerate page and child frames where login controls may be rendered.\n # @PRE page is a Playwright page-like object.\n # @POST Returns ordered roots starting with main page followed by frames.\n def _iter_login_roots(self, page) -> list[Any]:\n roots = [page]\n page_frames = getattr(page, \"frames\", [])\n try:\n for frame in page_frames:\n if frame not in roots:\n roots.append(frame)\n except Exception:\n pass\n return roots\n # endregion ScreenshotService._iter_login_roots\n\n # region ScreenshotService._extract_hidden_login_fields [TYPE Function]\n # @PURPOSE Collect hidden form fields required for direct login POST fallback.\n # @PRE Login page is loaded.\n # @POST Returns hidden input name/value mapping aggregated from page and child frames.\n async def _extract_hidden_login_fields(self, page) -> dict[str, str]:\n hidden_fields: dict[str, str] = {}\n for root in self._iter_login_roots(page):\n try:\n locator = root.locator(\"input[type='hidden'][name]\")\n count = await locator.count()\n for index in range(count):\n candidate = locator.nth(index)\n field_name = str(await candidate.get_attribute(\"name\") or \"\").strip()\n if not field_name or field_name in hidden_fields:\n continue\n hidden_fields[field_name] = str(await candidate.input_value()).strip()\n except Exception:\n continue\n return hidden_fields\n # endregion ScreenshotService._extract_hidden_login_fields\n\n # region ScreenshotService._extract_csrf_token [TYPE Function]\n # @PURPOSE Resolve CSRF token value from main page or embedded login frame.\n # @PRE Login page is loaded.\n # @POST Returns first non-empty csrf token or empty string.\n async def _extract_csrf_token(self, page) -> str:\n hidden_fields = await self._extract_hidden_login_fields(page)\n return str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n # endregion ScreenshotService._extract_csrf_token\n\n # region ScreenshotService._response_looks_like_login_page [TYPE Function]\n # @PURPOSE Detect when fallback login POST returned the login form again instead of an authenticated page.\n # @PRE response_text is normalized HTML or text from login POST response.\n # @POST Returns True when login-page markers dominate the response body.\n def _response_looks_like_login_page(self, response_text: str) -> bool:\n normalized = str(response_text or \"\").strip().lower()\n if not normalized:\n return False\n\n markers = [\n \"enter your login and password below\",\n \"username:\",\n \"password:\",\n \"sign in\",\n 'name=\"csrf_token\"',\n ]\n return sum(marker in normalized for marker in markers) >= 3\n # endregion ScreenshotService._response_looks_like_login_page\n\n # region ScreenshotService._redirect_looks_authenticated [TYPE Function]\n # @PURPOSE Treat non-login redirects after form POST as successful authentication without waiting for redirect target.\n # @PRE redirect_location may be empty or relative.\n # @POST Returns True when redirect target does not point back to login flow.\n def _redirect_looks_authenticated(self, redirect_location: str) -> bool:\n normalized = str(redirect_location or \"\").strip().lower()\n if not normalized:\n return True\n return \"/login\" not in normalized\n # endregion ScreenshotService._redirect_looks_authenticated\n\n # region ScreenshotService._submit_login_via_form_post [TYPE Function]\n # @PURPOSE Fallback login path that submits credentials directly with csrf token.\n # @PRE login_url is same-origin and csrf token can be read from DOM.\n # @POST Browser context receives authenticated cookies when login succeeds.\n async def _submit_login_via_form_post(self, page, login_url: str) -> bool:\n hidden_fields = await self._extract_hidden_login_fields(page)\n csrf_token = str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n if not csrf_token:\n logger.warning(\"[DEBUG] Direct form login fallback skipped: csrf_token not found\")\n return False\n\n try:\n request_context = page.context.request\n except Exception as context_error:\n logger.warning(f\"[DEBUG] Direct form login fallback skipped: request context unavailable: {context_error}\")\n return False\n\n parsed_url = urlsplit(login_url)\n origin = f\"{parsed_url.scheme}://{parsed_url.netloc}\" if parsed_url.scheme and parsed_url.netloc else login_url\n payload = dict(hidden_fields)\n payload[\"username\"] = self.env.username\n payload[\"password\"] = self.env.password\n logger.info(\n f\"[DEBUG] Attempting direct form login fallback via browser context request with hidden fields: {sorted(hidden_fields.keys())}\"\n )\n\n response = await request_context.post(\n login_url,\n form=payload,\n headers={\n \"Origin\": origin,\n \"Referer\": login_url,\n },\n timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS,\n fail_on_status_code=False,\n max_redirects=0,\n )\n response_url = str(getattr(response, \"url\", \"\") or \"\")\n response_status = int(getattr(response, \"status\", 0) or 0)\n response_headers = dict(getattr(response, \"headers\", {}) or {})\n redirect_location = str(\n response_headers.get(\"location\")\n or response_headers.get(\"Location\")\n or \"\"\n ).strip()\n redirect_statuses = {301, 302, 303, 307, 308}\n if response_status in redirect_statuses:\n redirect_authenticated = self._redirect_looks_authenticated(redirect_location)\n logger.info(\n f\"[DEBUG] Direct form login fallback redirect response: status={response_status} url={response_url} location={redirect_location!r} authenticated={redirect_authenticated}\"\n )\n return redirect_authenticated\n\n response_text = await response.text()\n text_snippet = \" \".join(response_text.split())[:200]\n looks_like_login_page = self._response_looks_like_login_page(response_text)\n logger.info(\n f\"[DEBUG] Direct form login fallback response: status={response_status} url={response_url} login_markup={looks_like_login_page} snippet={text_snippet!r}\"\n )\n return not looks_like_login_page\n # endregion ScreenshotService._submit_login_via_form_post\n\n # region ScreenshotService._find_login_field_locator [TYPE Function]\n # @PURPOSE Resolve login form input using semantic label text plus generic visible-input fallbacks.\n # @PRE field_name is `username` or `password`.\n # @POST Returns a locator for the corresponding input or None.\n async def _find_login_field_locator(self, page, field_name: str) -> Any:\n normalized = str(field_name or \"\").strip().lower()\n for root in self._iter_login_roots(page):\n if normalized == \"username\":\n input_candidates = [\n root.get_by_label(\"Username\", exact=False),\n root.get_by_label(\"Login\", exact=False),\n root.locator(\"label:text-matches('Username|Login', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Username|Login/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='username']\"),\n root.locator(\"input#username\"),\n root.locator(\"input[placeholder*='Username']\"),\n root.locator(\"input[type='text']\"),\n root.locator(\"input:not([type='password'])\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n if normalized == \"password\":\n input_candidates = [\n root.get_by_label(\"Password\", exact=False),\n root.locator(\"label:text-matches('Password', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Password/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='password']\"),\n root.locator(\"input#password\"),\n root.locator(\"input[placeholder*='Password']\"),\n root.locator(\"input[type='password']\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n return None\n # endregion ScreenshotService._find_login_field_locator\n\n # region ScreenshotService._find_submit_locator [TYPE Function]\n # @PURPOSE Resolve login submit button from main page or embedded auth frame.\n # @PRE page is ready for login interaction.\n # @POST Returns visible submit locator or None.\n async def _find_submit_locator(self, page) -> Any:\n selectors = [\n lambda root: root.get_by_role(\"button\", name=\"Sign in\", exact=False),\n lambda root: root.get_by_role(\"button\", name=\"Login\", exact=False),\n lambda root: root.locator(\"button[type='submit']\"),\n lambda root: root.locator(\"button#submit\"),\n lambda root: root.locator(\".btn-primary\"),\n lambda root: root.locator(\"input[type='submit']\"),\n ]\n for root in self._iter_login_roots(page):\n locator = await self._find_first_visible_locator([factory(root) for factory in selectors])\n if locator:\n return locator\n return None\n # endregion ScreenshotService._find_submit_locator\n\n # region ScreenshotService._goto_resilient [TYPE Function]\n # @PURPOSE Navigate without relying on networkidle for pages with long-polling or persistent requests.\n # @PRE page is a valid Playwright page and url is non-empty.\n # @POST Returns last navigation response or raises when both primary and fallback waits fail.\n async def _goto_resilient(\n self,\n page,\n url: str,\n primary_wait_until: str = \"domcontentloaded\",\n fallback_wait_until: str = \"load\",\n timeout: int = HTTP_REQUEST_TIMEOUT_MS,\n ):\n try:\n return await page.goto(url, wait_until=primary_wait_until, timeout=timeout)\n except Exception as primary_error:\n logger.warning(\n f\"[ScreenshotService._goto_resilient] Primary navigation wait '{primary_wait_until}' failed for {url}: {primary_error}\"\n )\n return await page.goto(url, wait_until=fallback_wait_until, timeout=timeout)\n # endregion ScreenshotService._goto_resilient\n\n # region ScreenshotService.capture_dashboard [TYPE Function]\n # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP.\n # @PRE dashboard_id is a valid string, output_path is a writable path.\n # @POST Returns True if screenshot is saved successfully.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, and writes a PNG file.\n # @UX_STATE [Navigating] -> Loading dashboard UI\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n async def capture_dashboard(self, dashboard_id: str, output_path: str) -> bool:\n with belief_scope(\"capture_dashboard\", f\"dashboard_id={dashboard_id}\"):\n logger.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n async with async_playwright() as p:\n browser = await p.chromium.launch(\n headless=True,\n args=[\n \"--disable-blink-features=AutomationControlled\",\n \"--disable-infobars\",\n \"--no-sandbox\"\n ]\n )\n # Set a realistic user agent to avoid 403 Forbidden from OpenResty/WAF\n user_agent = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\"\n # Construct base UI URL from environment (strip /api/v1 suffix)\n base_ui_url = self.env.url.rstrip(\"/\")\n if base_ui_url.endswith(\"/api/v1\"):\n base_ui_url = base_ui_url[:-len(\"/api/v1\")]\n\n # Create browser context with realistic headers\n context = await browser.new_context(\n viewport={'width': 1280, 'height': 720},\n user_agent=user_agent,\n extra_http_headers={\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Upgrade-Insecure-Requests\": \"1\",\n \"Sec-Fetch-Dest\": \"document\",\n \"Sec-Fetch-Mode\": \"navigate\",\n \"Sec-Fetch-Site\": \"none\",\n \"Sec-Fetch-User\": \"?1\"\n }\n )\n logger.info(\"Browser context created successfully\")\n\n page = await context.new_page()\n # Bypass navigator.webdriver detection\n await page.add_init_script(\"delete Object.getPrototypeOf(navigator).webdriver\")\n\n # 1. Navigate to login page and authenticate\n login_url = f\"{base_ui_url.rstrip('/')}/login/\"\n logger.info(f\"[DEBUG] Navigating to login page: {login_url}\")\n\n response = await self._goto_resilient(\n page,\n login_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n if response:\n logger.info(f\"[DEBUG] Login page response status: {response.status}\")\n\n # Wait for login form to be ready\n await page.wait_for_load_state(\"domcontentloaded\")\n\n # More exhaustive list of selectors for various Superset versions/themes\n selectors = {\n \"username\": ['input[name=\"username\"]', 'input#username', 'input[placeholder*=\"Username\"]', 'input[type=\"text\"]'],\n \"password\": ['input[name=\"password\"]', 'input#password', 'input[placeholder*=\"Password\"]', 'input[type=\"password\"]'],\n \"submit\": ['button[type=\"submit\"]', 'button#submit', '.btn-primary', 'input[type=\"submit\"]']\n }\n logger.info(\"[DEBUG] Attempting to find login form elements...\")\n\n try:\n used_direct_form_login = False\n # Find and fill username\n username_locator = await self._find_login_field_locator(page, \"username\")\n\n if not username_locator:\n roots = self._iter_login_roots(page)\n logger.info(f\"[DEBUG] Found {len(roots)} login roots including child frames\")\n for root_index, root in enumerate(roots[:5]):\n all_inputs = await root.locator('input').all()\n logger.info(f\"[DEBUG] Root {root_index}: found {len(all_inputs)} input fields\")\n for i, inp in enumerate(all_inputs[:5]): # Log first 5\n inp_type = await inp.get_attribute('type')\n inp_name = await inp.get_attribute('name')\n inp_id = await inp.get_attribute('id')\n logger.info(f\"[DEBUG] Root {root_index} input {i}: type={inp_type}, name={inp_name}, id={inp_id}\")\n used_direct_form_login = await self._submit_login_via_form_post(page, login_url)\n if not used_direct_form_login:\n raise RuntimeError(\"Could not find username input field on login page\")\n username_locator = None\n\n if username_locator is not None:\n logger.info(\"[DEBUG] Filling username field\")\n await username_locator.fill(self.env.username)\n\n # Find and fill password\n password_locator = await self._find_login_field_locator(page, \"password\") if username_locator is not None else None\n\n if username_locator is not None and not password_locator:\n raise RuntimeError(\"Could not find password input field on login page\")\n\n if password_locator is not None:\n logger.info(\"[DEBUG] Filling password field\")\n await password_locator.fill(self.env.password)\n\n # Click submit\n submit_locator = await self._find_submit_locator(page) if username_locator is not None else None\n\n if username_locator is not None and not submit_locator:\n raise RuntimeError(\"Could not find submit button on login page\")\n\n if submit_locator is not None:\n logger.info(\"[DEBUG] Clicking submit button\")\n await submit_locator.click()\n\n # Wait for navigation after login\n if not used_direct_form_login:\n try:\n await page.wait_for_load_state(\"load\", timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n except Exception as load_wait_error:\n logger.warning(f\"[DEBUG] Login post-submit load wait timed out: {load_wait_error}\")\n\n # Check if login was successful\n if not used_direct_form_login and \"/login\" in page.url:\n # Check for error messages on page\n error_msg = await page.locator(\".alert-danger, .error-message\").text_content() if await page.locator(\".alert-danger, .error-message\").count() > 0 else \"Unknown error\"\n logger.error(f\"[DEBUG] Login failed. Still on login page. Error: {error_msg}\")\n debug_path = output_path.replace(\".png\", \"_debug_failed_login.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(f\"Login failed: {error_msg}. Debug screenshot saved to {debug_path}\")\n\n logger.info(f\"[DEBUG] Login successful. Current URL: {page.url}\")\n\n # Check cookies after successful login\n page_cookies = await context.cookies()\n logger.info(f\"[DEBUG] Cookies after login: {len(page_cookies)}\")\n for c in page_cookies:\n logger.info(f\"[DEBUG] Cookie: name={c['name']}, domain={c['domain']}, value={c.get('value', '')[:20]}...\")\n\n except Exception as e:\n page_title = await page.title()\n logger.error(f\"UI Login failed. Page title: {page_title}, URL: {page.url}, Error: {e!s}\")\n debug_path = output_path.replace(\".png\", \"_debug_failed_login.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(f\"Login failed: {e!s}. Debug screenshot saved to {debug_path}\")\n\n # 2. Navigate to dashboard\n # @UX_STATE [Navigating] -> Loading dashboard UI\n dashboard_url = f\"{base_ui_url.rstrip('/')}/superset/dashboard/{dashboard_id}/?standalone=true\"\n\n if base_ui_url.startswith(\"https://\") and dashboard_url.startswith(\"http://\"):\n dashboard_url = dashboard_url.replace(\"http://\", \"https://\")\n\n logger.info(f\"[DEBUG] Navigating to dashboard: {dashboard_url}\")\n\n # Dashboard pages can keep polling/network activity open indefinitely.\n response = await self._goto_resilient(\n page,\n dashboard_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n\n if response:\n logger.info(f\"[DEBUG] Dashboard navigation response status: {response.status}, URL: {response.url}\")\n\n if \"/login\" in page.url:\n debug_path = output_path.replace(\".png\", \"_debug_failed_dashboard_auth.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(\n f\"Dashboard navigation redirected to login page after authentication. Debug screenshot saved to {debug_path}\"\n )\n\n try:\n # Wait for the dashboard grid to be present\n await page.wait_for_selector('.dashboard-component, .dashboard-header, [data-test=\"dashboard-grid\"]', timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n logger.info(\"[DEBUG] Dashboard container loaded\")\n\n # Wait for charts to finish loading (Superset uses loading spinners/skeletons)\n # We wait until loading indicators disappear or a timeout occurs\n try:\n # Wait for loading indicators to disappear\n await page.wait_for_selector('.loading, .ant-skeleton, .spinner', state=\"hidden\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Loading indicators hidden\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for loading indicators to hide\")\n\n # Wait for charts to actually render their content (e.g., ECharts, NVD3)\n # We look for common chart containers that should have content\n try:\n await page.wait_for_selector('.chart-container canvas, .slice_container svg, .superset-chart-canvas, .grid-content .chart-container', timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Chart content detected\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for chart content\")\n\n # Additional check: wait for all chart containers to have non-empty content\n logger.info(\"[DEBUG] Waiting for all charts to have rendered content...\")\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container, .slice_container');\n if (charts.length === 0) return true; // No charts to wait for\n \n // Check if all charts have rendered content (canvas, svg, or non-empty div)\n return Array.from(charts).every(chart => {\n const hasCanvas = chart.querySelector('canvas') !== null;\n const hasSvg = chart.querySelector('svg') !== null;\n const hasContent = chart.innerText.trim().length > 0 || chart.children.length > 0;\n return hasCanvas || hasSvg || hasContent;\n });\n }\"\"\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] All charts have rendered content\")\n\n # Scroll to bottom and back to top to trigger lazy loading of all charts\n logger.info(\"[DEBUG] Scrolling to trigger lazy loading...\")\n await page.evaluate(\"\"\"async () => {\n const delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n for (let i = 0; i < document.body.scrollHeight; i += 500) {\n window.scrollTo(0, i);\n await delay(100);\n }\n window.scrollTo(0, 0);\n await delay(500);\n }\"\"\")\n\n except Exception as e:\n logger.warning(f\"[DEBUG] Dashboard content wait failed: {e}, proceeding anyway after delay\")\n\n # Final stabilization delay - increased for complex dashboards\n logger.info(\"[DEBUG] Final stabilization delay...\")\n await asyncio.sleep(15)\n\n # Logic to handle tabs and full-page capture\n try:\n # 1. Handle Tabs (Recursive switching)\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n processed_tabs = set()\n\n async def switch_tabs(depth=0):\n if depth > 3:\n return # Limit recursion depth\n\n tab_selectors = [\n '.ant-tabs-nav-list .ant-tabs-tab',\n '.dashboard-component-tabs .ant-tabs-tab',\n '[data-test=\"dashboard-component-tabs\"] .ant-tabs-tab'\n ]\n\n found_tabs = []\n for selector in tab_selectors:\n found_tabs = await page.locator(selector).all()\n if found_tabs:\n break\n\n if found_tabs:\n logger.info(f\"[DEBUG][TabSwitching] Found {len(found_tabs)} tabs at depth {depth}\")\n for i, tab in enumerate(found_tabs):\n try:\n tab_text = (await tab.inner_text()).strip()\n tab_id = f\"{depth}_{i}_{tab_text}\"\n\n if tab_id in processed_tabs:\n continue\n\n if await tab.is_visible():\n logger.info(f\"[DEBUG][TabSwitching] Switching to tab: {tab_text}\")\n processed_tabs.add(tab_id)\n\n is_active = \"ant-tabs-tab-active\" in (await tab.get_attribute(\"class\") or \"\")\n if not is_active:\n await tab.click()\n await asyncio.sleep(2) # Wait for content to render\n\n await switch_tabs(depth + 1)\n except Exception as tab_e:\n logger.warning(f\"[DEBUG][TabSwitching] Failed to process tab {i}: {tab_e}\")\n\n try:\n first_tab = found_tabs[0]\n if \"ant-tabs-tab-active\" not in (await first_tab.get_attribute(\"class\") or \"\"):\n await first_tab.click()\n await asyncio.sleep(1)\n except Exception:\n pass\n\n await switch_tabs()\n\n # 2. Calculate full height for screenshot\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n full_height = await page.evaluate(\"\"\"() => {\n const body = document.body;\n const html = document.documentElement;\n const dashboardContent = document.querySelector('.dashboard-content');\n \n return Math.max(\n body.scrollHeight, body.offsetHeight,\n html.clientHeight, html.scrollHeight, html.offsetHeight,\n dashboardContent ? dashboardContent.scrollHeight + 100 : 0\n );\n }\"\"\")\n logger.info(f\"[DEBUG] Calculated full height: {full_height}\")\n\n # DIAGNOSTIC: Count chart elements before resize\n chart_count_before = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements BEFORE viewport resize: {chart_count_before}\")\n\n # DIAGNOSTIC: Capture pre-resize screenshot for comparison\n pre_resize_path = output_path.replace(\".png\", \"_preresize.png\")\n try:\n await page.screenshot(path=pre_resize_path, full_page=False, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n import os\n pre_resize_size = os.path.getsize(pre_resize_path) if os.path.exists(pre_resize_path) else 0\n logger.info(f\"[DIAGNOSTIC] Pre-resize screenshot saved: {pre_resize_path} ({pre_resize_size} bytes)\")\n except Exception as pre_e:\n logger.warning(f\"[DIAGNOSTIC] Failed to capture pre-resize screenshot: {pre_e}\")\n\n logger.info(f\"[DIAGNOSTIC] Resizing viewport from current to 1920x{int(full_height)}\")\n await page.set_viewport_size({\"width\": 1920, \"height\": int(full_height)})\n\n # DIAGNOSTIC: Increased wait time and log timing\n logger.info(\"[DIAGNOSTIC] Waiting 10 seconds after viewport resize for re-render...\")\n await asyncio.sleep(10)\n logger.info(\"[DIAGNOSTIC] Wait completed\")\n\n # DIAGNOSTIC: Count chart elements after resize and wait\n chart_count_after = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements AFTER viewport resize + wait: {chart_count_after}\")\n\n # DIAGNOSTIC: Check if any charts have error states\n chart_errors = await page.evaluate(\"\"\"() => {\n const errors = [];\n document.querySelectorAll('.chart-container, .slice_container').forEach((chart, i) => {\n const errorEl = chart.querySelector('.error, .alert-danger, .ant-alert-error');\n if (errorEl) {\n errors.push({index: i, text: errorEl.innerText.substring(0, 100)});\n }\n });\n return errors;\n }\"\"\")\n if chart_errors:\n logger.warning(f\"[DIAGNOSTIC] Charts with error states detected: {chart_errors}\")\n else:\n logger.info(\"[DIAGNOSTIC] No chart error states detected\")\n\n # 3. Take screenshot using CDP to bypass Playwright's font loading wait\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n logger.info(\"[DEBUG] Attempting full-page screenshot via CDP...\")\n cdp = await page.context.new_cdp_session(page)\n\n screenshot_data = await cdp.send(\"Page.captureScreenshot\", {\n \"format\": \"png\",\n \"fromSurface\": True,\n \"captureBeyondViewport\": True\n })\n\n image_data = base64.b64decode(screenshot_data[\"data\"])\n\n with open(output_path, 'wb') as f:\n f.write(image_data)\n\n # DIAGNOSTIC: Verify screenshot file\n import os\n final_size = os.path.getsize(output_path) if os.path.exists(output_path) else 0\n logger.info(f\"[DIAGNOSTIC] Final screenshot saved: {output_path}\")\n logger.info(f\"[DIAGNOSTIC] Final screenshot size: {final_size} bytes ({final_size / 1024:.2f} KB)\")\n\n # DIAGNOSTIC: Get image dimensions\n try:\n with Image.open(output_path) as final_img:\n logger.info(f\"[DIAGNOSTIC] Final screenshot dimensions: {final_img.width}x{final_img.height}\")\n except Exception as img_err:\n logger.warning(f\"[DIAGNOSTIC] Could not read final image dimensions: {img_err}\")\n\n logger.info(f\"Full-page screenshot saved to {output_path} (via CDP)\")\n except Exception as e:\n logger.error(f\"[DEBUG] Full-page/Tab capture failed: {e}\")\n try:\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception as e2:\n logger.error(f\"[DEBUG] Fallback screenshot also failed: {e2}\")\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n\n await browser.close()\n return True\n # endregion ScreenshotService.capture_dashboard\n# #endregion ScreenshotService\n\n# #region LLMClient [TYPE Class]\n# @BRIEF Wrapper for LLM provider APIs.\nclass LLMClient:\n # region LLMClient.__init__ [TYPE Function]\n # @PURPOSE Initializes the LLMClient with provider settings.\n # @PRE api_key, base_url, and default_model are non-empty strings.\n def __init__(self, provider_type: LLMProviderType, api_key: str, base_url: str, default_model: str):\n self.provider_type = provider_type\n normalized_key = (api_key or \"\").strip()\n if normalized_key.lower().startswith(\"bearer \"):\n normalized_key = normalized_key[7:].strip()\n self.api_key = normalized_key\n self.base_url = base_url\n self.default_model = default_model\n\n # DEBUG: Log initialization parameters (without exposing full API key)\n logger.info(\"[LLMClient.__init__] Initializing LLM client:\")\n logger.info(f\"[LLMClient.__init__] Provider Type: {provider_type}\")\n logger.info(f\"[LLMClient.__init__] Base URL: {base_url}\")\n logger.info(f\"[LLMClient.__init__] Default Model: {default_model}\")\n logger.info(f\"[LLMClient.__init__] API Key (first 8 chars): {self.api_key[:8] if self.api_key and len(self.api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n logger.info(f\"[LLMClient.__init__] API Key Length: {len(self.api_key) if self.api_key else 0}\")\n\n # Some OpenAI-compatible gateways are strict about auth header naming.\n default_headers = {\"Authorization\": f\"Bearer {self.api_key}\"}\n if self.provider_type == LLMProviderType.OPENROUTER:\n default_headers[\"HTTP-Referer\"] = (\n os.getenv(\"OPENROUTER_SITE_URL\", \"\").strip()\n or os.getenv(\"APP_BASE_URL\", \"\").strip()\n or \"http://localhost:8000\"\n )\n default_headers[\"X-Title\"] = os.getenv(\"OPENROUTER_APP_NAME\", \"\").strip() or \"ss-tools\"\n if self.provider_type == LLMProviderType.KILO:\n default_headers[\"Authentication\"] = f\"Bearer {self.api_key}\"\n default_headers[\"X-API-Key\"] = self.api_key\n # LiteLLM proxy uses standard OpenAI-compatible Bearer auth — no special headers needed.\n # It routes to upstream providers transparently, and the default Authorization header\n # is sufficient. No additional headers like HTTP-Referer or X-API-Key are required.\n\n http_client = httpx.AsyncClient(headers=default_headers, timeout=LLM_HTTP_TIMEOUT_S)\n self.client = AsyncOpenAI(\n api_key=self.api_key,\n base_url=base_url,\n default_headers=default_headers,\n http_client=http_client,\n )\n # endregion LLMClient.__init__\n\n # region LLMClient._supports_json_response_format [TYPE Function]\n # @PURPOSE Detect whether provider/model is likely compatible with response_format=json_object.\n # @PRE Client initialized with base_url and default_model.\n # @POST Returns False for known-incompatible combinations to avoid avoidable 400 errors.\n def _supports_json_response_format(self) -> bool:\n base = (self.base_url or \"\").lower()\n model = (self.default_model or \"\").lower()\n\n # OpenRouter routes to many upstream providers; some models reject json_object mode.\n if \"openrouter.ai\" in base:\n incompatible_tokens = (\n \"stepfun/\",\n \"step-\",\n \":free\",\n )\n if any(token in model for token in incompatible_tokens):\n return False\n return True\n # endregion LLMClient._supports_json_response_format\n\n # region LLMClient.get_json_completion [TYPE Function]\n # @PURPOSE Helper to handle LLM calls with JSON mode and fallback parsing.\n # @PRE messages is a list of valid message dictionaries.\n # @POST Returns a parsed JSON dictionary.\n # @SIDE_EFFECT Calls external LLM API.\n def _should_retry(exception: Exception) -> bool:\n \"\"\"Custom retry predicate that excludes authentication errors.\"\"\"\n # Don't retry on authentication errors\n if isinstance(exception, OpenAIAuthenticationError):\n return False\n # Retry on rate limit errors and other exceptions\n return isinstance(exception, (RateLimitError, Exception))\n\n @retry(\n stop=stop_after_attempt(5),\n wait=wait_exponential(multiplier=2, min=5, max=60),\n retry=retry_if_exception(_should_retry),\n reraise=True\n )\n async def get_json_completion(self, messages: list[dict[str, Any]]) -> dict[str, Any]:\n with belief_scope(\"get_json_completion\"):\n response = None\n try:\n use_json_mode = self._supports_json_response_format()\n try:\n logger.info(\n f\"[get_json_completion] Attempting LLM call for model: {self.default_model} \"\n f\"(json_mode={'on' if use_json_mode else 'off'})\"\n )\n logger.info(f\"[get_json_completion] Base URL being used: {self.base_url}\")\n logger.info(f\"[get_json_completion] Number of messages: {len(messages)}\")\n logger.info(f\"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}\")\n\n if use_json_mode:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages,\n response_format={\"type\": \"json_object\"}\n )\n else:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n except Exception as e:\n if use_json_mode and (\n \"JSON mode is not enabled\" in str(e)\n or \"json_object is not supported\" in str(e).lower()\n or \"response_format\" in str(e).lower()\n or \"400\" in str(e)\n ):\n logger.warning(f\"[get_json_completion] JSON mode failed or not supported: {e!s}. Falling back to plain text response.\")\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n else:\n raise e\n\n logger.debug(f\"[get_json_completion] LLM Response: {response}\")\n except OpenAIAuthenticationError as e:\n logger.error(f\"[get_json_completion] Authentication error: {e!s}\")\n # Do not retry on auth errors - re-raise to stop retry\n raise\n except RateLimitError as e:\n logger.warning(f\"[get_json_completion] Rate limit hit: {e!s}\")\n\n # Extract retry_delay from error metadata if available\n retry_delay = 5.0 # Default fallback\n try:\n # Based on logs, the raw response is in e.body or e.response.json()\n # The logs show 'metadata': {'raw': '...'} which suggests a proxy or specific client wrapper\n # Let's try to find the 'retryDelay' in the error message or response\n import re\n\n # Try to find \"retryDelay\": \"XXs\" in the string representation of the error\n error_str = str(e)\n match = re.search(r'\"retryDelay\":\\s*\"(\\d+)s\"', error_str)\n if match:\n retry_delay = float(match.group(1))\n else:\n # Try to parse from response if it's a standard OpenAI-like error with body\n if hasattr(e, 'body') and isinstance(e.body, dict):\n # Some providers put it in details\n details = e.body.get('error', {}).get('details', [])\n for detail in details:\n if detail.get('@type') == 'type.googleapis.com/google.rpc.RetryInfo':\n delay_str = detail.get('retryDelay', '5s')\n retry_delay = float(delay_str.rstrip('s'))\n break\n except Exception as parse_e:\n logger.debug(f\"[get_json_completion] Failed to parse retry delay: {parse_e}\")\n\n # Add a small safety margin (0.5s) as requested\n wait_time = retry_delay + 0.5\n logger.info(f\"[get_json_completion] Waiting for {wait_time}s before retry...\")\n await asyncio.sleep(wait_time)\n raise\n except Exception as e:\n logger.error(f\"[get_json_completion] LLM call failed: {e!s}\")\n raise\n\n if not response or not hasattr(response, 'choices') or not response.choices:\n raise RuntimeError(f\"Invalid LLM response: {response}\")\n\n content = response.choices[0].message.content\n logger.debug(f\"[get_json_completion] Raw content to parse: {content}\")\n\n try:\n return json.loads(content)\n except json.JSONDecodeError:\n logger.warning(\"[get_json_completion] Failed to parse JSON directly, attempting to extract from code blocks\")\n if \"```json\" in content:\n json_str = content.split(\"```json\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n elif \"```\" in content:\n json_str = content.split(\"```\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n else:\n raise\n # endregion LLMClient.get_json_completion\n\n # region LLMClient.test_runtime_connection [TYPE Function]\n # @PURPOSE Validate provider credentials using the same chat completions transport as runtime analysis.\n # @PRE Client is initialized with provider credentials and default_model.\n # @POST Returns lightweight JSON payload when runtime auth/model path is valid.\n # @SIDE_EFFECT Calls external LLM API.\n async def test_runtime_connection(self) -> dict[str, Any]:\n with belief_scope(\"test_runtime_connection\"):\n messages = [\n {\n \"role\": \"user\",\n \"content\": 'Return exactly this JSON object and nothing else: {\"ok\": true}',\n }\n ]\n return await self.get_json_completion(messages)\n # endregion LLMClient.test_runtime_connection\n\n # region LLMClient.fetch_models [TYPE Function]\n # @PURPOSE Fetch available models from the provider's API.\n # @PRE Client is initialized with provider credentials.\n # @POST Returns a list of model ID strings.\n # @SIDE_EFFECT Calls external LLM API /v1/models endpoint.\n async def fetch_models(self) -> list[str]:\n with belief_scope(\"LLMClient.fetch_models\"):\n try:\n response = await self.client.models.list()\n model_ids = [m.id for m in response.data]\n model_ids.sort()\n logger.reason(\n f\"[LLMClient.fetch_models] Fetched {len(model_ids)} models from {self.base_url}\",\n extra={\"src\": \"LLMClient.fetch_models\"},\n )\n return model_ids\n except Exception as e:\n logger.warning(\n f\"[LLMClient.fetch_models] Failed to fetch models: {e}\",\n )\n raise\n # endregion LLMClient.fetch_models\n\n # region LLMClient.analyze_dashboard [TYPE Function]\n # @PURPOSE Sends dashboard data (screenshot + logs) to LLM for health analysis.\n # @PRE screenshot_path exists, logs is a list of strings.\n # @POST Returns a structured analysis dictionary (status, summary, issues).\n # @SIDE_EFFECT Reads screenshot file and calls external LLM API.\n async def analyze_dashboard(\n self,\n screenshot_path: str,\n logs: list[str],\n prompt_template: str = DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n ) -> dict[str, Any]:\n with belief_scope(\"analyze_dashboard\"):\n # Optimize image to reduce token count (US1 / T023)\n # Gemini/Gemma models have limits on input tokens, and large images contribute significantly.\n try:\n with Image.open(screenshot_path) as img:\n # Convert to RGB if necessary\n if img.mode in (\"RGBA\", \"P\"):\n img = img.convert(\"RGB\")\n\n # Resize if too large (max 1024px width while maintaining aspect ratio)\n # We reduce width further to 1024px to stay within token limits for long dashboards\n max_width = 1024\n if img.width > max_width or img.height > 2048:\n # Calculate scaling factor to fit within 1024x2048\n scale = min(max_width / img.width, 2048 / img.height)\n if scale < 1.0:\n new_width = int(img.width * scale)\n new_height = int(img.height * scale)\n img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)\n logger.info(f\"[analyze_dashboard] Resized image from {img.width}x{img.height} to {new_width}x{new_height}\")\n\n # Compress and convert to base64\n buffer = io.BytesIO()\n # Lower quality to 60% to further reduce payload size\n img.save(buffer, format=\"JPEG\", quality=60, optimize=True)\n base_64_image = base64.b64encode(buffer.getvalue()).decode('utf-8')\n logger.info(f\"[analyze_dashboard] Optimized image size: {len(buffer.getvalue()) / 1024:.2f} KB\")\n except Exception as img_e:\n logger.warning(f\"[analyze_dashboard] Image optimization failed: {img_e}. Using raw image.\")\n with open(screenshot_path, \"rb\") as image_file:\n base_64_image = base64.b64encode(image_file.read()).decode('utf-8')\n\n log_text = \"\\n\".join(logs)\n prompt = render_prompt(prompt_template, {\"logs\": log_text})\n\n messages = [\n {\n \"role\": \"user\",\n \"content\": [\n {\"type\": \"text\", \"text\": prompt},\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": f\"data:image/jpeg;base64,{base_64_image}\"\n }\n }\n ]\n }\n ]\n\n try:\n return await self.get_json_completion(messages)\n except Exception as e:\n logger.error(f\"[analyze_dashboard] Failed to get analysis: {e!s}\")\n return {\n \"status\": \"UNKNOWN\",\n \"summary\": f\"Failed to get response from LLM: {e!s}\",\n \"issues\": [{\"severity\": \"UNKNOWN\", \"message\": \"LLM provider returned empty or invalid response\"}]\n }\n # endregion LLMClient.analyze_dashboard\n# #endregion LLMClient\n\n# #endregion LLMAnalysisService\n" + "body": "# #region LLMAnalysisService [C:5] [TYPE Module] [SEMANTICS llm, screenshot, playwright, openai, tenacity]\n# @BRIEF Services for LLM interaction and dashboard screenshots.\n# @LAYER Plugin\n# @RELATION DEPENDS_ON -> tenacity\n# @RELATION DEPENDS_ON -> tenacity\n# @RELATION DEPENDS_ON -> tenacity\n# @INVARIANT Screenshots must be 1920px width and capture full page height.\n# @DATA_CONTRACT DashboardSpec -> Screenshot + Analysis\n# @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.\n\nimport asyncio\nimport base64\nimport io\nimport json\nimport os\nimport shutil\nimport tempfile\nfrom typing import Any\nfrom urllib.parse import urlsplit\n\nimport httpx\nfrom openai import AsyncOpenAI, AuthenticationError as OpenAIAuthenticationError, RateLimitError\nfrom PIL import Image\nfrom playwright.async_api import async_playwright\nfrom tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential\n\nfrom ...core.config_models import Environment\nfrom ...core.logger import belief_scope, logger\nfrom ...services.llm_prompt_templates import DEFAULT_LLM_PROMPTS, render_prompt\nfrom .models import LLMProviderType\n\n# Timeout constants (milliseconds unless noted)\nPLAYWRIGHT_NAVIGATION_TIMEOUT_MS = 30000\nPLAYWRIGHT_WAIT_TIMEOUT_MS = 10000\nPLAYWRIGHT_SHORT_TIMEOUT_MS = 5000\nHTTP_REQUEST_TIMEOUT_MS = 60000\nSCREENSHOT_SERVICE_TIMEOUT_MS = 120000\nLLM_HTTP_TIMEOUT_S = 120 # seconds (httpx client timeout)\nDEFAULT_USER_AGENT = \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\"\n\n# #region ScreenshotService [TYPE Class]\n# @BRIEF Handles capturing screenshots of Superset dashboards.\nclass ScreenshotService:\n # region ScreenshotService.__init__ [TYPE Function]\n # @PURPOSE Initializes the ScreenshotService with environment configuration.\n # @PRE env is a valid Environment object.\n def __init__(self, env: Environment):\n self.env = env\n # endregion ScreenshotService.__init__\n\n # region ScreenshotService._find_first_visible_locator [TYPE Function]\n # @PURPOSE Resolve the first visible locator from multiple Playwright locator strategies.\n # @PRE candidates is a non-empty list of locator-like objects.\n # @POST Returns a locator ready for interaction or None when nothing matches.\n async def _find_first_visible_locator(self, candidates) -> Any:\n for locator in candidates:\n try:\n match_count = await locator.count()\n for index in range(match_count):\n candidate = locator.nth(index)\n if await candidate.is_visible():\n return candidate\n except Exception:\n continue\n return None\n # endregion ScreenshotService._find_first_visible_locator\n\n # region ScreenshotService._iter_login_roots [TYPE Function]\n # @PURPOSE Enumerate page and child frames where login controls may be rendered.\n # @PRE page is a Playwright page-like object.\n # @POST Returns ordered roots starting with main page followed by frames.\n def _iter_login_roots(self, page) -> list[Any]:\n roots = [page]\n page_frames = getattr(page, \"frames\", [])\n try:\n for frame in page_frames:\n if frame not in roots:\n roots.append(frame)\n except Exception:\n pass\n return roots\n # endregion ScreenshotService._iter_login_roots\n\n # region ScreenshotService._extract_hidden_login_fields [TYPE Function]\n # @PURPOSE Collect hidden form fields required for direct login POST fallback.\n # @PRE Login page is loaded.\n # @POST Returns hidden input name/value mapping aggregated from page and child frames.\n async def _extract_hidden_login_fields(self, page) -> dict[str, str]:\n hidden_fields: dict[str, str] = {}\n for root in self._iter_login_roots(page):\n try:\n locator = root.locator(\"input[type='hidden'][name]\")\n count = await locator.count()\n for index in range(count):\n candidate = locator.nth(index)\n field_name = str(await candidate.get_attribute(\"name\") or \"\").strip()\n if not field_name or field_name in hidden_fields:\n continue\n hidden_fields[field_name] = str(await candidate.input_value()).strip()\n except Exception:\n continue\n return hidden_fields\n # endregion ScreenshotService._extract_hidden_login_fields\n\n # region ScreenshotService._extract_csrf_token [TYPE Function]\n # @PURPOSE Resolve CSRF token value from main page or embedded login frame.\n # @PRE Login page is loaded.\n # @POST Returns first non-empty csrf token or empty string.\n async def _extract_csrf_token(self, page) -> str:\n hidden_fields = await self._extract_hidden_login_fields(page)\n return str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n # endregion ScreenshotService._extract_csrf_token\n\n # region ScreenshotService._response_looks_like_login_page [TYPE Function]\n # @PURPOSE Detect when fallback login POST returned the login form again instead of an authenticated page.\n # @PRE response_text is normalized HTML or text from login POST response.\n # @POST Returns True when login-page markers dominate the response body.\n def _response_looks_like_login_page(self, response_text: str) -> bool:\n normalized = str(response_text or \"\").strip().lower()\n if not normalized:\n return False\n\n markers = [\n \"enter your login and password below\",\n \"username:\",\n \"password:\",\n \"sign in\",\n 'name=\"csrf_token\"',\n ]\n return sum(marker in normalized for marker in markers) >= 3\n # endregion ScreenshotService._response_looks_like_login_page\n\n # region ScreenshotService._redirect_looks_authenticated [TYPE Function]\n # @PURPOSE Treat non-login redirects after form POST as successful authentication without waiting for redirect target.\n # @PRE redirect_location may be empty or relative.\n # @POST Returns True when redirect target does not point back to login flow.\n def _redirect_looks_authenticated(self, redirect_location: str) -> bool:\n normalized = str(redirect_location or \"\").strip().lower()\n if not normalized:\n return True\n return \"/login\" not in normalized\n # endregion ScreenshotService._redirect_looks_authenticated\n\n # region ScreenshotService._submit_login_via_form_post [TYPE Function]\n # @PURPOSE Fallback login path that submits credentials directly with csrf token.\n # @PRE login_url is same-origin and csrf token can be read from DOM.\n # @POST Browser context receives authenticated cookies when login succeeds.\n async def _submit_login_via_form_post(self, page, login_url: str) -> bool:\n hidden_fields = await self._extract_hidden_login_fields(page)\n csrf_token = str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n if not csrf_token:\n logger.warning(\"[DEBUG] Direct form login fallback skipped: csrf_token not found\")\n return False\n\n try:\n request_context = page.context.request\n except Exception as context_error:\n logger.warning(f\"[DEBUG] Direct form login fallback skipped: request context unavailable: {context_error}\")\n return False\n\n parsed_url = urlsplit(login_url)\n origin = f\"{parsed_url.scheme}://{parsed_url.netloc}\" if parsed_url.scheme and parsed_url.netloc else login_url\n payload = dict(hidden_fields)\n payload[\"username\"] = self.env.username\n payload[\"password\"] = self.env.password\n logger.info(\n f\"[DEBUG] Attempting direct form login fallback via browser context request with hidden fields: {sorted(hidden_fields.keys())}\"\n )\n\n response = await request_context.post(\n login_url,\n form=payload,\n headers={\n \"Origin\": origin,\n \"Referer\": login_url,\n },\n timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS,\n fail_on_status_code=False,\n max_redirects=0,\n )\n response_url = str(getattr(response, \"url\", \"\") or \"\")\n response_status = int(getattr(response, \"status\", 0) or 0)\n response_headers = dict(getattr(response, \"headers\", {}) or {})\n redirect_location = str(\n response_headers.get(\"location\")\n or response_headers.get(\"Location\")\n or \"\"\n ).strip()\n redirect_statuses = {301, 302, 303, 307, 308}\n if response_status in redirect_statuses:\n redirect_authenticated = self._redirect_looks_authenticated(redirect_location)\n logger.info(\n f\"[DEBUG] Direct form login fallback redirect response: status={response_status} url={response_url} location={redirect_location!r} authenticated={redirect_authenticated}\"\n )\n return redirect_authenticated\n\n response_text = await response.text()\n text_snippet = \" \".join(response_text.split())[:200]\n looks_like_login_page = self._response_looks_like_login_page(response_text)\n logger.info(\n f\"[DEBUG] Direct form login fallback response: status={response_status} url={response_url} login_markup={looks_like_login_page} snippet={text_snippet!r}\"\n )\n return not looks_like_login_page\n # endregion ScreenshotService._submit_login_via_form_post\n\n # region ScreenshotService._find_login_field_locator [TYPE Function]\n # @PURPOSE Resolve login form input using semantic label text plus generic visible-input fallbacks.\n # @PRE field_name is `username` or `password`.\n # @POST Returns a locator for the corresponding input or None.\n async def _find_login_field_locator(self, page, field_name: str) -> Any:\n normalized = str(field_name or \"\").strip().lower()\n for root in self._iter_login_roots(page):\n if normalized == \"username\":\n input_candidates = [\n root.get_by_label(\"Username\", exact=False),\n root.get_by_label(\"Login\", exact=False),\n root.locator(\"label:text-matches('Username|Login', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Username|Login/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='username']\"),\n root.locator(\"input#username\"),\n root.locator(\"input[placeholder*='Username']\"),\n root.locator(\"input[type='text']\"),\n root.locator(\"input:not([type='password'])\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n if normalized == \"password\":\n input_candidates = [\n root.get_by_label(\"Password\", exact=False),\n root.locator(\"label:text-matches('Password', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Password/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='password']\"),\n root.locator(\"input#password\"),\n root.locator(\"input[placeholder*='Password']\"),\n root.locator(\"input[type='password']\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n return None\n # endregion ScreenshotService._find_login_field_locator\n\n # region ScreenshotService._find_submit_locator [TYPE Function]\n # @PURPOSE Resolve login submit button from main page or embedded auth frame.\n # @PRE page is ready for login interaction.\n # @POST Returns visible submit locator or None.\n async def _find_submit_locator(self, page) -> Any:\n selectors = [\n lambda root: root.get_by_role(\"button\", name=\"Sign in\", exact=False),\n lambda root: root.get_by_role(\"button\", name=\"Login\", exact=False),\n lambda root: root.locator(\"button[type='submit']\"),\n lambda root: root.locator(\"button#submit\"),\n lambda root: root.locator(\".btn-primary\"),\n lambda root: root.locator(\"input[type='submit']\"),\n ]\n for root in self._iter_login_roots(page):\n locator = await self._find_first_visible_locator([factory(root) for factory in selectors])\n if locator:\n return locator\n return None\n # endregion ScreenshotService._find_submit_locator\n\n # region ScreenshotService._goto_resilient [TYPE Function]\n # @PURPOSE Navigate without relying on networkidle for pages with long-polling or persistent requests.\n # @PRE page is a valid Playwright page and url is non-empty.\n # @POST Returns last navigation response or raises when both primary and fallback waits fail.\n async def _goto_resilient(\n self,\n page,\n url: str,\n primary_wait_until: str = \"domcontentloaded\",\n fallback_wait_until: str = \"load\",\n timeout: int = HTTP_REQUEST_TIMEOUT_MS,\n ):\n try:\n return await page.goto(url, wait_until=primary_wait_until, timeout=timeout)\n except Exception as primary_error:\n logger.warning(\n f\"[ScreenshotService._goto_resilient] Primary navigation wait '{primary_wait_until}' failed for {url}: {primary_error}\"\n )\n return await page.goto(url, wait_until=fallback_wait_until, timeout=timeout)\n # endregion ScreenshotService._goto_resilient\n\n # region ScreenshotService._wait_for_charts_stabilized [TYPE Function] [C:2]\n # @BRIEF Wait until chart elements have non-zero dimensions, with polling.\n # @PRE page is a valid Playwright page.\n # @POST Waits for chart stabilization or raises on timeout (handled internally).\n # @RATIONALE Polls for actual chart rendering dimensions rather than using a fixed delay — charts may load at different speeds depending on dashboard complexity and network conditions.\n # @REJECTED Fixed sleep-based wait rejected — would either waste time (too long) or produce blank screenshots (too short); polling for actual canvas/svg dimensions is more reliable.\n async def _wait_for_charts_stabilized(self, page, timeout_ms: int = 15000):\n \"\"\"Wait until chart elements have non-zero dimensions, with polling.\"\"\"\n # Short initial delay for rendering pipeline to start\n await asyncio.sleep(0.5)\n try:\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container canvas, .slice_container svg, .grid-content canvas');\n if (charts.length === 0) return true;\n return Array.from(charts).some(c => {\n if (c.tagName === 'CANVAS') return c.width > 10 && c.height > 10;\n if (c.tagName === 'svg') {\n const bbox = c.getBoundingClientRect();\n return bbox.width > 10 && bbox.height > 10;\n }\n return false;\n });\n }\"\"\", timeout=timeout_ms)\n except Exception:\n logger.warning(\"[ScreenshotService] Chart stabilization wait timed out, proceeding anyway\")\n # endregion ScreenshotService._wait_for_charts_stabilized\n\n # region ScreenshotService._wait_for_resize_rendered [TYPE Function] [C:2]\n # @BRIEF Wait for charts to re-render after viewport resize.\n # @PRE page is a valid Playwright page; chart_count_before contains pre-resize element counts.\n # @POST Waits for chart content to return or timeout.\n # @RATIONALE After viewport resize, Superset triggers lazy chart re-rendering — this function polls for chart elements to reappear before taking the screenshot.\n # @REJECTED Single fixed wait after resize rejected — some dashboards re-render instantly while others take seconds; fixed wait is brittle across dashboard types.\n async def _wait_for_resize_rendered(self, page, chart_count_before: dict, timeout_ms: int = 10000):\n \"\"\"Wait for charts to re-render after viewport resize, with polling.\"\"\"\n try:\n await page.wait_for_function(\"\"\"(preCounts) => {\n const currentCharts = document.querySelectorAll('.chart-container, .slice_container').length;\n const currentCanvases = document.querySelectorAll('canvas').length;\n const currentSvgs = document.querySelectorAll('.chart-container svg, .slice_container svg').length;\n // At least one chart element must be present\n return currentCharts > 0 && (currentCanvases > 0 || currentSvgs > 0);\n }\"\"\", arg=chart_count_before, timeout=timeout_ms)\n except Exception:\n logger.warning(\"[ScreenshotService] Re-render wait timed out after viewport resize, proceeding anyway\")\n # endregion ScreenshotService._wait_for_resize_rendered\n\n # region ScreenshotService._save_debug_screenshot [TYPE Function] [C:1]\n # @BRIEF Save a debug screenshot to a temp directory for diagnostic purposes.\n # @PRE debug_dir exists and is writable.\n # @POST Returns the debug path or None on failure.\n # @RATIONALE Uses tempfile.mkdtemp() to avoid accumulating .png files in production storage. Temp dir is cleaned up on success (rmtree) or preserved on failure for debugging.\n # @REJECTED Old approach saved debug .png next to output path — accumulated _debug_failed_login.png, _preresize.png permanently in screenshots dir (F1). In-memory-only debug logging rejected — screenshot state is visual and cannot be captured in logs.\n async def _save_debug_screenshot(self, page, debug_dir: str, suffix: str) -> str | None:\n debug_path = os.path.join(debug_dir, suffix)\n try:\n await page.screenshot(path=debug_path)\n return debug_path\n except Exception:\n return None\n # endregion ScreenshotService._save_debug_screenshot\n\n # region ScreenshotService.capture_dashboard [TYPE Function] [C:4]\n # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP.\n # @PRE dashboard_id is a valid string, output_path is a writable path.\n # @POST Returns True if screenshot is saved successfully. Debug temp dir cleaned up on success, preserved on failure.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes a PNG file; creates and cleans up temp debug directory.\n # @UX_STATE [Navigating] -> Loading dashboard UI\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n # @RATIONALE Uses tempfile.mkdtemp() for all debug screenshots; cleans up on success (shutil.rmtree), preserves on failure for diagnostic analysis. Pre-resize screenshot is saved to temp dir and auto-cleaned on success.\n # @REJECTED Old approach saved debug .png files alongside output — accumulated permanently (F1). In-memory-only logging rejected — visual state cannot be captured in text.\n async def capture_dashboard(self, dashboard_id: str, output_path: str) -> bool:\n debug_dir = tempfile.mkdtemp(prefix=\"ss_screenshot_debug_\")\n success = False\n try:\n # -- begin original body --\n with belief_scope(\"capture_dashboard\", f\"dashboard_id={dashboard_id}\"):\n logger.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n async with async_playwright() as p:\n browser = await p.chromium.launch(\n headless=True,\n args=[\n \"--disable-blink-features=AutomationControlled\",\n \"--disable-infobars\",\n \"--no-sandbox\"\n ]\n )\n # Set a realistic user agent to avoid 403 Forbidden from OpenResty/WAF\n user_agent = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\"\n # Construct base UI URL from environment (strip /api/v1 suffix)\n base_ui_url = self.env.url.rstrip(\"/\")\n if base_ui_url.endswith(\"/api/v1\"):\n base_ui_url = base_ui_url[:-len(\"/api/v1\")]\n\n # Create browser context with realistic headers\n context = await browser.new_context(\n viewport={'width': 1280, 'height': 720},\n user_agent=user_agent,\n extra_http_headers={\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Upgrade-Insecure-Requests\": \"1\",\n \"Sec-Fetch-Dest\": \"document\",\n \"Sec-Fetch-Mode\": \"navigate\",\n \"Sec-Fetch-Site\": \"none\",\n \"Sec-Fetch-User\": \"?1\"\n }\n )\n logger.info(\"Browser context created successfully\")\n\n page = await context.new_page()\n # Bypass navigator.webdriver detection\n await page.add_init_script(\"delete Object.getPrototypeOf(navigator).webdriver\")\n\n # 1. Navigate to login page and authenticate\n login_url = f\"{base_ui_url.rstrip('/')}/login/\"\n logger.info(f\"[DEBUG] Navigating to login page: {login_url}\")\n\n response = await self._goto_resilient(\n page,\n login_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n if response:\n logger.info(f\"[DEBUG] Login page response status: {response.status}\")\n\n # Wait for login form to be ready\n await page.wait_for_load_state(\"domcontentloaded\")\n\n # More exhaustive list of selectors for various Superset versions/themes\n selectors = {\n \"username\": ['input[name=\"username\"]', 'input#username', 'input[placeholder*=\"Username\"]', 'input[type=\"text\"]'],\n \"password\": ['input[name=\"password\"]', 'input#password', 'input[placeholder*=\"Password\"]', 'input[type=\"password\"]'],\n \"submit\": ['button[type=\"submit\"]', 'button#submit', '.btn-primary', 'input[type=\"submit\"]']\n }\n logger.info(\"[DEBUG] Attempting to find login form elements...\")\n\n try:\n used_direct_form_login = False\n # Find and fill username\n username_locator = await self._find_login_field_locator(page, \"username\")\n\n if not username_locator:\n roots = self._iter_login_roots(page)\n logger.info(f\"[DEBUG] Found {len(roots)} login roots including child frames\")\n for root_index, root in enumerate(roots[:5]):\n all_inputs = await root.locator('input').all()\n logger.info(f\"[DEBUG] Root {root_index}: found {len(all_inputs)} input fields\")\n for i, inp in enumerate(all_inputs[:5]): # Log first 5\n inp_type = await inp.get_attribute('type')\n inp_name = await inp.get_attribute('name')\n inp_id = await inp.get_attribute('id')\n logger.info(f\"[DEBUG] Root {root_index} input {i}: type={inp_type}, name={inp_name}, id={inp_id}\")\n used_direct_form_login = await self._submit_login_via_form_post(page, login_url)\n if not used_direct_form_login:\n raise RuntimeError(\"Could not find username input field on login page\")\n username_locator = None\n\n if username_locator is not None:\n logger.info(\"[DEBUG] Filling username field\")\n await username_locator.fill(self.env.username)\n\n # Find and fill password\n password_locator = await self._find_login_field_locator(page, \"password\") if username_locator is not None else None\n\n if username_locator is not None and not password_locator:\n raise RuntimeError(\"Could not find password input field on login page\")\n\n if password_locator is not None:\n logger.info(\"[DEBUG] Filling password field\")\n await password_locator.fill(self.env.password)\n\n # Click submit\n submit_locator = await self._find_submit_locator(page) if username_locator is not None else None\n\n if username_locator is not None and not submit_locator:\n raise RuntimeError(\"Could not find submit button on login page\")\n\n if submit_locator is not None:\n logger.info(\"[DEBUG] Clicking submit button\")\n await submit_locator.click()\n\n # Wait for navigation after login\n if not used_direct_form_login:\n try:\n await page.wait_for_load_state(\"load\", timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n except Exception as load_wait_error:\n logger.warning(f\"[DEBUG] Login post-submit load wait timed out: {load_wait_error}\")\n\n # Check if login was successful\n if not used_direct_form_login and \"/login\" in page.url:\n # Check for error messages on page\n error_msg = await page.locator(\".alert-danger, .error-message\").text_content() if await page.locator(\".alert-danger, .error-message\").count() > 0 else \"Unknown error\"\n logger.error(f\"[DEBUG] Login failed. Still on login page. Error: {error_msg}\")\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_login.png\")\n raise RuntimeError(f\"Login failed: {error_msg}. Debug screenshot saved to {debug_path}\")\n\n logger.info(f\"[DEBUG] Login successful. Current URL: {page.url}\")\n\n # Check cookies after successful login\n page_cookies = await context.cookies()\n logger.info(f\"[DEBUG] Cookies after login: {len(page_cookies)}\")\n for c in page_cookies:\n logger.info(f\"[DEBUG] Cookie: name={c['name']}, domain={c['domain']}, value={c.get('value', '')[:20]}...\")\n\n except Exception as e:\n page_title = await page.title()\n logger.error(f\"UI Login failed. Page title: {page_title}, URL: {page.url}, Error: {e!s}\")\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_login.png\")\n raise RuntimeError(f\"Login failed: {e!s}. Debug screenshot saved to {debug_path}\")\n\n # 2. Navigate to dashboard\n # @UX_STATE [Navigating] -> Loading dashboard UI\n dashboard_url = f\"{base_ui_url.rstrip('/')}/superset/dashboard/{dashboard_id}/?standalone=true\"\n\n if base_ui_url.startswith(\"https://\") and dashboard_url.startswith(\"http://\"):\n dashboard_url = dashboard_url.replace(\"http://\", \"https://\")\n\n logger.info(f\"[DEBUG] Navigating to dashboard: {dashboard_url}\")\n\n # Dashboard pages can keep polling/network activity open indefinitely.\n response = await self._goto_resilient(\n page,\n dashboard_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n\n if response:\n logger.info(f\"[DEBUG] Dashboard navigation response status: {response.status}, URL: {response.url}\")\n\n if \"/login\" in page.url:\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_dashboard_auth.png\")\n raise RuntimeError(\n f\"Dashboard navigation redirected to login page after authentication. Debug screenshot saved to {debug_path}\"\n )\n\n try:\n # Wait for the dashboard grid to be present\n await page.wait_for_selector('.dashboard-component, .dashboard-header, [data-test=\"dashboard-grid\"]', timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n logger.info(\"[DEBUG] Dashboard container loaded\")\n\n # Wait for charts to finish loading (Superset uses loading spinners/skeletons)\n # We wait until loading indicators disappear or a timeout occurs\n try:\n # Wait for loading indicators to disappear\n await page.wait_for_selector('.loading, .ant-skeleton, .spinner', state=\"hidden\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Loading indicators hidden\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for loading indicators to hide\")\n\n # Wait for charts to actually render their content (e.g., ECharts, NVD3)\n # We look for common chart containers that should have content\n try:\n await page.wait_for_selector('.chart-container canvas, .slice_container svg, .superset-chart-canvas, .grid-content .chart-container', timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Chart content detected\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for chart content\")\n\n # Additional check: wait for all chart containers to have non-empty content\n logger.info(\"[DEBUG] Waiting for all charts to have rendered content...\")\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container, .slice_container');\n if (charts.length === 0) return true; // No charts to wait for\n \n // Check if all charts have rendered content (canvas, svg, or non-empty div)\n return Array.from(charts).every(chart => {\n const hasCanvas = chart.querySelector('canvas') !== null;\n const hasSvg = chart.querySelector('svg') !== null;\n const hasContent = chart.innerText.trim().length > 0 || chart.children.length > 0;\n return hasCanvas || hasSvg || hasContent;\n });\n }\"\"\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] All charts have rendered content\")\n\n # Scroll to bottom and back to top to trigger lazy loading of all charts\n logger.info(\"[DEBUG] Scrolling to trigger lazy loading...\")\n await page.evaluate(\"\"\"async () => {\n const delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n for (let i = 0; i < document.body.scrollHeight; i += 500) {\n window.scrollTo(0, i);\n await delay(100);\n }\n window.scrollTo(0, 0);\n await delay(500);\n }\"\"\")\n\n except Exception as e:\n logger.warning(f\"[DEBUG] Dashboard content wait failed: {e}, proceeding anyway after delay\")\n\n # Final stabilization delay - wait for charts to stabilize\n logger.info(\"[DEBUG] Waiting for charts to stabilize...\")\n await self._wait_for_charts_stabilized(page)\n\n # Logic to handle tabs and full-page capture\n try:\n async with asyncio.timeout(SCREENSHOT_SERVICE_TIMEOUT_MS / 1000):\n # 1. Handle Tabs (Recursive switching)\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n processed_tabs = set()\n\n async def switch_tabs(depth=0):\n if depth > 3:\n return # Limit recursion depth\n\n tab_selectors = [\n '.ant-tabs-nav-list .ant-tabs-tab',\n '.dashboard-component-tabs .ant-tabs-tab',\n '[data-test=\"dashboard-component-tabs\"] .ant-tabs-tab'\n ]\n\n found_tabs = []\n for selector in tab_selectors:\n found_tabs = await page.locator(selector).all()\n if found_tabs:\n break\n\n if found_tabs:\n logger.info(f\"[DEBUG][TabSwitching] Found {len(found_tabs)} tabs at depth {depth}\")\n for i, tab in enumerate(found_tabs):\n try:\n tab_text = (await tab.inner_text()).strip()\n tab_id = f\"{depth}_{i}_{tab_text}\"\n\n if tab_id in processed_tabs:\n continue\n\n if await tab.is_visible():\n logger.info(f\"[DEBUG][TabSwitching] Switching to tab: {tab_text}\")\n processed_tabs.add(tab_id)\n\n is_active = \"ant-tabs-tab-active\" in (await tab.get_attribute(\"class\") or \"\")\n if not is_active:\n await tab.click()\n # Wait for chart content to render in the newly active tab\n try:\n await page.wait_for_function(\"\"\"() => {\n const activeTab = document.querySelector('.ant-tabs-tab-active');\n if (!activeTab) return true;\n const tabPane = activeTab.closest('.ant-tabs')?.querySelector('.ant-tabs-content-holder');\n if (!tabPane) return true;\n const charts = tabPane.querySelectorAll('canvas, svg');\n return charts.length > 0;\n }\"\"\", timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception:\n logger.warning(f\"[TabSwitching] Content verification timed out for tab: {tab_text}\")\n\n await switch_tabs(depth + 1)\n except Exception as tab_e:\n logger.warning(f\"[DEBUG][TabSwitching] Failed to process tab {i}: {tab_e}\")\n\n try:\n first_tab = found_tabs[0]\n if \"ant-tabs-tab-active\" not in (await first_tab.get_attribute(\"class\") or \"\"):\n await first_tab.click()\n try:\n await page.wait_for_function(\"\"\"() => {\n const activeTab = document.querySelector('.ant-tabs-tab-active');\n if (!activeTab) return true;\n const tabPane = activeTab.closest('.ant-tabs')?.querySelector('.ant-tabs-content-holder');\n if (!tabPane) return true;\n const charts = tabPane.querySelectorAll('canvas, svg');\n return charts.length > 0;\n }\"\"\", timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n except Exception:\n logger.warning(\"[TabSwitching] Content verification timed out for first tab\")\n except Exception:\n pass\n\n await switch_tabs()\n\n # 2. Calculate full height for screenshot\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n full_height = await page.evaluate(\"\"\"() => {\n const body = document.body;\n const html = document.documentElement;\n const dashboardContent = document.querySelector('.dashboard-content');\n \n return Math.max(\n body.scrollHeight, body.offsetHeight,\n html.clientHeight, html.scrollHeight, html.offsetHeight,\n dashboardContent ? dashboardContent.scrollHeight + 100 : 0\n );\n }\"\"\")\n logger.info(f\"[DEBUG] Calculated full height: {full_height}\")\n\n # DIAGNOSTIC: Count chart elements before resize\n chart_count_before = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements BEFORE viewport resize: {chart_count_before}\")\n\n # DIAGNOSTIC: Capture pre-resize screenshot for comparison\n pre_resize_path = await self._save_debug_screenshot(page, debug_dir, \"preresize.png\")\n if pre_resize_path:\n pre_resize_size = os.path.getsize(pre_resize_path) if os.path.exists(pre_resize_path) else 0\n logger.info(f\"[DIAGNOSTIC] Pre-resize screenshot saved: {pre_resize_path} ({pre_resize_size} bytes)\")\n else:\n logger.warning(\"[DIAGNOSTIC] Failed to capture pre-resize screenshot\")\n\n logger.info(f\"[DIAGNOSTIC] Resizing viewport from current to 1920x{int(full_height)}\")\n await page.set_viewport_size({\"width\": 1920, \"height\": int(full_height)})\n\n # Wait for charts to re-render after viewport resize\n logger.info(\"[DIAGNOSTIC] Waiting for re-render after viewport resize...\")\n await self._wait_for_resize_rendered(page, chart_count_before)\n logger.info(\"[DIAGNOSTIC] Re-render wait completed\")\n\n # DIAGNOSTIC: Count chart elements after resize and wait\n chart_count_after = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements AFTER viewport resize + wait: {chart_count_after}\")\n\n # DIAGNOSTIC: Check if any charts have error states\n chart_errors = await page.evaluate(\"\"\"() => {\n const errors = [];\n document.querySelectorAll('.chart-container, .slice_container').forEach((chart, i) => {\n const errorEl = chart.querySelector('.error, .alert-danger, .ant-alert-error');\n if (errorEl) {\n errors.push({index: i, text: errorEl.innerText.substring(0, 100)});\n }\n });\n return errors;\n }\"\"\")\n if chart_errors:\n logger.warning(f\"[DIAGNOSTIC] Charts with error states detected: {chart_errors}\")\n else:\n logger.info(\"[DIAGNOSTIC] No chart error states detected\")\n\n # 3. Take screenshot using CDP to bypass Playwright's font loading wait\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n logger.info(\"[DEBUG] Attempting full-page screenshot via CDP...\")\n cdp_success = False\n try:\n cdp = await page.context.new_cdp_session(page)\n screenshot_data = await cdp.send(\"Page.captureScreenshot\", {\n \"format\": \"png\",\n \"fromSurface\": True,\n \"captureBeyondViewport\": True\n })\n image_data = base64.b64decode(screenshot_data[\"data\"])\n with open(output_path, 'wb') as f:\n f.write(image_data)\n logger.info(\"Full-page screenshot saved via CDP\")\n cdp_success = True\n except Exception as cdp_err:\n logger.warning(f\"CDP screenshot failed: {cdp_err}. Falling back to Playwright full_page.\")\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n logger.info(\"Full-page screenshot saved via Playwright fallback\")\n cdp_success = True\n\n if cdp_success:\n # DIAGNOSTIC: Verify screenshot file\n final_size = os.path.getsize(output_path) if os.path.exists(output_path) else 0\n logger.info(f\"[DIAGNOSTIC] Final screenshot saved: {output_path}\")\n logger.info(f\"[DIAGNOSTIC] Final screenshot size: {final_size} bytes ({final_size / 1024:.2f} KB)\")\n\n # DIAGNOSTIC: Get image dimensions\n try:\n with Image.open(output_path) as final_img:\n logger.info(f\"[DIAGNOSTIC] Final screenshot dimensions: {final_img.width}x{final_img.height}\")\n except Exception as img_err:\n logger.warning(f\"[DIAGNOSTIC] Could not read final image dimensions: {img_err}\")\n except asyncio.TimeoutError:\n logger.error(f\"Screenshot capture timed out after {SCREENSHOT_SERVICE_TIMEOUT_MS}ms\")\n try:\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n logger.info(\"Emergency timeout screenshot saved\")\n except Exception:\n pass\n except Exception as e:\n logger.error(f\"[DEBUG] Full-page/Tab capture failed: {e}\")\n try:\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception as e2:\n logger.error(f\"[DEBUG] Fallback screenshot also failed: {e2}\")\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n\n await browser.close()\n success = True\n return True\n finally:\n if success:\n shutil.rmtree(debug_dir, ignore_errors=True)\n else:\n logger.info(f\"Debug screenshots preserved in {debug_dir}\")\n # endregion ScreenshotService.capture_dashboard\n# #endregion ScreenshotService\n\n# #region LLMClient [TYPE Class]\n# @BRIEF Wrapper for LLM provider APIs.\nclass LLMClient:\n # region LLMClient.__init__ [TYPE Function]\n # @PURPOSE Initializes the LLMClient with provider settings.\n # @PRE api_key, base_url, and default_model are non-empty strings.\n def __init__(self, provider_type: LLMProviderType, api_key: str, base_url: str, default_model: str):\n self.provider_type = provider_type\n normalized_key = (api_key or \"\").strip()\n if normalized_key.lower().startswith(\"bearer \"):\n normalized_key = normalized_key[7:].strip()\n self.api_key = normalized_key\n self.base_url = base_url\n self.default_model = default_model\n\n # DEBUG: Log initialization parameters (without exposing full API key)\n logger.info(\"[LLMClient.__init__] Initializing LLM client:\")\n logger.info(f\"[LLMClient.__init__] Provider Type: {provider_type}\")\n logger.info(f\"[LLMClient.__init__] Base URL: {base_url}\")\n logger.info(f\"[LLMClient.__init__] Default Model: {default_model}\")\n logger.info(f\"[LLMClient.__init__] API Key (first 8 chars): {self.api_key[:8] if self.api_key and len(self.api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n logger.info(f\"[LLMClient.__init__] API Key Length: {len(self.api_key) if self.api_key else 0}\")\n\n # Some OpenAI-compatible gateways are strict about auth header naming.\n default_headers = {\"Authorization\": f\"Bearer {self.api_key}\"}\n if self.provider_type == LLMProviderType.OPENROUTER:\n default_headers[\"HTTP-Referer\"] = (\n os.getenv(\"OPENROUTER_SITE_URL\", \"\").strip()\n or os.getenv(\"APP_BASE_URL\", \"\").strip()\n or \"http://localhost:8000\"\n )\n default_headers[\"X-Title\"] = os.getenv(\"OPENROUTER_APP_NAME\", \"\").strip() or \"ss-tools\"\n if self.provider_type == LLMProviderType.KILO:\n default_headers[\"Authentication\"] = f\"Bearer {self.api_key}\"\n default_headers[\"X-API-Key\"] = self.api_key\n # LiteLLM proxy uses standard OpenAI-compatible Bearer auth — no special headers needed.\n # It routes to upstream providers transparently, and the default Authorization header\n # is sufficient. No additional headers like HTTP-Referer or X-API-Key are required.\n\n http_client = httpx.AsyncClient(headers=default_headers, timeout=LLM_HTTP_TIMEOUT_S)\n self.client = AsyncOpenAI(\n api_key=self.api_key,\n base_url=base_url,\n default_headers=default_headers,\n http_client=http_client,\n )\n # endregion LLMClient.__init__\n\n # region LLMClient._supports_json_response_format [TYPE Function]\n # @PURPOSE Detect whether provider/model is likely compatible with response_format=json_object.\n # @PRE Client initialized with base_url and default_model.\n # @POST Returns False for known-incompatible combinations to avoid avoidable 400 errors.\n def _supports_json_response_format(self) -> bool:\n base = (self.base_url or \"\").lower()\n model = (self.default_model or \"\").lower()\n\n # OpenRouter routes to many upstream providers; some models reject json_object mode.\n if \"openrouter.ai\" in base:\n incompatible_tokens = (\n \"stepfun/\",\n \"step-\",\n \":free\",\n )\n if any(token in model for token in incompatible_tokens):\n return False\n return True\n # endregion LLMClient._supports_json_response_format\n\n # region LLMClient.get_json_completion [TYPE Function]\n # @PURPOSE Helper to handle LLM calls with JSON mode and fallback parsing.\n # @PRE messages is a list of valid message dictionaries.\n # @POST Returns a parsed JSON dictionary.\n # @SIDE_EFFECT Calls external LLM API.\n def _should_retry(exception: Exception) -> bool:\n \"\"\"Custom retry predicate that excludes authentication errors.\"\"\"\n # Don't retry on authentication errors\n if isinstance(exception, OpenAIAuthenticationError):\n return False\n # Retry on rate limit errors and other exceptions\n return isinstance(exception, (RateLimitError, Exception))\n\n @retry(\n stop=stop_after_attempt(5),\n wait=wait_exponential(multiplier=2, min=5, max=60),\n retry=retry_if_exception(_should_retry),\n reraise=True\n )\n async def get_json_completion(self, messages: list[dict[str, Any]]) -> dict[str, Any]:\n with belief_scope(\"get_json_completion\"):\n response = None\n try:\n use_json_mode = self._supports_json_response_format()\n try:\n logger.info(\n f\"[get_json_completion] Attempting LLM call for model: {self.default_model} \"\n f\"(json_mode={'on' if use_json_mode else 'off'})\"\n )\n logger.info(f\"[get_json_completion] Base URL being used: {self.base_url}\")\n logger.info(f\"[get_json_completion] Number of messages: {len(messages)}\")\n logger.info(f\"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}\")\n\n if use_json_mode:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages,\n response_format={\"type\": \"json_object\"}\n )\n else:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n except Exception as e:\n if use_json_mode and (\n \"JSON mode is not enabled\" in str(e)\n or \"json_object is not supported\" in str(e).lower()\n or \"response_format\" in str(e).lower()\n or \"400\" in str(e)\n ):\n logger.warning(f\"[get_json_completion] JSON mode failed or not supported: {e!s}. Falling back to plain text response.\")\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n else:\n raise e\n\n logger.debug(f\"[get_json_completion] LLM Response: {response}\")\n except OpenAIAuthenticationError as e:\n logger.error(f\"[get_json_completion] Authentication error: {e!s}\")\n # Do not retry on auth errors - re-raise to stop retry\n raise\n except RateLimitError as e:\n logger.warning(f\"[get_json_completion] Rate limit hit: {e!s}\")\n\n # Extract retry_delay from error metadata if available\n retry_delay = 5.0 # Default fallback\n try:\n # Based on logs, the raw response is in e.body or e.response.json()\n # The logs show 'metadata': {'raw': '...'} which suggests a proxy or specific client wrapper\n # Let's try to find the 'retryDelay' in the error message or response\n import re\n\n # Try to find \"retryDelay\": \"XXs\" in the string representation of the error\n error_str = str(e)\n match = re.search(r'\"retryDelay\":\\s*\"(\\d+)s\"', error_str)\n if match:\n retry_delay = float(match.group(1))\n else:\n # Try to parse from response if it's a standard OpenAI-like error with body\n if hasattr(e, 'body') and isinstance(e.body, dict):\n # Some providers put it in details\n details = e.body.get('error', {}).get('details', [])\n for detail in details:\n if detail.get('@type') == 'type.googleapis.com/google.rpc.RetryInfo':\n delay_str = detail.get('retryDelay', '5s')\n retry_delay = float(delay_str.rstrip('s'))\n break\n except Exception as parse_e:\n logger.debug(f\"[get_json_completion] Failed to parse retry delay: {parse_e}\")\n\n # Add a small safety margin (0.5s) as requested\n wait_time = retry_delay + 0.5\n logger.info(f\"[get_json_completion] Waiting for {wait_time}s before retry...\")\n await asyncio.sleep(wait_time)\n raise\n except Exception as e:\n logger.error(f\"[get_json_completion] LLM call failed: {e!s}\")\n raise\n\n if not response or not hasattr(response, 'choices') or not response.choices:\n raise RuntimeError(f\"Invalid LLM response: {response}\")\n\n content = response.choices[0].message.content\n logger.debug(f\"[get_json_completion] Raw content to parse: {content}\")\n\n try:\n return json.loads(content)\n except json.JSONDecodeError:\n logger.warning(\"[get_json_completion] Failed to parse JSON directly, attempting to extract from code blocks\")\n if \"```json\" in content:\n json_str = content.split(\"```json\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n elif \"```\" in content:\n json_str = content.split(\"```\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n else:\n raise\n # endregion LLMClient.get_json_completion\n\n # region LLMClient.test_runtime_connection [TYPE Function]\n # @PURPOSE Validate provider credentials using the same chat completions transport as runtime analysis.\n # @PRE Client is initialized with provider credentials and default_model.\n # @POST Returns lightweight JSON payload when runtime auth/model path is valid.\n # @SIDE_EFFECT Calls external LLM API.\n async def test_runtime_connection(self) -> dict[str, Any]:\n with belief_scope(\"test_runtime_connection\"):\n messages = [\n {\n \"role\": \"user\",\n \"content\": 'Return exactly this JSON object and nothing else: {\"ok\": true}',\n }\n ]\n return await self.get_json_completion(messages)\n # endregion LLMClient.test_runtime_connection\n\n # region LLMClient.fetch_models [TYPE Function]\n # @PURPOSE Fetch available models from the provider's API.\n # @PRE Client is initialized with provider credentials.\n # @POST Returns a list of model ID strings.\n # @SIDE_EFFECT Calls external LLM API /v1/models endpoint.\n async def fetch_models(self) -> list[str]:\n with belief_scope(\"LLMClient.fetch_models\"):\n try:\n response = await self.client.models.list()\n model_ids = [m.id for m in response.data]\n model_ids.sort()\n logger.reason(\n f\"[LLMClient.fetch_models] Fetched {len(model_ids)} models from {self.base_url}\",\n extra={\"src\": \"LLMClient.fetch_models\"},\n )\n return model_ids\n except Exception as e:\n logger.warning(\n f\"[LLMClient.fetch_models] Failed to fetch models: {e}\",\n )\n raise\n # endregion LLMClient.fetch_models\n\n # region LLMClient.analyze_dashboard [TYPE Function]\n # @PURPOSE Sends dashboard data (screenshot + logs) to LLM for health analysis.\n # @PRE screenshot_path exists, logs is a list of strings.\n # @POST Returns a structured analysis dictionary (status, summary, issues).\n # @SIDE_EFFECT Reads screenshot file and calls external LLM API.\n async def analyze_dashboard(\n self,\n screenshot_path: str,\n logs: list[str],\n prompt_template: str = DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n ) -> dict[str, Any]:\n with belief_scope(\"analyze_dashboard\"):\n # Optimize image to reduce token count (US1 / T023)\n # Gemini/Gemma models have limits on input tokens, and large images contribute significantly.\n try:\n with Image.open(screenshot_path) as img:\n # Convert to RGB if necessary\n if img.mode in (\"RGBA\", \"P\"):\n img = img.convert(\"RGB\")\n\n # Resize if too large (max 1024px width while maintaining aspect ratio)\n # We reduce width further to 1024px to stay within token limits for long dashboards\n max_width = 1024\n if img.width > max_width or img.height > 2048:\n # Calculate scaling factor to fit within 1024x2048\n scale = min(max_width / img.width, 2048 / img.height)\n if scale < 1.0:\n new_width = int(img.width * scale)\n new_height = int(img.height * scale)\n img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)\n logger.info(f\"[analyze_dashboard] Resized image from {img.width}x{img.height} to {new_width}x{new_height}\")\n\n # Compress and convert to base64\n buffer = io.BytesIO()\n # Lower quality to 60% to further reduce payload size\n img.save(buffer, format=\"JPEG\", quality=60, optimize=True)\n base_64_image = base64.b64encode(buffer.getvalue()).decode('utf-8')\n logger.info(f\"[analyze_dashboard] Optimized image size: {len(buffer.getvalue()) / 1024:.2f} KB\")\n except Exception as img_e:\n logger.warning(f\"[analyze_dashboard] Image optimization failed: {img_e}. Using raw image.\")\n with open(screenshot_path, \"rb\") as image_file:\n base_64_image = base64.b64encode(image_file.read()).decode('utf-8')\n\n log_text = \"\\n\".join(logs)\n prompt = render_prompt(prompt_template, {\"logs\": log_text})\n\n messages = [\n {\n \"role\": \"user\",\n \"content\": [\n {\"type\": \"text\", \"text\": prompt},\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": f\"data:image/jpeg;base64,{base_64_image}\"\n }\n }\n ]\n }\n ]\n\n try:\n return await self.get_json_completion(messages)\n except Exception as e:\n logger.error(f\"[analyze_dashboard] Failed to get analysis: {e!s}\")\n return {\n \"status\": \"UNKNOWN\",\n \"summary\": f\"Failed to get response from LLM: {e!s}\",\n \"issues\": [{\"severity\": \"UNKNOWN\", \"message\": \"LLM provider returned empty or invalid response\"}]\n }\n # endregion LLMClient.analyze_dashboard\n\n# #endregion LLMClient\n\n# #endregion LLMAnalysisService\n" }, { "contract_id": "ScreenshotService", "contract_type": "Class", "file_path": "backend/src/plugins/llm_analysis/service.py", - "start_line": 39, - "end_line": 686, + "start_line": 41, + "end_line": 790, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -35722,14 +37004,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ScreenshotService [TYPE Class]\n# @BRIEF Handles capturing screenshots of Superset dashboards.\nclass ScreenshotService:\n # region ScreenshotService.__init__ [TYPE Function]\n # @PURPOSE Initializes the ScreenshotService with environment configuration.\n # @PRE env is a valid Environment object.\n def __init__(self, env: Environment):\n self.env = env\n # endregion ScreenshotService.__init__\n\n # region ScreenshotService._find_first_visible_locator [TYPE Function]\n # @PURPOSE Resolve the first visible locator from multiple Playwright locator strategies.\n # @PRE candidates is a non-empty list of locator-like objects.\n # @POST Returns a locator ready for interaction or None when nothing matches.\n async def _find_first_visible_locator(self, candidates) -> Any:\n for locator in candidates:\n try:\n match_count = await locator.count()\n for index in range(match_count):\n candidate = locator.nth(index)\n if await candidate.is_visible():\n return candidate\n except Exception:\n continue\n return None\n # endregion ScreenshotService._find_first_visible_locator\n\n # region ScreenshotService._iter_login_roots [TYPE Function]\n # @PURPOSE Enumerate page and child frames where login controls may be rendered.\n # @PRE page is a Playwright page-like object.\n # @POST Returns ordered roots starting with main page followed by frames.\n def _iter_login_roots(self, page) -> list[Any]:\n roots = [page]\n page_frames = getattr(page, \"frames\", [])\n try:\n for frame in page_frames:\n if frame not in roots:\n roots.append(frame)\n except Exception:\n pass\n return roots\n # endregion ScreenshotService._iter_login_roots\n\n # region ScreenshotService._extract_hidden_login_fields [TYPE Function]\n # @PURPOSE Collect hidden form fields required for direct login POST fallback.\n # @PRE Login page is loaded.\n # @POST Returns hidden input name/value mapping aggregated from page and child frames.\n async def _extract_hidden_login_fields(self, page) -> dict[str, str]:\n hidden_fields: dict[str, str] = {}\n for root in self._iter_login_roots(page):\n try:\n locator = root.locator(\"input[type='hidden'][name]\")\n count = await locator.count()\n for index in range(count):\n candidate = locator.nth(index)\n field_name = str(await candidate.get_attribute(\"name\") or \"\").strip()\n if not field_name or field_name in hidden_fields:\n continue\n hidden_fields[field_name] = str(await candidate.input_value()).strip()\n except Exception:\n continue\n return hidden_fields\n # endregion ScreenshotService._extract_hidden_login_fields\n\n # region ScreenshotService._extract_csrf_token [TYPE Function]\n # @PURPOSE Resolve CSRF token value from main page or embedded login frame.\n # @PRE Login page is loaded.\n # @POST Returns first non-empty csrf token or empty string.\n async def _extract_csrf_token(self, page) -> str:\n hidden_fields = await self._extract_hidden_login_fields(page)\n return str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n # endregion ScreenshotService._extract_csrf_token\n\n # region ScreenshotService._response_looks_like_login_page [TYPE Function]\n # @PURPOSE Detect when fallback login POST returned the login form again instead of an authenticated page.\n # @PRE response_text is normalized HTML or text from login POST response.\n # @POST Returns True when login-page markers dominate the response body.\n def _response_looks_like_login_page(self, response_text: str) -> bool:\n normalized = str(response_text or \"\").strip().lower()\n if not normalized:\n return False\n\n markers = [\n \"enter your login and password below\",\n \"username:\",\n \"password:\",\n \"sign in\",\n 'name=\"csrf_token\"',\n ]\n return sum(marker in normalized for marker in markers) >= 3\n # endregion ScreenshotService._response_looks_like_login_page\n\n # region ScreenshotService._redirect_looks_authenticated [TYPE Function]\n # @PURPOSE Treat non-login redirects after form POST as successful authentication without waiting for redirect target.\n # @PRE redirect_location may be empty or relative.\n # @POST Returns True when redirect target does not point back to login flow.\n def _redirect_looks_authenticated(self, redirect_location: str) -> bool:\n normalized = str(redirect_location or \"\").strip().lower()\n if not normalized:\n return True\n return \"/login\" not in normalized\n # endregion ScreenshotService._redirect_looks_authenticated\n\n # region ScreenshotService._submit_login_via_form_post [TYPE Function]\n # @PURPOSE Fallback login path that submits credentials directly with csrf token.\n # @PRE login_url is same-origin and csrf token can be read from DOM.\n # @POST Browser context receives authenticated cookies when login succeeds.\n async def _submit_login_via_form_post(self, page, login_url: str) -> bool:\n hidden_fields = await self._extract_hidden_login_fields(page)\n csrf_token = str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n if not csrf_token:\n logger.warning(\"[DEBUG] Direct form login fallback skipped: csrf_token not found\")\n return False\n\n try:\n request_context = page.context.request\n except Exception as context_error:\n logger.warning(f\"[DEBUG] Direct form login fallback skipped: request context unavailable: {context_error}\")\n return False\n\n parsed_url = urlsplit(login_url)\n origin = f\"{parsed_url.scheme}://{parsed_url.netloc}\" if parsed_url.scheme and parsed_url.netloc else login_url\n payload = dict(hidden_fields)\n payload[\"username\"] = self.env.username\n payload[\"password\"] = self.env.password\n logger.info(\n f\"[DEBUG] Attempting direct form login fallback via browser context request with hidden fields: {sorted(hidden_fields.keys())}\"\n )\n\n response = await request_context.post(\n login_url,\n form=payload,\n headers={\n \"Origin\": origin,\n \"Referer\": login_url,\n },\n timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS,\n fail_on_status_code=False,\n max_redirects=0,\n )\n response_url = str(getattr(response, \"url\", \"\") or \"\")\n response_status = int(getattr(response, \"status\", 0) or 0)\n response_headers = dict(getattr(response, \"headers\", {}) or {})\n redirect_location = str(\n response_headers.get(\"location\")\n or response_headers.get(\"Location\")\n or \"\"\n ).strip()\n redirect_statuses = {301, 302, 303, 307, 308}\n if response_status in redirect_statuses:\n redirect_authenticated = self._redirect_looks_authenticated(redirect_location)\n logger.info(\n f\"[DEBUG] Direct form login fallback redirect response: status={response_status} url={response_url} location={redirect_location!r} authenticated={redirect_authenticated}\"\n )\n return redirect_authenticated\n\n response_text = await response.text()\n text_snippet = \" \".join(response_text.split())[:200]\n looks_like_login_page = self._response_looks_like_login_page(response_text)\n logger.info(\n f\"[DEBUG] Direct form login fallback response: status={response_status} url={response_url} login_markup={looks_like_login_page} snippet={text_snippet!r}\"\n )\n return not looks_like_login_page\n # endregion ScreenshotService._submit_login_via_form_post\n\n # region ScreenshotService._find_login_field_locator [TYPE Function]\n # @PURPOSE Resolve login form input using semantic label text plus generic visible-input fallbacks.\n # @PRE field_name is `username` or `password`.\n # @POST Returns a locator for the corresponding input or None.\n async def _find_login_field_locator(self, page, field_name: str) -> Any:\n normalized = str(field_name or \"\").strip().lower()\n for root in self._iter_login_roots(page):\n if normalized == \"username\":\n input_candidates = [\n root.get_by_label(\"Username\", exact=False),\n root.get_by_label(\"Login\", exact=False),\n root.locator(\"label:text-matches('Username|Login', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Username|Login/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='username']\"),\n root.locator(\"input#username\"),\n root.locator(\"input[placeholder*='Username']\"),\n root.locator(\"input[type='text']\"),\n root.locator(\"input:not([type='password'])\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n if normalized == \"password\":\n input_candidates = [\n root.get_by_label(\"Password\", exact=False),\n root.locator(\"label:text-matches('Password', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Password/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='password']\"),\n root.locator(\"input#password\"),\n root.locator(\"input[placeholder*='Password']\"),\n root.locator(\"input[type='password']\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n return None\n # endregion ScreenshotService._find_login_field_locator\n\n # region ScreenshotService._find_submit_locator [TYPE Function]\n # @PURPOSE Resolve login submit button from main page or embedded auth frame.\n # @PRE page is ready for login interaction.\n # @POST Returns visible submit locator or None.\n async def _find_submit_locator(self, page) -> Any:\n selectors = [\n lambda root: root.get_by_role(\"button\", name=\"Sign in\", exact=False),\n lambda root: root.get_by_role(\"button\", name=\"Login\", exact=False),\n lambda root: root.locator(\"button[type='submit']\"),\n lambda root: root.locator(\"button#submit\"),\n lambda root: root.locator(\".btn-primary\"),\n lambda root: root.locator(\"input[type='submit']\"),\n ]\n for root in self._iter_login_roots(page):\n locator = await self._find_first_visible_locator([factory(root) for factory in selectors])\n if locator:\n return locator\n return None\n # endregion ScreenshotService._find_submit_locator\n\n # region ScreenshotService._goto_resilient [TYPE Function]\n # @PURPOSE Navigate without relying on networkidle for pages with long-polling or persistent requests.\n # @PRE page is a valid Playwright page and url is non-empty.\n # @POST Returns last navigation response or raises when both primary and fallback waits fail.\n async def _goto_resilient(\n self,\n page,\n url: str,\n primary_wait_until: str = \"domcontentloaded\",\n fallback_wait_until: str = \"load\",\n timeout: int = HTTP_REQUEST_TIMEOUT_MS,\n ):\n try:\n return await page.goto(url, wait_until=primary_wait_until, timeout=timeout)\n except Exception as primary_error:\n logger.warning(\n f\"[ScreenshotService._goto_resilient] Primary navigation wait '{primary_wait_until}' failed for {url}: {primary_error}\"\n )\n return await page.goto(url, wait_until=fallback_wait_until, timeout=timeout)\n # endregion ScreenshotService._goto_resilient\n\n # region ScreenshotService.capture_dashboard [TYPE Function]\n # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP.\n # @PRE dashboard_id is a valid string, output_path is a writable path.\n # @POST Returns True if screenshot is saved successfully.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, and writes a PNG file.\n # @UX_STATE [Navigating] -> Loading dashboard UI\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n async def capture_dashboard(self, dashboard_id: str, output_path: str) -> bool:\n with belief_scope(\"capture_dashboard\", f\"dashboard_id={dashboard_id}\"):\n logger.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n async with async_playwright() as p:\n browser = await p.chromium.launch(\n headless=True,\n args=[\n \"--disable-blink-features=AutomationControlled\",\n \"--disable-infobars\",\n \"--no-sandbox\"\n ]\n )\n # Set a realistic user agent to avoid 403 Forbidden from OpenResty/WAF\n user_agent = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\"\n # Construct base UI URL from environment (strip /api/v1 suffix)\n base_ui_url = self.env.url.rstrip(\"/\")\n if base_ui_url.endswith(\"/api/v1\"):\n base_ui_url = base_ui_url[:-len(\"/api/v1\")]\n\n # Create browser context with realistic headers\n context = await browser.new_context(\n viewport={'width': 1280, 'height': 720},\n user_agent=user_agent,\n extra_http_headers={\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Upgrade-Insecure-Requests\": \"1\",\n \"Sec-Fetch-Dest\": \"document\",\n \"Sec-Fetch-Mode\": \"navigate\",\n \"Sec-Fetch-Site\": \"none\",\n \"Sec-Fetch-User\": \"?1\"\n }\n )\n logger.info(\"Browser context created successfully\")\n\n page = await context.new_page()\n # Bypass navigator.webdriver detection\n await page.add_init_script(\"delete Object.getPrototypeOf(navigator).webdriver\")\n\n # 1. Navigate to login page and authenticate\n login_url = f\"{base_ui_url.rstrip('/')}/login/\"\n logger.info(f\"[DEBUG] Navigating to login page: {login_url}\")\n\n response = await self._goto_resilient(\n page,\n login_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n if response:\n logger.info(f\"[DEBUG] Login page response status: {response.status}\")\n\n # Wait for login form to be ready\n await page.wait_for_load_state(\"domcontentloaded\")\n\n # More exhaustive list of selectors for various Superset versions/themes\n selectors = {\n \"username\": ['input[name=\"username\"]', 'input#username', 'input[placeholder*=\"Username\"]', 'input[type=\"text\"]'],\n \"password\": ['input[name=\"password\"]', 'input#password', 'input[placeholder*=\"Password\"]', 'input[type=\"password\"]'],\n \"submit\": ['button[type=\"submit\"]', 'button#submit', '.btn-primary', 'input[type=\"submit\"]']\n }\n logger.info(\"[DEBUG] Attempting to find login form elements...\")\n\n try:\n used_direct_form_login = False\n # Find and fill username\n username_locator = await self._find_login_field_locator(page, \"username\")\n\n if not username_locator:\n roots = self._iter_login_roots(page)\n logger.info(f\"[DEBUG] Found {len(roots)} login roots including child frames\")\n for root_index, root in enumerate(roots[:5]):\n all_inputs = await root.locator('input').all()\n logger.info(f\"[DEBUG] Root {root_index}: found {len(all_inputs)} input fields\")\n for i, inp in enumerate(all_inputs[:5]): # Log first 5\n inp_type = await inp.get_attribute('type')\n inp_name = await inp.get_attribute('name')\n inp_id = await inp.get_attribute('id')\n logger.info(f\"[DEBUG] Root {root_index} input {i}: type={inp_type}, name={inp_name}, id={inp_id}\")\n used_direct_form_login = await self._submit_login_via_form_post(page, login_url)\n if not used_direct_form_login:\n raise RuntimeError(\"Could not find username input field on login page\")\n username_locator = None\n\n if username_locator is not None:\n logger.info(\"[DEBUG] Filling username field\")\n await username_locator.fill(self.env.username)\n\n # Find and fill password\n password_locator = await self._find_login_field_locator(page, \"password\") if username_locator is not None else None\n\n if username_locator is not None and not password_locator:\n raise RuntimeError(\"Could not find password input field on login page\")\n\n if password_locator is not None:\n logger.info(\"[DEBUG] Filling password field\")\n await password_locator.fill(self.env.password)\n\n # Click submit\n submit_locator = await self._find_submit_locator(page) if username_locator is not None else None\n\n if username_locator is not None and not submit_locator:\n raise RuntimeError(\"Could not find submit button on login page\")\n\n if submit_locator is not None:\n logger.info(\"[DEBUG] Clicking submit button\")\n await submit_locator.click()\n\n # Wait for navigation after login\n if not used_direct_form_login:\n try:\n await page.wait_for_load_state(\"load\", timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n except Exception as load_wait_error:\n logger.warning(f\"[DEBUG] Login post-submit load wait timed out: {load_wait_error}\")\n\n # Check if login was successful\n if not used_direct_form_login and \"/login\" in page.url:\n # Check for error messages on page\n error_msg = await page.locator(\".alert-danger, .error-message\").text_content() if await page.locator(\".alert-danger, .error-message\").count() > 0 else \"Unknown error\"\n logger.error(f\"[DEBUG] Login failed. Still on login page. Error: {error_msg}\")\n debug_path = output_path.replace(\".png\", \"_debug_failed_login.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(f\"Login failed: {error_msg}. Debug screenshot saved to {debug_path}\")\n\n logger.info(f\"[DEBUG] Login successful. Current URL: {page.url}\")\n\n # Check cookies after successful login\n page_cookies = await context.cookies()\n logger.info(f\"[DEBUG] Cookies after login: {len(page_cookies)}\")\n for c in page_cookies:\n logger.info(f\"[DEBUG] Cookie: name={c['name']}, domain={c['domain']}, value={c.get('value', '')[:20]}...\")\n\n except Exception as e:\n page_title = await page.title()\n logger.error(f\"UI Login failed. Page title: {page_title}, URL: {page.url}, Error: {e!s}\")\n debug_path = output_path.replace(\".png\", \"_debug_failed_login.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(f\"Login failed: {e!s}. Debug screenshot saved to {debug_path}\")\n\n # 2. Navigate to dashboard\n # @UX_STATE [Navigating] -> Loading dashboard UI\n dashboard_url = f\"{base_ui_url.rstrip('/')}/superset/dashboard/{dashboard_id}/?standalone=true\"\n\n if base_ui_url.startswith(\"https://\") and dashboard_url.startswith(\"http://\"):\n dashboard_url = dashboard_url.replace(\"http://\", \"https://\")\n\n logger.info(f\"[DEBUG] Navigating to dashboard: {dashboard_url}\")\n\n # Dashboard pages can keep polling/network activity open indefinitely.\n response = await self._goto_resilient(\n page,\n dashboard_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n\n if response:\n logger.info(f\"[DEBUG] Dashboard navigation response status: {response.status}, URL: {response.url}\")\n\n if \"/login\" in page.url:\n debug_path = output_path.replace(\".png\", \"_debug_failed_dashboard_auth.png\")\n await page.screenshot(path=debug_path)\n raise RuntimeError(\n f\"Dashboard navigation redirected to login page after authentication. Debug screenshot saved to {debug_path}\"\n )\n\n try:\n # Wait for the dashboard grid to be present\n await page.wait_for_selector('.dashboard-component, .dashboard-header, [data-test=\"dashboard-grid\"]', timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n logger.info(\"[DEBUG] Dashboard container loaded\")\n\n # Wait for charts to finish loading (Superset uses loading spinners/skeletons)\n # We wait until loading indicators disappear or a timeout occurs\n try:\n # Wait for loading indicators to disappear\n await page.wait_for_selector('.loading, .ant-skeleton, .spinner', state=\"hidden\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Loading indicators hidden\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for loading indicators to hide\")\n\n # Wait for charts to actually render their content (e.g., ECharts, NVD3)\n # We look for common chart containers that should have content\n try:\n await page.wait_for_selector('.chart-container canvas, .slice_container svg, .superset-chart-canvas, .grid-content .chart-container', timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Chart content detected\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for chart content\")\n\n # Additional check: wait for all chart containers to have non-empty content\n logger.info(\"[DEBUG] Waiting for all charts to have rendered content...\")\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container, .slice_container');\n if (charts.length === 0) return true; // No charts to wait for\n \n // Check if all charts have rendered content (canvas, svg, or non-empty div)\n return Array.from(charts).every(chart => {\n const hasCanvas = chart.querySelector('canvas') !== null;\n const hasSvg = chart.querySelector('svg') !== null;\n const hasContent = chart.innerText.trim().length > 0 || chart.children.length > 0;\n return hasCanvas || hasSvg || hasContent;\n });\n }\"\"\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] All charts have rendered content\")\n\n # Scroll to bottom and back to top to trigger lazy loading of all charts\n logger.info(\"[DEBUG] Scrolling to trigger lazy loading...\")\n await page.evaluate(\"\"\"async () => {\n const delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n for (let i = 0; i < document.body.scrollHeight; i += 500) {\n window.scrollTo(0, i);\n await delay(100);\n }\n window.scrollTo(0, 0);\n await delay(500);\n }\"\"\")\n\n except Exception as e:\n logger.warning(f\"[DEBUG] Dashboard content wait failed: {e}, proceeding anyway after delay\")\n\n # Final stabilization delay - increased for complex dashboards\n logger.info(\"[DEBUG] Final stabilization delay...\")\n await asyncio.sleep(15)\n\n # Logic to handle tabs and full-page capture\n try:\n # 1. Handle Tabs (Recursive switching)\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n processed_tabs = set()\n\n async def switch_tabs(depth=0):\n if depth > 3:\n return # Limit recursion depth\n\n tab_selectors = [\n '.ant-tabs-nav-list .ant-tabs-tab',\n '.dashboard-component-tabs .ant-tabs-tab',\n '[data-test=\"dashboard-component-tabs\"] .ant-tabs-tab'\n ]\n\n found_tabs = []\n for selector in tab_selectors:\n found_tabs = await page.locator(selector).all()\n if found_tabs:\n break\n\n if found_tabs:\n logger.info(f\"[DEBUG][TabSwitching] Found {len(found_tabs)} tabs at depth {depth}\")\n for i, tab in enumerate(found_tabs):\n try:\n tab_text = (await tab.inner_text()).strip()\n tab_id = f\"{depth}_{i}_{tab_text}\"\n\n if tab_id in processed_tabs:\n continue\n\n if await tab.is_visible():\n logger.info(f\"[DEBUG][TabSwitching] Switching to tab: {tab_text}\")\n processed_tabs.add(tab_id)\n\n is_active = \"ant-tabs-tab-active\" in (await tab.get_attribute(\"class\") or \"\")\n if not is_active:\n await tab.click()\n await asyncio.sleep(2) # Wait for content to render\n\n await switch_tabs(depth + 1)\n except Exception as tab_e:\n logger.warning(f\"[DEBUG][TabSwitching] Failed to process tab {i}: {tab_e}\")\n\n try:\n first_tab = found_tabs[0]\n if \"ant-tabs-tab-active\" not in (await first_tab.get_attribute(\"class\") or \"\"):\n await first_tab.click()\n await asyncio.sleep(1)\n except Exception:\n pass\n\n await switch_tabs()\n\n # 2. Calculate full height for screenshot\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n full_height = await page.evaluate(\"\"\"() => {\n const body = document.body;\n const html = document.documentElement;\n const dashboardContent = document.querySelector('.dashboard-content');\n \n return Math.max(\n body.scrollHeight, body.offsetHeight,\n html.clientHeight, html.scrollHeight, html.offsetHeight,\n dashboardContent ? dashboardContent.scrollHeight + 100 : 0\n );\n }\"\"\")\n logger.info(f\"[DEBUG] Calculated full height: {full_height}\")\n\n # DIAGNOSTIC: Count chart elements before resize\n chart_count_before = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements BEFORE viewport resize: {chart_count_before}\")\n\n # DIAGNOSTIC: Capture pre-resize screenshot for comparison\n pre_resize_path = output_path.replace(\".png\", \"_preresize.png\")\n try:\n await page.screenshot(path=pre_resize_path, full_page=False, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n import os\n pre_resize_size = os.path.getsize(pre_resize_path) if os.path.exists(pre_resize_path) else 0\n logger.info(f\"[DIAGNOSTIC] Pre-resize screenshot saved: {pre_resize_path} ({pre_resize_size} bytes)\")\n except Exception as pre_e:\n logger.warning(f\"[DIAGNOSTIC] Failed to capture pre-resize screenshot: {pre_e}\")\n\n logger.info(f\"[DIAGNOSTIC] Resizing viewport from current to 1920x{int(full_height)}\")\n await page.set_viewport_size({\"width\": 1920, \"height\": int(full_height)})\n\n # DIAGNOSTIC: Increased wait time and log timing\n logger.info(\"[DIAGNOSTIC] Waiting 10 seconds after viewport resize for re-render...\")\n await asyncio.sleep(10)\n logger.info(\"[DIAGNOSTIC] Wait completed\")\n\n # DIAGNOSTIC: Count chart elements after resize and wait\n chart_count_after = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements AFTER viewport resize + wait: {chart_count_after}\")\n\n # DIAGNOSTIC: Check if any charts have error states\n chart_errors = await page.evaluate(\"\"\"() => {\n const errors = [];\n document.querySelectorAll('.chart-container, .slice_container').forEach((chart, i) => {\n const errorEl = chart.querySelector('.error, .alert-danger, .ant-alert-error');\n if (errorEl) {\n errors.push({index: i, text: errorEl.innerText.substring(0, 100)});\n }\n });\n return errors;\n }\"\"\")\n if chart_errors:\n logger.warning(f\"[DIAGNOSTIC] Charts with error states detected: {chart_errors}\")\n else:\n logger.info(\"[DIAGNOSTIC] No chart error states detected\")\n\n # 3. Take screenshot using CDP to bypass Playwright's font loading wait\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n logger.info(\"[DEBUG] Attempting full-page screenshot via CDP...\")\n cdp = await page.context.new_cdp_session(page)\n\n screenshot_data = await cdp.send(\"Page.captureScreenshot\", {\n \"format\": \"png\",\n \"fromSurface\": True,\n \"captureBeyondViewport\": True\n })\n\n image_data = base64.b64decode(screenshot_data[\"data\"])\n\n with open(output_path, 'wb') as f:\n f.write(image_data)\n\n # DIAGNOSTIC: Verify screenshot file\n import os\n final_size = os.path.getsize(output_path) if os.path.exists(output_path) else 0\n logger.info(f\"[DIAGNOSTIC] Final screenshot saved: {output_path}\")\n logger.info(f\"[DIAGNOSTIC] Final screenshot size: {final_size} bytes ({final_size / 1024:.2f} KB)\")\n\n # DIAGNOSTIC: Get image dimensions\n try:\n with Image.open(output_path) as final_img:\n logger.info(f\"[DIAGNOSTIC] Final screenshot dimensions: {final_img.width}x{final_img.height}\")\n except Exception as img_err:\n logger.warning(f\"[DIAGNOSTIC] Could not read final image dimensions: {img_err}\")\n\n logger.info(f\"Full-page screenshot saved to {output_path} (via CDP)\")\n except Exception as e:\n logger.error(f\"[DEBUG] Full-page/Tab capture failed: {e}\")\n try:\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception as e2:\n logger.error(f\"[DEBUG] Fallback screenshot also failed: {e2}\")\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n\n await browser.close()\n return True\n # endregion ScreenshotService.capture_dashboard\n# #endregion ScreenshotService\n" + "body": "# #region ScreenshotService [TYPE Class]\n# @BRIEF Handles capturing screenshots of Superset dashboards.\nclass ScreenshotService:\n # region ScreenshotService.__init__ [TYPE Function]\n # @PURPOSE Initializes the ScreenshotService with environment configuration.\n # @PRE env is a valid Environment object.\n def __init__(self, env: Environment):\n self.env = env\n # endregion ScreenshotService.__init__\n\n # region ScreenshotService._find_first_visible_locator [TYPE Function]\n # @PURPOSE Resolve the first visible locator from multiple Playwright locator strategies.\n # @PRE candidates is a non-empty list of locator-like objects.\n # @POST Returns a locator ready for interaction or None when nothing matches.\n async def _find_first_visible_locator(self, candidates) -> Any:\n for locator in candidates:\n try:\n match_count = await locator.count()\n for index in range(match_count):\n candidate = locator.nth(index)\n if await candidate.is_visible():\n return candidate\n except Exception:\n continue\n return None\n # endregion ScreenshotService._find_first_visible_locator\n\n # region ScreenshotService._iter_login_roots [TYPE Function]\n # @PURPOSE Enumerate page and child frames where login controls may be rendered.\n # @PRE page is a Playwright page-like object.\n # @POST Returns ordered roots starting with main page followed by frames.\n def _iter_login_roots(self, page) -> list[Any]:\n roots = [page]\n page_frames = getattr(page, \"frames\", [])\n try:\n for frame in page_frames:\n if frame not in roots:\n roots.append(frame)\n except Exception:\n pass\n return roots\n # endregion ScreenshotService._iter_login_roots\n\n # region ScreenshotService._extract_hidden_login_fields [TYPE Function]\n # @PURPOSE Collect hidden form fields required for direct login POST fallback.\n # @PRE Login page is loaded.\n # @POST Returns hidden input name/value mapping aggregated from page and child frames.\n async def _extract_hidden_login_fields(self, page) -> dict[str, str]:\n hidden_fields: dict[str, str] = {}\n for root in self._iter_login_roots(page):\n try:\n locator = root.locator(\"input[type='hidden'][name]\")\n count = await locator.count()\n for index in range(count):\n candidate = locator.nth(index)\n field_name = str(await candidate.get_attribute(\"name\") or \"\").strip()\n if not field_name or field_name in hidden_fields:\n continue\n hidden_fields[field_name] = str(await candidate.input_value()).strip()\n except Exception:\n continue\n return hidden_fields\n # endregion ScreenshotService._extract_hidden_login_fields\n\n # region ScreenshotService._extract_csrf_token [TYPE Function]\n # @PURPOSE Resolve CSRF token value from main page or embedded login frame.\n # @PRE Login page is loaded.\n # @POST Returns first non-empty csrf token or empty string.\n async def _extract_csrf_token(self, page) -> str:\n hidden_fields = await self._extract_hidden_login_fields(page)\n return str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n # endregion ScreenshotService._extract_csrf_token\n\n # region ScreenshotService._response_looks_like_login_page [TYPE Function]\n # @PURPOSE Detect when fallback login POST returned the login form again instead of an authenticated page.\n # @PRE response_text is normalized HTML or text from login POST response.\n # @POST Returns True when login-page markers dominate the response body.\n def _response_looks_like_login_page(self, response_text: str) -> bool:\n normalized = str(response_text or \"\").strip().lower()\n if not normalized:\n return False\n\n markers = [\n \"enter your login and password below\",\n \"username:\",\n \"password:\",\n \"sign in\",\n 'name=\"csrf_token\"',\n ]\n return sum(marker in normalized for marker in markers) >= 3\n # endregion ScreenshotService._response_looks_like_login_page\n\n # region ScreenshotService._redirect_looks_authenticated [TYPE Function]\n # @PURPOSE Treat non-login redirects after form POST as successful authentication without waiting for redirect target.\n # @PRE redirect_location may be empty or relative.\n # @POST Returns True when redirect target does not point back to login flow.\n def _redirect_looks_authenticated(self, redirect_location: str) -> bool:\n normalized = str(redirect_location or \"\").strip().lower()\n if not normalized:\n return True\n return \"/login\" not in normalized\n # endregion ScreenshotService._redirect_looks_authenticated\n\n # region ScreenshotService._submit_login_via_form_post [TYPE Function]\n # @PURPOSE Fallback login path that submits credentials directly with csrf token.\n # @PRE login_url is same-origin and csrf token can be read from DOM.\n # @POST Browser context receives authenticated cookies when login succeeds.\n async def _submit_login_via_form_post(self, page, login_url: str) -> bool:\n hidden_fields = await self._extract_hidden_login_fields(page)\n csrf_token = str(hidden_fields.get(\"csrf_token\") or \"\").strip()\n if not csrf_token:\n logger.warning(\"[DEBUG] Direct form login fallback skipped: csrf_token not found\")\n return False\n\n try:\n request_context = page.context.request\n except Exception as context_error:\n logger.warning(f\"[DEBUG] Direct form login fallback skipped: request context unavailable: {context_error}\")\n return False\n\n parsed_url = urlsplit(login_url)\n origin = f\"{parsed_url.scheme}://{parsed_url.netloc}\" if parsed_url.scheme and parsed_url.netloc else login_url\n payload = dict(hidden_fields)\n payload[\"username\"] = self.env.username\n payload[\"password\"] = self.env.password\n logger.info(\n f\"[DEBUG] Attempting direct form login fallback via browser context request with hidden fields: {sorted(hidden_fields.keys())}\"\n )\n\n response = await request_context.post(\n login_url,\n form=payload,\n headers={\n \"Origin\": origin,\n \"Referer\": login_url,\n },\n timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS,\n fail_on_status_code=False,\n max_redirects=0,\n )\n response_url = str(getattr(response, \"url\", \"\") or \"\")\n response_status = int(getattr(response, \"status\", 0) or 0)\n response_headers = dict(getattr(response, \"headers\", {}) or {})\n redirect_location = str(\n response_headers.get(\"location\")\n or response_headers.get(\"Location\")\n or \"\"\n ).strip()\n redirect_statuses = {301, 302, 303, 307, 308}\n if response_status in redirect_statuses:\n redirect_authenticated = self._redirect_looks_authenticated(redirect_location)\n logger.info(\n f\"[DEBUG] Direct form login fallback redirect response: status={response_status} url={response_url} location={redirect_location!r} authenticated={redirect_authenticated}\"\n )\n return redirect_authenticated\n\n response_text = await response.text()\n text_snippet = \" \".join(response_text.split())[:200]\n looks_like_login_page = self._response_looks_like_login_page(response_text)\n logger.info(\n f\"[DEBUG] Direct form login fallback response: status={response_status} url={response_url} login_markup={looks_like_login_page} snippet={text_snippet!r}\"\n )\n return not looks_like_login_page\n # endregion ScreenshotService._submit_login_via_form_post\n\n # region ScreenshotService._find_login_field_locator [TYPE Function]\n # @PURPOSE Resolve login form input using semantic label text plus generic visible-input fallbacks.\n # @PRE field_name is `username` or `password`.\n # @POST Returns a locator for the corresponding input or None.\n async def _find_login_field_locator(self, page, field_name: str) -> Any:\n normalized = str(field_name or \"\").strip().lower()\n for root in self._iter_login_roots(page):\n if normalized == \"username\":\n input_candidates = [\n root.get_by_label(\"Username\", exact=False),\n root.get_by_label(\"Login\", exact=False),\n root.locator(\"label:text-matches('Username|Login', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Username|Login/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='username']\"),\n root.locator(\"input#username\"),\n root.locator(\"input[placeholder*='Username']\"),\n root.locator(\"input[type='text']\"),\n root.locator(\"input:not([type='password'])\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n if normalized == \"password\":\n input_candidates = [\n root.get_by_label(\"Password\", exact=False),\n root.locator(\"label:text-matches('Password', 'i')\").locator(\"xpath=following::input[1]\"),\n root.locator(\"text=/Password/i\").locator(\"xpath=following::input[1]\"),\n root.locator(\"input[name='password']\"),\n root.locator(\"input#password\"),\n root.locator(\"input[placeholder*='Password']\"),\n root.locator(\"input[type='password']\"),\n ]\n locator = await self._find_first_visible_locator(input_candidates)\n if locator:\n return locator\n\n return None\n # endregion ScreenshotService._find_login_field_locator\n\n # region ScreenshotService._find_submit_locator [TYPE Function]\n # @PURPOSE Resolve login submit button from main page or embedded auth frame.\n # @PRE page is ready for login interaction.\n # @POST Returns visible submit locator or None.\n async def _find_submit_locator(self, page) -> Any:\n selectors = [\n lambda root: root.get_by_role(\"button\", name=\"Sign in\", exact=False),\n lambda root: root.get_by_role(\"button\", name=\"Login\", exact=False),\n lambda root: root.locator(\"button[type='submit']\"),\n lambda root: root.locator(\"button#submit\"),\n lambda root: root.locator(\".btn-primary\"),\n lambda root: root.locator(\"input[type='submit']\"),\n ]\n for root in self._iter_login_roots(page):\n locator = await self._find_first_visible_locator([factory(root) for factory in selectors])\n if locator:\n return locator\n return None\n # endregion ScreenshotService._find_submit_locator\n\n # region ScreenshotService._goto_resilient [TYPE Function]\n # @PURPOSE Navigate without relying on networkidle for pages with long-polling or persistent requests.\n # @PRE page is a valid Playwright page and url is non-empty.\n # @POST Returns last navigation response or raises when both primary and fallback waits fail.\n async def _goto_resilient(\n self,\n page,\n url: str,\n primary_wait_until: str = \"domcontentloaded\",\n fallback_wait_until: str = \"load\",\n timeout: int = HTTP_REQUEST_TIMEOUT_MS,\n ):\n try:\n return await page.goto(url, wait_until=primary_wait_until, timeout=timeout)\n except Exception as primary_error:\n logger.warning(\n f\"[ScreenshotService._goto_resilient] Primary navigation wait '{primary_wait_until}' failed for {url}: {primary_error}\"\n )\n return await page.goto(url, wait_until=fallback_wait_until, timeout=timeout)\n # endregion ScreenshotService._goto_resilient\n\n # region ScreenshotService._wait_for_charts_stabilized [TYPE Function] [C:2]\n # @BRIEF Wait until chart elements have non-zero dimensions, with polling.\n # @PRE page is a valid Playwright page.\n # @POST Waits for chart stabilization or raises on timeout (handled internally).\n # @RATIONALE Polls for actual chart rendering dimensions rather than using a fixed delay — charts may load at different speeds depending on dashboard complexity and network conditions.\n # @REJECTED Fixed sleep-based wait rejected — would either waste time (too long) or produce blank screenshots (too short); polling for actual canvas/svg dimensions is more reliable.\n async def _wait_for_charts_stabilized(self, page, timeout_ms: int = 15000):\n \"\"\"Wait until chart elements have non-zero dimensions, with polling.\"\"\"\n # Short initial delay for rendering pipeline to start\n await asyncio.sleep(0.5)\n try:\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container canvas, .slice_container svg, .grid-content canvas');\n if (charts.length === 0) return true;\n return Array.from(charts).some(c => {\n if (c.tagName === 'CANVAS') return c.width > 10 && c.height > 10;\n if (c.tagName === 'svg') {\n const bbox = c.getBoundingClientRect();\n return bbox.width > 10 && bbox.height > 10;\n }\n return false;\n });\n }\"\"\", timeout=timeout_ms)\n except Exception:\n logger.warning(\"[ScreenshotService] Chart stabilization wait timed out, proceeding anyway\")\n # endregion ScreenshotService._wait_for_charts_stabilized\n\n # region ScreenshotService._wait_for_resize_rendered [TYPE Function] [C:2]\n # @BRIEF Wait for charts to re-render after viewport resize.\n # @PRE page is a valid Playwright page; chart_count_before contains pre-resize element counts.\n # @POST Waits for chart content to return or timeout.\n # @RATIONALE After viewport resize, Superset triggers lazy chart re-rendering — this function polls for chart elements to reappear before taking the screenshot.\n # @REJECTED Single fixed wait after resize rejected — some dashboards re-render instantly while others take seconds; fixed wait is brittle across dashboard types.\n async def _wait_for_resize_rendered(self, page, chart_count_before: dict, timeout_ms: int = 10000):\n \"\"\"Wait for charts to re-render after viewport resize, with polling.\"\"\"\n try:\n await page.wait_for_function(\"\"\"(preCounts) => {\n const currentCharts = document.querySelectorAll('.chart-container, .slice_container').length;\n const currentCanvases = document.querySelectorAll('canvas').length;\n const currentSvgs = document.querySelectorAll('.chart-container svg, .slice_container svg').length;\n // At least one chart element must be present\n return currentCharts > 0 && (currentCanvases > 0 || currentSvgs > 0);\n }\"\"\", arg=chart_count_before, timeout=timeout_ms)\n except Exception:\n logger.warning(\"[ScreenshotService] Re-render wait timed out after viewport resize, proceeding anyway\")\n # endregion ScreenshotService._wait_for_resize_rendered\n\n # region ScreenshotService._save_debug_screenshot [TYPE Function] [C:1]\n # @BRIEF Save a debug screenshot to a temp directory for diagnostic purposes.\n # @PRE debug_dir exists and is writable.\n # @POST Returns the debug path or None on failure.\n # @RATIONALE Uses tempfile.mkdtemp() to avoid accumulating .png files in production storage. Temp dir is cleaned up on success (rmtree) or preserved on failure for debugging.\n # @REJECTED Old approach saved debug .png next to output path — accumulated _debug_failed_login.png, _preresize.png permanently in screenshots dir (F1). In-memory-only debug logging rejected — screenshot state is visual and cannot be captured in logs.\n async def _save_debug_screenshot(self, page, debug_dir: str, suffix: str) -> str | None:\n debug_path = os.path.join(debug_dir, suffix)\n try:\n await page.screenshot(path=debug_path)\n return debug_path\n except Exception:\n return None\n # endregion ScreenshotService._save_debug_screenshot\n\n # region ScreenshotService.capture_dashboard [TYPE Function] [C:4]\n # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP.\n # @PRE dashboard_id is a valid string, output_path is a writable path.\n # @POST Returns True if screenshot is saved successfully. Debug temp dir cleaned up on success, preserved on failure.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes a PNG file; creates and cleans up temp debug directory.\n # @UX_STATE [Navigating] -> Loading dashboard UI\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n # @RATIONALE Uses tempfile.mkdtemp() for all debug screenshots; cleans up on success (shutil.rmtree), preserves on failure for diagnostic analysis. Pre-resize screenshot is saved to temp dir and auto-cleaned on success.\n # @REJECTED Old approach saved debug .png files alongside output — accumulated permanently (F1). In-memory-only logging rejected — visual state cannot be captured in text.\n async def capture_dashboard(self, dashboard_id: str, output_path: str) -> bool:\n debug_dir = tempfile.mkdtemp(prefix=\"ss_screenshot_debug_\")\n success = False\n try:\n # -- begin original body --\n with belief_scope(\"capture_dashboard\", f\"dashboard_id={dashboard_id}\"):\n logger.info(f\"Capturing screenshot for dashboard {dashboard_id}\")\n async with async_playwright() as p:\n browser = await p.chromium.launch(\n headless=True,\n args=[\n \"--disable-blink-features=AutomationControlled\",\n \"--disable-infobars\",\n \"--no-sandbox\"\n ]\n )\n # Set a realistic user agent to avoid 403 Forbidden from OpenResty/WAF\n user_agent = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\"\n # Construct base UI URL from environment (strip /api/v1 suffix)\n base_ui_url = self.env.url.rstrip(\"/\")\n if base_ui_url.endswith(\"/api/v1\"):\n base_ui_url = base_ui_url[:-len(\"/api/v1\")]\n\n # Create browser context with realistic headers\n context = await browser.new_context(\n viewport={'width': 1280, 'height': 720},\n user_agent=user_agent,\n extra_http_headers={\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Upgrade-Insecure-Requests\": \"1\",\n \"Sec-Fetch-Dest\": \"document\",\n \"Sec-Fetch-Mode\": \"navigate\",\n \"Sec-Fetch-Site\": \"none\",\n \"Sec-Fetch-User\": \"?1\"\n }\n )\n logger.info(\"Browser context created successfully\")\n\n page = await context.new_page()\n # Bypass navigator.webdriver detection\n await page.add_init_script(\"delete Object.getPrototypeOf(navigator).webdriver\")\n\n # 1. Navigate to login page and authenticate\n login_url = f\"{base_ui_url.rstrip('/')}/login/\"\n logger.info(f\"[DEBUG] Navigating to login page: {login_url}\")\n\n response = await self._goto_resilient(\n page,\n login_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n if response:\n logger.info(f\"[DEBUG] Login page response status: {response.status}\")\n\n # Wait for login form to be ready\n await page.wait_for_load_state(\"domcontentloaded\")\n\n # More exhaustive list of selectors for various Superset versions/themes\n selectors = {\n \"username\": ['input[name=\"username\"]', 'input#username', 'input[placeholder*=\"Username\"]', 'input[type=\"text\"]'],\n \"password\": ['input[name=\"password\"]', 'input#password', 'input[placeholder*=\"Password\"]', 'input[type=\"password\"]'],\n \"submit\": ['button[type=\"submit\"]', 'button#submit', '.btn-primary', 'input[type=\"submit\"]']\n }\n logger.info(\"[DEBUG] Attempting to find login form elements...\")\n\n try:\n used_direct_form_login = False\n # Find and fill username\n username_locator = await self._find_login_field_locator(page, \"username\")\n\n if not username_locator:\n roots = self._iter_login_roots(page)\n logger.info(f\"[DEBUG] Found {len(roots)} login roots including child frames\")\n for root_index, root in enumerate(roots[:5]):\n all_inputs = await root.locator('input').all()\n logger.info(f\"[DEBUG] Root {root_index}: found {len(all_inputs)} input fields\")\n for i, inp in enumerate(all_inputs[:5]): # Log first 5\n inp_type = await inp.get_attribute('type')\n inp_name = await inp.get_attribute('name')\n inp_id = await inp.get_attribute('id')\n logger.info(f\"[DEBUG] Root {root_index} input {i}: type={inp_type}, name={inp_name}, id={inp_id}\")\n used_direct_form_login = await self._submit_login_via_form_post(page, login_url)\n if not used_direct_form_login:\n raise RuntimeError(\"Could not find username input field on login page\")\n username_locator = None\n\n if username_locator is not None:\n logger.info(\"[DEBUG] Filling username field\")\n await username_locator.fill(self.env.username)\n\n # Find and fill password\n password_locator = await self._find_login_field_locator(page, \"password\") if username_locator is not None else None\n\n if username_locator is not None and not password_locator:\n raise RuntimeError(\"Could not find password input field on login page\")\n\n if password_locator is not None:\n logger.info(\"[DEBUG] Filling password field\")\n await password_locator.fill(self.env.password)\n\n # Click submit\n submit_locator = await self._find_submit_locator(page) if username_locator is not None else None\n\n if username_locator is not None and not submit_locator:\n raise RuntimeError(\"Could not find submit button on login page\")\n\n if submit_locator is not None:\n logger.info(\"[DEBUG] Clicking submit button\")\n await submit_locator.click()\n\n # Wait for navigation after login\n if not used_direct_form_login:\n try:\n await page.wait_for_load_state(\"load\", timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n except Exception as load_wait_error:\n logger.warning(f\"[DEBUG] Login post-submit load wait timed out: {load_wait_error}\")\n\n # Check if login was successful\n if not used_direct_form_login and \"/login\" in page.url:\n # Check for error messages on page\n error_msg = await page.locator(\".alert-danger, .error-message\").text_content() if await page.locator(\".alert-danger, .error-message\").count() > 0 else \"Unknown error\"\n logger.error(f\"[DEBUG] Login failed. Still on login page. Error: {error_msg}\")\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_login.png\")\n raise RuntimeError(f\"Login failed: {error_msg}. Debug screenshot saved to {debug_path}\")\n\n logger.info(f\"[DEBUG] Login successful. Current URL: {page.url}\")\n\n # Check cookies after successful login\n page_cookies = await context.cookies()\n logger.info(f\"[DEBUG] Cookies after login: {len(page_cookies)}\")\n for c in page_cookies:\n logger.info(f\"[DEBUG] Cookie: name={c['name']}, domain={c['domain']}, value={c.get('value', '')[:20]}...\")\n\n except Exception as e:\n page_title = await page.title()\n logger.error(f\"UI Login failed. Page title: {page_title}, URL: {page.url}, Error: {e!s}\")\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_login.png\")\n raise RuntimeError(f\"Login failed: {e!s}. Debug screenshot saved to {debug_path}\")\n\n # 2. Navigate to dashboard\n # @UX_STATE [Navigating] -> Loading dashboard UI\n dashboard_url = f\"{base_ui_url.rstrip('/')}/superset/dashboard/{dashboard_id}/?standalone=true\"\n\n if base_ui_url.startswith(\"https://\") and dashboard_url.startswith(\"http://\"):\n dashboard_url = dashboard_url.replace(\"http://\", \"https://\")\n\n logger.info(f\"[DEBUG] Navigating to dashboard: {dashboard_url}\")\n\n # Dashboard pages can keep polling/network activity open indefinitely.\n response = await self._goto_resilient(\n page,\n dashboard_url,\n primary_wait_until=\"domcontentloaded\",\n fallback_wait_until=\"load\",\n timeout=HTTP_REQUEST_TIMEOUT_MS,\n )\n\n if response:\n logger.info(f\"[DEBUG] Dashboard navigation response status: {response.status}, URL: {response.url}\")\n\n if \"/login\" in page.url:\n debug_path = await self._save_debug_screenshot(page, debug_dir, \"failed_dashboard_auth.png\")\n raise RuntimeError(\n f\"Dashboard navigation redirected to login page after authentication. Debug screenshot saved to {debug_path}\"\n )\n\n try:\n # Wait for the dashboard grid to be present\n await page.wait_for_selector('.dashboard-component, .dashboard-header, [data-test=\"dashboard-grid\"]', timeout=PLAYWRIGHT_NAVIGATION_TIMEOUT_MS)\n logger.info(\"[DEBUG] Dashboard container loaded\")\n\n # Wait for charts to finish loading (Superset uses loading spinners/skeletons)\n # We wait until loading indicators disappear or a timeout occurs\n try:\n # Wait for loading indicators to disappear\n await page.wait_for_selector('.loading, .ant-skeleton, .spinner', state=\"hidden\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Loading indicators hidden\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for loading indicators to hide\")\n\n # Wait for charts to actually render their content (e.g., ECharts, NVD3)\n # We look for common chart containers that should have content\n try:\n await page.wait_for_selector('.chart-container canvas, .slice_container svg, .superset-chart-canvas, .grid-content .chart-container', timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] Chart content detected\")\n except Exception:\n logger.warning(\"[DEBUG] Timeout waiting for chart content\")\n\n # Additional check: wait for all chart containers to have non-empty content\n logger.info(\"[DEBUG] Waiting for all charts to have rendered content...\")\n await page.wait_for_function(\"\"\"() => {\n const charts = document.querySelectorAll('.chart-container, .slice_container');\n if (charts.length === 0) return true; // No charts to wait for\n \n // Check if all charts have rendered content (canvas, svg, or non-empty div)\n return Array.from(charts).every(chart => {\n const hasCanvas = chart.querySelector('canvas') !== null;\n const hasSvg = chart.querySelector('svg') !== null;\n const hasContent = chart.innerText.trim().length > 0 || chart.children.length > 0;\n return hasCanvas || hasSvg || hasContent;\n });\n }\"\"\", timeout=HTTP_REQUEST_TIMEOUT_MS)\n logger.info(\"[DEBUG] All charts have rendered content\")\n\n # Scroll to bottom and back to top to trigger lazy loading of all charts\n logger.info(\"[DEBUG] Scrolling to trigger lazy loading...\")\n await page.evaluate(\"\"\"async () => {\n const delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n for (let i = 0; i < document.body.scrollHeight; i += 500) {\n window.scrollTo(0, i);\n await delay(100);\n }\n window.scrollTo(0, 0);\n await delay(500);\n }\"\"\")\n\n except Exception as e:\n logger.warning(f\"[DEBUG] Dashboard content wait failed: {e}, proceeding anyway after delay\")\n\n # Final stabilization delay - wait for charts to stabilize\n logger.info(\"[DEBUG] Waiting for charts to stabilize...\")\n await self._wait_for_charts_stabilized(page)\n\n # Logic to handle tabs and full-page capture\n try:\n async with asyncio.timeout(SCREENSHOT_SERVICE_TIMEOUT_MS / 1000):\n # 1. Handle Tabs (Recursive switching)\n # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading\n processed_tabs = set()\n\n async def switch_tabs(depth=0):\n if depth > 3:\n return # Limit recursion depth\n\n tab_selectors = [\n '.ant-tabs-nav-list .ant-tabs-tab',\n '.dashboard-component-tabs .ant-tabs-tab',\n '[data-test=\"dashboard-component-tabs\"] .ant-tabs-tab'\n ]\n\n found_tabs = []\n for selector in tab_selectors:\n found_tabs = await page.locator(selector).all()\n if found_tabs:\n break\n\n if found_tabs:\n logger.info(f\"[DEBUG][TabSwitching] Found {len(found_tabs)} tabs at depth {depth}\")\n for i, tab in enumerate(found_tabs):\n try:\n tab_text = (await tab.inner_text()).strip()\n tab_id = f\"{depth}_{i}_{tab_text}\"\n\n if tab_id in processed_tabs:\n continue\n\n if await tab.is_visible():\n logger.info(f\"[DEBUG][TabSwitching] Switching to tab: {tab_text}\")\n processed_tabs.add(tab_id)\n\n is_active = \"ant-tabs-tab-active\" in (await tab.get_attribute(\"class\") or \"\")\n if not is_active:\n await tab.click()\n # Wait for chart content to render in the newly active tab\n try:\n await page.wait_for_function(\"\"\"() => {\n const activeTab = document.querySelector('.ant-tabs-tab-active');\n if (!activeTab) return true;\n const tabPane = activeTab.closest('.ant-tabs')?.querySelector('.ant-tabs-content-holder');\n if (!tabPane) return true;\n const charts = tabPane.querySelectorAll('canvas, svg');\n return charts.length > 0;\n }\"\"\", timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception:\n logger.warning(f\"[TabSwitching] Content verification timed out for tab: {tab_text}\")\n\n await switch_tabs(depth + 1)\n except Exception as tab_e:\n logger.warning(f\"[DEBUG][TabSwitching] Failed to process tab {i}: {tab_e}\")\n\n try:\n first_tab = found_tabs[0]\n if \"ant-tabs-tab-active\" not in (await first_tab.get_attribute(\"class\") or \"\"):\n await first_tab.click()\n try:\n await page.wait_for_function(\"\"\"() => {\n const activeTab = document.querySelector('.ant-tabs-tab-active');\n if (!activeTab) return true;\n const tabPane = activeTab.closest('.ant-tabs')?.querySelector('.ant-tabs-content-holder');\n if (!tabPane) return true;\n const charts = tabPane.querySelectorAll('canvas, svg');\n return charts.length > 0;\n }\"\"\", timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n except Exception:\n logger.warning(\"[TabSwitching] Content verification timed out for first tab\")\n except Exception:\n pass\n\n await switch_tabs()\n\n # 2. Calculate full height for screenshot\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n full_height = await page.evaluate(\"\"\"() => {\n const body = document.body;\n const html = document.documentElement;\n const dashboardContent = document.querySelector('.dashboard-content');\n \n return Math.max(\n body.scrollHeight, body.offsetHeight,\n html.clientHeight, html.scrollHeight, html.offsetHeight,\n dashboardContent ? dashboardContent.scrollHeight + 100 : 0\n );\n }\"\"\")\n logger.info(f\"[DEBUG] Calculated full height: {full_height}\")\n\n # DIAGNOSTIC: Count chart elements before resize\n chart_count_before = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements BEFORE viewport resize: {chart_count_before}\")\n\n # DIAGNOSTIC: Capture pre-resize screenshot for comparison\n pre_resize_path = await self._save_debug_screenshot(page, debug_dir, \"preresize.png\")\n if pre_resize_path:\n pre_resize_size = os.path.getsize(pre_resize_path) if os.path.exists(pre_resize_path) else 0\n logger.info(f\"[DIAGNOSTIC] Pre-resize screenshot saved: {pre_resize_path} ({pre_resize_size} bytes)\")\n else:\n logger.warning(\"[DIAGNOSTIC] Failed to capture pre-resize screenshot\")\n\n logger.info(f\"[DIAGNOSTIC] Resizing viewport from current to 1920x{int(full_height)}\")\n await page.set_viewport_size({\"width\": 1920, \"height\": int(full_height)})\n\n # Wait for charts to re-render after viewport resize\n logger.info(\"[DIAGNOSTIC] Waiting for re-render after viewport resize...\")\n await self._wait_for_resize_rendered(page, chart_count_before)\n logger.info(\"[DIAGNOSTIC] Re-render wait completed\")\n\n # DIAGNOSTIC: Count chart elements after resize and wait\n chart_count_after = await page.evaluate(\"\"\"() => {\n return {\n chartContainers: document.querySelectorAll('.chart-container, .slice_container').length,\n canvasElements: document.querySelectorAll('canvas').length,\n svgElements: document.querySelectorAll('.chart-container svg, .slice_container svg').length,\n visibleCharts: document.querySelectorAll('.chart-container:visible, .slice_container:visible').length\n };\n }\"\"\")\n logger.info(f\"[DIAGNOSTIC] Chart elements AFTER viewport resize + wait: {chart_count_after}\")\n\n # DIAGNOSTIC: Check if any charts have error states\n chart_errors = await page.evaluate(\"\"\"() => {\n const errors = [];\n document.querySelectorAll('.chart-container, .slice_container').forEach((chart, i) => {\n const errorEl = chart.querySelector('.error, .alert-danger, .ant-alert-error');\n if (errorEl) {\n errors.push({index: i, text: errorEl.innerText.substring(0, 100)});\n }\n });\n return errors;\n }\"\"\")\n if chart_errors:\n logger.warning(f\"[DIAGNOSTIC] Charts with error states detected: {chart_errors}\")\n else:\n logger.info(\"[DIAGNOSTIC] No chart error states detected\")\n\n # 3. Take screenshot using CDP to bypass Playwright's font loading wait\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n logger.info(\"[DEBUG] Attempting full-page screenshot via CDP...\")\n cdp_success = False\n try:\n cdp = await page.context.new_cdp_session(page)\n screenshot_data = await cdp.send(\"Page.captureScreenshot\", {\n \"format\": \"png\",\n \"fromSurface\": True,\n \"captureBeyondViewport\": True\n })\n image_data = base64.b64decode(screenshot_data[\"data\"])\n with open(output_path, 'wb') as f:\n f.write(image_data)\n logger.info(\"Full-page screenshot saved via CDP\")\n cdp_success = True\n except Exception as cdp_err:\n logger.warning(f\"CDP screenshot failed: {cdp_err}. Falling back to Playwright full_page.\")\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n logger.info(\"Full-page screenshot saved via Playwright fallback\")\n cdp_success = True\n\n if cdp_success:\n # DIAGNOSTIC: Verify screenshot file\n final_size = os.path.getsize(output_path) if os.path.exists(output_path) else 0\n logger.info(f\"[DIAGNOSTIC] Final screenshot saved: {output_path}\")\n logger.info(f\"[DIAGNOSTIC] Final screenshot size: {final_size} bytes ({final_size / 1024:.2f} KB)\")\n\n # DIAGNOSTIC: Get image dimensions\n try:\n with Image.open(output_path) as final_img:\n logger.info(f\"[DIAGNOSTIC] Final screenshot dimensions: {final_img.width}x{final_img.height}\")\n except Exception as img_err:\n logger.warning(f\"[DIAGNOSTIC] Could not read final image dimensions: {img_err}\")\n except asyncio.TimeoutError:\n logger.error(f\"Screenshot capture timed out after {SCREENSHOT_SERVICE_TIMEOUT_MS}ms\")\n try:\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n logger.info(\"Emergency timeout screenshot saved\")\n except Exception:\n pass\n except Exception as e:\n logger.error(f\"[DEBUG] Full-page/Tab capture failed: {e}\")\n try:\n await page.screenshot(path=output_path, full_page=True, timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS)\n except Exception as e2:\n logger.error(f\"[DEBUG] Fallback screenshot also failed: {e2}\")\n await page.screenshot(path=output_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n\n await browser.close()\n success = True\n return True\n finally:\n if success:\n shutil.rmtree(debug_dir, ignore_errors=True)\n else:\n logger.info(f\"Debug screenshots preserved in {debug_dir}\")\n # endregion ScreenshotService.capture_dashboard\n# #endregion ScreenshotService\n" }, { "contract_id": "LLMClient", "contract_type": "Class", "file_path": "backend/src/plugins/llm_analysis/service.py", - "start_line": 688, - "end_line": 988, + "start_line": 792, + "end_line": 1093, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -35739,26 +37021,26 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region LLMClient [TYPE Class]\n# @BRIEF Wrapper for LLM provider APIs.\nclass LLMClient:\n # region LLMClient.__init__ [TYPE Function]\n # @PURPOSE Initializes the LLMClient with provider settings.\n # @PRE api_key, base_url, and default_model are non-empty strings.\n def __init__(self, provider_type: LLMProviderType, api_key: str, base_url: str, default_model: str):\n self.provider_type = provider_type\n normalized_key = (api_key or \"\").strip()\n if normalized_key.lower().startswith(\"bearer \"):\n normalized_key = normalized_key[7:].strip()\n self.api_key = normalized_key\n self.base_url = base_url\n self.default_model = default_model\n\n # DEBUG: Log initialization parameters (without exposing full API key)\n logger.info(\"[LLMClient.__init__] Initializing LLM client:\")\n logger.info(f\"[LLMClient.__init__] Provider Type: {provider_type}\")\n logger.info(f\"[LLMClient.__init__] Base URL: {base_url}\")\n logger.info(f\"[LLMClient.__init__] Default Model: {default_model}\")\n logger.info(f\"[LLMClient.__init__] API Key (first 8 chars): {self.api_key[:8] if self.api_key and len(self.api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n logger.info(f\"[LLMClient.__init__] API Key Length: {len(self.api_key) if self.api_key else 0}\")\n\n # Some OpenAI-compatible gateways are strict about auth header naming.\n default_headers = {\"Authorization\": f\"Bearer {self.api_key}\"}\n if self.provider_type == LLMProviderType.OPENROUTER:\n default_headers[\"HTTP-Referer\"] = (\n os.getenv(\"OPENROUTER_SITE_URL\", \"\").strip()\n or os.getenv(\"APP_BASE_URL\", \"\").strip()\n or \"http://localhost:8000\"\n )\n default_headers[\"X-Title\"] = os.getenv(\"OPENROUTER_APP_NAME\", \"\").strip() or \"ss-tools\"\n if self.provider_type == LLMProviderType.KILO:\n default_headers[\"Authentication\"] = f\"Bearer {self.api_key}\"\n default_headers[\"X-API-Key\"] = self.api_key\n # LiteLLM proxy uses standard OpenAI-compatible Bearer auth — no special headers needed.\n # It routes to upstream providers transparently, and the default Authorization header\n # is sufficient. No additional headers like HTTP-Referer or X-API-Key are required.\n\n http_client = httpx.AsyncClient(headers=default_headers, timeout=LLM_HTTP_TIMEOUT_S)\n self.client = AsyncOpenAI(\n api_key=self.api_key,\n base_url=base_url,\n default_headers=default_headers,\n http_client=http_client,\n )\n # endregion LLMClient.__init__\n\n # region LLMClient._supports_json_response_format [TYPE Function]\n # @PURPOSE Detect whether provider/model is likely compatible with response_format=json_object.\n # @PRE Client initialized with base_url and default_model.\n # @POST Returns False for known-incompatible combinations to avoid avoidable 400 errors.\n def _supports_json_response_format(self) -> bool:\n base = (self.base_url or \"\").lower()\n model = (self.default_model or \"\").lower()\n\n # OpenRouter routes to many upstream providers; some models reject json_object mode.\n if \"openrouter.ai\" in base:\n incompatible_tokens = (\n \"stepfun/\",\n \"step-\",\n \":free\",\n )\n if any(token in model for token in incompatible_tokens):\n return False\n return True\n # endregion LLMClient._supports_json_response_format\n\n # region LLMClient.get_json_completion [TYPE Function]\n # @PURPOSE Helper to handle LLM calls with JSON mode and fallback parsing.\n # @PRE messages is a list of valid message dictionaries.\n # @POST Returns a parsed JSON dictionary.\n # @SIDE_EFFECT Calls external LLM API.\n def _should_retry(exception: Exception) -> bool:\n \"\"\"Custom retry predicate that excludes authentication errors.\"\"\"\n # Don't retry on authentication errors\n if isinstance(exception, OpenAIAuthenticationError):\n return False\n # Retry on rate limit errors and other exceptions\n return isinstance(exception, (RateLimitError, Exception))\n\n @retry(\n stop=stop_after_attempt(5),\n wait=wait_exponential(multiplier=2, min=5, max=60),\n retry=retry_if_exception(_should_retry),\n reraise=True\n )\n async def get_json_completion(self, messages: list[dict[str, Any]]) -> dict[str, Any]:\n with belief_scope(\"get_json_completion\"):\n response = None\n try:\n use_json_mode = self._supports_json_response_format()\n try:\n logger.info(\n f\"[get_json_completion] Attempting LLM call for model: {self.default_model} \"\n f\"(json_mode={'on' if use_json_mode else 'off'})\"\n )\n logger.info(f\"[get_json_completion] Base URL being used: {self.base_url}\")\n logger.info(f\"[get_json_completion] Number of messages: {len(messages)}\")\n logger.info(f\"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}\")\n\n if use_json_mode:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages,\n response_format={\"type\": \"json_object\"}\n )\n else:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n except Exception as e:\n if use_json_mode and (\n \"JSON mode is not enabled\" in str(e)\n or \"json_object is not supported\" in str(e).lower()\n or \"response_format\" in str(e).lower()\n or \"400\" in str(e)\n ):\n logger.warning(f\"[get_json_completion] JSON mode failed or not supported: {e!s}. Falling back to plain text response.\")\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n else:\n raise e\n\n logger.debug(f\"[get_json_completion] LLM Response: {response}\")\n except OpenAIAuthenticationError as e:\n logger.error(f\"[get_json_completion] Authentication error: {e!s}\")\n # Do not retry on auth errors - re-raise to stop retry\n raise\n except RateLimitError as e:\n logger.warning(f\"[get_json_completion] Rate limit hit: {e!s}\")\n\n # Extract retry_delay from error metadata if available\n retry_delay = 5.0 # Default fallback\n try:\n # Based on logs, the raw response is in e.body or e.response.json()\n # The logs show 'metadata': {'raw': '...'} which suggests a proxy or specific client wrapper\n # Let's try to find the 'retryDelay' in the error message or response\n import re\n\n # Try to find \"retryDelay\": \"XXs\" in the string representation of the error\n error_str = str(e)\n match = re.search(r'\"retryDelay\":\\s*\"(\\d+)s\"', error_str)\n if match:\n retry_delay = float(match.group(1))\n else:\n # Try to parse from response if it's a standard OpenAI-like error with body\n if hasattr(e, 'body') and isinstance(e.body, dict):\n # Some providers put it in details\n details = e.body.get('error', {}).get('details', [])\n for detail in details:\n if detail.get('@type') == 'type.googleapis.com/google.rpc.RetryInfo':\n delay_str = detail.get('retryDelay', '5s')\n retry_delay = float(delay_str.rstrip('s'))\n break\n except Exception as parse_e:\n logger.debug(f\"[get_json_completion] Failed to parse retry delay: {parse_e}\")\n\n # Add a small safety margin (0.5s) as requested\n wait_time = retry_delay + 0.5\n logger.info(f\"[get_json_completion] Waiting for {wait_time}s before retry...\")\n await asyncio.sleep(wait_time)\n raise\n except Exception as e:\n logger.error(f\"[get_json_completion] LLM call failed: {e!s}\")\n raise\n\n if not response or not hasattr(response, 'choices') or not response.choices:\n raise RuntimeError(f\"Invalid LLM response: {response}\")\n\n content = response.choices[0].message.content\n logger.debug(f\"[get_json_completion] Raw content to parse: {content}\")\n\n try:\n return json.loads(content)\n except json.JSONDecodeError:\n logger.warning(\"[get_json_completion] Failed to parse JSON directly, attempting to extract from code blocks\")\n if \"```json\" in content:\n json_str = content.split(\"```json\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n elif \"```\" in content:\n json_str = content.split(\"```\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n else:\n raise\n # endregion LLMClient.get_json_completion\n\n # region LLMClient.test_runtime_connection [TYPE Function]\n # @PURPOSE Validate provider credentials using the same chat completions transport as runtime analysis.\n # @PRE Client is initialized with provider credentials and default_model.\n # @POST Returns lightweight JSON payload when runtime auth/model path is valid.\n # @SIDE_EFFECT Calls external LLM API.\n async def test_runtime_connection(self) -> dict[str, Any]:\n with belief_scope(\"test_runtime_connection\"):\n messages = [\n {\n \"role\": \"user\",\n \"content\": 'Return exactly this JSON object and nothing else: {\"ok\": true}',\n }\n ]\n return await self.get_json_completion(messages)\n # endregion LLMClient.test_runtime_connection\n\n # region LLMClient.fetch_models [TYPE Function]\n # @PURPOSE Fetch available models from the provider's API.\n # @PRE Client is initialized with provider credentials.\n # @POST Returns a list of model ID strings.\n # @SIDE_EFFECT Calls external LLM API /v1/models endpoint.\n async def fetch_models(self) -> list[str]:\n with belief_scope(\"LLMClient.fetch_models\"):\n try:\n response = await self.client.models.list()\n model_ids = [m.id for m in response.data]\n model_ids.sort()\n logger.reason(\n f\"[LLMClient.fetch_models] Fetched {len(model_ids)} models from {self.base_url}\",\n extra={\"src\": \"LLMClient.fetch_models\"},\n )\n return model_ids\n except Exception as e:\n logger.warning(\n f\"[LLMClient.fetch_models] Failed to fetch models: {e}\",\n )\n raise\n # endregion LLMClient.fetch_models\n\n # region LLMClient.analyze_dashboard [TYPE Function]\n # @PURPOSE Sends dashboard data (screenshot + logs) to LLM for health analysis.\n # @PRE screenshot_path exists, logs is a list of strings.\n # @POST Returns a structured analysis dictionary (status, summary, issues).\n # @SIDE_EFFECT Reads screenshot file and calls external LLM API.\n async def analyze_dashboard(\n self,\n screenshot_path: str,\n logs: list[str],\n prompt_template: str = DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n ) -> dict[str, Any]:\n with belief_scope(\"analyze_dashboard\"):\n # Optimize image to reduce token count (US1 / T023)\n # Gemini/Gemma models have limits on input tokens, and large images contribute significantly.\n try:\n with Image.open(screenshot_path) as img:\n # Convert to RGB if necessary\n if img.mode in (\"RGBA\", \"P\"):\n img = img.convert(\"RGB\")\n\n # Resize if too large (max 1024px width while maintaining aspect ratio)\n # We reduce width further to 1024px to stay within token limits for long dashboards\n max_width = 1024\n if img.width > max_width or img.height > 2048:\n # Calculate scaling factor to fit within 1024x2048\n scale = min(max_width / img.width, 2048 / img.height)\n if scale < 1.0:\n new_width = int(img.width * scale)\n new_height = int(img.height * scale)\n img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)\n logger.info(f\"[analyze_dashboard] Resized image from {img.width}x{img.height} to {new_width}x{new_height}\")\n\n # Compress and convert to base64\n buffer = io.BytesIO()\n # Lower quality to 60% to further reduce payload size\n img.save(buffer, format=\"JPEG\", quality=60, optimize=True)\n base_64_image = base64.b64encode(buffer.getvalue()).decode('utf-8')\n logger.info(f\"[analyze_dashboard] Optimized image size: {len(buffer.getvalue()) / 1024:.2f} KB\")\n except Exception as img_e:\n logger.warning(f\"[analyze_dashboard] Image optimization failed: {img_e}. Using raw image.\")\n with open(screenshot_path, \"rb\") as image_file:\n base_64_image = base64.b64encode(image_file.read()).decode('utf-8')\n\n log_text = \"\\n\".join(logs)\n prompt = render_prompt(prompt_template, {\"logs\": log_text})\n\n messages = [\n {\n \"role\": \"user\",\n \"content\": [\n {\"type\": \"text\", \"text\": prompt},\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": f\"data:image/jpeg;base64,{base_64_image}\"\n }\n }\n ]\n }\n ]\n\n try:\n return await self.get_json_completion(messages)\n except Exception as e:\n logger.error(f\"[analyze_dashboard] Failed to get analysis: {e!s}\")\n return {\n \"status\": \"UNKNOWN\",\n \"summary\": f\"Failed to get response from LLM: {e!s}\",\n \"issues\": [{\"severity\": \"UNKNOWN\", \"message\": \"LLM provider returned empty or invalid response\"}]\n }\n # endregion LLMClient.analyze_dashboard\n# #endregion LLMClient\n" + "body": "# #region LLMClient [TYPE Class]\n# @BRIEF Wrapper for LLM provider APIs.\nclass LLMClient:\n # region LLMClient.__init__ [TYPE Function]\n # @PURPOSE Initializes the LLMClient with provider settings.\n # @PRE api_key, base_url, and default_model are non-empty strings.\n def __init__(self, provider_type: LLMProviderType, api_key: str, base_url: str, default_model: str):\n self.provider_type = provider_type\n normalized_key = (api_key or \"\").strip()\n if normalized_key.lower().startswith(\"bearer \"):\n normalized_key = normalized_key[7:].strip()\n self.api_key = normalized_key\n self.base_url = base_url\n self.default_model = default_model\n\n # DEBUG: Log initialization parameters (without exposing full API key)\n logger.info(\"[LLMClient.__init__] Initializing LLM client:\")\n logger.info(f\"[LLMClient.__init__] Provider Type: {provider_type}\")\n logger.info(f\"[LLMClient.__init__] Base URL: {base_url}\")\n logger.info(f\"[LLMClient.__init__] Default Model: {default_model}\")\n logger.info(f\"[LLMClient.__init__] API Key (first 8 chars): {self.api_key[:8] if self.api_key and len(self.api_key) > 8 else 'EMPTY_OR_NONE'}...\")\n logger.info(f\"[LLMClient.__init__] API Key Length: {len(self.api_key) if self.api_key else 0}\")\n\n # Some OpenAI-compatible gateways are strict about auth header naming.\n default_headers = {\"Authorization\": f\"Bearer {self.api_key}\"}\n if self.provider_type == LLMProviderType.OPENROUTER:\n default_headers[\"HTTP-Referer\"] = (\n os.getenv(\"OPENROUTER_SITE_URL\", \"\").strip()\n or os.getenv(\"APP_BASE_URL\", \"\").strip()\n or \"http://localhost:8000\"\n )\n default_headers[\"X-Title\"] = os.getenv(\"OPENROUTER_APP_NAME\", \"\").strip() or \"ss-tools\"\n if self.provider_type == LLMProviderType.KILO:\n default_headers[\"Authentication\"] = f\"Bearer {self.api_key}\"\n default_headers[\"X-API-Key\"] = self.api_key\n # LiteLLM proxy uses standard OpenAI-compatible Bearer auth — no special headers needed.\n # It routes to upstream providers transparently, and the default Authorization header\n # is sufficient. No additional headers like HTTP-Referer or X-API-Key are required.\n\n http_client = httpx.AsyncClient(headers=default_headers, timeout=LLM_HTTP_TIMEOUT_S)\n self.client = AsyncOpenAI(\n api_key=self.api_key,\n base_url=base_url,\n default_headers=default_headers,\n http_client=http_client,\n )\n # endregion LLMClient.__init__\n\n # region LLMClient._supports_json_response_format [TYPE Function]\n # @PURPOSE Detect whether provider/model is likely compatible with response_format=json_object.\n # @PRE Client initialized with base_url and default_model.\n # @POST Returns False for known-incompatible combinations to avoid avoidable 400 errors.\n def _supports_json_response_format(self) -> bool:\n base = (self.base_url or \"\").lower()\n model = (self.default_model or \"\").lower()\n\n # OpenRouter routes to many upstream providers; some models reject json_object mode.\n if \"openrouter.ai\" in base:\n incompatible_tokens = (\n \"stepfun/\",\n \"step-\",\n \":free\",\n )\n if any(token in model for token in incompatible_tokens):\n return False\n return True\n # endregion LLMClient._supports_json_response_format\n\n # region LLMClient.get_json_completion [TYPE Function]\n # @PURPOSE Helper to handle LLM calls with JSON mode and fallback parsing.\n # @PRE messages is a list of valid message dictionaries.\n # @POST Returns a parsed JSON dictionary.\n # @SIDE_EFFECT Calls external LLM API.\n def _should_retry(exception: Exception) -> bool:\n \"\"\"Custom retry predicate that excludes authentication errors.\"\"\"\n # Don't retry on authentication errors\n if isinstance(exception, OpenAIAuthenticationError):\n return False\n # Retry on rate limit errors and other exceptions\n return isinstance(exception, (RateLimitError, Exception))\n\n @retry(\n stop=stop_after_attempt(5),\n wait=wait_exponential(multiplier=2, min=5, max=60),\n retry=retry_if_exception(_should_retry),\n reraise=True\n )\n async def get_json_completion(self, messages: list[dict[str, Any]]) -> dict[str, Any]:\n with belief_scope(\"get_json_completion\"):\n response = None\n try:\n use_json_mode = self._supports_json_response_format()\n try:\n logger.info(\n f\"[get_json_completion] Attempting LLM call for model: {self.default_model} \"\n f\"(json_mode={'on' if use_json_mode else 'off'})\"\n )\n logger.info(f\"[get_json_completion] Base URL being used: {self.base_url}\")\n logger.info(f\"[get_json_completion] Number of messages: {len(messages)}\")\n logger.info(f\"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}\")\n\n if use_json_mode:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages,\n response_format={\"type\": \"json_object\"}\n )\n else:\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n except Exception as e:\n if use_json_mode and (\n \"JSON mode is not enabled\" in str(e)\n or \"json_object is not supported\" in str(e).lower()\n or \"response_format\" in str(e).lower()\n or \"400\" in str(e)\n ):\n logger.warning(f\"[get_json_completion] JSON mode failed or not supported: {e!s}. Falling back to plain text response.\")\n response = await self.client.chat.completions.create(\n model=self.default_model,\n messages=messages\n )\n else:\n raise e\n\n logger.debug(f\"[get_json_completion] LLM Response: {response}\")\n except OpenAIAuthenticationError as e:\n logger.error(f\"[get_json_completion] Authentication error: {e!s}\")\n # Do not retry on auth errors - re-raise to stop retry\n raise\n except RateLimitError as e:\n logger.warning(f\"[get_json_completion] Rate limit hit: {e!s}\")\n\n # Extract retry_delay from error metadata if available\n retry_delay = 5.0 # Default fallback\n try:\n # Based on logs, the raw response is in e.body or e.response.json()\n # The logs show 'metadata': {'raw': '...'} which suggests a proxy or specific client wrapper\n # Let's try to find the 'retryDelay' in the error message or response\n import re\n\n # Try to find \"retryDelay\": \"XXs\" in the string representation of the error\n error_str = str(e)\n match = re.search(r'\"retryDelay\":\\s*\"(\\d+)s\"', error_str)\n if match:\n retry_delay = float(match.group(1))\n else:\n # Try to parse from response if it's a standard OpenAI-like error with body\n if hasattr(e, 'body') and isinstance(e.body, dict):\n # Some providers put it in details\n details = e.body.get('error', {}).get('details', [])\n for detail in details:\n if detail.get('@type') == 'type.googleapis.com/google.rpc.RetryInfo':\n delay_str = detail.get('retryDelay', '5s')\n retry_delay = float(delay_str.rstrip('s'))\n break\n except Exception as parse_e:\n logger.debug(f\"[get_json_completion] Failed to parse retry delay: {parse_e}\")\n\n # Add a small safety margin (0.5s) as requested\n wait_time = retry_delay + 0.5\n logger.info(f\"[get_json_completion] Waiting for {wait_time}s before retry...\")\n await asyncio.sleep(wait_time)\n raise\n except Exception as e:\n logger.error(f\"[get_json_completion] LLM call failed: {e!s}\")\n raise\n\n if not response or not hasattr(response, 'choices') or not response.choices:\n raise RuntimeError(f\"Invalid LLM response: {response}\")\n\n content = response.choices[0].message.content\n logger.debug(f\"[get_json_completion] Raw content to parse: {content}\")\n\n try:\n return json.loads(content)\n except json.JSONDecodeError:\n logger.warning(\"[get_json_completion] Failed to parse JSON directly, attempting to extract from code blocks\")\n if \"```json\" in content:\n json_str = content.split(\"```json\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n elif \"```\" in content:\n json_str = content.split(\"```\")[1].split(\"```\")[0].strip()\n return json.loads(json_str)\n else:\n raise\n # endregion LLMClient.get_json_completion\n\n # region LLMClient.test_runtime_connection [TYPE Function]\n # @PURPOSE Validate provider credentials using the same chat completions transport as runtime analysis.\n # @PRE Client is initialized with provider credentials and default_model.\n # @POST Returns lightweight JSON payload when runtime auth/model path is valid.\n # @SIDE_EFFECT Calls external LLM API.\n async def test_runtime_connection(self) -> dict[str, Any]:\n with belief_scope(\"test_runtime_connection\"):\n messages = [\n {\n \"role\": \"user\",\n \"content\": 'Return exactly this JSON object and nothing else: {\"ok\": true}',\n }\n ]\n return await self.get_json_completion(messages)\n # endregion LLMClient.test_runtime_connection\n\n # region LLMClient.fetch_models [TYPE Function]\n # @PURPOSE Fetch available models from the provider's API.\n # @PRE Client is initialized with provider credentials.\n # @POST Returns a list of model ID strings.\n # @SIDE_EFFECT Calls external LLM API /v1/models endpoint.\n async def fetch_models(self) -> list[str]:\n with belief_scope(\"LLMClient.fetch_models\"):\n try:\n response = await self.client.models.list()\n model_ids = [m.id for m in response.data]\n model_ids.sort()\n logger.reason(\n f\"[LLMClient.fetch_models] Fetched {len(model_ids)} models from {self.base_url}\",\n extra={\"src\": \"LLMClient.fetch_models\"},\n )\n return model_ids\n except Exception as e:\n logger.warning(\n f\"[LLMClient.fetch_models] Failed to fetch models: {e}\",\n )\n raise\n # endregion LLMClient.fetch_models\n\n # region LLMClient.analyze_dashboard [TYPE Function]\n # @PURPOSE Sends dashboard data (screenshot + logs) to LLM for health analysis.\n # @PRE screenshot_path exists, logs is a list of strings.\n # @POST Returns a structured analysis dictionary (status, summary, issues).\n # @SIDE_EFFECT Reads screenshot file and calls external LLM API.\n async def analyze_dashboard(\n self,\n screenshot_path: str,\n logs: list[str],\n prompt_template: str = DEFAULT_LLM_PROMPTS[\"dashboard_validation_prompt\"],\n ) -> dict[str, Any]:\n with belief_scope(\"analyze_dashboard\"):\n # Optimize image to reduce token count (US1 / T023)\n # Gemini/Gemma models have limits on input tokens, and large images contribute significantly.\n try:\n with Image.open(screenshot_path) as img:\n # Convert to RGB if necessary\n if img.mode in (\"RGBA\", \"P\"):\n img = img.convert(\"RGB\")\n\n # Resize if too large (max 1024px width while maintaining aspect ratio)\n # We reduce width further to 1024px to stay within token limits for long dashboards\n max_width = 1024\n if img.width > max_width or img.height > 2048:\n # Calculate scaling factor to fit within 1024x2048\n scale = min(max_width / img.width, 2048 / img.height)\n if scale < 1.0:\n new_width = int(img.width * scale)\n new_height = int(img.height * scale)\n img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)\n logger.info(f\"[analyze_dashboard] Resized image from {img.width}x{img.height} to {new_width}x{new_height}\")\n\n # Compress and convert to base64\n buffer = io.BytesIO()\n # Lower quality to 60% to further reduce payload size\n img.save(buffer, format=\"JPEG\", quality=60, optimize=True)\n base_64_image = base64.b64encode(buffer.getvalue()).decode('utf-8')\n logger.info(f\"[analyze_dashboard] Optimized image size: {len(buffer.getvalue()) / 1024:.2f} KB\")\n except Exception as img_e:\n logger.warning(f\"[analyze_dashboard] Image optimization failed: {img_e}. Using raw image.\")\n with open(screenshot_path, \"rb\") as image_file:\n base_64_image = base64.b64encode(image_file.read()).decode('utf-8')\n\n log_text = \"\\n\".join(logs)\n prompt = render_prompt(prompt_template, {\"logs\": log_text})\n\n messages = [\n {\n \"role\": \"user\",\n \"content\": [\n {\"type\": \"text\", \"text\": prompt},\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": f\"data:image/jpeg;base64,{base_64_image}\"\n }\n }\n ]\n }\n ]\n\n try:\n return await self.get_json_completion(messages)\n except Exception as e:\n logger.error(f\"[analyze_dashboard] Failed to get analysis: {e!s}\")\n return {\n \"status\": \"UNKNOWN\",\n \"summary\": f\"Failed to get response from LLM: {e!s}\",\n \"issues\": [{\"severity\": \"UNKNOWN\", \"message\": \"LLM provider returned empty or invalid response\"}]\n }\n # endregion LLMClient.analyze_dashboard\n\n# #endregion LLMClient\n" }, { "contract_id": "MapperPluginModule", "contract_type": "Module", "file_path": "backend/src/plugins/mapper.py", "start_line": 1, - "end_line": 213, + "end_line": 196, "tier": "TIER_1", "complexity": 1, "metadata": { "LAYER": "Plugins", - "PURPOSE": "Implements a plugin for mapping dataset columns using external database connections or Excel files." + "PURPOSE": "Implements a plugin for mapping dataset columns using Superset SQL Lab or Excel files." }, "relations": [ { "source_id": "MapperPluginModule", "relation_type": "DEPENDS_ON", - "target_id": "Inherits from PluginBase. Uses DatasetMapper from superset_tool.", - "target_ref": "Inherits from PluginBase. Uses DatasetMapper from superset_tool." + "target_id": "Inherits from PluginBase. Uses DatasetMapper and SupersetSqlLabExecutor.", + "target_ref": "Inherits from PluginBase. Uses DatasetMapper and SupersetSqlLabExecutor." }, { "source_id": "MapperPluginModule", @@ -35789,14 +37071,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MapperPluginModule [TYPE Module] [SEMANTICS mapper, dataset, column, excel, mapping]\n# @BRIEF Implements a plugin for mapping dataset columns using external database connections or Excel files.\n# @LAYER: Plugins\n# @RELATION Inherits from PluginBase. Uses DatasetMapper from superset_tool.\n# @RELATION USES -> TaskContext\n\nfrom typing import Any\n\nfrom ..core.database import SessionLocal\nfrom ..core.logger import belief_scope, logger\nfrom ..core.plugin_base import PluginBase\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager.context import TaskContext\nfrom ..core.utils.dataset_mapper import DatasetMapper\nfrom ..models.connection import ConnectionConfig\n\n\n# #region MapperPlugin [TYPE Class]\n# @BRIEF Plugin for mapping dataset columns verbose names.\nclass MapperPlugin(PluginBase):\n \"\"\"\n Plugin for mapping dataset columns verbose names.\n \"\"\"\n\n @property\n # region id [TYPE Function]\n # @PURPOSE: Returns the unique identifier for the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string ID.\n # @RETURN: str - \"dataset-mapper\"\n def id(self) -> str:\n with belief_scope(\"id\"):\n return \"dataset-mapper\"\n # endregion id\n\n @property\n # region name [TYPE Function]\n # @PURPOSE: Returns the human-readable name of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string name.\n # @RETURN: str - Plugin name.\n def name(self) -> str:\n with belief_scope(\"name\"):\n return \"Dataset Mapper\"\n # endregion name\n\n @property\n # region description [TYPE Function]\n # @PURPOSE: Returns a description of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string description.\n # @RETURN: str - Plugin description.\n def description(self) -> str:\n with belief_scope(\"description\"):\n return \"Map dataset column verbose names using PostgreSQL comments or Excel files.\"\n # endregion description\n\n @property\n # region version [TYPE Function]\n # @PURPOSE: Returns the version of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string version.\n # @RETURN: str - \"1.0.0\"\n def version(self) -> str:\n with belief_scope(\"version\"):\n return \"1.0.0\"\n # endregion version\n\n @property\n # region ui_route [TYPE Function]\n # @PURPOSE: Returns the frontend route for the mapper plugin.\n # @RETURN: str - \"/tools/mapper\"\n def ui_route(self) -> str:\n with belief_scope(\"ui_route\"):\n return \"/tools/mapper\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Returns the JSON schema for the mapper plugin parameters.\n # @PRE: Plugin instance exists.\n # @POST: Returns dictionary schema.\n # @RETURN: Dict[str, Any] - JSON schema.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"env\": {\n \"type\": \"string\",\n \"title\": \"Environment\",\n \"description\": \"The Superset environment (e.g., 'dev').\"\n },\n \"dataset_id\": {\n \"type\": \"integer\",\n \"title\": \"Dataset ID\",\n \"description\": \"The ID of the dataset to update.\"\n },\n \"source\": {\n \"type\": \"string\",\n \"title\": \"Mapping Source\",\n \"enum\": [\"postgres\", \"excel\"],\n \"default\": \"postgres\"\n },\n \"connection_id\": {\n \"type\": \"string\",\n \"title\": \"Saved Connection\",\n \"description\": \"The ID of a saved database connection (for postgres source).\"\n },\n \"table_name\": {\n \"type\": \"string\",\n \"title\": \"Table Name\",\n \"description\": \"Target table name in PostgreSQL.\"\n },\n \"table_schema\": {\n \"type\": \"string\",\n \"title\": \"Table Schema\",\n \"description\": \"Target table schema in PostgreSQL.\",\n \"default\": \"public\"\n },\n \"excel_path\": {\n \"type\": \"string\",\n \"title\": \"Excel Path\",\n \"description\": \"Path to the Excel file (for excel source).\"\n }\n },\n \"required\": [\"env\", \"dataset_id\", \"source\"]\n }\n # endregion get_schema\n\n # region execute [TYPE Function]\n # @PURPOSE: Executes the dataset mapping logic with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Mapping parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: Params contain valid 'env', 'dataset_id', and 'source'. params must be a dictionary.\n # @POST: Updates the dataset in Superset.\n # @RETURN: Dict[str, Any] - Execution status.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"execute\"):\n env_name = params.get(\"env\")\n dataset_id = params.get(\"dataset_id\")\n source = params.get(\"source\")\n\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n superset_log = log.with_source(\"superset_api\") if context else log\n db_log = log.with_source(\"postgres\") if context else log\n\n if not env_name or dataset_id is None or not source:\n log.error(\"Missing required parameters: env, dataset_id, source\")\n raise ValueError(\"Missing required parameters: env, dataset_id, source\")\n\n # Get config and initialize client\n from ..dependencies import get_config_manager\n config_manager = get_config_manager()\n env_config = config_manager.get_environment(env_name)\n if not env_config:\n log.error(f\"Environment '{env_name}' not found in configuration.\")\n raise ValueError(f\"Environment '{env_name}' not found in configuration.\")\n\n client = SupersetClient(env_config)\n client.authenticate()\n\n postgres_config = None\n if source == \"postgres\":\n connection_id = params.get(\"connection_id\")\n if not connection_id:\n log.error(\"connection_id is required for postgres source.\")\n raise ValueError(\"connection_id is required for postgres source.\")\n\n # Load connection from DB\n db = SessionLocal()\n try:\n conn_config = db.query(ConnectionConfig).filter(ConnectionConfig.id == connection_id).first()\n if not conn_config:\n db_log.error(f\"Connection {connection_id} not found.\")\n raise ValueError(f\"Connection {connection_id} not found.\")\n\n postgres_config = {\n 'dbname': conn_config.database,\n 'user': conn_config.username,\n 'password': conn_config.password,\n 'host': conn_config.host,\n 'port': str(conn_config.port) if conn_config.port else '5432'\n }\n db_log.debug(f\"Loaded connection config for {conn_config.host}:{conn_config.port}/{conn_config.database}\")\n finally:\n db.close()\n\n log.info(f\"Starting mapping for dataset {dataset_id} in {env_name}\")\n\n mapper = DatasetMapper()\n\n try:\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=source,\n postgres_config=postgres_config,\n excel_path=params.get(\"excel_path\"),\n table_name=params.get(\"table_name\"),\n table_schema=params.get(\"table_schema\") or \"public\"\n )\n superset_log.info(f\"Mapping completed for dataset {dataset_id}\")\n return {\"status\": \"success\", \"dataset_id\": dataset_id}\n except Exception as e:\n log.error(f\"Mapping failed: {e}\")\n raise\n # endregion execute\n\n# #endregion MapperPlugin\n# #endregion MapperPluginModule\n" + "body": "# #region MapperPluginModule [TYPE Module] [SEMANTICS mapper, dataset, column, sqllab, excel, mapping]\n# @BRIEF Implements a plugin for mapping dataset columns using Superset SQL Lab or Excel files.\n# @LAYER: Plugins\n# @RELATION Inherits from PluginBase. Uses DatasetMapper and SupersetSqlLabExecutor.\n# @RELATION USES -> TaskContext\n\nfrom typing import Any\n\nfrom ..core.logger import belief_scope, logger\nfrom ..core.plugin_base import PluginBase\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager.context import TaskContext\nfrom ..core.utils.dataset_mapper import DatasetMapper\n\n\n# #region MapperPlugin [TYPE Class]\n# @BRIEF Plugin for mapping dataset columns verbose names.\nclass MapperPlugin(PluginBase):\n \"\"\"\n Plugin for mapping dataset columns verbose names.\n \"\"\"\n\n @property\n # region id [TYPE Function]\n # @PURPOSE: Returns the unique identifier for the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string ID.\n # @RETURN: str - \"dataset-mapper\"\n def id(self) -> str:\n with belief_scope(\"id\"):\n return \"dataset-mapper\"\n # endregion id\n\n @property\n # region name [TYPE Function]\n # @PURPOSE: Returns the human-readable name of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string name.\n # @RETURN: str - Plugin name.\n def name(self) -> str:\n with belief_scope(\"name\"):\n return \"Dataset Mapper\"\n # endregion name\n\n @property\n # region description [TYPE Function]\n # @PURPOSE: Returns a description of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string description.\n # @RETURN: str - Plugin description.\n def description(self) -> str:\n with belief_scope(\"description\"):\n return \"Map dataset column verbose names using Superset SQL Lab or Excel files.\"\n # endregion description\n\n @property\n # region version [TYPE Function]\n # @PURPOSE: Returns the version of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string version.\n # @RETURN: str - \"1.0.0\"\n def version(self) -> str:\n with belief_scope(\"version\"):\n return \"1.0.0\"\n # endregion version\n\n @property\n # region ui_route [TYPE Function]\n # @PURPOSE: Returns the frontend route for the mapper plugin.\n # @RETURN: str - \"/tools/mapper\"\n def ui_route(self) -> str:\n with belief_scope(\"ui_route\"):\n return \"/tools/mapper\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Returns the JSON schema for the mapper plugin parameters.\n # @PRE: Plugin instance exists.\n # @POST: Returns dictionary schema.\n # @RETURN: Dict[str, Any] - JSON schema.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"env\": {\n \"type\": \"string\",\n \"title\": \"Environment\",\n \"description\": \"The Superset environment (e.g., 'dev').\"\n },\n \"dataset_id\": {\n \"type\": \"integer\",\n \"title\": \"Dataset ID\",\n \"description\": \"The ID of the dataset to update.\"\n },\n \"source\": {\n \"type\": \"string\",\n \"title\": \"Mapping Source\",\n \"enum\": [\"sqllab\", \"excel\"],\n \"default\": \"sqllab\"\n },\n \"database_id\": {\n \"type\": \"integer\",\n \"title\": \"Superset Database ID\",\n \"description\": \"Target database ID in Superset (for sqllab source).\"\n },\n \"sql_query\": {\n \"type\": \"string\",\n \"title\": \"SQL Query\",\n \"description\": \"Custom SQL query returning column_name and verbose_name columns. Default: information_schema.columns.\",\n \"default\": \"\"\n },\n \"excel_path\": {\n \"type\": \"string\",\n \"title\": \"Excel Path\",\n \"description\": \"Path to the Excel file (for excel source).\"\n }\n },\n \"required\": [\"env\", \"dataset_id\", \"source\"]\n }\n # endregion get_schema\n\n # region execute [TYPE Function]\n # @PURPOSE: Executes the dataset mapping logic with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Mapping parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: Params contain valid 'env', 'dataset_id', and 'source'. params must be a dictionary.\n # @POST: Updates the dataset in Superset.\n # @RETURN: Dict[str, Any] - Execution status.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"execute\"):\n env_name = params.get(\"env\")\n dataset_id = params.get(\"dataset_id\")\n source = params.get(\"source\")\n\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n superset_log = log.with_source(\"superset_api\") if context else log\n\n if not env_name or dataset_id is None or not source:\n log.error(\"Missing required parameters: env, dataset_id, source\")\n raise ValueError(\"Missing required parameters: env, dataset_id, source\")\n\n # Get config and initialize client\n from ..dependencies import get_config_manager\n config_manager = get_config_manager()\n env_config = config_manager.get_environment(env_name)\n if not env_config:\n log.error(f\"Environment '{env_name}' not found in configuration.\")\n raise ValueError(f\"Environment '{env_name}' not found in configuration.\")\n\n client = SupersetClient(env_config)\n client.authenticate()\n\n log.info(f\"Starting mapping for dataset {dataset_id} in {env_name}\")\n\n mapper = DatasetMapper()\n\n try:\n if source == \"sqllab\":\n # Use Superset SQL Lab to query database metadata\n from ..plugins.translate.superset_executor import SupersetSqlLabExecutor\n executor = SupersetSqlLabExecutor(config_manager, env_name)\n database_id = params.get(\"database_id\")\n if not database_id:\n log.error(\"database_id is required for sqllab source.\")\n raise ValueError(\"database_id is required for sqllab source.\")\n executor.resolve_database_id(target_database_id=str(database_id))\n\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=\"sqllab\",\n sqllab_executor=executor,\n database_id=database_id,\n sql_query=params.get(\"sql_query\"),\n )\n else:\n # Excel source\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=\"excel\",\n excel_path=params.get(\"excel_path\") or params.get(\"file_data\")\n )\n superset_log.info(f\"Mapping completed for dataset {dataset_id}\")\n return {\"status\": \"success\", \"dataset_id\": dataset_id}\n except Exception as e:\n log.error(f\"Mapping failed: {e}\")\n raise\n # endregion execute\n\n# #endregion MapperPlugin\n# #endregion MapperPluginModule\n" }, { "contract_id": "MapperPlugin", "contract_type": "Class", "file_path": "backend/src/plugins/mapper.py", - "start_line": 18, - "end_line": 212, + "start_line": 16, + "end_line": 195, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -35806,7 +37088,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MapperPlugin [TYPE Class]\n# @BRIEF Plugin for mapping dataset columns verbose names.\nclass MapperPlugin(PluginBase):\n \"\"\"\n Plugin for mapping dataset columns verbose names.\n \"\"\"\n\n @property\n # region id [TYPE Function]\n # @PURPOSE: Returns the unique identifier for the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string ID.\n # @RETURN: str - \"dataset-mapper\"\n def id(self) -> str:\n with belief_scope(\"id\"):\n return \"dataset-mapper\"\n # endregion id\n\n @property\n # region name [TYPE Function]\n # @PURPOSE: Returns the human-readable name of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string name.\n # @RETURN: str - Plugin name.\n def name(self) -> str:\n with belief_scope(\"name\"):\n return \"Dataset Mapper\"\n # endregion name\n\n @property\n # region description [TYPE Function]\n # @PURPOSE: Returns a description of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string description.\n # @RETURN: str - Plugin description.\n def description(self) -> str:\n with belief_scope(\"description\"):\n return \"Map dataset column verbose names using PostgreSQL comments or Excel files.\"\n # endregion description\n\n @property\n # region version [TYPE Function]\n # @PURPOSE: Returns the version of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string version.\n # @RETURN: str - \"1.0.0\"\n def version(self) -> str:\n with belief_scope(\"version\"):\n return \"1.0.0\"\n # endregion version\n\n @property\n # region ui_route [TYPE Function]\n # @PURPOSE: Returns the frontend route for the mapper plugin.\n # @RETURN: str - \"/tools/mapper\"\n def ui_route(self) -> str:\n with belief_scope(\"ui_route\"):\n return \"/tools/mapper\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Returns the JSON schema for the mapper plugin parameters.\n # @PRE: Plugin instance exists.\n # @POST: Returns dictionary schema.\n # @RETURN: Dict[str, Any] - JSON schema.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"env\": {\n \"type\": \"string\",\n \"title\": \"Environment\",\n \"description\": \"The Superset environment (e.g., 'dev').\"\n },\n \"dataset_id\": {\n \"type\": \"integer\",\n \"title\": \"Dataset ID\",\n \"description\": \"The ID of the dataset to update.\"\n },\n \"source\": {\n \"type\": \"string\",\n \"title\": \"Mapping Source\",\n \"enum\": [\"postgres\", \"excel\"],\n \"default\": \"postgres\"\n },\n \"connection_id\": {\n \"type\": \"string\",\n \"title\": \"Saved Connection\",\n \"description\": \"The ID of a saved database connection (for postgres source).\"\n },\n \"table_name\": {\n \"type\": \"string\",\n \"title\": \"Table Name\",\n \"description\": \"Target table name in PostgreSQL.\"\n },\n \"table_schema\": {\n \"type\": \"string\",\n \"title\": \"Table Schema\",\n \"description\": \"Target table schema in PostgreSQL.\",\n \"default\": \"public\"\n },\n \"excel_path\": {\n \"type\": \"string\",\n \"title\": \"Excel Path\",\n \"description\": \"Path to the Excel file (for excel source).\"\n }\n },\n \"required\": [\"env\", \"dataset_id\", \"source\"]\n }\n # endregion get_schema\n\n # region execute [TYPE Function]\n # @PURPOSE: Executes the dataset mapping logic with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Mapping parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: Params contain valid 'env', 'dataset_id', and 'source'. params must be a dictionary.\n # @POST: Updates the dataset in Superset.\n # @RETURN: Dict[str, Any] - Execution status.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"execute\"):\n env_name = params.get(\"env\")\n dataset_id = params.get(\"dataset_id\")\n source = params.get(\"source\")\n\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n superset_log = log.with_source(\"superset_api\") if context else log\n db_log = log.with_source(\"postgres\") if context else log\n\n if not env_name or dataset_id is None or not source:\n log.error(\"Missing required parameters: env, dataset_id, source\")\n raise ValueError(\"Missing required parameters: env, dataset_id, source\")\n\n # Get config and initialize client\n from ..dependencies import get_config_manager\n config_manager = get_config_manager()\n env_config = config_manager.get_environment(env_name)\n if not env_config:\n log.error(f\"Environment '{env_name}' not found in configuration.\")\n raise ValueError(f\"Environment '{env_name}' not found in configuration.\")\n\n client = SupersetClient(env_config)\n client.authenticate()\n\n postgres_config = None\n if source == \"postgres\":\n connection_id = params.get(\"connection_id\")\n if not connection_id:\n log.error(\"connection_id is required for postgres source.\")\n raise ValueError(\"connection_id is required for postgres source.\")\n\n # Load connection from DB\n db = SessionLocal()\n try:\n conn_config = db.query(ConnectionConfig).filter(ConnectionConfig.id == connection_id).first()\n if not conn_config:\n db_log.error(f\"Connection {connection_id} not found.\")\n raise ValueError(f\"Connection {connection_id} not found.\")\n\n postgres_config = {\n 'dbname': conn_config.database,\n 'user': conn_config.username,\n 'password': conn_config.password,\n 'host': conn_config.host,\n 'port': str(conn_config.port) if conn_config.port else '5432'\n }\n db_log.debug(f\"Loaded connection config for {conn_config.host}:{conn_config.port}/{conn_config.database}\")\n finally:\n db.close()\n\n log.info(f\"Starting mapping for dataset {dataset_id} in {env_name}\")\n\n mapper = DatasetMapper()\n\n try:\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=source,\n postgres_config=postgres_config,\n excel_path=params.get(\"excel_path\"),\n table_name=params.get(\"table_name\"),\n table_schema=params.get(\"table_schema\") or \"public\"\n )\n superset_log.info(f\"Mapping completed for dataset {dataset_id}\")\n return {\"status\": \"success\", \"dataset_id\": dataset_id}\n except Exception as e:\n log.error(f\"Mapping failed: {e}\")\n raise\n # endregion execute\n\n# #endregion MapperPlugin\n" + "body": "# #region MapperPlugin [TYPE Class]\n# @BRIEF Plugin for mapping dataset columns verbose names.\nclass MapperPlugin(PluginBase):\n \"\"\"\n Plugin for mapping dataset columns verbose names.\n \"\"\"\n\n @property\n # region id [TYPE Function]\n # @PURPOSE: Returns the unique identifier for the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string ID.\n # @RETURN: str - \"dataset-mapper\"\n def id(self) -> str:\n with belief_scope(\"id\"):\n return \"dataset-mapper\"\n # endregion id\n\n @property\n # region name [TYPE Function]\n # @PURPOSE: Returns the human-readable name of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string name.\n # @RETURN: str - Plugin name.\n def name(self) -> str:\n with belief_scope(\"name\"):\n return \"Dataset Mapper\"\n # endregion name\n\n @property\n # region description [TYPE Function]\n # @PURPOSE: Returns a description of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string description.\n # @RETURN: str - Plugin description.\n def description(self) -> str:\n with belief_scope(\"description\"):\n return \"Map dataset column verbose names using Superset SQL Lab or Excel files.\"\n # endregion description\n\n @property\n # region version [TYPE Function]\n # @PURPOSE: Returns the version of the mapper plugin.\n # @PRE: Plugin instance exists.\n # @POST: Returns string version.\n # @RETURN: str - \"1.0.0\"\n def version(self) -> str:\n with belief_scope(\"version\"):\n return \"1.0.0\"\n # endregion version\n\n @property\n # region ui_route [TYPE Function]\n # @PURPOSE: Returns the frontend route for the mapper plugin.\n # @RETURN: str - \"/tools/mapper\"\n def ui_route(self) -> str:\n with belief_scope(\"ui_route\"):\n return \"/tools/mapper\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Returns the JSON schema for the mapper plugin parameters.\n # @PRE: Plugin instance exists.\n # @POST: Returns dictionary schema.\n # @RETURN: Dict[str, Any] - JSON schema.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"env\": {\n \"type\": \"string\",\n \"title\": \"Environment\",\n \"description\": \"The Superset environment (e.g., 'dev').\"\n },\n \"dataset_id\": {\n \"type\": \"integer\",\n \"title\": \"Dataset ID\",\n \"description\": \"The ID of the dataset to update.\"\n },\n \"source\": {\n \"type\": \"string\",\n \"title\": \"Mapping Source\",\n \"enum\": [\"sqllab\", \"excel\"],\n \"default\": \"sqllab\"\n },\n \"database_id\": {\n \"type\": \"integer\",\n \"title\": \"Superset Database ID\",\n \"description\": \"Target database ID in Superset (for sqllab source).\"\n },\n \"sql_query\": {\n \"type\": \"string\",\n \"title\": \"SQL Query\",\n \"description\": \"Custom SQL query returning column_name and verbose_name columns. Default: information_schema.columns.\",\n \"default\": \"\"\n },\n \"excel_path\": {\n \"type\": \"string\",\n \"title\": \"Excel Path\",\n \"description\": \"Path to the Excel file (for excel source).\"\n }\n },\n \"required\": [\"env\", \"dataset_id\", \"source\"]\n }\n # endregion get_schema\n\n # region execute [TYPE Function]\n # @PURPOSE: Executes the dataset mapping logic with TaskContext support.\n # @PARAM: params (Dict[str, Any]) - Mapping parameters.\n # @PARAM: context (Optional[TaskContext]) - Task context for logging with source attribution.\n # @PRE: Params contain valid 'env', 'dataset_id', and 'source'. params must be a dictionary.\n # @POST: Updates the dataset in Superset.\n # @RETURN: Dict[str, Any] - Execution status.\n async def execute(self, params: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"execute\"):\n env_name = params.get(\"env\")\n dataset_id = params.get(\"dataset_id\")\n source = params.get(\"source\")\n\n # Use TaskContext logger if available, otherwise fall back to app logger\n log = context.logger if context else logger\n\n # Create sub-loggers for different components\n superset_log = log.with_source(\"superset_api\") if context else log\n\n if not env_name or dataset_id is None or not source:\n log.error(\"Missing required parameters: env, dataset_id, source\")\n raise ValueError(\"Missing required parameters: env, dataset_id, source\")\n\n # Get config and initialize client\n from ..dependencies import get_config_manager\n config_manager = get_config_manager()\n env_config = config_manager.get_environment(env_name)\n if not env_config:\n log.error(f\"Environment '{env_name}' not found in configuration.\")\n raise ValueError(f\"Environment '{env_name}' not found in configuration.\")\n\n client = SupersetClient(env_config)\n client.authenticate()\n\n log.info(f\"Starting mapping for dataset {dataset_id} in {env_name}\")\n\n mapper = DatasetMapper()\n\n try:\n if source == \"sqllab\":\n # Use Superset SQL Lab to query database metadata\n from ..plugins.translate.superset_executor import SupersetSqlLabExecutor\n executor = SupersetSqlLabExecutor(config_manager, env_name)\n database_id = params.get(\"database_id\")\n if not database_id:\n log.error(\"database_id is required for sqllab source.\")\n raise ValueError(\"database_id is required for sqllab source.\")\n executor.resolve_database_id(target_database_id=str(database_id))\n\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=\"sqllab\",\n sqllab_executor=executor,\n database_id=database_id,\n sql_query=params.get(\"sql_query\"),\n )\n else:\n # Excel source\n mapper.run_mapping(\n superset_client=client,\n dataset_id=dataset_id,\n source=\"excel\",\n excel_path=params.get(\"excel_path\") or params.get(\"file_data\")\n )\n superset_log.info(f\"Mapping completed for dataset {dataset_id}\")\n return {\"status\": \"success\", \"dataset_id\": dataset_id}\n except Exception as e:\n log.error(f\"Mapping failed: {e}\")\n raise\n # endregion execute\n\n# #endregion MapperPlugin\n" }, { "contract_id": "MigrationPlugin", @@ -41858,6 +43140,176 @@ "tier_source": "AutoCalculated", "body": "# #region TargetSchemaValidationResponse [C:1] [TYPE Class]\n# @BRIEF Schema for target table schema validation response.\nclass TargetSchemaValidationResponse(BaseModel):\n table_exists: bool = False\n error: str | None = None\n expected_columns: list[TargetSchemaColumnInfo] = Field(default_factory=list, description=\"Columns that the INSERT expects\")\n actual_columns: list[TargetSchemaColumnInfo] = Field(default_factory=list, description=\"Columns that exist in the target table\")\n missing_columns: list[TargetSchemaColumnInfo] = Field(default_factory=list, description=\"Expected columns NOT found in target table\")\n extra_columns: list[TargetSchemaColumnInfo] = Field(default_factory=list, description=\"Actual columns NOT in expected list\")\n all_present: bool = False\n# #endregion TargetSchemaValidationResponse\n" }, + { + "contract_id": "ValidationSchemas", + "contract_type": "Module", + "file_path": "backend/src/schemas/validation.py", + "start_line": 1, + "end_line": 139, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "API", + "PURPOSE": "Pydantic v2 schemas for validation task management and run history API serialization." + }, + "relations": [ + { + "source_id": "ValidationSchemas", + "relation_type": "DEPENDS_ON", + "target_id": "pydantic", + "target_ref": "pydantic" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationSchemas [C:3] [TYPE Module] [SEMANTICS pydantic, validation, schema, task, run]\n# @BRIEF Pydantic v2 schemas for validation task management and run history API serialization.\n# @LAYER API\n# @RELATION DEPENDS_ON -> pydantic\n\nfrom datetime import datetime\nfrom typing import Any\n\nfrom pydantic import BaseModel, Field\n\n\n# #region ValidationTaskCreate [C:1] [TYPE Class]\n# @BRIEF Schema for creating a new validation task (policy).\nclass ValidationTaskCreate(BaseModel):\n name: str = Field(..., description=\"Human-readable task name\")\n environment_id: str = Field(..., description=\"Target Superset environment ID\")\n dashboard_ids: list[str] = Field(..., description=\"List of dashboard IDs to validate (use single-element array for v1)\")\n provider_id: str = Field(..., description=\"LLM provider ID — must be multimodal\")\n schedule_days: list[int] | None = Field(None, description=\"Days of week (0-6, 0=Sunday). Omit or empty for manual-only.\")\n window_start: str | None = Field(None, description=\"Window start time, HH:MM format\")\n window_end: str | None = Field(None, description=\"Window end time, HH:MM format\")\n notify_owners: bool = Field(True, description=\"Notify dashboard owners on failure\")\n custom_channels: list[str] | None = Field(None, description=\"Additional notification channels\")\n alert_condition: str = Field(\"FAIL_ONLY\", description=\"FAIL_ONLY, WARN_AND_FAIL, or ALWAYS\")\n is_active: bool = Field(True, description=\"Whether the task is active\")\n# #endregion ValidationTaskCreate\n\n\n# #region ValidationTaskUpdate [C:1] [TYPE Class]\n# @BRIEF Schema for updating an existing validation task (policy).\nclass ValidationTaskUpdate(BaseModel):\n name: str | None = None\n environment_id: str | None = None\n dashboard_ids: list[str] | None = None\n provider_id: str | None = None\n schedule_days: list[int] | None = None\n window_start: str | None = None\n window_end: str | None = None\n notify_owners: bool | None = None\n custom_channels: list[str] | None = None\n alert_condition: str | None = None\n is_active: bool | None = None\n# #endregion ValidationTaskUpdate\n\n\n# #region ValidationTaskResponse [C:1] [TYPE Class]\n# @BRIEF Schema for validation task API responses — includes last run status from join.\nclass ValidationTaskResponse(BaseModel):\n id: str\n name: str\n environment_id: str\n is_active: bool\n dashboard_ids: list[str]\n provider_id: str | None = None\n schedule_days: list[int] | None = None\n window_start: str | None = None\n window_end: str | None = None\n notify_owners: bool = True\n custom_channels: list[str] | None = None\n alert_condition: str = \"FAIL_ONLY\"\n created_at: datetime\n updated_at: datetime | None = None\n last_run_status: str | None = None\n last_run_at: datetime | None = None\n\n class Config:\n from_attributes = True\n# #endregion ValidationTaskResponse\n\n\n# #region ValidationTaskListResponse [C:1] [TYPE Class]\n# @BRIEF Schema for paginated task list response.\nclass ValidationTaskListResponse(BaseModel):\n items: list[ValidationTaskResponse] = []\n total: int = 0\n page: int = 1\n page_size: int = 20\n# #endregion ValidationTaskListResponse\n\n\n# #region ValidationRunResponse [C:1] [TYPE Class]\n# @BRIEF Schema for validation run history listing.\nclass ValidationRunResponse(BaseModel):\n id: str\n task_id: str | None = None\n dashboard_id: str\n environment_id: str | None = None\n status: str\n summary: str = \"\"\n timestamp: datetime | None = None\n screenshot_path: str | None = None\n task_name: str | None = None # resolved from ValidationPolicy at query time\n\n class Config:\n from_attributes = True\n# #endregion ValidationRunResponse\n\n\n# #region ValidationRunListResponse [C:1] [TYPE Class]\n# @BRIEF Schema for paginated run list response.\nclass ValidationRunListResponse(BaseModel):\n items: list[ValidationRunResponse] = []\n total: int = 0\n page: int = 1\n page_size: int = 20\n# #endregion ValidationRunListResponse\n\n\n# #region ValidationRunDetailResponse [C:1] [TYPE Class]\n# @BRIEF Schema for full run detail including parsed issues and raw response.\nclass ValidationRunDetailResponse(BaseModel):\n id: str\n task_id: str | None = None\n dashboard_id: str\n environment_id: str | None = None\n status: str\n summary: str = \"\"\n timestamp: datetime | None = None\n screenshot_path: str | None = None\n issues: list[dict[str, Any]] = Field(default_factory=list)\n raw_response: str | None = None\n task_name: str | None = None\n\n class Config:\n from_attributes = True\n# #endregion ValidationRunDetailResponse\n\n\n# #region TriggerRunResponse [C:1] [TYPE Class]\n# @BRIEF Schema for trigger-run response — returns spawned task ID.\nclass TriggerRunResponse(BaseModel):\n task_id: str\n spawned_task_id: str\n status: str = \"PENDING\"\n message: str = \"Validation task spawned\"\n# #endregion TriggerRunResponse\n\n\n# #endregion ValidationSchemas\n" + }, + { + "contract_id": "ValidationTaskCreate", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 12, + "end_line": 26, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for creating a new validation task (policy)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationTaskCreate [C:1] [TYPE Class]\n# @BRIEF Schema for creating a new validation task (policy).\nclass ValidationTaskCreate(BaseModel):\n name: str = Field(..., description=\"Human-readable task name\")\n environment_id: str = Field(..., description=\"Target Superset environment ID\")\n dashboard_ids: list[str] = Field(..., description=\"List of dashboard IDs to validate (use single-element array for v1)\")\n provider_id: str = Field(..., description=\"LLM provider ID — must be multimodal\")\n schedule_days: list[int] | None = Field(None, description=\"Days of week (0-6, 0=Sunday). Omit or empty for manual-only.\")\n window_start: str | None = Field(None, description=\"Window start time, HH:MM format\")\n window_end: str | None = Field(None, description=\"Window end time, HH:MM format\")\n notify_owners: bool = Field(True, description=\"Notify dashboard owners on failure\")\n custom_channels: list[str] | None = Field(None, description=\"Additional notification channels\")\n alert_condition: str = Field(\"FAIL_ONLY\", description=\"FAIL_ONLY, WARN_AND_FAIL, or ALWAYS\")\n is_active: bool = Field(True, description=\"Whether the task is active\")\n# #endregion ValidationTaskCreate\n" + }, + { + "contract_id": "ValidationTaskUpdate", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 29, + "end_line": 43, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for updating an existing validation task (policy)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationTaskUpdate [C:1] [TYPE Class]\n# @BRIEF Schema for updating an existing validation task (policy).\nclass ValidationTaskUpdate(BaseModel):\n name: str | None = None\n environment_id: str | None = None\n dashboard_ids: list[str] | None = None\n provider_id: str | None = None\n schedule_days: list[int] | None = None\n window_start: str | None = None\n window_end: str | None = None\n notify_owners: bool | None = None\n custom_channels: list[str] | None = None\n alert_condition: str | None = None\n is_active: bool | None = None\n# #endregion ValidationTaskUpdate\n" + }, + { + "contract_id": "ValidationTaskResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 46, + "end_line": 68, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for validation task API responses — includes last run status from join." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationTaskResponse [C:1] [TYPE Class]\n# @BRIEF Schema for validation task API responses — includes last run status from join.\nclass ValidationTaskResponse(BaseModel):\n id: str\n name: str\n environment_id: str\n is_active: bool\n dashboard_ids: list[str]\n provider_id: str | None = None\n schedule_days: list[int] | None = None\n window_start: str | None = None\n window_end: str | None = None\n notify_owners: bool = True\n custom_channels: list[str] | None = None\n alert_condition: str = \"FAIL_ONLY\"\n created_at: datetime\n updated_at: datetime | None = None\n last_run_status: str | None = None\n last_run_at: datetime | None = None\n\n class Config:\n from_attributes = True\n# #endregion ValidationTaskResponse\n" + }, + { + "contract_id": "ValidationTaskListResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 71, + "end_line": 78, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for paginated task list response." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationTaskListResponse [C:1] [TYPE Class]\n# @BRIEF Schema for paginated task list response.\nclass ValidationTaskListResponse(BaseModel):\n items: list[ValidationTaskResponse] = []\n total: int = 0\n page: int = 1\n page_size: int = 20\n# #endregion ValidationTaskListResponse\n" + }, + { + "contract_id": "ValidationRunResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 81, + "end_line": 96, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for validation run history listing." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationRunResponse [C:1] [TYPE Class]\n# @BRIEF Schema for validation run history listing.\nclass ValidationRunResponse(BaseModel):\n id: str\n task_id: str | None = None\n dashboard_id: str\n environment_id: str | None = None\n status: str\n summary: str = \"\"\n timestamp: datetime | None = None\n screenshot_path: str | None = None\n task_name: str | None = None # resolved from ValidationPolicy at query time\n\n class Config:\n from_attributes = True\n# #endregion ValidationRunResponse\n" + }, + { + "contract_id": "ValidationRunListResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 99, + "end_line": 106, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for paginated run list response." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationRunListResponse [C:1] [TYPE Class]\n# @BRIEF Schema for paginated run list response.\nclass ValidationRunListResponse(BaseModel):\n items: list[ValidationRunResponse] = []\n total: int = 0\n page: int = 1\n page_size: int = 20\n# #endregion ValidationRunListResponse\n" + }, + { + "contract_id": "ValidationRunDetailResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 109, + "end_line": 126, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for full run detail including parsed issues and raw response." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationRunDetailResponse [C:1] [TYPE Class]\n# @BRIEF Schema for full run detail including parsed issues and raw response.\nclass ValidationRunDetailResponse(BaseModel):\n id: str\n task_id: str | None = None\n dashboard_id: str\n environment_id: str | None = None\n status: str\n summary: str = \"\"\n timestamp: datetime | None = None\n screenshot_path: str | None = None\n issues: list[dict[str, Any]] = Field(default_factory=list)\n raw_response: str | None = None\n task_name: str | None = None\n\n class Config:\n from_attributes = True\n# #endregion ValidationRunDetailResponse\n" + }, + { + "contract_id": "TriggerRunResponse", + "contract_type": "Class", + "file_path": "backend/src/schemas/validation.py", + "start_line": 129, + "end_line": 136, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Schema for trigger-run response — returns spawned task ID." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region TriggerRunResponse [C:1] [TYPE Class]\n# @BRIEF Schema for trigger-run response — returns spawned task ID.\nclass TriggerRunResponse(BaseModel):\n task_id: str\n spawned_task_id: str\n status: str = \"PENDING\"\n message: str = \"Validation task spawned\"\n# #endregion TriggerRunResponse\n" + }, { "contract_id": "ScriptsPackage", "contract_type": "Package", @@ -50079,6 +51531,134 @@ "tier_source": "AutoCalculated", "body": " # #region _resolve_environment [C:2] [TYPE Function]\n # @BRIEF Resolve environment model from configured environments by id.\n # @PRE environment_id is provided.\n # @POST Returns environment object when found else None.\n def _resolve_environment(self, environment_id: str):\n environments = self.config_manager.get_environments()\n for env in environments:\n if str(getattr(env, \"id\", \"\")) == str(environment_id):\n return env\n return None\n # #endregion _resolve_environment\n" }, + { + "contract_id": "ValidationRunService", + "contract_type": "Module", + "file_path": "backend/src/services/validation_run_service.py", + "start_line": 1, + "end_line": 135, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "Service", + "PURPOSE": "Business logic for validation run queries: list, detail, delete." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationRunService [C:3] [TYPE Module] [SEMANTICS validation, run, service, sqlalchemy]\n# @BRIEF Business logic for validation run queries: list, detail, delete.\n# @LAYER Service\n\nfrom datetime import date\n\nfrom sqlalchemy.orm import Session\n\nfrom ..core.logger import logger\nfrom ..models.llm import ValidationPolicy, ValidationRecord\nfrom ..schemas.validation import ValidationRunDetailResponse, ValidationRunResponse\n\n\n# #region ValidationRunService [C:4] [TYPE Class]\n# @BRIEF Queries and manages validation run history records.\n# @RATIONALE Separates run history queries from task CRUD — run data has different access patterns (filter-heavy, paginated) than task configuration.\n# @REJECTED Merging run service into task service rejected — would create a large class with mixed responsibilities and different query patterns.\nclass ValidationRunService:\n\n def __init__(self, db: Session):\n self.db = db\n\n # #region _resolve_task_name [C:2] [TYPE Function]\n def _resolve_task_name(self, record: ValidationRecord) -> str | None:\n \"\"\"Find matching ValidationPolicy name by dashboard + environment.\"\"\"\n if not record.dashboard_id or not record.environment_id:\n return None\n candidates = (\n self.db.query(ValidationPolicy)\n .filter(ValidationPolicy.environment_id == record.environment_id)\n .all()\n )\n for policy in candidates:\n dids = list(policy.dashboard_ids) if policy.dashboard_ids else []\n if record.dashboard_id in dids:\n return policy.name\n return None\n\n # #endregion _resolve_task_name\n\n # #region list_runs [C:3] [TYPE Function]\n # @RATIONALE Supports 6 optional filters + pagination at the query level, enabling flexible cross-task run exploration without application-level filtering.\n # @REJECTED Application-level filtering after loading all runs rejected — would be unscalable with large run histories; database-level WHERE clauses are more efficient.\n def list_runs(\n self,\n task_id: str | None = None,\n dashboard_id: str | None = None,\n environment_id: str | None = None,\n status: str | None = None,\n date_from: date | None = None,\n date_to: date | None = None,\n page: int = 1,\n page_size: int = 20,\n ) -> tuple[int, list[ValidationRunResponse]]:\n query = self.db.query(ValidationRecord)\n\n if task_id:\n query = query.filter(ValidationRecord.task_id == task_id)\n if dashboard_id:\n query = query.filter(ValidationRecord.dashboard_id == dashboard_id)\n if environment_id:\n query = query.filter(ValidationRecord.environment_id == environment_id)\n if status:\n query = query.filter(ValidationRecord.status == status.upper())\n if date_from:\n query = query.filter(ValidationRecord.timestamp >= date_from)\n if date_to:\n query = query.filter(ValidationRecord.timestamp <= date_to)\n\n total = query.count()\n records = (\n query.order_by(ValidationRecord.timestamp.desc())\n .offset((page - 1) * page_size)\n .limit(page_size)\n .all()\n )\n\n items = [\n ValidationRunResponse(\n id=r.id,\n task_id=r.task_id,\n dashboard_id=r.dashboard_id,\n environment_id=r.environment_id,\n status=r.status,\n summary=r.summary or \"\",\n timestamp=r.timestamp,\n screenshot_path=r.screenshot_path,\n task_name=self._resolve_task_name(r),\n )\n for r in records\n ]\n return total, items\n\n # #endregion list_runs\n\n # #region get_run_detail [C:3] [TYPE Function]\n # @RATIONALE Returns full join including issues list and raw_response for the report UI — single query avoids N+1 when displaying the run detail page.\n # @REJECTED Lazy-loading issues and raw_response separately rejected — would cause N+1 queries on the detail page; both fields are always needed for the report view.\n def get_run_detail(self, run_id: str) -> ValidationRunDetailResponse:\n record = self.db.query(ValidationRecord).filter(ValidationRecord.id == run_id).first()\n if not record:\n raise ValueError(f\"Validation run '{run_id}' not found\")\n\n return ValidationRunDetailResponse(\n id=record.id,\n task_id=record.task_id,\n dashboard_id=record.dashboard_id,\n environment_id=record.environment_id,\n status=record.status,\n summary=record.summary or \"\",\n timestamp=record.timestamp,\n screenshot_path=record.screenshot_path,\n issues=list(record.issues) if record.issues else [],\n raw_response=record.raw_response,\n task_name=self._resolve_task_name(record),\n )\n\n # #endregion get_run_detail\n\n # #region delete_run [C:2] [TYPE Function]\n # @RATIONALE Cleans up the database record only — screenshot cleanup is caller responsibility to maintain separation of concerns between DB and filesystem.\n # @REJECTED Automatic screenshot file deletion in service layer rejected — would couple DB cleanup to filesystem operations, complicating testing and error handling.\n def delete_run(self, run_id: str) -> bool:\n record = self.db.query(ValidationRecord).filter(ValidationRecord.id == run_id).first()\n if not record:\n return False\n self.db.delete(record)\n self.db.commit()\n logger.info(\"[ValidationRunService] Deleted run '%s'\", run_id)\n return True\n\n # #endregion delete_run\n\n# #endregion ValidationRunService\n# #endregion ValidationRunService\n" + }, + { + "contract_id": "_resolve_task_name", + "contract_type": "Function", + "file_path": "backend/src/services/validation_run_service.py", + "start_line": 23, + "end_line": 39, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _resolve_task_name [C:2] [TYPE Function]\n def _resolve_task_name(self, record: ValidationRecord) -> str | None:\n \"\"\"Find matching ValidationPolicy name by dashboard + environment.\"\"\"\n if not record.dashboard_id or not record.environment_id:\n return None\n candidates = (\n self.db.query(ValidationPolicy)\n .filter(ValidationPolicy.environment_id == record.environment_id)\n .all()\n )\n for policy in candidates:\n dids = list(policy.dashboard_ids) if policy.dashboard_ids else []\n if record.dashboard_id in dids:\n return policy.name\n return None\n\n # #endregion _resolve_task_name\n" + }, + { + "contract_id": "ValidationService", + "contract_type": "Module", + "file_path": "backend/src/services/validation_service.py", + "start_line": 1, + "end_line": 265, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "Service", + "PURPOSE": "Business logic for validation task CRUD and trigger-run." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationService [C:3] [TYPE Module] [SEMANTICS validation, service, sqlalchemy, task]\n# @BRIEF Business logic for validation task CRUD and trigger-run.\n# @LAYER Service\n\nfrom datetime import time\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ..core.logger import logger\nfrom ..core.task_manager import TaskManager\nfrom ..models.llm import LLMProvider, ValidationPolicy, ValidationRecord\nfrom ..schemas.validation import ValidationTaskCreate, ValidationTaskResponse, ValidationTaskUpdate\nfrom .llm_provider import LLMProviderService\n\n\ndef _parse_time(value: str | None) -> time | None:\n \"\"\"Parse HH:MM string to datetime.time, or return None.\"\"\"\n if not value:\n return None\n try:\n parts = value.strip().split(\":\")\n return time(int(parts[0]), int(parts[1]))\n except (ValueError, IndexError):\n return None\n\n\ndef _format_time(value: time | None) -> str | None:\n \"\"\"Format datetime.time to HH:MM string, or return None.\"\"\"\n if value is None:\n return None\n return f\"{value.hour:02d}:{value.minute:02d}\"\n\n\n# #region ValidationTaskService [C:4] [TYPE Class]\n# @BRIEF Validation task (policy) CRUD with provider validation and trigger-run.\n# @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.\n# @REJECTED Embedding CRUD in route handlers rejected — would duplicate validation logic across endpoints; centralized service ensures consistent provider/environment validation before persistence.\nclass ValidationTaskService:\n\n def __init__(self, db: Session, config_manager=None, username: str | None = None):\n self.db = db\n self.config_manager = config_manager\n self.username = username or \"system\"\n\n # #region _validate_provider [C:2] [TYPE Function]\n # @RATIONALE Centralizes multimodal LLM provider check so all task operations (create, update, trigger) share the same validation gate. Uses LLMProviderService for reuse.\n # @REJECTED Duplicating multimodal check in each caller rejected — would create maintenance burden if provider validation rules change or error messages need updating.\n def _validate_provider(self, provider_id: str) -> LLMProvider:\n if not provider_id or not provider_id.strip():\n raise ValueError(\"provider_id is required\")\n svc = LLMProviderService(self.db)\n provider = svc.get_provider(provider_id)\n if not provider:\n raise ValueError(f\"LLM provider '{provider_id}' not found\")\n if not bool(provider.is_multimodal):\n raise ValueError(\n f\"LLM provider '{provider.name}' is not multimodal. \"\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n return provider\n\n # #endregion _validate_provider\n\n # #region _validate_environment [C:1] [TYPE Function]\n def _validate_environment(self, environment_id: str) -> None:\n if not self.config_manager:\n return\n env = self.config_manager.get_environment(environment_id)\n if not env:\n raise ValueError(f\"Environment '{environment_id}' not found\")\n\n # #endregion _validate_environment\n\n # #region _policy_to_response [C:2] [TYPE Function]\n def _policy_to_response(self, policy: ValidationPolicy) -> ValidationTaskResponse:\n last_run = None\n if policy.dashboard_ids:\n last_run = (\n self.db.query(ValidationRecord)\n .filter(\n ValidationRecord.dashboard_id.in_(policy.dashboard_ids),\n ValidationRecord.environment_id == policy.environment_id,\n )\n .order_by(ValidationRecord.timestamp.desc())\n .first()\n )\n return ValidationTaskResponse(\n id=policy.id,\n name=policy.name,\n environment_id=policy.environment_id,\n is_active=bool(policy.is_active) if policy.is_active is not None else True,\n dashboard_ids=list(policy.dashboard_ids) if policy.dashboard_ids else [],\n provider_id=policy.provider_id,\n schedule_days=list(policy.schedule_days) if policy.schedule_days else None,\n window_start=_format_time(policy.window_start),\n window_end=_format_time(policy.window_end),\n notify_owners=bool(policy.notify_owners) if policy.notify_owners is not None else True,\n custom_channels=list(policy.custom_channels) if policy.custom_channels else None,\n alert_condition=policy.alert_condition or \"FAIL_ONLY\",\n created_at=policy.created_at,\n updated_at=policy.updated_at,\n last_run_status=str(last_run.status) if last_run else None,\n last_run_at=last_run.timestamp if last_run else None,\n )\n\n # #endregion _policy_to_response\n\n # #region list_tasks [C:3] [TYPE Function]\n # @RATIONALE Uses query-time filtering with optional is_active/environment_id params rather than post-filtering results in memory, reducing overhead with large task counts.\n # @REJECTED In-memory filtering after loading all rows rejected — would be inefficient with hundreds of tasks; database-level filtering scales better.\n def list_tasks(\n self,\n is_active: bool | None = None,\n environment_id: str | None = None,\n page: int = 1,\n page_size: int = 20,\n ) -> tuple[int, list[ValidationTaskResponse]]:\n query = self.db.query(ValidationPolicy)\n if is_active is not None:\n query = query.filter(ValidationPolicy.is_active == is_active)\n if environment_id:\n query = query.filter(ValidationPolicy.environment_id == environment_id)\n\n total = query.count()\n policies = (\n query.order_by(ValidationPolicy.created_at.desc())\n .offset((page - 1) * page_size)\n .limit(page_size)\n .all()\n )\n return total, [self._policy_to_response(p) for p in policies]\n\n # #endregion list_tasks\n\n # #region create_task [C:4] [TYPE Function]\n # @RATIONALE Validates provider (multimodal check) and environment before persisting the policy, ensuring referential integrity at creation time and preventing silent runtime failures.\n # @REJECTED Lazy validation on first run rejected — would allow creation of invalid task configurations with non-multimodal providers that fail only at runtime during dashboard validation.\n def create_task(self, payload: ValidationTaskCreate) -> ValidationTaskResponse:\n self._validate_provider(payload.provider_id)\n self._validate_environment(payload.environment_id)\n\n ws = _parse_time(payload.window_start)\n we = _parse_time(payload.window_end)\n\n policy = ValidationPolicy(\n name=payload.name,\n environment_id=payload.environment_id,\n is_active=payload.is_active,\n dashboard_ids=payload.dashboard_ids or [],\n provider_id=payload.provider_id,\n schedule_days=payload.schedule_days or [],\n window_start=ws or time(9, 0),\n window_end=we or time(18, 0),\n notify_owners=payload.notify_owners,\n custom_channels=payload.custom_channels,\n alert_condition=payload.alert_condition or \"FAIL_ONLY\",\n )\n self.db.add(policy)\n self.db.commit()\n self.db.refresh(policy)\n logger.info(\n \"[ValidationTaskService] Created task '%s' (id=%s)\", policy.name, policy.id\n )\n return self._policy_to_response(policy)\n\n # #endregion create_task\n\n # #region get_task [C:3] [TYPE Function]\n # @RATIONALE Returns full task response including last_run_status via joined subquery — gives the UI immediate visibility into task health without a second API call.\n # @REJECTED Separate query for last run status rejected — double-query pattern would add latency on every task detail request.\n def get_task(self, task_id: str) -> ValidationTaskResponse:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n return self._policy_to_response(policy)\n\n # #endregion get_task\n\n # #region update_task [C:4] [TYPE Function]\n # @RATIONALE Re-validates provider/environment only when those fields change (via exclude_unset), avoiding unnecessary DB calls on partial updates and allowing other fields to be updated independently.\n # @REJECTED Full re-validation on every update rejected — would prevent updating non-critical fields (e.g., schedule, name) when a provider is temporarily unavailable.\n def update_task(self, task_id: str, payload: ValidationTaskUpdate) -> ValidationTaskResponse:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n\n update_data = payload.model_dump(exclude_unset=True)\n\n if \"provider_id\" in update_data and update_data[\"provider_id\"]:\n self._validate_provider(update_data[\"provider_id\"])\n if \"environment_id\" in update_data and update_data[\"environment_id\"]:\n self._validate_environment(update_data[\"environment_id\"])\n\n if \"window_start\" in update_data:\n ws = _parse_time(update_data.pop(\"window_start\", None))\n if ws is not None:\n policy.window_start = ws\n if \"window_end\" in update_data:\n we = _parse_time(update_data.pop(\"window_end\", None))\n if we is not None:\n policy.window_end = we\n\n for key, value in update_data.items():\n if hasattr(policy, key):\n setattr(policy, key, value)\n\n self.db.commit()\n self.db.refresh(policy)\n logger.info(\"[ValidationTaskService] Updated task '%s' (id=%s)\", policy.name, policy.id)\n return self._policy_to_response(policy)\n\n # #endregion update_task\n\n # #region delete_task [C:3] [TYPE Function]\n# @RATIONALE Scope run deletion by policy_id instead of dashboard_id+environment_id to prevent deleting runs belonging to other tasks that validate the same dashboard. Requires policy_id column on ValidationRecord, set by the plugin during execution.\n# @REJECTED Always-cascade delete rejected – would destroy run history unexpectedly. Scoping by dashboard_id+environment_id rejected – caused cross-task data loss (F4). Explicit delete_runs flag with policy_id scoping gives users safe control.\n\n def delete_task(self, task_id: str, delete_runs: bool = False) -> None:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n\n if delete_runs:\n self.db.query(ValidationRecord).filter(\n ValidationRecord.policy_id == policy.id,\n ).delete(synchronize_session=False)\n\n self.db.delete(policy)\n self.db.commit()\n logger.info(\n \"[ValidationTaskService] Deleted task '%s' (id=%s)\", policy.name, policy.id\n )\n\n # #endregion delete_task\n # #region trigger_run [C:4] [TYPE Function]\n # @RATIONALE Uses TaskManager.create_task() to spawn validation via the llm_dashboard_validation plugin — reuses existing scheduling, persistence, retry, and notification infrastructure.\n # @REJECTED Direct LLM provider call from service layer rejected — would bypass TaskManager's persistence, retry logic, logging pipeline, and WebSocket notifications.\n async def trigger_run(self, task_id: str, task_manager: TaskManager) -> str:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n if not policy.dashboard_ids:\n raise ValueError(f\"Validation task '{task_id}' has no dashboard IDs configured\")\n if policy.provider_id:\n self._validate_provider(policy.provider_id)\n\n dashboard_id = policy.dashboard_ids[0]\n params: dict[str, Any] = {\n \"dashboard_id\": dashboard_id,\n \"environment_id\": policy.environment_id,\n \"provider_id\": policy.provider_id or \"\",\n \"policy_id\": task_id,\n }\n task = await task_manager.create_task(plugin_id=\"llm_dashboard_validation\", params=params)\n logger.info(\n \"[ValidationTaskService] Triggered run for task '%s' dashboard=%s spawned=%s\",\n policy.name, dashboard_id, task.id,\n )\n return task.id\n\n # #endregion trigger_run\n\n# #endregion ValidationTaskService\n# #endregion ValidationService\n" + }, + { + "contract_id": "ValidationTaskService", + "contract_type": "Class", + "file_path": "backend/src/services/validation_service.py", + "start_line": 35, + "end_line": 264, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "Validation task (policy) CRUD with provider validation and trigger-run.", + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ValidationTaskService [C:4] [TYPE Class]\n# @BRIEF Validation task (policy) CRUD with provider validation and trigger-run.\n# @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.\n# @REJECTED Embedding CRUD in route handlers rejected — would duplicate validation logic across endpoints; centralized service ensures consistent provider/environment validation before persistence.\nclass ValidationTaskService:\n\n def __init__(self, db: Session, config_manager=None, username: str | None = None):\n self.db = db\n self.config_manager = config_manager\n self.username = username or \"system\"\n\n # #region _validate_provider [C:2] [TYPE Function]\n # @RATIONALE Centralizes multimodal LLM provider check so all task operations (create, update, trigger) share the same validation gate. Uses LLMProviderService for reuse.\n # @REJECTED Duplicating multimodal check in each caller rejected — would create maintenance burden if provider validation rules change or error messages need updating.\n def _validate_provider(self, provider_id: str) -> LLMProvider:\n if not provider_id or not provider_id.strip():\n raise ValueError(\"provider_id is required\")\n svc = LLMProviderService(self.db)\n provider = svc.get_provider(provider_id)\n if not provider:\n raise ValueError(f\"LLM provider '{provider_id}' not found\")\n if not bool(provider.is_multimodal):\n raise ValueError(\n f\"LLM provider '{provider.name}' is not multimodal. \"\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n return provider\n\n # #endregion _validate_provider\n\n # #region _validate_environment [C:1] [TYPE Function]\n def _validate_environment(self, environment_id: str) -> None:\n if not self.config_manager:\n return\n env = self.config_manager.get_environment(environment_id)\n if not env:\n raise ValueError(f\"Environment '{environment_id}' not found\")\n\n # #endregion _validate_environment\n\n # #region _policy_to_response [C:2] [TYPE Function]\n def _policy_to_response(self, policy: ValidationPolicy) -> ValidationTaskResponse:\n last_run = None\n if policy.dashboard_ids:\n last_run = (\n self.db.query(ValidationRecord)\n .filter(\n ValidationRecord.dashboard_id.in_(policy.dashboard_ids),\n ValidationRecord.environment_id == policy.environment_id,\n )\n .order_by(ValidationRecord.timestamp.desc())\n .first()\n )\n return ValidationTaskResponse(\n id=policy.id,\n name=policy.name,\n environment_id=policy.environment_id,\n is_active=bool(policy.is_active) if policy.is_active is not None else True,\n dashboard_ids=list(policy.dashboard_ids) if policy.dashboard_ids else [],\n provider_id=policy.provider_id,\n schedule_days=list(policy.schedule_days) if policy.schedule_days else None,\n window_start=_format_time(policy.window_start),\n window_end=_format_time(policy.window_end),\n notify_owners=bool(policy.notify_owners) if policy.notify_owners is not None else True,\n custom_channels=list(policy.custom_channels) if policy.custom_channels else None,\n alert_condition=policy.alert_condition or \"FAIL_ONLY\",\n created_at=policy.created_at,\n updated_at=policy.updated_at,\n last_run_status=str(last_run.status) if last_run else None,\n last_run_at=last_run.timestamp if last_run else None,\n )\n\n # #endregion _policy_to_response\n\n # #region list_tasks [C:3] [TYPE Function]\n # @RATIONALE Uses query-time filtering with optional is_active/environment_id params rather than post-filtering results in memory, reducing overhead with large task counts.\n # @REJECTED In-memory filtering after loading all rows rejected — would be inefficient with hundreds of tasks; database-level filtering scales better.\n def list_tasks(\n self,\n is_active: bool | None = None,\n environment_id: str | None = None,\n page: int = 1,\n page_size: int = 20,\n ) -> tuple[int, list[ValidationTaskResponse]]:\n query = self.db.query(ValidationPolicy)\n if is_active is not None:\n query = query.filter(ValidationPolicy.is_active == is_active)\n if environment_id:\n query = query.filter(ValidationPolicy.environment_id == environment_id)\n\n total = query.count()\n policies = (\n query.order_by(ValidationPolicy.created_at.desc())\n .offset((page - 1) * page_size)\n .limit(page_size)\n .all()\n )\n return total, [self._policy_to_response(p) for p in policies]\n\n # #endregion list_tasks\n\n # #region create_task [C:4] [TYPE Function]\n # @RATIONALE Validates provider (multimodal check) and environment before persisting the policy, ensuring referential integrity at creation time and preventing silent runtime failures.\n # @REJECTED Lazy validation on first run rejected — would allow creation of invalid task configurations with non-multimodal providers that fail only at runtime during dashboard validation.\n def create_task(self, payload: ValidationTaskCreate) -> ValidationTaskResponse:\n self._validate_provider(payload.provider_id)\n self._validate_environment(payload.environment_id)\n\n ws = _parse_time(payload.window_start)\n we = _parse_time(payload.window_end)\n\n policy = ValidationPolicy(\n name=payload.name,\n environment_id=payload.environment_id,\n is_active=payload.is_active,\n dashboard_ids=payload.dashboard_ids or [],\n provider_id=payload.provider_id,\n schedule_days=payload.schedule_days or [],\n window_start=ws or time(9, 0),\n window_end=we or time(18, 0),\n notify_owners=payload.notify_owners,\n custom_channels=payload.custom_channels,\n alert_condition=payload.alert_condition or \"FAIL_ONLY\",\n )\n self.db.add(policy)\n self.db.commit()\n self.db.refresh(policy)\n logger.info(\n \"[ValidationTaskService] Created task '%s' (id=%s)\", policy.name, policy.id\n )\n return self._policy_to_response(policy)\n\n # #endregion create_task\n\n # #region get_task [C:3] [TYPE Function]\n # @RATIONALE Returns full task response including last_run_status via joined subquery — gives the UI immediate visibility into task health without a second API call.\n # @REJECTED Separate query for last run status rejected — double-query pattern would add latency on every task detail request.\n def get_task(self, task_id: str) -> ValidationTaskResponse:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n return self._policy_to_response(policy)\n\n # #endregion get_task\n\n # #region update_task [C:4] [TYPE Function]\n # @RATIONALE Re-validates provider/environment only when those fields change (via exclude_unset), avoiding unnecessary DB calls on partial updates and allowing other fields to be updated independently.\n # @REJECTED Full re-validation on every update rejected — would prevent updating non-critical fields (e.g., schedule, name) when a provider is temporarily unavailable.\n def update_task(self, task_id: str, payload: ValidationTaskUpdate) -> ValidationTaskResponse:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n\n update_data = payload.model_dump(exclude_unset=True)\n\n if \"provider_id\" in update_data and update_data[\"provider_id\"]:\n self._validate_provider(update_data[\"provider_id\"])\n if \"environment_id\" in update_data and update_data[\"environment_id\"]:\n self._validate_environment(update_data[\"environment_id\"])\n\n if \"window_start\" in update_data:\n ws = _parse_time(update_data.pop(\"window_start\", None))\n if ws is not None:\n policy.window_start = ws\n if \"window_end\" in update_data:\n we = _parse_time(update_data.pop(\"window_end\", None))\n if we is not None:\n policy.window_end = we\n\n for key, value in update_data.items():\n if hasattr(policy, key):\n setattr(policy, key, value)\n\n self.db.commit()\n self.db.refresh(policy)\n logger.info(\"[ValidationTaskService] Updated task '%s' (id=%s)\", policy.name, policy.id)\n return self._policy_to_response(policy)\n\n # #endregion update_task\n\n # #region delete_task [C:3] [TYPE Function]\n# @RATIONALE Scope run deletion by policy_id instead of dashboard_id+environment_id to prevent deleting runs belonging to other tasks that validate the same dashboard. Requires policy_id column on ValidationRecord, set by the plugin during execution.\n# @REJECTED Always-cascade delete rejected – would destroy run history unexpectedly. Scoping by dashboard_id+environment_id rejected – caused cross-task data loss (F4). Explicit delete_runs flag with policy_id scoping gives users safe control.\n\n def delete_task(self, task_id: str, delete_runs: bool = False) -> None:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n\n if delete_runs:\n self.db.query(ValidationRecord).filter(\n ValidationRecord.policy_id == policy.id,\n ).delete(synchronize_session=False)\n\n self.db.delete(policy)\n self.db.commit()\n logger.info(\n \"[ValidationTaskService] Deleted task '%s' (id=%s)\", policy.name, policy.id\n )\n\n # #endregion delete_task\n # #region trigger_run [C:4] [TYPE Function]\n # @RATIONALE Uses TaskManager.create_task() to spawn validation via the llm_dashboard_validation plugin — reuses existing scheduling, persistence, retry, and notification infrastructure.\n # @REJECTED Direct LLM provider call from service layer rejected — would bypass TaskManager's persistence, retry logic, logging pipeline, and WebSocket notifications.\n async def trigger_run(self, task_id: str, task_manager: TaskManager) -> str:\n policy = self.db.query(ValidationPolicy).filter(ValidationPolicy.id == task_id).first()\n if not policy:\n raise ValueError(f\"Validation task '{task_id}' not found\")\n if not policy.dashboard_ids:\n raise ValueError(f\"Validation task '{task_id}' has no dashboard IDs configured\")\n if policy.provider_id:\n self._validate_provider(policy.provider_id)\n\n dashboard_id = policy.dashboard_ids[0]\n params: dict[str, Any] = {\n \"dashboard_id\": dashboard_id,\n \"environment_id\": policy.environment_id,\n \"provider_id\": policy.provider_id or \"\",\n \"policy_id\": task_id,\n }\n task = await task_manager.create_task(plugin_id=\"llm_dashboard_validation\", params=params)\n logger.info(\n \"[ValidationTaskService] Triggered run for task '%s' dashboard=%s spawned=%s\",\n policy.name, dashboard_id, task.id,\n )\n return task.id\n\n # #endregion trigger_run\n\n# #endregion ValidationTaskService\n" + }, + { + "contract_id": "_validate_provider", + "contract_type": "Function", + "file_path": "backend/src/services/validation_service.py", + "start_line": 46, + "end_line": 63, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "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." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _validate_provider [C:2] [TYPE Function]\n # @RATIONALE Centralizes multimodal LLM provider check so all task operations (create, update, trigger) share the same validation gate. Uses LLMProviderService for reuse.\n # @REJECTED Duplicating multimodal check in each caller rejected — would create maintenance burden if provider validation rules change or error messages need updating.\n def _validate_provider(self, provider_id: str) -> LLMProvider:\n if not provider_id or not provider_id.strip():\n raise ValueError(\"provider_id is required\")\n svc = LLMProviderService(self.db)\n provider = svc.get_provider(provider_id)\n if not provider:\n raise ValueError(f\"LLM provider '{provider_id}' not found\")\n if not bool(provider.is_multimodal):\n raise ValueError(\n f\"LLM provider '{provider.name}' is not multimodal. \"\n \"Dashboard validation requires a multimodal model (image input support).\"\n )\n return provider\n\n # #endregion _validate_provider\n" + }, + { + "contract_id": "_validate_environment", + "contract_type": "Function", + "file_path": "backend/src/services/validation_service.py", + "start_line": 65, + "end_line": 73, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _validate_environment [C:1] [TYPE Function]\n def _validate_environment(self, environment_id: str) -> None:\n if not self.config_manager:\n return\n env = self.config_manager.get_environment(environment_id)\n if not env:\n raise ValueError(f\"Environment '{environment_id}' not found\")\n\n # #endregion _validate_environment\n" + }, + { + "contract_id": "_policy_to_response", + "contract_type": "Function", + "file_path": "backend/src/services/validation_service.py", + "start_line": 75, + "end_line": 107, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _policy_to_response [C:2] [TYPE Function]\n def _policy_to_response(self, policy: ValidationPolicy) -> ValidationTaskResponse:\n last_run = None\n if policy.dashboard_ids:\n last_run = (\n self.db.query(ValidationRecord)\n .filter(\n ValidationRecord.dashboard_id.in_(policy.dashboard_ids),\n ValidationRecord.environment_id == policy.environment_id,\n )\n .order_by(ValidationRecord.timestamp.desc())\n .first()\n )\n return ValidationTaskResponse(\n id=policy.id,\n name=policy.name,\n environment_id=policy.environment_id,\n is_active=bool(policy.is_active) if policy.is_active is not None else True,\n dashboard_ids=list(policy.dashboard_ids) if policy.dashboard_ids else [],\n provider_id=policy.provider_id,\n schedule_days=list(policy.schedule_days) if policy.schedule_days else None,\n window_start=_format_time(policy.window_start),\n window_end=_format_time(policy.window_end),\n notify_owners=bool(policy.notify_owners) if policy.notify_owners is not None else True,\n custom_channels=list(policy.custom_channels) if policy.custom_channels else None,\n alert_condition=policy.alert_condition or \"FAIL_ONLY\",\n created_at=policy.created_at,\n updated_at=policy.updated_at,\n last_run_status=str(last_run.status) if last_run else None,\n last_run_at=last_run.timestamp if last_run else None,\n )\n\n # #endregion _policy_to_response\n" + }, { "contract_id": "TestSessionConfig", "contract_type": "Module", @@ -50105,7 +51685,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TestSessionConfig [C:2] [TYPE Module] [SEMANTICS test, conftest, db]\n# @BRIEF Shared pytest fixtures and session configuration for backend tests.\n# @RELATION BINDS_TO -> [init_db]\n# @PRE All test modules use sys.path patching to import from src/.\n# @POST Database tables exist before test session executes.\n# @RATIONALE AUTH_SECRET_KEY/AUTH_DATABASE_URL/DATABASE_URL/DEV_MODE must be set before\n# any project import because src.core.auth.config creates an AuthConfig()\n# singleton at module level that crashes without these env vars (crash-early fix).\nimport os\nimport sys\nfrom pathlib import Path\n\n# Set env defaults for module-level AuthConfig() singleton — crash-early fix\nos.environ.setdefault(\"AUTH_SECRET_KEY\", \"test-secret-key-for-testing\")\nos.environ.setdefault(\"AUTH_DATABASE_URL\", \"sqlite:///:memory:test_auth\")\nos.environ.setdefault(\"DATABASE_URL\", \"sqlite:///:memory:test_main\")\nos.environ.setdefault(\"DEV_MODE\", \"true\")\n\nsys.path.insert(0, str(Path(__file__).parent.parent / \"src\"))\n\nimport pytest\n\n\n@pytest.fixture(scope=\"session\", autouse=True)\ndef ensure_db_tables():\n \"\"\"Ensure all tables exist before test session.\n\n This fixture runs once per test session, creating all registered\n SQLAlchemy tables. Individual test modules may also create their\n own in-memory engines — this guarantees the real engine schema\n is initialized for tests that depend on it.\n\n NOTE: src.core.database may fail to import due to a pydantic-settings v2\n compatibility issue with the deprecated Field(env=...) parameter in AuthConfig.\n Tests that need the database import it directly and manage the env themselves.\n \"\"\"\n try:\n from src.core.database import init_db\n init_db()\n except Exception:\n pass # Graceful degradation — tests requiring DB manage env themselves\n# #endregion TestSessionConfig\n" + "body": "# #region TestSessionConfig [C:2] [TYPE Module] [SEMANTICS test, conftest, db]\n# @BRIEF Shared pytest fixtures and session configuration for backend tests.\n# @RELATION BINDS_TO -> [init_db]\n# @PRE All test modules use sys.path patching to import from src/.\n# @POST Database tables exist before test session executes.\n# @RATIONALE AUTH_SECRET_KEY/AUTH_DATABASE_URL/DATABASE_URL/DEV_MODE must be set before\n# any project import because src.core.auth.config creates an AuthConfig()\n# singleton at module level that crashes without these env vars (crash-early fix).\nimport os\nimport sys\nfrom pathlib import Path\n\n# Set env defaults for module-level AuthConfig() singleton — crash-early fix\nos.environ.setdefault(\"SECRET_KEY\", \"test-secret-key-for-testing\")\nos.environ.setdefault(\"AUTH_DATABASE_URL\", \"sqlite:///:memory:test_auth\")\nos.environ.setdefault(\"DATABASE_URL\", \"sqlite:///:memory:test_main\")\nos.environ.setdefault(\"DEV_MODE\", \"true\")\n\nsys.path.insert(0, str(Path(__file__).parent.parent / \"src\"))\n\nimport pytest\n\n\n@pytest.fixture(scope=\"session\", autouse=True)\ndef ensure_db_tables():\n \"\"\"Ensure all tables exist before test session.\n\n This fixture runs once per test session, creating all registered\n SQLAlchemy tables. Individual test modules may also create their\n own in-memory engines — this guarantees the real engine schema\n is initialized for tests that depend on it.\n\n NOTE: src.core.database may fail to import due to a pydantic-settings v2\n compatibility issue with the deprecated Field(env=...) parameter in AuthConfig.\n Tests that need the database import it directly and manage the env themselves.\n \"\"\"\n try:\n from src.core.database import init_db\n init_db()\n except Exception:\n pass # Graceful degradation — tests requiring DB manage env themselves\n# #endregion TestSessionConfig\n" }, { "contract_id": "TestArchiveParser", @@ -62630,7 +64210,7 @@ "contract_type": "Component", "file_path": "frontend/src/components/Navbar.svelte", "start_line": 1, - "end_line": 90, + "end_line": 89, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -62716,7 +64296,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n
\n \n Superset Tools\n \n \n
\n\n" + "body": "\n\n\n\n\n\n
\n \n Superset Tools\n \n \n
\n\n" }, { "contract_id": "PasswordPrompt", @@ -65328,104 +66908,6 @@ "tier_source": "AutoCalculated", "body": "\n\n\n\n\n\n\n\n{#if !task}\n
\n {$t.tasks?.result_select_task}\n
\n{:else if !result}\n
\n

{$t.tasks?.result_not_structured}

\n
\n{:else if pluginId === 'llm_dashboard_validation'}\n
\n
\n

{$t.tasks?.result_llm_validation}

\n {result.status || 'UNKNOWN'}\n
\n

{result.summary || $t.tasks?.result_no_summary}

\n {#if result.issues?.length}\n
\n

{$t.tasks?.issues} ({result.issues.length})

\n
    \n {#each result.issues as issue}\n
  • \n
    \n {issue.severity}\n {issue.message}\n
    \n {#if issue.location}\n

    {$t.tasks?.location}: {issue.location}

    \n {/if}\n
  • \n {/each}\n
\n
\n {/if}\n
\n{:else if pluginId === 'superset-backup'}\n
\n
\n

{$t.tasks?.backup_result}

\n {result.status || 'UNKNOWN'}\n
\n
\n

{$t.dashboard?.environment}: {result.environment || $t.common?.not_available}

\n

{$t.tasks?.total}: {result.total_dashboards ?? 0}

\n

{$t.tasks?.successful}: {result.backed_up_dashboards ?? 0}

\n

{$t.tasks?.failed}: {result.failed_dashboards ?? 0}

\n
\n {#if result.failures?.length}\n
\n

{$t.tasks?.errors}

\n
    \n {#each result.failures as failure}\n
  • \n {failure.title || failure.id}: {failure.error}\n
  • \n {/each}\n
\n
\n {/if}\n
\n{:else if pluginId === 'superset-migration'}\n
\n
\n

{$t.tasks?.migration_result}

\n {result.status || 'UNKNOWN'}\n
\n
\n

{$t.migration?.source_env}: {result.source_environment || $t.common?.not_available}

\n

{$t.migration?.target_env}: {result.target_environment || $t.common?.not_available}

\n

{$t.tasks?.selected}: {result.selected_dashboards ?? 0}

\n

{$t.tasks?.successful}: {result.migrated_dashboards?.length ?? 0}

\n

{$t.tasks?.with_errors}: {result.failed_dashboards?.length ?? 0}

\n

{$t.tasks?.mappings}: {result.mapping_count ?? 0}

\n
\n {#if result.failed_dashboards?.length}\n
\n

{$t.tasks?.migration_errors}

\n
    \n {#each result.failed_dashboards as failed}\n
  • \n {failed.title || failed.id}: {failed.error}\n
  • \n {/each}\n
\n
\n {/if}\n
\n{:else}\n
\n
{JSON.stringify(result, null, 2)}
\n
\n{/if}\n\n\n" }, - { - "contract_id": "ConnectionList", - "contract_type": "Component", - "file_path": "frontend/src/components/tools/ConnectionList.svelte", - "start_line": 1, - "end_line": 88, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "LAYER": "UI", - "PURPOSE": "UI component for listing and deleting saved database connection configurations.", - "SEMANTICS": [ - "connection", - "list", - "settings" - ] - }, - "relations": [ - { - "source_id": "ConnectionList", - "relation_type": "USES", - "target_id": "frontend/src/services/connectionService.js", - "target_ref": "frontend/src/services/connectionService.js" - } - ], - "schema_warnings": [ - { - "code": "tag_not_for_contract_type", - "tag": "LAYER", - "message": "@LAYER is not allowed for contract type 'Component'", - "detail": { - "actual_type": "Component", - "allowed_types": [ - "Module", - "Skill", - "Agent" - ] - } - }, - { - "code": "tag_forbidden_by_complexity", - "tag": "LAYER", - "message": "@LAYER is forbidden for contract type 'Component' at C3", - "detail": { - "actual_complexity": 3, - "contract_type": "Component" - } - }, - { - "code": "tag_not_for_contract_type", - "tag": "SEMANTICS", - "message": "@SEMANTICS is not allowed for contract type 'Component'", - "detail": { - "actual_type": "Component", - "allowed_types": [ - "Module", - "Function", - "Class", - "Block", - "Skill", - "Agent" - ] - } - }, - { - "code": "tag_forbidden_by_complexity", - "tag": "SEMANTICS", - "message": "@SEMANTICS is forbidden for contract type 'Component' at C3", - "detail": { - "actual_complexity": 3, - "contract_type": "Component" - } - } - ], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n \n\n\n\n" - }, - { - "contract_id": "fetchConnections:Function", - "contract_type": "Function", - "file_path": "frontend/src/components/tools/ConnectionList.svelte", - "start_line": 22, - "end_line": 36, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "POST": "connections array is populated.", - "PRE": "None.", - "PURPOSE": "Fetches the list of connections from the backend." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": " // #region fetchConnections:Function [TYPE Function]\n // @PURPOSE: Fetches the list of connections from the backend.\n // @PRE: None.\n // @POST: connections array is populated.\n async function fetchConnections() {\n isLoading = true;\n try {\n connections = await getConnections();\n } catch (e) {\n addToast($t.connections?.fetch_failed, 'error');\n } finally {\n isLoading = false;\n }\n }\n // #endregion fetchConnections:Function\n" - }, { "contract_id": "handleRunDebug:Function", "contract_type": "Function", @@ -65492,18 +66974,18 @@ "contract_type": "Component", "file_path": "frontend/src/components/tools/MapperTool.svelte", "start_line": 1, - "end_line": 252, + "end_line": 236, "tier": "TIER_2", "complexity": 3, "metadata": { "COMPLEXITY": 3, "LAYER": "UI", - "PURPOSE": "UI component for mapping dataset column verbose names using the MapperPlugin.", + "PURPOSE": "UI component for mapping dataset column verbose names using Superset SQL Lab or Excel files.", "SEMANTICS": [ "mapper", "tool", "dataset", - "postgresql", + "sqllab", "excel" ] }, @@ -65513,12 +66995,6 @@ "relation_type": "USES", "target_id": "frontend/src/services/toolsService.js", "target_ref": "frontend/src/services/toolsService.js" - }, - { - "source_id": "MapperTool", - "relation_type": "USES", - "target_id": "frontend/src/services/connectionService.js", - "target_ref": "frontend/src/services/connectionService.js" } ], "schema_warnings": [ @@ -65572,52 +67048,52 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n
\n \n
\n
\n
\n ({ value: e.id, label: e.name }))\n ]}\n />\n
\n
\n \n
\n
\n\n
\n {$t.mapper.source}\n
\n \n \n
\n
\n\n {#if source === 'postgres'}\n
\n
\n ({ value: c.id, label: c.name }))\n ]}\n />\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n {:else}\n
\n \n
\n {/if}\n\n
\n \n {#if isGeneratingDocs}\n {$t.mapper?.generating}\n {:else}\n {$t.datasets?.generate_docs}\n {/if}\n \n \n {isRunning ? $t.mapper.starting : $t.mapper.run}\n \n
\n
\n
\n\n generatedDoc = null}\n onSave={handleApplyDoc}\n />\n
\n\n\n" + "body": "\n\n\n\n\n\n\n
\n \n
\n
\n
\n ({ value: e.id, label: e.name }))\n ]}\n />\n
\n
\n \n
\n
\n\n
\n {$t.mapper.source}\n
\n \n \n
\n
\n\n {#if source === 'sqllab'}\n
\n
\n \n
\n
\n \n
\n
\n {:else}\n
\n \n
\n {/if}\n\n
\n \n {#if isGeneratingDocs}\n {$t.mapper?.generating}\n {:else}\n {$t.datasets?.generate_docs}\n {/if}\n \n \n {isRunning ? $t.mapper.starting : $t.mapper.run}\n \n
\n
\n
\n\n generatedDoc = null}\n onSave={handleApplyDoc}\n />\n
\n\n\n" }, { "contract_id": "fetchData:Function", "contract_type": "Function", "file_path": "frontend/src/components/tools/MapperTool.svelte", - "start_line": 37, - "end_line": 49, + "start_line": 33, + "end_line": 44, "tier": "TIER_1", "complexity": 1, "metadata": { - "POST": "envs and connections arrays are populated.", + "POST": "envs array is populated.", "PRE": "None.", - "PURPOSE": "Fetches environments and saved connections." + "PURPOSE": "Fetches environments." }, "relations": [], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region fetchData:Function [TYPE Function]\n // @PURPOSE: Fetches environments and saved connections.\n // @PRE: None.\n // @POST: envs and connections arrays are populated.\n async function fetchData() {\n try {\n envs = await api.fetchApi('/environments');\n connections = await getConnections();\n } catch (e) {\n addToast($t.mapper.errors.fetch_failed, 'error');\n }\n }\n // #endregion fetchData:Function\n" + "body": " // #region fetchData:Function [TYPE Function]\n // @PURPOSE: Fetches environments.\n // @PRE: None.\n // @POST: envs array is populated.\n async function fetchData() {\n try {\n envs = await api.fetchApi('/environments');\n } catch (e) {\n addToast($t.mapper.errors.fetch_failed, 'error');\n }\n }\n // #endregion fetchData:Function\n" }, { "contract_id": "handleRunMapper:Function", "contract_type": "Function", "file_path": "frontend/src/components/tools/MapperTool.svelte", - "start_line": 51, - "end_line": 92, + "start_line": 46, + "end_line": 86, "tier": "TIER_1", "complexity": 1, "metadata": { "POST": "Mapper task is started and selectedTask is updated.", "PRE": "selectedEnv and datasetId are set; source-specific fields are valid.", - "PURPOSE": "Triggers the MapperPlugin task." + "PURPOSE": "Triggers the MapperPlugin task via new sqllab/excel sources." }, "relations": [], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region handleRunMapper:Function [TYPE Function]\n // @PURPOSE: Triggers the MapperPlugin task.\n // @PRE: selectedEnv and datasetId are set; source-specific fields are valid.\n // @POST: Mapper task is started and selectedTask is updated.\n async function handleRunMapper() {\n if (!selectedEnv || !datasetId) {\n addToast($t.mapper.errors.required_fields, 'warning');\n return;\n }\n\n if (source === 'postgres' && (!selectedConnection || !tableName)) {\n addToast($t.mapper.errors.postgres_required, 'warning');\n return;\n }\n\n if (source === 'excel' && !excelPath) {\n addToast($t.mapper.errors.excel_required, 'warning');\n return;\n }\n\n isRunning = true;\n try {\n const env = envs.find(e => e.id === selectedEnv);\n const task = await runTask('dataset-mapper', {\n env: env.name,\n dataset_id: parseInt(datasetId),\n source,\n connection_id: selectedConnection,\n table_name: tableName,\n table_schema: tableSchema,\n excel_path: excelPath\n });\n \n selectedTask.set(task);\n addToast($t.mapper.success.started, 'success');\n } catch (e) {\n addToast(e.message, 'error');\n } finally {\n isRunning = false;\n }\n }\n // #endregion handleRunMapper:Function\n" + "body": " // #region handleRunMapper:Function [TYPE Function]\n // @PURPOSE: Triggers the MapperPlugin task via new sqllab/excel sources.\n // @PRE: selectedEnv and datasetId are set; source-specific fields are valid.\n // @POST: Mapper task is started and selectedTask is updated.\n async function handleRunMapper() {\n if (!selectedEnv || !datasetId) {\n addToast($t.mapper.errors.required_fields, 'warning');\n return;\n }\n\n if (source === 'sqllab' && !databaseId) {\n addToast($t.mapper.errors.sqllab_required, 'warning');\n return;\n }\n\n if (source === 'excel' && !excelPath) {\n addToast($t.mapper.errors.excel_required, 'warning');\n return;\n }\n\n isRunning = true;\n try {\n const env = envs.find(e => e.id === selectedEnv);\n const task = await runTask('dataset-mapper', {\n env: env.name,\n dataset_id: parseInt(datasetId),\n source,\n database_id: databaseId ? parseInt(databaseId) : undefined,\n sql_query: sqlQuery || undefined,\n excel_path: excelPath\n });\n \n selectedTask.set(task);\n addToast($t.mapper.success.started, 'success');\n } catch (e) {\n addToast(e.message, 'error');\n } finally {\n isRunning = false;\n }\n }\n // #endregion handleRunMapper:Function\n" }, { "contract_id": "handleGenerateDocs:Function", "contract_type": "Function", "file_path": "frontend/src/components/tools/MapperTool.svelte", - "start_line": 94, - "end_line": 129, + "start_line": 88, + "end_line": 123, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -65679,7 +67155,7 @@ "contract_type": "Module", "file_path": "frontend/src/lib/api.js", "start_line": 1, - "end_line": 241, + "end_line": 242, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -65724,7 +67200,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region ApiModule [C:3] [TYPE Module] [SEMANTICS api, client, fetch, auth, error-handling]\n// @BRIEF Handles all communication with the backend API via fetch wrappers with auth, error normalization, and toast feedback.\n// @RELATION DEPENDS_ON -> [ToastsModule]\n// @RELATION CALLED_BY -> [TranslateApi]\nimport { addToast } from './toasts.js';\nimport { PUBLIC_WS_URL } from '$env/static/public';\n\nconst API_BASE_URL = '/api';\n\nasync function buildApiError(response) {\n const errorData = await response.json().catch(() => ({}));\n const detail = errorData?.detail;\n const message = detail\n ? (typeof detail === 'string' ? detail : (typeof detail?.message === 'string' ? detail.message : JSON.stringify(detail)))\n : `API request failed with status ${response.status}`;\n const error = new Error(message);\n /** @type {any} */ (error).status = response.status;\n /** @type {any} */ (error).detail = detail;\n if (detail && typeof detail === 'object' && detail.error_code) {\n /** @type {any} */ (error).error_code = String(detail.error_code);\n }\n return error;\n}\n\nfunction notifyApiError(error) {\n if (error?.status === 401) { addToast(`401 Unauthorized: ${error.message}`, 'error'); return; }\n if (error?.status >= 500) { addToast(`Server error (${error.status}): ${error.message}`, 'error'); return; }\n addToast(error.message, 'error');\n}\n\nfunction shouldSuppressApiErrorToast(endpoint, error) {\n const isGitStatusEndpoint = typeof endpoint === 'string' && endpoint.startsWith('/git/repositories/') && endpoint.endsWith('/status');\n const isNoRepoError = (error?.status === 400 || error?.status === 404) && /Repository for dashboard .* not found/i.test(String(error?.message || ''));\n const isGitPullEndpoint = typeof endpoint === 'string' && endpoint.startsWith('/git/repositories/') && endpoint.endsWith('/pull');\n const isUnfinishedMergeError = error?.status === 409 && (String(error?.error_code || '') === 'GIT_UNFINISHED_MERGE' || String(error?.detail?.error_code || '') === 'GIT_UNFINISHED_MERGE');\n const isDatasetClarificationEndpoint = typeof endpoint === 'string' && /\\/dataset-orchestration\\/sessions\\/[^/]+\\/clarification$/.test(endpoint);\n const isMissingClarificationSession = error?.status === 404 && /Clarification session not found/i.test(String(error?.message || ''));\n return (isGitStatusEndpoint && isNoRepoError) || (isGitPullEndpoint && isUnfinishedMergeError) || (isDatasetClarificationEndpoint && isMissingClarificationSession);\n}\n\nexport const getWsUrl = (taskId) => {\n let baseUrl = PUBLIC_WS_URL;\n if (!baseUrl) {\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n baseUrl = `${protocol}//${window.location.host}`;\n }\n return `${baseUrl}/ws/logs/${taskId}`;\n};\n\nfunction getAuthHeaders(extraHeaders = {}) {\n const headers = { 'Content-Type': 'application/json', ...extraHeaders };\n if (typeof window !== 'undefined') {\n const token = localStorage.getItem('auth_token');\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n return headers;\n}\n\nasync function fetchApi(endpoint, options = {}) {\n try {\n console.log(`[api.fetchApi][Action] Fetching from endpoint=${endpoint}`);\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { headers: getAuthHeaders(options.headers || {}) });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.fetchApi][Coherence:Failed] ${endpoint}:`, error);\n if (!options.suppressToast) notifyApiError(error);\n throw error;\n }\n}\n\nasync function fetchApiBlob(endpoint, options = {}) {\n const notifyError = options.notifyError !== false;\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { headers: getAuthHeaders(options.headers || {}) });\n if (response.status === 202) {\n const payload = await response.json().catch(() => ({ message: \"Resource is being prepared\" }));\n const error = new Error(payload?.message || \"Resource is being prepared\");\n /** @type {any} */ (error).status = 202;\n throw error;\n }\n if (!response.ok) throw await buildApiError(response);\n return await response.blob();\n } catch (error) {\n if (notifyError) notifyApiError(error);\n throw error;\n }\n}\n\nasync function postApi(endpoint, body, options = {}) {\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, {\n method: 'POST', headers: getAuthHeaders(options.headers || {}), body: JSON.stringify(body),\n });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.postApi][Coherence:Failed] ${endpoint}:`, error);\n if (!options.suppressToast) notifyApiError(error);\n throw error;\n }\n}\n\nasync function deleteApi(endpoint, options = {}) {\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { method: 'DELETE', headers: getAuthHeaders(options.headers || {}) });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.deleteApi][Coherence:Failed] ${endpoint}:`, error);\n notifyApiError(error);\n throw error;\n }\n}\n\nasync function requestApi(endpoint, method = 'GET', body = null, requestOptions = {}) {\n try {\n const fetchOptions = { method, headers: getAuthHeaders(requestOptions.headers || {}) };\n if (body) fetchOptions.body = JSON.stringify(body);\n const response = await fetch(`${API_BASE_URL}${endpoint}`, fetchOptions);\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.requestApi][Coherence:Failed] ${method} ${endpoint}:`, error);\n if (!shouldSuppressApiErrorToast(endpoint, error)) notifyApiError(error);\n throw error;\n }\n}\n\nexport const api = {\n fetchApi, postApi, deleteApi, requestApi,\n getPlugins: () => fetchApi('/plugins'),\n getTasks: (options = {}) => {\n const params = new URLSearchParams();\n if (options.limit != null) params.append('limit', String(options.limit));\n if (options.offset != null) params.append('offset', String(options.offset));\n if (options.status) params.append('status', options.status);\n if (options.task_type) params.append('task_type', options.task_type);\n if (options.completed_only != null) params.append('completed_only', String(Boolean(options.completed_only)));\n if (Array.isArray(options.plugin_id)) options.plugin_id.forEach((pid) => params.append('plugin_id', pid));\n const query = params.toString();\n return fetchApi(`/tasks${query ? `?${query}` : ''}`);\n },\n getTask: (taskId) => fetchApi(`/tasks/${taskId}`),\n getTaskLogs: (taskId, options = {}) => {\n const params = new URLSearchParams();\n if (options.level) params.append('level', options.level);\n if (options.source) params.append('source', options.source);\n if (options.search) params.append('search', options.search);\n if (options.offset != null) params.append('offset', String(options.offset));\n if (options.limit != null) params.append('limit', String(options.limit));\n return fetchApi(`/tasks/${taskId}/logs${params.toString() ? `?${params.toString()}` : ''}`);\n },\n createTask: (pluginId, params) => postApi('/tasks', { plugin_id: pluginId, params }),\n getProfilePreferences: () => fetchApi('/profile/preferences'),\n updateProfilePreferences: (payload) => requestApi('/profile/preferences', 'PATCH', payload),\n lookupSupersetAccounts: (environmentId, options = {}) => {\n const eid = String(environmentId || '').trim();\n if (!eid) throw new Error('environmentId is required for Superset account lookup');\n const params = new URLSearchParams({ environment_id: eid });\n if (options.search) params.append('search', options.search);\n if (options.page_index != null) params.append('page_index', String(options.page_index));\n if (options.page_size != null) params.append('page_size', String(options.page_size));\n if (options.sort_column) params.append('sort_column', options.sort_column);\n if (options.sort_order) params.append('sort_order', options.sort_order);\n return fetchApi(`/profile/superset-accounts?${params.toString()}`);\n },\n getSettings: () => fetchApi('/settings'),\n updateGlobalSettings: (s) => requestApi('/settings/global', 'PATCH', s),\n getEnvironments: () => fetchApi('/settings/environments'),\n addEnvironment: (env) => postApi('/settings/environments', env),\n updateEnvironment: (id, env) => requestApi(`/settings/environments/${id}`, 'PUT', env),\n deleteEnvironment: (id) => requestApi(`/settings/environments/${id}`, 'DELETE'),\n testEnvironmentConnection: (id) => postApi(`/settings/environments/${id}/test`, {}),\n updateEnvironmentSchedule: (id, s) => requestApi(`/environments/${id}/schedule`, 'PUT', s),\n getStorageSettings: () => fetchApi('/settings/storage'),\n updateStorageSettings: (s) => requestApi('/settings/storage', 'PUT', s),\n getEnvironmentsList: () => fetchApi('/environments'),\n getLlmStatus: () => fetchApi('/llm/status'),\n fetchLlmModels: (p) => postApi('/llm/providers/fetch-models', p),\n getEnvironmentDatabases: (id) => fetchApi(`/environments/${id}/databases`),\n getStorageFileBlob: (path) => fetchApiBlob(`/storage/file?path=${encodeURIComponent(path)}`),\n getDashboards: (envId, options = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (options.search) params.append('search', options.search);\n if (options.page) params.append('page', options.page);\n if (options.page_size) params.append('page_size', options.page_size);\n if (options.page_context) params.append('page_context', options.page_context);\n if (options.apply_profile_default != null) params.append('apply_profile_default', String(Boolean(options.apply_profile_default)));\n if (options.override_show_all != null) params.append('override_show_all', String(Boolean(options.override_show_all)));\n if (options.filters?.title) for (const v of options.filters.title) params.append('filter_title', v);\n if (options.filters?.git_status) for (const v of options.filters.git_status) params.append('filter_git_status', v);\n if (options.filters?.llm_status) for (const v of options.filters.llm_status) params.append('filter_llm_status', v);\n if (options.filters?.changed_on) for (const v of options.filters.changed_on) params.append('filter_changed_on', v);\n if (options.filters?.actor) for (const v of options.filters.actor) params.append('filter_actor', v);\n return fetchApi(`/dashboards?${params.toString()}`);\n },\n getDashboardDetail: (envId, ref) => fetchApi(`/dashboards/${encodeURIComponent(String(ref))}?env_id=${envId}`),\n getDashboardTaskHistory: (envId, ref, opts = {}) => {\n const params = new URLSearchParams();\n if (envId) params.append('env_id', envId);\n if (opts.limit) params.append('limit', opts.limit);\n return fetchApi(`/dashboards/${encodeURIComponent(String(ref))}/tasks?${params.toString()}`);\n },\n getDashboardThumbnail: (envId, ref, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.force != null) params.append('force', String(Boolean(opts.force)));\n return fetchApiBlob(`/dashboards/${encodeURIComponent(String(ref))}/thumbnail?${params.toString()}`, { notifyError: false });\n },\n getDatabaseMappings: (src, tgt) => fetchApi(`/dashboards/db-mappings?source_env_id=${src}&target_env_id=${tgt}`),\n calculateMigrationDryRun: (p) => postApi('/migration/dry-run', p),\n getDatasets: (envId, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.search) params.append('search', opts.search);\n if (opts.page) params.append('page', opts.page);\n if (opts.page_size) params.append('page_size', opts.page_size);\n return fetchApi(`/datasets?${params.toString()}`);\n },\n getDatasetIds: (envId, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.search) params.append('search', opts.search);\n return fetchApi(`/datasets/ids?${params.toString()}`);\n },\n getDatasetDetail: (envId, datasetId) => fetchApi(`/datasets/${datasetId}?env_id=${envId}`),\n getConsolidatedSettings: () => fetchApi('/settings/consolidated'),\n updateConsolidatedSettings: (s) => requestApi('/settings/consolidated', 'PATCH', s),\n getValidationPolicies: () => fetchApi('/settings/automation/policies'),\n createValidationPolicy: (p) => postApi('/settings/automation/policies', p),\n updateValidationPolicy: (id, p) => requestApi(`/settings/automation/policies/${id}`, 'PATCH', p),\n deleteValidationPolicy: (id) => requestApi(`/settings/automation/policies/${id}`, 'DELETE'),\n getTranslationSchedules: () => fetchApi('/settings/automation/translation-schedules'),\n getHealthSummary: (environmentId) => {\n const query = environmentId ? `?env_id=${encodeURIComponent(environmentId)}` : '';\n return fetchApi(`/health/summary${query}`, { suppressToast: true });\n },\n};\n// #endregion ApiModule\n" + "body": "// #region ApiModule [C:3] [TYPE Module] [SEMANTICS api, client, fetch, auth, error-handling]\n// @BRIEF Handles all communication with the backend API via fetch wrappers with auth, error normalization, and toast feedback.\n// @RELATION DEPENDS_ON -> [ToastsModule]\n// @RELATION CALLED_BY -> [TranslateApi]\nimport { addToast } from './toasts.js';\nimport { PUBLIC_WS_URL } from '$env/static/public';\n\nconst API_BASE_URL = '/api';\n\nasync function buildApiError(response) {\n const errorData = await response.json().catch(() => ({}));\n const detail = errorData?.detail;\n const message = detail\n ? (typeof detail === 'string' ? detail : (typeof detail?.message === 'string' ? detail.message : JSON.stringify(detail)))\n : `API request failed with status ${response.status}`;\n const error = new Error(message);\n /** @type {any} */ (error).status = response.status;\n /** @type {any} */ (error).detail = detail;\n if (detail && typeof detail === 'object' && detail.error_code) {\n /** @type {any} */ (error).error_code = String(detail.error_code);\n }\n return error;\n}\n\nfunction notifyApiError(error) {\n if (error?.status === 401) { addToast(`401 Unauthorized: ${error.message}`, 'error'); return; }\n if (error?.status >= 500) { addToast(`Server error (${error.status}): ${error.message}`, 'error'); return; }\n addToast(error.message, 'error');\n}\n\nfunction shouldSuppressApiErrorToast(endpoint, error) {\n const isGitStatusEndpoint = typeof endpoint === 'string' && endpoint.startsWith('/git/repositories/') && endpoint.endsWith('/status');\n const isNoRepoError = (error?.status === 400 || error?.status === 404) && /Repository for dashboard .* not found/i.test(String(error?.message || ''));\n const isGitPullEndpoint = typeof endpoint === 'string' && endpoint.startsWith('/git/repositories/') && endpoint.endsWith('/pull');\n const isUnfinishedMergeError = error?.status === 409 && (String(error?.error_code || '') === 'GIT_UNFINISHED_MERGE' || String(error?.detail?.error_code || '') === 'GIT_UNFINISHED_MERGE');\n const isDatasetClarificationEndpoint = typeof endpoint === 'string' && /\\/dataset-orchestration\\/sessions\\/[^/]+\\/clarification$/.test(endpoint);\n const isMissingClarificationSession = error?.status === 404 && /Clarification session not found/i.test(String(error?.message || ''));\n return (isGitStatusEndpoint && isNoRepoError) || (isGitPullEndpoint && isUnfinishedMergeError) || (isDatasetClarificationEndpoint && isMissingClarificationSession);\n}\n\nexport const getWsUrl = (taskId) => {\n let baseUrl = PUBLIC_WS_URL;\n if (!baseUrl) {\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n baseUrl = `${protocol}//${window.location.host}`;\n }\n return `${baseUrl}/ws/logs/${taskId}`;\n};\n\nfunction getAuthHeaders(extraHeaders = {}) {\n const headers = { 'Content-Type': 'application/json', ...extraHeaders };\n if (typeof window !== 'undefined') {\n const token = localStorage.getItem('auth_token');\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n return headers;\n}\n\nasync function fetchApi(endpoint, options = {}) {\n try {\n console.log(`[api.fetchApi][Action] Fetching from endpoint=${endpoint}`);\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { headers: getAuthHeaders(options.headers || {}) });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.fetchApi][Coherence:Failed] ${endpoint}:`, error);\n if (!options.suppressToast) notifyApiError(error);\n throw error;\n }\n}\n\nasync function fetchApiBlob(endpoint, options = {}) {\n const notifyError = options.notifyError !== false;\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { headers: getAuthHeaders(options.headers || {}) });\n if (response.status === 202) {\n const payload = await response.json().catch(() => ({ message: \"Resource is being prepared\" }));\n const error = new Error(payload?.message || \"Resource is being prepared\");\n /** @type {any} */ (error).status = 202;\n throw error;\n }\n if (!response.ok) throw await buildApiError(response);\n return await response.blob();\n } catch (error) {\n if (notifyError) notifyApiError(error);\n throw error;\n }\n}\n\nasync function postApi(endpoint, body, options = {}) {\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, {\n method: 'POST', headers: getAuthHeaders(options.headers || {}), body: JSON.stringify(body),\n });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.postApi][Coherence:Failed] ${endpoint}:`, error);\n if (!options.suppressToast) notifyApiError(error);\n throw error;\n }\n}\n\nasync function deleteApi(endpoint, options = {}) {\n try {\n const response = await fetch(`${API_BASE_URL}${endpoint}`, { method: 'DELETE', headers: getAuthHeaders(options.headers || {}) });\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.deleteApi][Coherence:Failed] ${endpoint}:`, error);\n notifyApiError(error);\n throw error;\n }\n}\n\nasync function requestApi(endpoint, method = 'GET', body = null, requestOptions = {}) {\n try {\n const fetchOptions = { method, headers: getAuthHeaders(requestOptions.headers || {}) };\n if (body) fetchOptions.body = JSON.stringify(body);\n const response = await fetch(`${API_BASE_URL}${endpoint}`, fetchOptions);\n if (!response.ok) throw await buildApiError(response);\n if (response.status === 204) return null;\n return await response.json();\n } catch (error) {\n console.error(`[api.requestApi][Coherence:Failed] ${method} ${endpoint}:`, error);\n if (!shouldSuppressApiErrorToast(endpoint, error)) notifyApiError(error);\n throw error;\n }\n}\n\nexport const api = {\n fetchApi, postApi, deleteApi, requestApi,\n getPlugins: () => fetchApi('/plugins'),\n getTasks: (options = {}) => {\n const params = new URLSearchParams();\n if (options.limit != null) params.append('limit', String(options.limit));\n if (options.offset != null) params.append('offset', String(options.offset));\n if (options.status) params.append('status', options.status);\n if (options.task_type) params.append('task_type', options.task_type);\n if (options.completed_only != null) params.append('completed_only', String(Boolean(options.completed_only)));\n if (Array.isArray(options.plugin_id)) options.plugin_id.forEach((pid) => params.append('plugin_id', pid));\n const query = params.toString();\n return fetchApi(`/tasks${query ? `?${query}` : ''}`);\n },\n getTask: (taskId) => fetchApi(`/tasks/${taskId}`),\n getTaskLogs: (taskId, options = {}) => {\n const params = new URLSearchParams();\n if (options.level) params.append('level', options.level);\n if (options.source) params.append('source', options.source);\n if (options.search) params.append('search', options.search);\n if (options.offset != null) params.append('offset', String(options.offset));\n if (options.limit != null) params.append('limit', String(options.limit));\n return fetchApi(`/tasks/${taskId}/logs${params.toString() ? `?${params.toString()}` : ''}`);\n },\n createTask: (pluginId, params) => postApi('/tasks', { plugin_id: pluginId, params }),\n getProfilePreferences: () => fetchApi('/profile/preferences'),\n updateProfilePreferences: (payload) => requestApi('/profile/preferences', 'PATCH', payload),\n lookupSupersetAccounts: (environmentId, options = {}) => {\n const eid = String(environmentId || '').trim();\n if (!eid) throw new Error('environmentId is required for Superset account lookup');\n const params = new URLSearchParams({ environment_id: eid });\n if (options.search) params.append('search', options.search);\n if (options.page_index != null) params.append('page_index', String(options.page_index));\n if (options.page_size != null) params.append('page_size', String(options.page_size));\n if (options.sort_column) params.append('sort_column', options.sort_column);\n if (options.sort_order) params.append('sort_order', options.sort_order);\n return fetchApi(`/profile/superset-accounts?${params.toString()}`);\n },\n getSettings: () => fetchApi('/settings'),\n updateGlobalSettings: (s) => requestApi('/settings/global', 'PATCH', s),\n getEnvironments: () => fetchApi('/settings/environments'),\n addEnvironment: (env) => postApi('/settings/environments', env),\n updateEnvironment: (id, env) => requestApi(`/settings/environments/${id}`, 'PUT', env),\n deleteEnvironment: (id) => requestApi(`/settings/environments/${id}`, 'DELETE'),\n testEnvironmentConnection: (id) => postApi(`/settings/environments/${id}/test`, {}),\n updateEnvironmentSchedule: (id, s) => requestApi(`/environments/${id}/schedule`, 'PUT', s),\n getStorageSettings: () => fetchApi('/settings/storage'),\n updateStorageSettings: (s) => requestApi('/settings/storage', 'PUT', s),\n getEnvironmentsList: () => fetchApi('/environments'),\n getLlmStatus: () => fetchApi('/llm/status'),\n fetchLlmModels: (p) => postApi('/llm/providers/fetch-models', p),\n getEnvironmentDatabases: (id) => fetchApi(`/environments/${id}/databases`),\n getStorageFileBlob: (path) => fetchApiBlob(`/storage/file?path=${encodeURIComponent(path)}`),\n getDashboards: (envId, options = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (options.search) params.append('search', options.search);\n if (options.page) params.append('page', options.page);\n if (options.page_size) params.append('page_size', options.page_size);\n if (options.page_context) params.append('page_context', options.page_context);\n if (options.apply_profile_default != null) params.append('apply_profile_default', String(Boolean(options.apply_profile_default)));\n if (options.override_show_all != null) params.append('override_show_all', String(Boolean(options.override_show_all)));\n if (options.filters?.title) for (const v of options.filters.title) params.append('filter_title', v);\n if (options.filters?.git_status) for (const v of options.filters.git_status) params.append('filter_git_status', v);\n if (options.filters?.llm_status) for (const v of options.filters.llm_status) params.append('filter_llm_status', v);\n if (options.filters?.changed_on) for (const v of options.filters.changed_on) params.append('filter_changed_on', v);\n if (options.filters?.actor) for (const v of options.filters.actor) params.append('filter_actor', v);\n return fetchApi(`/dashboards?${params.toString()}`);\n },\n getDashboardDetail: (envId, ref) => fetchApi(`/dashboards/${encodeURIComponent(String(ref))}?env_id=${envId}`),\n getDashboardTaskHistory: (envId, ref, opts = {}) => {\n const params = new URLSearchParams();\n if (envId) params.append('env_id', envId);\n if (opts.limit) params.append('limit', opts.limit);\n return fetchApi(`/dashboards/${encodeURIComponent(String(ref))}/tasks?${params.toString()}`);\n },\n getDashboardThumbnail: (envId, ref, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.force != null) params.append('force', String(Boolean(opts.force)));\n return fetchApiBlob(`/dashboards/${encodeURIComponent(String(ref))}/thumbnail?${params.toString()}`, { notifyError: false });\n },\n getDatabaseMappings: (src, tgt) => fetchApi(`/dashboards/db-mappings?source_env_id=${src}&target_env_id=${tgt}`),\n calculateMigrationDryRun: (p) => postApi('/migration/dry-run', p),\n getDatasets: (envId, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.search) params.append('search', opts.search);\n if (opts.filter) params.append('filter', opts.filter);\n if (opts.page) params.append('page', opts.page);\n if (opts.page_size) params.append('page_size', opts.page_size);\n return fetchApi(`/datasets?${params.toString()}`);\n },\n getDatasetIds: (envId, opts = {}) => {\n const params = new URLSearchParams({ env_id: envId });\n if (opts.search) params.append('search', opts.search);\n return fetchApi(`/datasets/ids?${params.toString()}`);\n },\n getDatasetDetail: (envId, datasetId) => fetchApi(`/datasets/${datasetId}?env_id=${envId}`),\n getConsolidatedSettings: () => fetchApi('/settings/consolidated'),\n updateConsolidatedSettings: (s) => requestApi('/settings/consolidated', 'PATCH', s),\n getValidationPolicies: () => fetchApi('/settings/automation/policies'),\n createValidationPolicy: (p) => postApi('/settings/automation/policies', p),\n updateValidationPolicy: (id, p) => requestApi(`/settings/automation/policies/${id}`, 'PATCH', p),\n deleteValidationPolicy: (id) => requestApi(`/settings/automation/policies/${id}`, 'DELETE'),\n getTranslationSchedules: () => fetchApi('/settings/automation/translation-schedules'),\n getHealthSummary: (environmentId) => {\n const query = environmentId ? `?env_id=${encodeURIComponent(environmentId)}` : '';\n return fetchApi(`/health/summary${query}`, { suppressToast: true });\n },\n};\n// #endregion ApiModule\n" }, { "contract_id": "ReportsApiTest", @@ -66888,6 +68364,461 @@ "tier_source": "AutoCalculated", "body": "/**\n * Check target table schema — validate expected vs actual columns for translation inserts.\n * @param {{\n * environment_id: string,\n * target_database_id: string,\n * target_schema: string,\n * target_table: string,\n * target_key_cols: string[],\n * target_column: string|null,\n * translation_column: string|null,\n * target_language_column: string|null,\n * target_source_column: string|null,\n * target_source_language_column: string|null,\n * }} payload\n * @returns {Promise<{\n * table_exists: boolean,\n * error: string|null,\n * expected_columns: Array<{name: string, data_type: string|null, is_nullable: boolean}>,\n * actual_columns: Array<{name: string, data_type: string|null, is_nullable: boolean}>,\n * missing_columns: Array<{name: string, data_type: string|null, is_nullable: boolean}>,\n * extra_columns: Array<{name: string, data_type: string|null, is_nullable: boolean}>,\n * all_present: boolean,\n * }>}\n */" }, + { + "contract_id": "ValidationApi", + "contract_type": "Module", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 1, + "end_line": 102, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "API client functions for the Validation section — tasks and runs CRUD.", + "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." + }, + "relations": [ + { + "source_id": "ValidationApi", + "relation_type": "CALLED_BY", + "target_id": "ValidationTaskList", + "target_ref": "[ValidationTaskList]" + }, + { + "source_id": "ValidationApi", + "relation_type": "CALLED_BY", + "target_id": "ValidationTaskConfig", + "target_ref": "[ValidationTaskConfig]" + }, + { + "source_id": "ValidationApi", + "relation_type": "CALLED_BY", + "target_id": "ValidationHistory", + "target_ref": "[ValidationHistory]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region ValidationApi [C:2] [TYPE Module] [SEMANTICS validation, api]\n// @BRIEF API client functions for the Validation section — tasks and runs CRUD.\n// @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.\n// @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.\n// @RELATION CALLED_BY -> [ValidationTaskList]\n// @RELATION CALLED_BY -> [ValidationTaskConfig]\n// @RELATION CALLED_BY -> [ValidationHistory]\n\nimport { fetchApi, postApi, requestApi, deleteApi } from '$lib/api.js';\n\n// #region buildParams:Function [C:1] [TYPE Function]\n// @BRIEF Build URLSearchParams from a params object, skipping null/undefined/empty values.\n/** @param {Record} params */\nfunction buildParams(params) {\n\tconst qs = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(params)) {\n\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\tqs.append(key, String(value));\n\t\t}\n\t}\n\treturn qs.toString();\n}\n// #endregion buildParams:Function\n\n// ── Tasks ──────────────────────────────────────────────────────\n\n// #region fetchTasks:Function [C:1] [TYPE Function]\n/** @param {{ is_active?: boolean, environment_id?: string, page?: number, page_size?: number }} [params] */\nexport async function fetchTasks(params = {}) {\n\tconst qs = buildParams(params);\n\treturn fetchApi(`/validation/tasks${qs ? `?${qs}` : ''}`);\n}\n// #endregion fetchTasks:Function\n\n// #region createTask:Function [C:1] [TYPE Function]\n/** @param {Record} data */\nexport async function createTask(data) {\n\treturn postApi('/validation/tasks', data);\n}\n// #endregion createTask:Function\n\n// #region fetchTask:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function fetchTask(id) {\n\treturn fetchApi(`/validation/tasks/${id}`);\n}\n// #endregion fetchTask:Function\n\n// #region updateTask:Function [C:1] [TYPE Function]\n/** @param {string} id @param {Record} data */\nexport async function updateTask(id, data) {\n\treturn requestApi(`/validation/tasks/${id}`, 'PUT', data);\n}\n// #endregion updateTask:Function\n\n// #region deleteTask:Function [C:1] [TYPE Function]\n/** @param {string} id @param {boolean} [deleteRuns] */\nexport async function deleteTask(id, deleteRuns = false) {\n\tconst qs = deleteRuns ? '?delete_runs=true' : '';\n\treturn deleteApi(`/validation/tasks/${id}${qs}`);\n}\n// #endregion deleteTask:Function\n\n// #region triggerRun:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function triggerRun(id) {\n\treturn postApi(`/validation/tasks/${id}/run`, {});\n}\n// #endregion triggerRun:Function\n\n// #region duplicateTask:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function duplicateTask(id) {\n\treturn postApi(`/validation/tasks/${id}/duplicate`, {});\n}\n// #endregion duplicateTask:Function\n\n// ── Runs ────────────────────────────────────────────────────────\n\n// #region fetchRuns:Function [C:1] [TYPE Function]\n/** @param {{ task_id?: string, dashboard_id?: string, environment_id?: string, status?: string, date_from?: string, date_to?: string, page?: number, page_size?: number }} [params] */\nexport async function fetchRuns(params = {}) {\n\tconst qs = buildParams(params);\n\treturn fetchApi(`/validation/runs${qs ? `?${qs}` : ''}`);\n}\n// #endregion fetchRuns:Function\n\n// #region fetchRunDetail:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function fetchRunDetail(id) {\n\treturn fetchApi(`/validation/runs/${id}`);\n}\n// #endregion fetchRunDetail:Function\n\n// #region deleteRun:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function deleteRun(id) {\n\treturn deleteApi(`/validation/runs/${id}`);\n}\n// #endregion deleteRun:Function\n\n// #endregion ValidationApi\n" + }, + { + "contract_id": "buildParams:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 11, + "end_line": 23, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{Record} params", + "PURPOSE": "Build URLSearchParams from a params object, skipping null/undefined/empty values." + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region buildParams:Function [C:1] [TYPE Function]\n// @BRIEF Build URLSearchParams from a params object, skipping null/undefined/empty values.\n/** @param {Record} params */\nfunction buildParams(params) {\n\tconst qs = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(params)) {\n\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\tqs.append(key, String(value));\n\t\t}\n\t}\n\treturn qs.toString();\n}\n// #endregion buildParams:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::buildParams", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 13, + "end_line": 14, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {Record} params */" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::fetchTasks", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 28, + "end_line": 29, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {{ is_active?: boolean, environment_id?: string, page?: number, page_size?: number }} [params] */" + }, + { + "contract_id": "createTask:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 35, + "end_line": 40, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{Record} data" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region createTask:Function [C:1] [TYPE Function]\n/** @param {Record} data */\nexport async function createTask(data) {\n\treturn postApi('/validation/tasks', data);\n}\n// #endregion createTask:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::createTask", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 36, + "end_line": 37, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {Record} data */" + }, + { + "contract_id": "fetchTask:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 42, + "end_line": 47, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region fetchTask:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function fetchTask(id) {\n\treturn fetchApi(`/validation/tasks/${id}`);\n}\n// #endregion fetchTask:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::fetchTask", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 43, + "end_line": 44, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id */" + }, + { + "contract_id": "updateTask:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 49, + "end_line": 54, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id @param {Record} data" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region updateTask:Function [C:1] [TYPE Function]\n/** @param {string} id @param {Record} data */\nexport async function updateTask(id, data) {\n\treturn requestApi(`/validation/tasks/${id}`, 'PUT', data);\n}\n// #endregion updateTask:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::updateTask", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 50, + "end_line": 51, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id @param {Record} data */" + }, + { + "contract_id": "deleteTask:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 56, + "end_line": 62, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id @param {boolean} [deleteRuns]" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region deleteTask:Function [C:1] [TYPE Function]\n/** @param {string} id @param {boolean} [deleteRuns] */\nexport async function deleteTask(id, deleteRuns = false) {\n\tconst qs = deleteRuns ? '?delete_runs=true' : '';\n\treturn deleteApi(`/validation/tasks/${id}${qs}`);\n}\n// #endregion deleteTask:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::deleteTask", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 57, + "end_line": 58, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id @param {boolean} [deleteRuns] */" + }, + { + "contract_id": "triggerRun:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 64, + "end_line": 69, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region triggerRun:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function triggerRun(id) {\n\treturn postApi(`/validation/tasks/${id}/run`, {});\n}\n// #endregion triggerRun:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::triggerRun", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 65, + "end_line": 66, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id */" + }, + { + "contract_id": "duplicateTask:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 71, + "end_line": 76, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region duplicateTask:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function duplicateTask(id) {\n\treturn postApi(`/validation/tasks/${id}/duplicate`, {});\n}\n// #endregion duplicateTask:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::duplicateTask", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 72, + "end_line": 73, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id */" + }, + { + "contract_id": "fetchRuns:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 80, + "end_line": 86, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "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]" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region fetchRuns:Function [C:1] [TYPE Function]\n/** @param {{ task_id?: string, dashboard_id?: string, environment_id?: string, status?: string, date_from?: string, date_to?: string, page?: number, page_size?: number }} [params] */\nexport async function fetchRuns(params = {}) {\n\tconst qs = buildParams(params);\n\treturn fetchApi(`/validation/runs${qs ? `?${qs}` : ''}`);\n}\n// #endregion fetchRuns:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::fetchRuns", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 81, + "end_line": 82, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {{ task_id?: string, dashboard_id?: string, environment_id?: string, status?: string, date_from?: string, date_to?: string, page?: number, page_size?: number }} [params] */" + }, + { + "contract_id": "fetchRunDetail:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 88, + "end_line": 93, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region fetchRunDetail:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function fetchRunDetail(id) {\n\treturn fetchApi(`/validation/runs/${id}`);\n}\n// #endregion fetchRunDetail:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::fetchRunDetail", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 89, + "end_line": 90, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id */" + }, + { + "contract_id": "deleteRun:Function", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 95, + "end_line": 100, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PARAM": "{string} id" + }, + "relations": [], + "schema_warnings": [ + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region deleteRun:Function [C:1] [TYPE Function]\n/** @param {string} id */\nexport async function deleteRun(id) {\n\treturn deleteApi(`/validation/runs/${id}`);\n}\n// #endregion deleteRun:Function\n" + }, + { + "contract_id": "frontend/src/lib/api/validation.js::deleteRun", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/validation.js", + "start_line": 96, + "end_line": 97, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/** @param {string} id */" + }, { "contract_id": "PermissionsTest", "contract_type": "Module", @@ -69615,7 +71546,7 @@ "contract_type": "Function", "file_path": "frontend/src/lib/components/layout/sidebarNavigation.js", "start_line": 1, - "end_line": 204, + "end_line": 217, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -69670,7 +71601,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region SidebarNavigation:Module [TYPE Function]\n// @SEMANTICS: navigation, sidebar, rbac, menu, filtering\n// @PURPOSE: Build sidebar navigation sections and categories filtered by user permissions and feature flags.\n// @LAYER: UI\n// @RELATION: DEPENDS_ON -> [Permissions]\n// @RELATION: BINDS_TO -> [Sidebar]\n// @INVARIANT: Admin role can access all categories and subitems through permission utility.\n\nimport { hasPermission } from \"$lib/auth/permissions.js\";\n\n// #region isItemAllowed:Function [TYPE Function]\n// @PURPOSE: Check whether a single menu node can be shown for a given user.\n// @PRE: item can contain optional requiredPermission/requiredAction.\n// @POST: Returns true when no permission is required or permission check passes.\nfunction isItemAllowed(user, item) {\n if (!item?.requiredPermission) return true;\n return hasPermission(\n user,\n item.requiredPermission,\n item.requiredAction || \"READ\",\n );\n}\n// #endregion isItemAllowed:Function\n\n// #region isFeatureEnabled:Function [TYPE Function]\nfunction isFeatureEnabled(item, features) {\n if (!item?.requiredFeature) return true;\n return features[item.requiredFeature] !== false;\n}\n// #endregion isFeatureEnabled:Function\n\n// #region buildSidebarSections:Function [TYPE Function]\n// @PURPOSE: Build translated sidebar sections with categories, filtered by RBAC permissions and feature flags.\n// @PRE: i18nState provides nav labels; user can be null; features default to {} (all enabled).\n// @POST: Returns only sections/categories/subitems available for provided user and enabled features.\nexport function buildSidebarSections(i18nState, user, features = {}) {\n const nav = i18nState?.nav || {};\n\n // ── Section 1: Resources ─────────────────────────────────\n const resources = {\n id: \"resources\",\n label: nav.section_resources,\n categories: [\n {\n id: \"dashboards\",\n label: nav.dashboards,\n icon: \"dashboard\",\n tone: \"from-sky-100 to-sky-200 text-sky-700 ring-sky-200\",\n path: \"/dashboards\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.overview, path: \"/dashboards\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.health_center, path: \"/dashboards/health\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"health_monitor\" },\n ],\n },\n {\n id: \"datasets\",\n label: nav.datasets,\n icon: \"database\",\n tone: \"from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200\",\n path: \"/datasets\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_datasets, path: \"/datasets\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.dataset_review_workspace, path: \"/datasets/review\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"dataset_review\" },\n ],\n },\n {\n id: \"migration\",\n label: nav.migration,\n icon: \"layers\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/migration\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.migration_overview || \"Overview\", path: \"/migration\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.migration_mappings || \"Mappings\", path: \"/migration/mappings\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 2: Operations ────────────────────────────────\n const operations = {\n id: \"operations\",\n label: nav.section_operations,\n categories: [\n {\n id: \"git\",\n label: nav.git,\n icon: \"activity\",\n tone: \"from-purple-100 to-purple-200 text-purple-700 ring-purple-200\",\n path: \"/git\",\n subItems: [\n { label: nav.git_repo_status || \"Repository Status\", path: \"/git\" },\n ],\n },\n {\n id: \"translation\",\n label: nav.translation,\n icon: \"translate\",\n tone: \"from-cyan-100 to-teal-100 text-teal-700 ring-teal-200\",\n path: \"/translate\",\n requiredPermission: \"translate.job\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.translation_jobs, path: \"/translate\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n { label: nav.translation_dictionaries, path: \"/translate/dictionaries\", requiredPermission: \"translate.dictionary\", requiredAction: \"VIEW\" },\n { label: nav.translation_history, path: \"/translate/history\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"reports\",\n label: nav.reports,\n icon: \"reports\",\n tone: \"from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200\",\n path: \"/reports\",\n requiredPermission: \"tasks\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_reports || \"All Reports\", path: \"/reports\", requiredPermission: \"tasks\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 3: System ────────────────────────────────────\n const system = {\n id: \"system\",\n label: nav.section_system,\n categories: [\n {\n id: \"tools\",\n label: nav.tools,\n icon: \"list\",\n tone: \"from-slate-100 to-slate-200 text-slate-700 ring-slate-200\",\n path: \"/tools/mapper\",\n subItems: [\n { label: nav.tools_mapper, path: \"/tools/mapper\" },\n { label: nav.tools_debug, path: \"/tools/debug\" },\n { label: nav.tools_storage, path: \"/tools/storage\" },\n { label: nav.tools_backups, path: \"/tools/backups\" },\n ],\n },\n {\n id: \"storage\",\n label: nav.storage,\n icon: \"storage\",\n tone: \"from-amber-100 to-amber-200 text-amber-800 ring-amber-200\",\n path: \"/storage\",\n requiredPermission: \"plugin:storage\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.repositories, path: \"/storage/repos\", requiredPermission: \"plugin:storage\", requiredAction: \"READ\" },\n ],\n },\n {\n id: \"admin\",\n label: nav.admin,\n icon: \"admin\",\n tone: \"from-rose-100 to-rose-200 text-rose-700 ring-rose-200\",\n path: \"/admin/users\",\n subItems: [\n { label: nav.admin_users, path: \"/admin/users\", requiredPermission: \"admin:users\", requiredAction: \"READ\" },\n { label: nav.admin_roles, path: \"/admin/roles\", requiredPermission: \"admin:roles\", requiredAction: \"READ\" },\n { label: nav.admin_settings, path: \"/admin/settings\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n { label: nav.admin_llm, path: \"/admin/settings/llm\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n const allSections = [resources, operations, system];\n\n // Filter by permissions and features\n return allSections\n .map((section) => ({\n ...section,\n categories: section.categories\n .map((category) => {\n const visibleSubItems = (category.subItems || []).filter(\n (sub) => isItemAllowed(user, sub) && isFeatureEnabled(sub, features),\n );\n return { ...category, subItems: visibleSubItems };\n })\n .filter((category) => {\n if (!isItemAllowed(user, category)) return false;\n return Array.isArray(category.subItems) && category.subItems.length > 0;\n }),\n }))\n .filter((section) => section.categories.length > 0);\n}\n// #endregion buildSidebarSections:Function\n\n// ── Legacy adapter for backward compatibility ──────────────\n// @DEPRECATED Use buildSidebarSections instead. Returns flat category list for old consumers.\nexport function buildSidebarCategories(i18nState, user, features = {}) {\n const sections = buildSidebarSections(i18nState, user, features);\n return sections.flatMap((s) => s.categories);\n}\n// #endregion SidebarNavigation:Module\n" + "body": "// #region SidebarNavigation:Module [TYPE Function]\n// @SEMANTICS: navigation, sidebar, rbac, menu, filtering\n// @PURPOSE: Build sidebar navigation sections and categories filtered by user permissions and feature flags.\n// @LAYER: UI\n// @RELATION: DEPENDS_ON -> [Permissions]\n// @RELATION: BINDS_TO -> [Sidebar]\n// @INVARIANT: Admin role can access all categories and subitems through permission utility.\n\nimport { hasPermission } from \"$lib/auth/permissions.js\";\n\n// #region isItemAllowed:Function [TYPE Function]\n// @PURPOSE: Check whether a single menu node can be shown for a given user.\n// @PRE: item can contain optional requiredPermission/requiredAction.\n// @POST: Returns true when no permission is required or permission check passes.\nfunction isItemAllowed(user, item) {\n if (!item?.requiredPermission) return true;\n return hasPermission(\n user,\n item.requiredPermission,\n item.requiredAction || \"READ\",\n );\n}\n// #endregion isItemAllowed:Function\n\n// #region isFeatureEnabled:Function [TYPE Function]\nfunction isFeatureEnabled(item, features) {\n if (!item?.requiredFeature) return true;\n return features[item.requiredFeature] !== false;\n}\n// #endregion isFeatureEnabled:Function\n\n// #region buildSidebarSections:Function [TYPE Function]\n// @PURPOSE: Build translated sidebar sections with categories, filtered by RBAC permissions and feature flags.\n// @PRE: i18nState provides nav labels; user can be null; features default to {} (all enabled).\n// @POST: Returns only sections/categories/subitems available for provided user and enabled features.\nexport function buildSidebarSections(i18nState, user, features = {}) {\n const nav = i18nState?.nav || {};\n\n // ── Section 1: Resources ─────────────────────────────────\n const resources = {\n id: \"resources\",\n label: nav.section_resources,\n categories: [\n {\n id: \"dashboards\",\n label: nav.dashboards,\n icon: \"dashboard\",\n tone: \"from-sky-100 to-sky-200 text-sky-700 ring-sky-200\",\n path: \"/dashboards\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.overview, path: \"/dashboards\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.health_center, path: \"/dashboards/health\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"health_monitor\" },\n ],\n },\n {\n id: \"datasets\",\n label: nav.datasets,\n icon: \"database\",\n tone: \"from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200\",\n path: \"/datasets\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_datasets, path: \"/datasets\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.dataset_review_workspace, path: \"/datasets/review\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"dataset_review\" },\n ],\n },\n {\n id: \"migration\",\n label: nav.migration,\n icon: \"layers\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/migration\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.migration_overview || \"Overview\", path: \"/migration\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.migration_mappings || \"Mappings\", path: \"/migration/mappings\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 2: Operations ────────────────────────────────\n const operations = {\n id: \"operations\",\n label: nav.section_operations,\n categories: [\n {\n id: \"git\",\n label: nav.git,\n icon: \"activity\",\n tone: \"from-purple-100 to-purple-200 text-purple-700 ring-purple-200\",\n path: \"/git\",\n subItems: [\n { label: nav.git_repo_status || \"Repository Status\", path: \"/git\" },\n ],\n },\n {\n id: \"translation\",\n label: nav.translation,\n icon: \"translate\",\n tone: \"from-cyan-100 to-teal-100 text-teal-700 ring-teal-200\",\n path: \"/translate\",\n requiredPermission: \"translate.job\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.translation_jobs, path: \"/translate\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n { label: nav.translation_dictionaries, path: \"/translate/dictionaries\", requiredPermission: \"translate.dictionary\", requiredAction: \"VIEW\" },\n { label: nav.translation_history, path: \"/translate/history\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"validation\",\n label: nav.validation,\n icon: \"activity\",\n tone: \"from-amber-100 to-yellow-100 text-amber-700 ring-amber-200\",\n path: \"/validation\",\n requiredPermission: \"validation.task\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.validation_tasks, path: \"/validation\", requiredPermission: \"validation.task\", requiredAction: \"VIEW\" },\n { label: nav.validation_history, path: \"/validation/history\", requiredPermission: \"validation.run\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"reports\",\n label: nav.reports,\n icon: \"reports\",\n tone: \"from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200\",\n path: \"/reports\",\n requiredPermission: \"tasks\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_reports || \"All Reports\", path: \"/reports\", requiredPermission: \"tasks\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 3: System ────────────────────────────────────\n const system = {\n id: \"system\",\n label: nav.section_system,\n categories: [\n {\n id: \"tools\",\n label: nav.tools,\n icon: \"list\",\n tone: \"from-slate-100 to-slate-200 text-slate-700 ring-slate-200\",\n path: \"/tools/mapper\",\n subItems: [\n { label: nav.tools_mapper, path: \"/tools/mapper\" },\n { label: nav.tools_debug, path: \"/tools/debug\" },\n { label: nav.tools_storage, path: \"/tools/storage\" },\n { label: nav.tools_backups, path: \"/tools/backups\" },\n ],\n },\n {\n id: \"storage\",\n label: nav.storage,\n icon: \"storage\",\n tone: \"from-amber-100 to-amber-200 text-amber-800 ring-amber-200\",\n path: \"/storage\",\n requiredPermission: \"plugin:storage\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.repositories, path: \"/storage/repos\", requiredPermission: \"plugin:storage\", requiredAction: \"READ\" },\n ],\n },\n {\n id: \"admin\",\n label: nav.admin,\n icon: \"admin\",\n tone: \"from-rose-100 to-rose-200 text-rose-700 ring-rose-200\",\n path: \"/admin/users\",\n subItems: [\n { label: nav.admin_users, path: \"/admin/users\", requiredPermission: \"admin:users\", requiredAction: \"READ\" },\n { label: nav.admin_roles, path: \"/admin/roles\", requiredPermission: \"admin:roles\", requiredAction: \"READ\" },\n { label: nav.admin_settings, path: \"/admin/settings\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n { label: nav.admin_llm, path: \"/admin/settings/llm\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n const allSections = [resources, operations, system];\n\n // Filter by permissions and features\n return allSections\n .map((section) => ({\n ...section,\n categories: section.categories\n .map((category) => {\n const visibleSubItems = (category.subItems || []).filter(\n (sub) => isItemAllowed(user, sub) && isFeatureEnabled(sub, features),\n );\n return { ...category, subItems: visibleSubItems };\n })\n .filter((category) => {\n if (!isItemAllowed(user, category)) return false;\n return Array.isArray(category.subItems) && category.subItems.length > 0;\n }),\n }))\n .filter((section) => section.categories.length > 0);\n}\n// #endregion buildSidebarSections:Function\n\n// ── Legacy adapter for backward compatibility ──────────────\n// @DEPRECATED Use buildSidebarSections instead. Returns flat category list for old consumers.\nexport function buildSidebarCategories(i18nState, user, features = {}) {\n const sections = buildSidebarSections(i18nState, user, features);\n return sections.flatMap((s) => s.categories);\n}\n// #endregion SidebarNavigation:Module\n" }, { "contract_id": "isItemAllowed:Function", @@ -69711,7 +71642,7 @@ "contract_type": "Function", "file_path": "frontend/src/lib/components/layout/sidebarNavigation.js", "start_line": 32, - "end_line": 196, + "end_line": 209, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -69723,7 +71654,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region buildSidebarSections:Function [TYPE Function]\n// @PURPOSE: Build translated sidebar sections with categories, filtered by RBAC permissions and feature flags.\n// @PRE: i18nState provides nav labels; user can be null; features default to {} (all enabled).\n// @POST: Returns only sections/categories/subitems available for provided user and enabled features.\nexport function buildSidebarSections(i18nState, user, features = {}) {\n const nav = i18nState?.nav || {};\n\n // ── Section 1: Resources ─────────────────────────────────\n const resources = {\n id: \"resources\",\n label: nav.section_resources,\n categories: [\n {\n id: \"dashboards\",\n label: nav.dashboards,\n icon: \"dashboard\",\n tone: \"from-sky-100 to-sky-200 text-sky-700 ring-sky-200\",\n path: \"/dashboards\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.overview, path: \"/dashboards\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.health_center, path: \"/dashboards/health\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"health_monitor\" },\n ],\n },\n {\n id: \"datasets\",\n label: nav.datasets,\n icon: \"database\",\n tone: \"from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200\",\n path: \"/datasets\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_datasets, path: \"/datasets\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.dataset_review_workspace, path: \"/datasets/review\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"dataset_review\" },\n ],\n },\n {\n id: \"migration\",\n label: nav.migration,\n icon: \"layers\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/migration\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.migration_overview || \"Overview\", path: \"/migration\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.migration_mappings || \"Mappings\", path: \"/migration/mappings\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 2: Operations ────────────────────────────────\n const operations = {\n id: \"operations\",\n label: nav.section_operations,\n categories: [\n {\n id: \"git\",\n label: nav.git,\n icon: \"activity\",\n tone: \"from-purple-100 to-purple-200 text-purple-700 ring-purple-200\",\n path: \"/git\",\n subItems: [\n { label: nav.git_repo_status || \"Repository Status\", path: \"/git\" },\n ],\n },\n {\n id: \"translation\",\n label: nav.translation,\n icon: \"translate\",\n tone: \"from-cyan-100 to-teal-100 text-teal-700 ring-teal-200\",\n path: \"/translate\",\n requiredPermission: \"translate.job\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.translation_jobs, path: \"/translate\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n { label: nav.translation_dictionaries, path: \"/translate/dictionaries\", requiredPermission: \"translate.dictionary\", requiredAction: \"VIEW\" },\n { label: nav.translation_history, path: \"/translate/history\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"reports\",\n label: nav.reports,\n icon: \"reports\",\n tone: \"from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200\",\n path: \"/reports\",\n requiredPermission: \"tasks\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_reports || \"All Reports\", path: \"/reports\", requiredPermission: \"tasks\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 3: System ────────────────────────────────────\n const system = {\n id: \"system\",\n label: nav.section_system,\n categories: [\n {\n id: \"tools\",\n label: nav.tools,\n icon: \"list\",\n tone: \"from-slate-100 to-slate-200 text-slate-700 ring-slate-200\",\n path: \"/tools/mapper\",\n subItems: [\n { label: nav.tools_mapper, path: \"/tools/mapper\" },\n { label: nav.tools_debug, path: \"/tools/debug\" },\n { label: nav.tools_storage, path: \"/tools/storage\" },\n { label: nav.tools_backups, path: \"/tools/backups\" },\n ],\n },\n {\n id: \"storage\",\n label: nav.storage,\n icon: \"storage\",\n tone: \"from-amber-100 to-amber-200 text-amber-800 ring-amber-200\",\n path: \"/storage\",\n requiredPermission: \"plugin:storage\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.repositories, path: \"/storage/repos\", requiredPermission: \"plugin:storage\", requiredAction: \"READ\" },\n ],\n },\n {\n id: \"admin\",\n label: nav.admin,\n icon: \"admin\",\n tone: \"from-rose-100 to-rose-200 text-rose-700 ring-rose-200\",\n path: \"/admin/users\",\n subItems: [\n { label: nav.admin_users, path: \"/admin/users\", requiredPermission: \"admin:users\", requiredAction: \"READ\" },\n { label: nav.admin_roles, path: \"/admin/roles\", requiredPermission: \"admin:roles\", requiredAction: \"READ\" },\n { label: nav.admin_settings, path: \"/admin/settings\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n { label: nav.admin_llm, path: \"/admin/settings/llm\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n const allSections = [resources, operations, system];\n\n // Filter by permissions and features\n return allSections\n .map((section) => ({\n ...section,\n categories: section.categories\n .map((category) => {\n const visibleSubItems = (category.subItems || []).filter(\n (sub) => isItemAllowed(user, sub) && isFeatureEnabled(sub, features),\n );\n return { ...category, subItems: visibleSubItems };\n })\n .filter((category) => {\n if (!isItemAllowed(user, category)) return false;\n return Array.isArray(category.subItems) && category.subItems.length > 0;\n }),\n }))\n .filter((section) => section.categories.length > 0);\n}\n// #endregion buildSidebarSections:Function\n" + "body": "// #region buildSidebarSections:Function [TYPE Function]\n// @PURPOSE: Build translated sidebar sections with categories, filtered by RBAC permissions and feature flags.\n// @PRE: i18nState provides nav labels; user can be null; features default to {} (all enabled).\n// @POST: Returns only sections/categories/subitems available for provided user and enabled features.\nexport function buildSidebarSections(i18nState, user, features = {}) {\n const nav = i18nState?.nav || {};\n\n // ── Section 1: Resources ─────────────────────────────────\n const resources = {\n id: \"resources\",\n label: nav.section_resources,\n categories: [\n {\n id: \"dashboards\",\n label: nav.dashboards,\n icon: \"dashboard\",\n tone: \"from-sky-100 to-sky-200 text-sky-700 ring-sky-200\",\n path: \"/dashboards\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.overview, path: \"/dashboards\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.health_center, path: \"/dashboards/health\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"health_monitor\" },\n ],\n },\n {\n id: \"datasets\",\n label: nav.datasets,\n icon: \"database\",\n tone: \"from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200\",\n path: \"/datasets\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_datasets, path: \"/datasets\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.dataset_review_workspace, path: \"/datasets/review\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\", requiredFeature: \"dataset_review\" },\n ],\n },\n {\n id: \"migration\",\n label: nav.migration,\n icon: \"layers\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/migration\",\n requiredPermission: \"plugin:migration\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.migration_overview || \"Overview\", path: \"/migration\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n { label: nav.migration_mappings || \"Mappings\", path: \"/migration/mappings\", requiredPermission: \"plugin:migration\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 2: Operations ────────────────────────────────\n const operations = {\n id: \"operations\",\n label: nav.section_operations,\n categories: [\n {\n id: \"git\",\n label: nav.git,\n icon: \"activity\",\n tone: \"from-purple-100 to-purple-200 text-purple-700 ring-purple-200\",\n path: \"/git\",\n subItems: [\n { label: nav.git_repo_status || \"Repository Status\", path: \"/git\" },\n ],\n },\n {\n id: \"translation\",\n label: nav.translation,\n icon: \"translate\",\n tone: \"from-cyan-100 to-teal-100 text-teal-700 ring-teal-200\",\n path: \"/translate\",\n requiredPermission: \"translate.job\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.translation_jobs, path: \"/translate\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n { label: nav.translation_dictionaries, path: \"/translate/dictionaries\", requiredPermission: \"translate.dictionary\", requiredAction: \"VIEW\" },\n { label: nav.translation_history, path: \"/translate/history\", requiredPermission: \"translate.job\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"validation\",\n label: nav.validation,\n icon: \"activity\",\n tone: \"from-amber-100 to-yellow-100 text-amber-700 ring-amber-200\",\n path: \"/validation\",\n requiredPermission: \"validation.task\",\n requiredAction: \"VIEW\",\n subItems: [\n { label: nav.validation_tasks, path: \"/validation\", requiredPermission: \"validation.task\", requiredAction: \"VIEW\" },\n { label: nav.validation_history, path: \"/validation/history\", requiredPermission: \"validation.run\", requiredAction: \"VIEW\" },\n ],\n },\n {\n id: \"reports\",\n label: nav.reports,\n icon: \"reports\",\n tone: \"from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200\",\n path: \"/reports\",\n requiredPermission: \"tasks\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.all_reports || \"All Reports\", path: \"/reports\", requiredPermission: \"tasks\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n // ── Section 3: System ────────────────────────────────────\n const system = {\n id: \"system\",\n label: nav.section_system,\n categories: [\n {\n id: \"tools\",\n label: nav.tools,\n icon: \"list\",\n tone: \"from-slate-100 to-slate-200 text-slate-700 ring-slate-200\",\n path: \"/tools/mapper\",\n subItems: [\n { label: nav.tools_mapper, path: \"/tools/mapper\" },\n { label: nav.tools_debug, path: \"/tools/debug\" },\n { label: nav.tools_storage, path: \"/tools/storage\" },\n { label: nav.tools_backups, path: \"/tools/backups\" },\n ],\n },\n {\n id: \"storage\",\n label: nav.storage,\n icon: \"storage\",\n tone: \"from-amber-100 to-amber-200 text-amber-800 ring-amber-200\",\n path: \"/storage\",\n requiredPermission: \"plugin:storage\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.repositories, path: \"/storage/repos\", requiredPermission: \"plugin:storage\", requiredAction: \"READ\" },\n ],\n },\n {\n id: \"admin\",\n label: nav.admin,\n icon: \"admin\",\n tone: \"from-rose-100 to-rose-200 text-rose-700 ring-rose-200\",\n path: \"/admin/users\",\n subItems: [\n { label: nav.admin_users, path: \"/admin/users\", requiredPermission: \"admin:users\", requiredAction: \"READ\" },\n { label: nav.admin_roles, path: \"/admin/roles\", requiredPermission: \"admin:roles\", requiredAction: \"READ\" },\n { label: nav.admin_settings, path: \"/admin/settings\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n { label: nav.admin_llm, path: \"/admin/settings/llm\", requiredPermission: \"admin:settings\", requiredAction: \"READ\" },\n ],\n },\n ],\n };\n\n const allSections = [resources, operations, system];\n\n // Filter by permissions and features\n return allSections\n .map((section) => ({\n ...section,\n categories: section.categories\n .map((category) => {\n const visibleSubItems = (category.subItems || []).filter(\n (sub) => isItemAllowed(user, sub) && isFeatureEnabled(sub, features),\n );\n return { ...category, subItems: visibleSubItems };\n })\n .filter((category) => {\n if (!isItemAllowed(user, category)) return false;\n return Array.isArray(category.subItems) && category.subItems.length > 0;\n }),\n }))\n .filter((section) => section.categories.length > 0);\n}\n// #endregion buildSidebarSections:Function\n" }, { "contract_id": "ReportCardTest:Module", @@ -71466,7 +73397,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region I18nModule [C:3] [TYPE Module] [SEMANTICS i18n, localization, store, locale, translation]\n// @BRIEF Centralized internationalization management using Svelte stores with Russian and English locale support persisted in LocalStorage.\n// @RELATION DEPENDS_ON -> [LocaleEn]\n// @RELATION DEPENDS_ON -> [LocaleRu]\n\n// #region i18n:Module [TYPE Function]\n//\n// @SEMANTICS: i18n, localization, svelte-store, translation\n// @PURPOSE: Centralized internationalization management using Svelte stores.\n// @LAYER: Infra\n// @RELATION: DEPENDS_ON -> i18n_ru_locale\n// @RELATION: DEPENDS_ON -> i18n_en_locale\n//\n// @INVARIANT: Locale must be either 'ru' or 'en'.\n// @INVARIANT: Persistence is handled via LocalStorage.\n\n// [SECTION: IMPORTS]\nimport { writable, derived } from 'svelte/store';\n\n// Domain-split locale files (INV_7: each file < 400 lines)\nimport enCommon from './locales/en/common.json';\nimport enNav from './locales/en/nav.json';\nimport enHealth from './locales/en/health.json';\nimport enLlm from './locales/en/llm.json';\nimport enSettings from './locales/en/settings.json';\nimport enGit from './locales/en/git.json';\nimport enDashboard from './locales/en/dashboard.json';\nimport enProfile from './locales/en/profile.json';\nimport enReports from './locales/en/reports.json';\nimport enDatasets from './locales/en/datasets.json';\nimport enDatasetReview from './locales/en/dataset_review.json';\nimport enTasks from './locales/en/tasks.json';\nimport enDebug from './locales/en/debug.json';\nimport enAdmin from './locales/en/admin.json';\nimport enTranslate from './locales/en/translate.json';\nimport enAssistant from './locales/en/assistant.json';\nimport enAuth from './locales/en/auth.json';\nimport enConnections from './locales/en/connections.json';\nimport enMapper from './locales/en/mapper.json';\nimport enMigration from './locales/en/migration.json';\nimport enStorage from './locales/en/storage.json';\n\nimport ruCommon from './locales/ru/common.json';\nimport ruNav from './locales/ru/nav.json';\nimport ruHealth from './locales/ru/health.json';\nimport ruLlm from './locales/ru/llm.json';\nimport ruSettings from './locales/ru/settings.json';\nimport ruGit from './locales/ru/git.json';\nimport ruDashboard from './locales/ru/dashboard.json';\nimport ruProfile from './locales/ru/profile.json';\nimport ruReports from './locales/ru/reports.json';\nimport ruDatasets from './locales/ru/datasets.json';\nimport ruDatasetReview from './locales/ru/dataset_review.json';\nimport ruTasks from './locales/ru/tasks.json';\nimport ruDebug from './locales/ru/debug.json';\nimport ruAdmin from './locales/ru/admin.json';\nimport ruTranslate from './locales/ru/translate.json';\nimport ruAssistant from './locales/ru/assistant.json';\nimport ruAuth from './locales/ru/auth.json';\nimport ruConnections from './locales/ru/connections.json';\nimport ruMapper from './locales/ru/mapper.json';\nimport ruMigration from './locales/ru/migration.json';\nimport ruStorage from './locales/ru/storage.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tcommon: enCommon,\n\tnav: enNav,\n\thealth: enHealth,\n\tllm: enLlm,\n\tsettings: enSettings,\n\tgit: enGit,\n\tdashboard: enDashboard,\n\tprofile: enProfile,\n\treports: enReports,\n\tdatasets: enDatasets,\n\tdataset_review: enDatasetReview,\n\ttasks: enTasks,\n\tdebug: enDebug,\n\tadmin: enAdmin,\n\ttranslate: enTranslate,\n\tassistant: enAssistant,\n\tauth: enAuth,\n\tconnections: enConnections,\n\tmapper: enMapper,\n\tmigration: enMigration,\n\tstorage: enStorage,\n};\n\nconst ru = {\n\tcommon: ruCommon,\n\tnav: ruNav,\n\thealth: ruHealth,\n\tllm: ruLlm,\n\tsettings: ruSettings,\n\tgit: ruGit,\n\tdashboard: ruDashboard,\n\tprofile: ruProfile,\n\treports: ruReports,\n\tdatasets: ruDatasets,\n\tdataset_review: ruDatasetReview,\n\ttasks: ruTasks,\n\tdebug: ruDebug,\n\tadmin: ruAdmin,\n\ttranslate: ruTranslate,\n\tassistant: ruAssistant,\n\tauth: ruAuth,\n\tconnections: ruConnections,\n\tmapper: ruMapper,\n\tmigration: ruMigration,\n\tstorage: ruStorage,\n};\n\nconst translations = { ru, en };\ntype Locale = keyof typeof translations;\n\n/**\n * @purpose Determines the starting locale.\n * @returns {Locale}\n */\nconst getInitialLocale = (): Locale => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem('locale');\n if (saved === 'ru' || saved === 'en') return saved as Locale;\n }\n return 'ru';\n};\n\n// #region locale:Store [TYPE Function]\n/**\n * @purpose Holds the current active locale string.\n * @side_effect Writes to LocalStorage on change.\n */\nexport const locale = writable(getInitialLocale());\n\nif (typeof localStorage !== 'undefined') {\n locale.subscribe((val) => localStorage.setItem('locale', val));\n}\n// #endregion locale:Store\n\n// #region t:Store [TYPE Function]\n/**\n * @purpose Derived store providing the translation dictionary.\n * @relation BINDS_TO -> locale\n */\nexport const t = derived(locale, ($locale) => {\n const dictionary = (translations[$locale] || translations.ru) as any;\n return dictionary;\n});\n// #endregion t:Store\n\n// #region _:Function [TYPE Function]\n/**\n * @purpose Get translation by key path.\n * @param key - Translation key path (e.g., 'nav.dashboard')\n * @returns Translation string or key if not found\n */\nexport function _(key: string): string {\n const currentLocale = getInitialLocale();\n const dictionary = (translations[currentLocale] || translations.ru) as any;\n \n // Navigate through nested keys\n const keys = key.split('.');\n let value: any = dictionary;\n \n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k];\n } else {\n return key; // Return key if translation not found\n }\n }\n \n return typeof value === 'string' ? value : key;\n}\n// #endregion _:Function\n\n// #endregion i18n:Module\n// #endregion I18nModule\n" + "body": "// #region I18nModule [C:3] [TYPE Module] [SEMANTICS i18n, localization, store, locale, translation]\n// @BRIEF Centralized internationalization management using Svelte stores with Russian and English locale support persisted in LocalStorage.\n// @RELATION DEPENDS_ON -> [LocaleEn]\n// @RELATION DEPENDS_ON -> [LocaleRu]\n\n// #region i18n:Module [TYPE Function]\n//\n// @SEMANTICS: i18n, localization, svelte-store, translation\n// @PURPOSE: Centralized internationalization management using Svelte stores.\n// @LAYER: Infra\n// @RELATION: DEPENDS_ON -> i18n_ru_locale\n// @RELATION: DEPENDS_ON -> i18n_en_locale\n//\n// @INVARIANT: Locale must be either 'ru' or 'en'.\n// @INVARIANT: Persistence is handled via LocalStorage.\n\n// [SECTION: IMPORTS]\nimport { writable, derived } from 'svelte/store';\n\n// Domain-split locale files (INV_7: each file < 400 lines)\nimport enCommon from './locales/en/common.json';\nimport enNav from './locales/en/nav.json';\nimport enHealth from './locales/en/health.json';\nimport enLlm from './locales/en/llm.json';\nimport enSettings from './locales/en/settings.json';\nimport enGit from './locales/en/git.json';\nimport enDashboard from './locales/en/dashboard.json';\nimport enProfile from './locales/en/profile.json';\nimport enReports from './locales/en/reports.json';\nimport enDatasets from './locales/en/datasets.json';\nimport enDatasetReview from './locales/en/dataset_review.json';\nimport enTasks from './locales/en/tasks.json';\nimport enDebug from './locales/en/debug.json';\nimport enAdmin from './locales/en/admin.json';\nimport enTranslate from './locales/en/translate.json';\nimport enValidation from './locales/en/validation.json';\nimport enAssistant from './locales/en/assistant.json';\nimport enAuth from './locales/en/auth.json';\nimport enMapper from './locales/en/mapper.json';\nimport enMigration from './locales/en/migration.json';\nimport enStorage from './locales/en/storage.json';\n\nimport ruCommon from './locales/ru/common.json';\nimport ruNav from './locales/ru/nav.json';\nimport ruHealth from './locales/ru/health.json';\nimport ruLlm from './locales/ru/llm.json';\nimport ruSettings from './locales/ru/settings.json';\nimport ruGit from './locales/ru/git.json';\nimport ruDashboard from './locales/ru/dashboard.json';\nimport ruProfile from './locales/ru/profile.json';\nimport ruReports from './locales/ru/reports.json';\nimport ruDatasets from './locales/ru/datasets.json';\nimport ruDatasetReview from './locales/ru/dataset_review.json';\nimport ruTasks from './locales/ru/tasks.json';\nimport ruDebug from './locales/ru/debug.json';\nimport ruAdmin from './locales/ru/admin.json';\nimport ruTranslate from './locales/ru/translate.json';\nimport ruValidation from './locales/ru/validation.json';\nimport ruAssistant from './locales/ru/assistant.json';\nimport ruAuth from './locales/ru/auth.json';\nimport ruMapper from './locales/ru/mapper.json';\nimport ruMigration from './locales/ru/migration.json';\nimport ruStorage from './locales/ru/storage.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tcommon: enCommon,\n\tnav: enNav,\n\thealth: enHealth,\n\tllm: enLlm,\n\tsettings: enSettings,\n\tgit: enGit,\n\tdashboard: enDashboard,\n\tprofile: enProfile,\n\treports: enReports,\n\tdatasets: enDatasets,\n\tdataset_review: enDatasetReview,\n\ttasks: enTasks,\n\tdebug: enDebug,\n\tadmin: enAdmin,\n\ttranslate: enTranslate,\n\tvalidation: enValidation,\n\tassistant: enAssistant,\n\tauth: enAuth,\n\tmapper: enMapper,\n\tmigration: enMigration,\n\tstorage: enStorage,\n};\n\nconst ru = {\n\tcommon: ruCommon,\n\tnav: ruNav,\n\thealth: ruHealth,\n\tllm: ruLlm,\n\tsettings: ruSettings,\n\tgit: ruGit,\n\tdashboard: ruDashboard,\n\tprofile: ruProfile,\n\treports: ruReports,\n\tdatasets: ruDatasets,\n\tdataset_review: ruDatasetReview,\n\ttasks: ruTasks,\n\tdebug: ruDebug,\n\tadmin: ruAdmin,\n\ttranslate: ruTranslate,\n\tvalidation: ruValidation,\n\tassistant: ruAssistant,\n\tauth: ruAuth,\n\tmapper: ruMapper,\n\tmigration: ruMigration,\n\tstorage: ruStorage,\n};\n\nconst translations = { ru, en };\ntype Locale = keyof typeof translations;\n\n/**\n * @purpose Determines the starting locale.\n * @returns {Locale}\n */\nconst getInitialLocale = (): Locale => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem('locale');\n if (saved === 'ru' || saved === 'en') return saved as Locale;\n }\n return 'ru';\n};\n\n// #region locale:Store [TYPE Function]\n/**\n * @purpose Holds the current active locale string.\n * @side_effect Writes to LocalStorage on change.\n */\nexport const locale = writable(getInitialLocale());\n\nif (typeof localStorage !== 'undefined') {\n locale.subscribe((val) => localStorage.setItem('locale', val));\n}\n// #endregion locale:Store\n\n// #region t:Store [TYPE Function]\n/**\n * @purpose Derived store providing the translation dictionary.\n * @relation BINDS_TO -> locale\n */\nexport const t = derived(locale, ($locale) => {\n const dictionary = (translations[$locale] || translations.ru) as any;\n return dictionary;\n});\n// #endregion t:Store\n\n// #region _:Function [TYPE Function]\n/**\n * @purpose Get translation by key path.\n * @param key - Translation key path (e.g., 'nav.dashboard')\n * @returns Translation string or key if not found\n */\nexport function _(key: string): string {\n const currentLocale = getInitialLocale();\n const dictionary = (translations[currentLocale] || translations.ru) as any;\n \n // Navigate through nested keys\n const keys = key.split('.');\n let value: any = dictionary;\n \n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k];\n } else {\n return key; // Return key if translation not found\n }\n }\n \n return typeof value === 'string' ? value : key;\n}\n// #endregion _:Function\n\n// #endregion i18n:Module\n// #endregion I18nModule\n" }, { "contract_id": "i18n:Module", @@ -71545,7 +73476,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region i18n:Module [TYPE Function]\n//\n// @SEMANTICS: i18n, localization, svelte-store, translation\n// @PURPOSE: Centralized internationalization management using Svelte stores.\n// @LAYER: Infra\n// @RELATION: DEPENDS_ON -> i18n_ru_locale\n// @RELATION: DEPENDS_ON -> i18n_en_locale\n//\n// @INVARIANT: Locale must be either 'ru' or 'en'.\n// @INVARIANT: Persistence is handled via LocalStorage.\n\n// [SECTION: IMPORTS]\nimport { writable, derived } from 'svelte/store';\n\n// Domain-split locale files (INV_7: each file < 400 lines)\nimport enCommon from './locales/en/common.json';\nimport enNav from './locales/en/nav.json';\nimport enHealth from './locales/en/health.json';\nimport enLlm from './locales/en/llm.json';\nimport enSettings from './locales/en/settings.json';\nimport enGit from './locales/en/git.json';\nimport enDashboard from './locales/en/dashboard.json';\nimport enProfile from './locales/en/profile.json';\nimport enReports from './locales/en/reports.json';\nimport enDatasets from './locales/en/datasets.json';\nimport enDatasetReview from './locales/en/dataset_review.json';\nimport enTasks from './locales/en/tasks.json';\nimport enDebug from './locales/en/debug.json';\nimport enAdmin from './locales/en/admin.json';\nimport enTranslate from './locales/en/translate.json';\nimport enAssistant from './locales/en/assistant.json';\nimport enAuth from './locales/en/auth.json';\nimport enConnections from './locales/en/connections.json';\nimport enMapper from './locales/en/mapper.json';\nimport enMigration from './locales/en/migration.json';\nimport enStorage from './locales/en/storage.json';\n\nimport ruCommon from './locales/ru/common.json';\nimport ruNav from './locales/ru/nav.json';\nimport ruHealth from './locales/ru/health.json';\nimport ruLlm from './locales/ru/llm.json';\nimport ruSettings from './locales/ru/settings.json';\nimport ruGit from './locales/ru/git.json';\nimport ruDashboard from './locales/ru/dashboard.json';\nimport ruProfile from './locales/ru/profile.json';\nimport ruReports from './locales/ru/reports.json';\nimport ruDatasets from './locales/ru/datasets.json';\nimport ruDatasetReview from './locales/ru/dataset_review.json';\nimport ruTasks from './locales/ru/tasks.json';\nimport ruDebug from './locales/ru/debug.json';\nimport ruAdmin from './locales/ru/admin.json';\nimport ruTranslate from './locales/ru/translate.json';\nimport ruAssistant from './locales/ru/assistant.json';\nimport ruAuth from './locales/ru/auth.json';\nimport ruConnections from './locales/ru/connections.json';\nimport ruMapper from './locales/ru/mapper.json';\nimport ruMigration from './locales/ru/migration.json';\nimport ruStorage from './locales/ru/storage.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tcommon: enCommon,\n\tnav: enNav,\n\thealth: enHealth,\n\tllm: enLlm,\n\tsettings: enSettings,\n\tgit: enGit,\n\tdashboard: enDashboard,\n\tprofile: enProfile,\n\treports: enReports,\n\tdatasets: enDatasets,\n\tdataset_review: enDatasetReview,\n\ttasks: enTasks,\n\tdebug: enDebug,\n\tadmin: enAdmin,\n\ttranslate: enTranslate,\n\tassistant: enAssistant,\n\tauth: enAuth,\n\tconnections: enConnections,\n\tmapper: enMapper,\n\tmigration: enMigration,\n\tstorage: enStorage,\n};\n\nconst ru = {\n\tcommon: ruCommon,\n\tnav: ruNav,\n\thealth: ruHealth,\n\tllm: ruLlm,\n\tsettings: ruSettings,\n\tgit: ruGit,\n\tdashboard: ruDashboard,\n\tprofile: ruProfile,\n\treports: ruReports,\n\tdatasets: ruDatasets,\n\tdataset_review: ruDatasetReview,\n\ttasks: ruTasks,\n\tdebug: ruDebug,\n\tadmin: ruAdmin,\n\ttranslate: ruTranslate,\n\tassistant: ruAssistant,\n\tauth: ruAuth,\n\tconnections: ruConnections,\n\tmapper: ruMapper,\n\tmigration: ruMigration,\n\tstorage: ruStorage,\n};\n\nconst translations = { ru, en };\ntype Locale = keyof typeof translations;\n\n/**\n * @purpose Determines the starting locale.\n * @returns {Locale}\n */\nconst getInitialLocale = (): Locale => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem('locale');\n if (saved === 'ru' || saved === 'en') return saved as Locale;\n }\n return 'ru';\n};\n\n// #region locale:Store [TYPE Function]\n/**\n * @purpose Holds the current active locale string.\n * @side_effect Writes to LocalStorage on change.\n */\nexport const locale = writable(getInitialLocale());\n\nif (typeof localStorage !== 'undefined') {\n locale.subscribe((val) => localStorage.setItem('locale', val));\n}\n// #endregion locale:Store\n\n// #region t:Store [TYPE Function]\n/**\n * @purpose Derived store providing the translation dictionary.\n * @relation BINDS_TO -> locale\n */\nexport const t = derived(locale, ($locale) => {\n const dictionary = (translations[$locale] || translations.ru) as any;\n return dictionary;\n});\n// #endregion t:Store\n\n// #region _:Function [TYPE Function]\n/**\n * @purpose Get translation by key path.\n * @param key - Translation key path (e.g., 'nav.dashboard')\n * @returns Translation string or key if not found\n */\nexport function _(key: string): string {\n const currentLocale = getInitialLocale();\n const dictionary = (translations[currentLocale] || translations.ru) as any;\n \n // Navigate through nested keys\n const keys = key.split('.');\n let value: any = dictionary;\n \n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k];\n } else {\n return key; // Return key if translation not found\n }\n }\n \n return typeof value === 'string' ? value : key;\n}\n// #endregion _:Function\n\n// #endregion i18n:Module\n" + "body": "// #region i18n:Module [TYPE Function]\n//\n// @SEMANTICS: i18n, localization, svelte-store, translation\n// @PURPOSE: Centralized internationalization management using Svelte stores.\n// @LAYER: Infra\n// @RELATION: DEPENDS_ON -> i18n_ru_locale\n// @RELATION: DEPENDS_ON -> i18n_en_locale\n//\n// @INVARIANT: Locale must be either 'ru' or 'en'.\n// @INVARIANT: Persistence is handled via LocalStorage.\n\n// [SECTION: IMPORTS]\nimport { writable, derived } from 'svelte/store';\n\n// Domain-split locale files (INV_7: each file < 400 lines)\nimport enCommon from './locales/en/common.json';\nimport enNav from './locales/en/nav.json';\nimport enHealth from './locales/en/health.json';\nimport enLlm from './locales/en/llm.json';\nimport enSettings from './locales/en/settings.json';\nimport enGit from './locales/en/git.json';\nimport enDashboard from './locales/en/dashboard.json';\nimport enProfile from './locales/en/profile.json';\nimport enReports from './locales/en/reports.json';\nimport enDatasets from './locales/en/datasets.json';\nimport enDatasetReview from './locales/en/dataset_review.json';\nimport enTasks from './locales/en/tasks.json';\nimport enDebug from './locales/en/debug.json';\nimport enAdmin from './locales/en/admin.json';\nimport enTranslate from './locales/en/translate.json';\nimport enValidation from './locales/en/validation.json';\nimport enAssistant from './locales/en/assistant.json';\nimport enAuth from './locales/en/auth.json';\nimport enMapper from './locales/en/mapper.json';\nimport enMigration from './locales/en/migration.json';\nimport enStorage from './locales/en/storage.json';\n\nimport ruCommon from './locales/ru/common.json';\nimport ruNav from './locales/ru/nav.json';\nimport ruHealth from './locales/ru/health.json';\nimport ruLlm from './locales/ru/llm.json';\nimport ruSettings from './locales/ru/settings.json';\nimport ruGit from './locales/ru/git.json';\nimport ruDashboard from './locales/ru/dashboard.json';\nimport ruProfile from './locales/ru/profile.json';\nimport ruReports from './locales/ru/reports.json';\nimport ruDatasets from './locales/ru/datasets.json';\nimport ruDatasetReview from './locales/ru/dataset_review.json';\nimport ruTasks from './locales/ru/tasks.json';\nimport ruDebug from './locales/ru/debug.json';\nimport ruAdmin from './locales/ru/admin.json';\nimport ruTranslate from './locales/ru/translate.json';\nimport ruValidation from './locales/ru/validation.json';\nimport ruAssistant from './locales/ru/assistant.json';\nimport ruAuth from './locales/ru/auth.json';\nimport ruMapper from './locales/ru/mapper.json';\nimport ruMigration from './locales/ru/migration.json';\nimport ruStorage from './locales/ru/storage.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tcommon: enCommon,\n\tnav: enNav,\n\thealth: enHealth,\n\tllm: enLlm,\n\tsettings: enSettings,\n\tgit: enGit,\n\tdashboard: enDashboard,\n\tprofile: enProfile,\n\treports: enReports,\n\tdatasets: enDatasets,\n\tdataset_review: enDatasetReview,\n\ttasks: enTasks,\n\tdebug: enDebug,\n\tadmin: enAdmin,\n\ttranslate: enTranslate,\n\tvalidation: enValidation,\n\tassistant: enAssistant,\n\tauth: enAuth,\n\tmapper: enMapper,\n\tmigration: enMigration,\n\tstorage: enStorage,\n};\n\nconst ru = {\n\tcommon: ruCommon,\n\tnav: ruNav,\n\thealth: ruHealth,\n\tllm: ruLlm,\n\tsettings: ruSettings,\n\tgit: ruGit,\n\tdashboard: ruDashboard,\n\tprofile: ruProfile,\n\treports: ruReports,\n\tdatasets: ruDatasets,\n\tdataset_review: ruDatasetReview,\n\ttasks: ruTasks,\n\tdebug: ruDebug,\n\tadmin: ruAdmin,\n\ttranslate: ruTranslate,\n\tvalidation: ruValidation,\n\tassistant: ruAssistant,\n\tauth: ruAuth,\n\tmapper: ruMapper,\n\tmigration: ruMigration,\n\tstorage: ruStorage,\n};\n\nconst translations = { ru, en };\ntype Locale = keyof typeof translations;\n\n/**\n * @purpose Determines the starting locale.\n * @returns {Locale}\n */\nconst getInitialLocale = (): Locale => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem('locale');\n if (saved === 'ru' || saved === 'en') return saved as Locale;\n }\n return 'ru';\n};\n\n// #region locale:Store [TYPE Function]\n/**\n * @purpose Holds the current active locale string.\n * @side_effect Writes to LocalStorage on change.\n */\nexport const locale = writable(getInitialLocale());\n\nif (typeof localStorage !== 'undefined') {\n locale.subscribe((val) => localStorage.setItem('locale', val));\n}\n// #endregion locale:Store\n\n// #region t:Store [TYPE Function]\n/**\n * @purpose Derived store providing the translation dictionary.\n * @relation BINDS_TO -> locale\n */\nexport const t = derived(locale, ($locale) => {\n const dictionary = (translations[$locale] || translations.ru) as any;\n return dictionary;\n});\n// #endregion t:Store\n\n// #region _:Function [TYPE Function]\n/**\n * @purpose Get translation by key path.\n * @param key - Translation key path (e.g., 'nav.dashboard')\n * @returns Translation string or key if not found\n */\nexport function _(key: string): string {\n const currentLocale = getInitialLocale();\n const dictionary = (translations[currentLocale] || translations.ru) as any;\n \n // Navigate through nested keys\n const keys = key.split('.');\n let value: any = dictionary;\n \n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k];\n } else {\n return key; // Return key if translation not found\n }\n }\n \n return typeof value === 'string' ? value : key;\n}\n// #endregion _:Function\n\n// #endregion i18n:Module\n" }, { "contract_id": "locale:Store", @@ -78237,6 +80168,330 @@ "tier_source": "AutoCalculated", "body": "// #region HealthPageIntegrationTest:Module [TYPE Function]\n// @SEMANTICS: health-page, integration-test, slug-link, delete-flow\n// @PURPOSE: Lock dashboard health page contract for slug navigation and report deletion.\n// @LAYER: UI Tests\n// @RELATION: DEPENDS_ON -> [HealthCenterPage]\n\nimport { describe, it, expect } from 'vitest';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst PAGE_PATH = path.resolve(\n process.cwd(),\n 'src/routes/dashboards/health/+page.svelte',\n);\n\ndescribe('Dashboard health page contract', () => {\n it('renders slug-first dashboard link bound to environment route context', () => {\n const source = fs.readFileSync(PAGE_PATH, 'utf-8');\n\n expect(source).toContain(\"{$t.health?.table_dashboard}\");\n expect(source).toContain(\"item.dashboard_slug || item.dashboard_id\");\n expect(source).toContain(\"href={`/dashboards/${encodeURIComponent(String(item.dashboard_slug || item.dashboard_id))}?env_id=${encodeURIComponent(item.environment_id)}`}\");\n });\n\n it('keeps explicit delete report flow with confirm and DELETE request', () => {\n const source = fs.readFileSync(PAGE_PATH, 'utf-8');\n\n expect(source).toContain('async function handleDeleteReport(item)');\n expect(source).toContain(\"requestApi(`/health/summary/${item.record_id}`, 'DELETE')\");\n expect(source).toContain(\"$t.health?.delete_confirm.replace('{slug}', item.dashboard_slug || item.dashboard_id)\");\n expect(source).toContain(\"$t.common?.delete\");\n });\n\n it('reuses global health store refresh for all-environment summary loads', () => {\n const source = fs.readFileSync(PAGE_PATH, 'utf-8');\n\n expect(source).toContain(\"import { healthStore } from '$lib/stores/health.js';\");\n expect(source).toContain('? getHealthSummary(selectedEnvId)');\n expect(source).toContain(': healthStore.refresh();');\n });\n});\n// #endregion HealthPageIntegrationTest:Module\n" }, + { + "contract_id": "DatasetHub", + "contract_type": "Page", + "file_path": "frontend/src/routes/datasets/+page.svelte", + "start_line": 1, + "end_line": 407, + "tier": "TIER_3", + "complexity": 5, + "metadata": { + "COMPLEXITY": 5 + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Page' at C5", + "detail": { + "actual_complexity": 5, + "contract_type": "Page" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n
\n \n
\n

{$t.nav?.datasets}

\n
\n \n {$t.datasets?.all}: {stats?.total ?? 0}\n \n \n
\n
\n\n \n {#if dsError}\n
\n {dsError}\n \n
\n {/if}\n\n \n \n\n \n
\n \n
\n \n
\n\n \n {#if isMobile && mobileSlideOpen}\n \n \n \n \n
\n {detailData?.table_name ?? $t.datasets?.no_selection}\n \n
\n detailData && loadDetail(detailData.id)} envId={selectedEnv} />\n
\n {:else if !isMobile}\n
\n selectedDatasetId && loadDetail(selectedDatasetId)} envId={selectedEnv} />\n
\n {/if}\n
\n\n \n {#if selectedIds.size >= 2}\n
\n
\n ✓ {selectedIds.size} {$t.datasets?.selected}\n
\n \n \n \n
\n
\n
\n {/if}\n\n \n {#if showMapColumnsModal}\n
{ if (e.target === e.currentTarget) showMapColumnsModal = false; }}>\n
e.stopPropagation()}>\n

{$t.datasets?.bulk_map_columns}

\n

{$t.datasets?.selected_count?.replace('{count}', String(selectedIds.size))}

\n \n {#if mapSourceType === \"sqllab\"}\n \n \n \n \n {:else}\n mapFileData = e.target.files} />\n {/if}\n
\n \n \n
\n
\n
\n {/if}\n\n \n {#if showGenerateDocsModal}\n
{ if (e.target === e.currentTarget) showGenerateDocsModal = false; }}>\n
e.stopPropagation()}>\n

{$t.datasets?.bulk_docs_generation}

\n

{$t.datasets?.selected_count?.replace('{count}', String(selectedIds.size))}

\n \n
\n \n \n
\n
\n
\n {/if}\n\n\n" + }, + { + "contract_id": "ColumnsTable", + "contract_type": "Component", + "file_path": "frontend/src/routes/datasets/ColumnsTable.svelte", + "start_line": 1, + "end_line": 135, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "LAYER": "UI", + "PURPOSE": "Table of dataset columns with type chips, description, and inline-edit capability.", + "UX_REACTIVITY": "Props -> columns, datasetId", + "UX_STATE": "Editing -> One row in edit mode (textarea), others dimmed." + }, + "relations": [ + { + "source_id": "ColumnsTable", + "relation_type": "CALLS", + "target_id": "api_module", + "target_ref": "[api_module]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Component'", + "detail": { + "actual_type": "Component", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Component' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Component" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n
\n \n \n \n \n \n \n \n \n \n \n {#if columns.length === 0}\n \n {:else}\n {#each columns as col (col.id)}\n \n \n \n \n \n \n {/each}\n {/if}\n \n
{$t.datasets?.table_name ?? 'Column'}{$t.dashboard?.type ?? 'Type'}{$t.dashboard?.description ?? 'Description'}
{$t.datasets?.detail_empty ?? 'No data'}
\n {#if col.verbose_name}\n {col.verbose_name}\n {:else}\n {col.name}\n {/if}\n \n \n {col.type ?? '—'}\n \n \n {#if editingRowId === col.id}\n
\n \n {#if editError}\n {editError}\n {/if}\n
\n saveEdit(col)}\n disabled={isSaving}\n >{isSaving ? '...' : ($t.datasets?.save_description ?? 'Save')}\n {$t.common?.cancel ?? 'Cancel'}\n
\n
\n {:else if col.description}\n {col.description}\n {:else}\n {'✏️ ' + ($t.datasets?.add_description ?? 'Add description')}\n {/if}\n
\n {#if editingRowId !== col.id}\n startEdit(col)}\n aria-label={$t.datasets?.add_description ?? 'Edit'}\n >✏️\n {/if}\n
\n
\n\n" + }, + { + "contract_id": "DatasetList", + "contract_type": "Component", + "file_path": "frontend/src/routes/datasets/DatasetList.svelte", + "start_line": 1, + "end_line": 168, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "LAYER": "UI", + "PURPOSE": "Renders paginated dataset cards with mapping progress bars, checkboxes, and quick actions.", + "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." + }, + "relations": [ + { + "source_id": "DatasetList", + "relation_type": "BINDS_TO", + "target_id": "environmentContextStore", + "target_ref": "[environmentContextStore]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Component'", + "detail": { + "actual_type": "Component", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Component' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Component" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n \n
\n { selectedIds = new Set(datasets.map(d => d.id)); oncheckbox?.({}, 'all'); }}\n >{$t.datasets?.select_all}\n { selectedIds = new Set(); oncheckbox?.({}, 'clear-all'); }}\n >{$t.datasets?.deselect_all}\n
\n
\n\n\n{#if isLoading}\n
\n {#each Array(3) as _}\n
\n
\n
\n
\n
\n {/each}\n
\n{:else if error}\n
\n {error}\n
\n{:else if datasets.length === 0}\n
{$t.datasets?.empty}
\n{:else}\n \n
\n {#each datasets as dataset}\n handleCardClick(dataset, e)}\n role=\"button\"\n tabindex=\"0\"\n >\n
\n \n handleCheckboxChange(dataset, e)}\n />\n \n
\n
{dataset.table_name}
\n
\n {dataset.schema ?? '-'}\n {dataset.column_count ?? 0} {$t.datasets?.columns?.toLowerCase() ?? 'columns'}\n {#if dataset.metric_count > 0}\n {dataset.metric_count} {$t.datasets?.metric_count ?? 'metrics'}\n {/if}\n
\n \n {#if dataset.mappedFields?.total}\n
\n
\n
\n
\n
\n {dataset.mappedFields.mapped}/{dataset.mappedFields.total} {$t.datasets?.mapped_of_total}\n
\n
\n {/if}\n
\n \n
\n { e.stopPropagation(); onaction?.(dataset, 'map_columns'); }}\n >{$t.datasets?.action_map_columns}\n { e.stopPropagation(); onaction?.(dataset, 'generate_docs'); }}\n >{$t.datasets?.generate_docs}\n
\n
\n \n {/each}\n \n\n \n {#if totalPages > 1}\n
\n \n {($t.datasets?.showing ?? 'Showing {start}-{end} of {total}').replace('{start}', String((page - 1) * pageSize + 1)).replace('{end}', String(Math.min(page * pageSize, total))).replace('{total}', String(total))}\n \n
\n \n \n {page} / {totalPages}\n \n \n
\n
\n {/if}\n{/if}\n\n" + }, + { + "contract_id": "DatasetPreview", + "contract_type": "Component", + "file_path": "frontend/src/routes/datasets/DatasetPreview.svelte", + "start_line": 1, + "end_line": 84, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "UI", + "PURPOSE": "Right panel showing dataset detail: header info, columns table, metrics table, linked dashboards. Presentational.", + "UX_STATE": "Error -> Error banner with retry." + }, + "relations": [ + { + "source_id": "DatasetPreview", + "relation_type": "DEPENDS_ON", + "target_id": "ColumnsTable", + "target_ref": "[ColumnsTable]" + }, + { + "source_id": "DatasetPreview", + "relation_type": "DEPENDS_ON", + "target_id": "MetricsTable", + "target_ref": "[MetricsTable]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Component'", + "detail": { + "actual_type": "Component", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Component' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Component" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n{#if isLoading}\n
\n
\n
\n
\n {#each Array(3) as _, i (i)}\n
\n {/each}\n
\n
\n{:else if error}\n
\n
{error}
\n {#if onretry}\n \n {/if}\n
\n{:else if !dataset}\n
\n
\n \n

{$t.datasets?.no_selection ?? 'Select a dataset from the list'}

\n
\n
\n{:else}\n
\n \n
\n

{dataset.table_name ?? dataset.id}

\n
\n {#if dataset.schema}📁 {dataset.schema}{/if}\n {dataset.column_count ?? 0} {$t.datasets?.columns?.toLowerCase() ?? 'columns'}\n {dataset.metric_count ?? 0} {$t.datasets?.metric_count ?? 'metrics'}\n {#if dataset.linked_dashboard_count > 0}\n 📊 {dataset.linked_dashboard_count} dashboards\n {/if}\n
\n {#if dataset.linked_dashboards?.length}\n
\n {#each dataset.linked_dashboards as dash}\n \n {dash.title}\n \n {/each}\n
\n {/if}\n {#if dataset.created_on}\n
{$t.dashboard?.created ?? 'Created'}: {dataset.created_on}
\n {/if}\n
\n\n \n
\n

{$t.datasets?.columns ?? 'Columns'} ({dataset.column_count ?? 0})

\n \n
\n\n \n
\n

{$t.datasets?.metrics ?? 'Metrics'} ({dataset.metric_count ?? 0})

\n \n
\n
\n{/if}\n\n" + }, + { + "contract_id": "MetricsTable", + "contract_type": "Component", + "file_path": "frontend/src/routes/datasets/MetricsTable.svelte", + "start_line": 1, + "end_line": 121, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "LAYER": "UI", + "PURPOSE": "Table of dataset metrics with expression, description, and inline-edit capability.", + "UX_REACTIVITY": "Props -> metrics, datasetId", + "UX_STATE": "Editing -> One row in edit mode." + }, + "relations": [ + { + "source_id": "MetricsTable", + "relation_type": "CALLS", + "target_id": "api_module", + "target_ref": "[api_module]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Component'", + "detail": { + "actual_type": "Component", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Component' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Component" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n
\n \n \n \n \n \n \n \n \n \n {#if metrics.length === 0}\n \n {:else}\n {#each metrics as metric (metric.id)}\n \n \n \n \n \n {/each}\n {/if}\n \n
{$t.datasets?.metrics ?? 'Metric'}{$t.dashboard?.description ?? 'Description'}
{$t.datasets?.detail_empty ?? 'No data'}
\n {#if metric.verbose_name}\n {metric.verbose_name}\n {:else}\n {metric.metric_name}\n {/if}\n {#if !metric.description && metric.expression}\n
{metric.expression}
\n {/if}\n
\n {#if editingRowId === metric.id}\n
\n \n {#if editError}\n {editError}\n {/if}\n
\n saveEdit(metric)}\n disabled={isSaving}\n >{isSaving ? '...' : ($t.datasets?.save_description ?? 'Save')}\n {$t.common?.cancel ?? 'Cancel'}\n
\n
\n {:else if metric.description}\n {metric.description}\n {:else}\n {'✏️ ' + ($t.datasets?.add_description ?? 'Add description')}\n {/if}\n
\n {#if editingRowId !== metric.id}\n startEdit(metric)}\n aria-label={$t.datasets?.add_description ?? 'Edit'}\n >✏️\n {/if}\n
\n
\n\n" + }, + { + "contract_id": "StatsBar", + "contract_type": "Component", + "file_path": "frontend/src/routes/datasets/StatsBar.svelte", + "start_line": 1, + "end_line": 51, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "UI", + "PURPOSE": "Displays 4 aggregate metric tiles (All, Without mapping, Mapped, Linked) and emits filter selection.", + "TYPE": "{{ stats: import('./types').StatsCounts | null, activeFilter: string | null, isLoading?: boolean }}", + "UX_REACTIVITY": "Events -> onfilter(filterKey) dispatched on tile click; parent calls loadDatasets(filter=filterKey).", + "UX_STATE": "Filtered -> Selected tile has accent border; parent triggers API reload with filter param." + }, + "relations": [ + { + "source_id": "StatsBar", + "relation_type": "BINDS_TO", + "target_id": "environmentContextStore", + "target_ref": "[environmentContextStore]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Component'", + "detail": { + "actual_type": "Component", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Component' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Component" + } + }, + { + "code": "invalid_enum_value", + "tag": "TYPE", + "message": "@TYPE value '{{ stats: import('./types').StatsCounts | null, activeFilter: string | null, isLoading?: boolean }}' is not in allowed enum", + "detail": { + "allowed": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Tombstone", + "Skill", + "Agent" + ], + "value": "{{ stats: import('./types').StatsCounts | null, activeFilter: string | null, isLoading?: boolean }}" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n {#each tiles as tile (tile.key)}\n {#if isLoading}\n
\n
\n
\n
\n {:else}\n handleTileClick(tile.key)}\n aria-pressed={activeFilter === tile.key}\n >\n
{$t.datasets?.[tile.label] ?? tile.label}
\n
{tile.getCount(stats)}
\n \n {/if}\n {/each}\n
\n\n" + }, { "contract_id": "DatasetReviewWorkspaceEntry", "contract_type": "Page", @@ -81275,7 +83530,7 @@ "contract_type": "Page", "file_path": "frontend/src/routes/settings/+page.svelte", "start_line": 1, - "end_line": 291, + "end_line": 274, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -81306,12 +83561,6 @@ "target_id": "LoggingSettings", "target_ref": "[LoggingSettings]" }, - { - "source_id": "SettingsPage", - "relation_type": "DEPENDS_ON", - "target_id": "DatabaseConnectionsTab", - "target_ref": "[DatabaseConnectionsTab]" - }, { "source_id": "SettingsPage", "relation_type": "DEPENDS_ON", @@ -81689,7 +83938,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n \n
\n

\n {$t.settings?.title}\n

\n \n {$t.common?.refresh}\n \n
\n\n \n {#if error}\n \n {error}\n \n {$t.common?.retry}\n \n
\n {/if}\n\n \n {#if isLoading}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n {:else if settings}\n \n
\n handleTabChange(\"environments\")}\n >\n {$t.settings?.environments}\n \n handleTabChange(\"logging\")}\n >\n {$t.settings?.logging}\n \n handleTabChange(\"connections\")}\n >\n {$t.settings?.connections}\n \n handleTabChange(\"git\")}\n >\n {$t.nav?.settings_git || $t.nav?.git || \"Git\"}\n \n handleTabChange(\"llm\")}\n >\n {$t.settings?.llm}\n \n handleTabChange(\"migration\")}\n >\n {$t.settings?.migration_sync}\n \n handleTabChange(\"storage\")}\n >\n {$t.settings?.storage}\n \n handleTabChange(\"features\")}\n >\n {$t.settings?.features || \"Features\"}\n \n handleTabChange(\"automation\")}\n >\n {$t.settings?.automation || \"Automation\"}\n \n
\n\n \n
\n {#if activeTab === \"environments\"}\n \n {:else if activeTab === \"logging\"}\n \n {:else if activeTab === \"connections\"}\n \n {:else if activeTab === \"git\"}\n \n {:else if activeTab === \"llm\"}\n \n {:else if activeTab === \"migration\"}\n \n {:else if activeTab === \"storage\"}\n \n {:else if activeTab === \"features\"}\n \n {:else if activeTab === \"automation\"}\n \n {/if}\n
\n {/if}\n\n\n" + "body": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n \n
\n

\n {$t.settings?.title}\n

\n \n {$t.common?.refresh}\n \n
\n\n \n {#if error}\n \n {error}\n \n {$t.common?.retry}\n \n
\n {/if}\n\n \n {#if isLoading}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n {:else if settings}\n \n
\n handleTabChange(\"environments\")}\n >\n {$t.settings?.environments}\n \n handleTabChange(\"logging\")}\n >\n {$t.settings?.logging}\n \n handleTabChange(\"git\")}\n >\n {$t.nav?.settings_git || $t.nav?.git || \"Git\"}\n \n handleTabChange(\"llm\")}\n >\n {$t.settings?.llm}\n \n handleTabChange(\"migration\")}\n >\n {$t.settings?.migration_sync}\n \n handleTabChange(\"storage\")}\n >\n {$t.settings?.storage}\n \n handleTabChange(\"features\")}\n >\n {$t.settings?.features || \"Features\"}\n \n handleTabChange(\"automation\")}\n >\n {$t.settings?.automation || \"Automation\"}\n \n
\n\n \n
\n {#if activeTab === \"environments\"}\n \n {:else if activeTab === \"logging\"}\n \n {:else if activeTab === \"git\"}\n \n {:else if activeTab === \"llm\"}\n \n {:else if activeTab === \"migration\"}\n \n {:else if activeTab === \"storage\"}\n \n {:else if activeTab === \"features\"}\n \n {:else if activeTab === \"automation\"}\n \n {/if}\n
\n {/if}\n\n\n" }, { "contract_id": "frontend/src/routes/settings/+page.ts::load", @@ -81706,59 +83955,6 @@ "tier_source": "AutoCalculated", "body": "/** @type {import('./$types').PageLoad} */" }, - { - "contract_id": "DatabaseConnectionsTab", - "contract_type": "Component", - "file_path": "frontend/src/routes/settings/DatabaseConnectionsTab.svelte", - "start_line": 1, - "end_line": 342, - "tier": "TIER_2", - "complexity": 3, - "metadata": { - "COMPLEXITY": 3, - "LAYER": "UI", - "POST": "Connections list is displayed; user can create and delete connections.", - "PRE": "API client is initialized.", - "PURPOSE": "Database connections management tab: list, create, delete external DB connections.", - "UX_FEEDBACK": "Toast on create/delete success/failure.", - "UX_STATE": "FormVisible -> Connection creation form displayed." - }, - "relations": [ - { - "source_id": "DatabaseConnectionsTab", - "relation_type": "CALLS", - "target_id": "api_module", - "target_ref": "[api_module]" - } - ], - "schema_warnings": [ - { - "code": "tag_not_for_contract_type", - "tag": "LAYER", - "message": "@LAYER is not allowed for contract type 'Component'", - "detail": { - "actual_type": "Component", - "allowed_types": [ - "Module", - "Skill", - "Agent" - ] - } - }, - { - "code": "tag_forbidden_by_complexity", - "tag": "LAYER", - "message": "@LAYER is forbidden for contract type 'Component' at C3", - "detail": { - "actual_complexity": 3, - "contract_type": "Component" - } - } - ], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n

\n {$t.settings?.connections}\n

\n

\n {$t.settings?.connections_description}\n

\n
\n\n {#if connections.length > 0 || isConnectionFormVisible}\n \n {$t.connections?.add_new}\n \n {/if}\n
\n\n {#if isConnectionFormVisible}\n
\n {\n event.preventDefault();\n handleCreateConnection();\n }}\n >\n
\n {$t.connections?.name}\n \n
\n\n
\n
\n Type\n \n \n \n
\n
\n {$t.connections?.host}\n \n
\n
\n\n
\n
\n {$t.connections?.port}\n \n
\n
\n {$t.connections?.db_name}\n \n
\n
\n\n
\n
\n {$t.connections?.user}\n \n
\n
\n {$t.connections?.pass}\n \n
\n
\n\n
\n \n {$t.common?.cancel}\n \n \n {isSubmittingConnection\n ? ($t.settings?.saving || $t.common?.loading || \"Saving...\")\n : $t.connections?.create}\n \n
\n \n
\n {/if}\n\n {#if isLoadingConnections}\n \n {$t.common?.loading || \"Loading...\"}\n
\n {:else if connections.length > 0}\n
\n \n \n \n {$t.connections?.name}\n {$t.connections?.host}\n {$t.connections?.user}\n {$t.settings?.env_actions || \"Actions\"}\n \n \n \n {#each connections as connection}\n \n \n \n \n \n \n {/each}\n \n
\n {connection.name}\n \n {connection.type}://{connection.host}:{connection.port}/{connection.database}\n \n {connection.username}\n \n handleDeleteConnection(connection.id)}\n >\n {$t.connections?.delete}\n \n
\n
\n {:else if !isConnectionFormVisible}\n \n

\n {$t.settings?.no_external_connections}\n

\n {\n openConnectionForm();\n void loadConnections();\n }}\n >\n {$t.connections?.add_new}\n \n \n {:else}\n \n {$t.connections?.no_saved}\n \n {/if}\n\n\n" - }, { "contract_id": "FeaturesSettings", "contract_type": "Component", @@ -82070,7 +84266,7 @@ "contract_type": "Function", "file_path": "frontend/src/routes/settings/__tests__/settings_page.ux.test.js", "start_line": 1, - "end_line": 217, + "end_line": 214, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -82135,7 +84331,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "// #region SettingsPageUxTest:Module [TYPE Function]\n// @SEMANTICS: settings, page, ux-tests, save-flow\n// @RELATION: DEPENDS_ON -> [SettingsPage]\n// @PURPOSE: Test UX states and transitions\n// @LAYER: UI (Tests)\n\n\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport { render, screen, fireEvent, waitFor } from '@testing-library/svelte';\nimport SettingsPage from '../+page.svelte';\nimport { api } from '$lib/api';\nimport { addToast } from '$lib/toasts';\n\nvi.mock('$lib/api', () => ({\n api: {\n getConsolidatedSettings: vi.fn(),\n requestApi: vi.fn(),\n putApi: vi.fn(),\n postApi: vi.fn(),\n updateConsolidatedSettings: vi.fn()\n }\n}));\n\nvi.mock('$lib/toasts', () => ({\n addToast: vi.fn()\n}));\n\nvi.mock('$lib/i18n', () => ({\n t: {\n subscribe: (fn) => {\n fn({\n settings: {\n title: 'Settings',\n migration_sync: 'Migration Sync',\n migration_sync_title: 'Cross-Environment ID Synchronization',\n migration_sync_description: 'Sync IDs across environments',\n sync_schedule: 'Sync Schedule',\n sync_now: 'Sync Now',\n syncing: 'Syncing...',\n saving: 'Saving...',\n environments: 'Environments',\n logging: 'Logging',\n logging_description: 'Configure logging',\n log_level: 'Log Level',\n task_log_level: 'Task Log Level',\n enable_belief_state: 'Enable Belief State',\n connections: 'Connections',\n llm: 'LLM',\n storage: 'Storage',\n save_success: 'Settings saved',\n save_failed: 'Failed',\n save_logging: 'Save Logging Config',\n env_description: 'Configure environments',\n load_failed: 'Failed to load settings',\n migration_sync_failed: 'Sync failed'\n },\n common: { refresh: 'Refresh', retry: 'Retry', save: 'Save' },\n tasks: { cron_label: 'Cron Expression', cron_hint: 'Standard cron format' },\n nav: { settings_git: 'Git' },\n connections: { name: 'Name', user: 'User' }\n });\n return () => { };\n }\n },\n _: vi.fn((key) => key)\n}));\n\n// Mock child components\nvi.mock('../../components/llm/ProviderConfig.svelte', () => ({\n default: class ProviderConfigMock {\n constructor(options) {\n options.target.innerHTML = `
`;\n }\n }\n}));\n\ndescribe('SettingsPage UX Contracts', () => {\n const mockSettings = {\n environments: [],\n logging: { level: 'INFO', task_log_level: 'INFO', enable_belief_state: false },\n connections: [],\n llm: {}\n };\n\n const mockMigrationSettings = {\n cron: \"0 2 * * *\"\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n // @UX_STATE: Loading -> Shows skeleton loader\n // @UX_STATE: Loaded -> Shows tabbed settings interface\n it('should transition from Loading to Loaded state', async () => {\n // Delay resolution to capture loading state\n let resolveSettings;\n api.getConsolidatedSettings.mockImplementation(() => new Promise(resolve => {\n resolveSettings = resolve;\n }));\n\n api.requestApi.mockImplementation((url) => {\n if (url === '/migration/settings') return Promise.resolve(mockMigrationSettings);\n if (url.includes('/migration/mappings-data')) return Promise.resolve({ items: [], total: 0 });\n return Promise.resolve({});\n });\n\n render(SettingsPage);\n\n // Assert Loading skeleton is present (by checking for the pulse class)\n // Note: checking for classes used in skeleton\n const skeletonElements = document.querySelectorAll('.animate-pulse');\n expect(skeletonElements.length).toBeGreaterThan(0);\n\n // Resolve the API call\n resolveSettings(mockSettings);\n\n // Assert Loaded state - use getAllByText because 'Environments' may appear\n // both as tab text and section heading on the default tab\n await waitFor(() => {\n expect(screen.getByText('Settings')).toBeTruthy();\n expect(screen.getAllByText('Environments').length).toBeGreaterThan(0);\n });\n });\n\n // @UX_STATE: Error -> Shows error banner with retry button\n it('should show error banner when loading fails', async () => {\n api.getConsolidatedSettings.mockRejectedValue(new Error('Network Error'));\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n\n render(SettingsPage);\n\n await waitFor(() => {\n expect(screen.getByText('Network Error')).toBeTruthy();\n expect(screen.getByText('Retry')).toBeTruthy();\n });\n });\n\n // @UX_RECOVERY: Refresh button reloads settings data\n it('should reload settings data when retry button is clicked', async () => {\n let callCount = 0;\n api.getConsolidatedSettings.mockImplementation(async () => {\n callCount++;\n if (callCount === 1) throw new Error('First call failed');\n return mockSettings;\n });\n\n api.requestApi.mockImplementation((url) => {\n if (url === '/migration/settings') return Promise.resolve(mockMigrationSettings);\n if (url.includes('/migration/mappings-data')) return Promise.resolve({ items: [], total: 0 });\n return Promise.resolve({});\n });\n\n render(SettingsPage);\n\n // Wait for error state\n await waitFor(() => {\n expect(screen.getByText('First call failed')).toBeTruthy();\n });\n\n // Click retry\n const retryBtn = screen.getByText('Retry');\n await fireEvent.click(retryBtn);\n\n // Verify recovery (Loaded state) - use getAllByText because 'Environments'\n // appears both as tab text and section heading\n await waitFor(() => {\n expect(screen.queryByText('First call failed')).toBeNull();\n expect(screen.getAllByText('Environments').length).toBeGreaterThan(0);\n });\n // We expect it to have been called twice (1. initial mount, 2. retry click)\n expect(api.getConsolidatedSettings).toHaveBeenCalledTimes(2);\n });\n\n // @UX_FEEDBACK: Toast notifications on save success/failure\n it('should show success toast when settings are saved', async () => {\n api.getConsolidatedSettings.mockResolvedValue(mockSettings);\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n api.updateConsolidatedSettings.mockResolvedValue({});\n\n render(SettingsPage);\n await waitFor(() => expect(screen.getByText('Settings')).toBeTruthy());\n\n // Navigate to Logging tab where the Save button is\n // 'Logging' appears in both the tab and section heading; use getAllByText\n await fireEvent.click(screen.getAllByText('Logging')[0]);\n\n const saveBtn = screen.getByText('Save Logging Config');\n await fireEvent.click(saveBtn);\n\n await waitFor(() => {\n expect(addToast).toHaveBeenCalledWith('Settings saved', 'success');\n });\n });\n\n it('should show error toast when settings save fails', async () => {\n api.getConsolidatedSettings.mockResolvedValue(mockSettings);\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n api.updateConsolidatedSettings.mockRejectedValue(new Error('Save Error'));\n\n render(SettingsPage);\n await waitFor(() => expect(screen.getByText('Settings')).toBeTruthy());\n\n // Navigate to Logging tab where the Save button is\n // 'Logging' appears in both the tab and section heading; use getAllByText\n await fireEvent.click(screen.getAllByText('Logging')[0]);\n\n const saveBtn = screen.getByText('Save Logging Config');\n await fireEvent.click(saveBtn);\n\n await waitFor(() => {\n expect(addToast).toHaveBeenCalledWith('Failed', 'error');\n });\n });\n});\n\n// #endregion SettingsPageUxTest:Module\n" + "body": "// #region SettingsPageUxTest:Module [TYPE Function]\n// @SEMANTICS: settings, page, ux-tests, save-flow\n// @RELATION: DEPENDS_ON -> [SettingsPage]\n// @PURPOSE: Test UX states and transitions\n// @LAYER: UI (Tests)\n\n\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport { render, screen, fireEvent, waitFor } from '@testing-library/svelte';\nimport SettingsPage from '../+page.svelte';\nimport { api } from '$lib/api';\nimport { addToast } from '$lib/toasts';\n\nvi.mock('$lib/api', () => ({\n api: {\n getConsolidatedSettings: vi.fn(),\n requestApi: vi.fn(),\n putApi: vi.fn(),\n postApi: vi.fn(),\n updateConsolidatedSettings: vi.fn()\n }\n}));\n\nvi.mock('$lib/toasts', () => ({\n addToast: vi.fn()\n}));\n\nvi.mock('$lib/i18n', () => ({\n t: {\n subscribe: (fn) => {\n fn({\n settings: {\n title: 'Settings',\n migration_sync: 'Migration Sync',\n migration_sync_title: 'Cross-Environment ID Synchronization',\n migration_sync_description: 'Sync IDs across environments',\n sync_schedule: 'Sync Schedule',\n sync_now: 'Sync Now',\n syncing: 'Syncing...',\n saving: 'Saving...',\n environments: 'Environments',\n logging: 'Logging',\n logging_description: 'Configure logging',\n log_level: 'Log Level',\n task_log_level: 'Task Log Level',\n enable_belief_state: 'Enable Belief State',\n llm: 'LLM',\n storage: 'Storage',\n save_success: 'Settings saved',\n save_failed: 'Failed',\n save_logging: 'Save Logging Config',\n env_description: 'Configure environments',\n load_failed: 'Failed to load settings',\n migration_sync_failed: 'Sync failed'\n },\n common: { refresh: 'Refresh', retry: 'Retry', save: 'Save' },\n tasks: { cron_label: 'Cron Expression', cron_hint: 'Standard cron format' },\n nav: { settings_git: 'Git' },\n });\n return () => { };\n }\n },\n _: vi.fn((key) => key)\n}));\n\n// Mock child components\nvi.mock('../../components/llm/ProviderConfig.svelte', () => ({\n default: class ProviderConfigMock {\n constructor(options) {\n options.target.innerHTML = `
`;\n }\n }\n}));\n\ndescribe('SettingsPage UX Contracts', () => {\n const mockSettings = {\n environments: [],\n logging: { level: 'INFO', task_log_level: 'INFO', enable_belief_state: false },\n llm: {}\n };\n\n const mockMigrationSettings = {\n cron: \"0 2 * * *\"\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n // @UX_STATE: Loading -> Shows skeleton loader\n // @UX_STATE: Loaded -> Shows tabbed settings interface\n it('should transition from Loading to Loaded state', async () => {\n // Delay resolution to capture loading state\n let resolveSettings;\n api.getConsolidatedSettings.mockImplementation(() => new Promise(resolve => {\n resolveSettings = resolve;\n }));\n\n api.requestApi.mockImplementation((url) => {\n if (url === '/migration/settings') return Promise.resolve(mockMigrationSettings);\n if (url.includes('/migration/mappings-data')) return Promise.resolve({ items: [], total: 0 });\n return Promise.resolve({});\n });\n\n render(SettingsPage);\n\n // Assert Loading skeleton is present (by checking for the pulse class)\n // Note: checking for classes used in skeleton\n const skeletonElements = document.querySelectorAll('.animate-pulse');\n expect(skeletonElements.length).toBeGreaterThan(0);\n\n // Resolve the API call\n resolveSettings(mockSettings);\n\n // Assert Loaded state - use getAllByText because 'Environments' may appear\n // both as tab text and section heading on the default tab\n await waitFor(() => {\n expect(screen.getByText('Settings')).toBeTruthy();\n expect(screen.getAllByText('Environments').length).toBeGreaterThan(0);\n });\n });\n\n // @UX_STATE: Error -> Shows error banner with retry button\n it('should show error banner when loading fails', async () => {\n api.getConsolidatedSettings.mockRejectedValue(new Error('Network Error'));\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n\n render(SettingsPage);\n\n await waitFor(() => {\n expect(screen.getByText('Network Error')).toBeTruthy();\n expect(screen.getByText('Retry')).toBeTruthy();\n });\n });\n\n // @UX_RECOVERY: Refresh button reloads settings data\n it('should reload settings data when retry button is clicked', async () => {\n let callCount = 0;\n api.getConsolidatedSettings.mockImplementation(async () => {\n callCount++;\n if (callCount === 1) throw new Error('First call failed');\n return mockSettings;\n });\n\n api.requestApi.mockImplementation((url) => {\n if (url === '/migration/settings') return Promise.resolve(mockMigrationSettings);\n if (url.includes('/migration/mappings-data')) return Promise.resolve({ items: [], total: 0 });\n return Promise.resolve({});\n });\n\n render(SettingsPage);\n\n // Wait for error state\n await waitFor(() => {\n expect(screen.getByText('First call failed')).toBeTruthy();\n });\n\n // Click retry\n const retryBtn = screen.getByText('Retry');\n await fireEvent.click(retryBtn);\n\n // Verify recovery (Loaded state) - use getAllByText because 'Environments'\n // appears both as tab text and section heading\n await waitFor(() => {\n expect(screen.queryByText('First call failed')).toBeNull();\n expect(screen.getAllByText('Environments').length).toBeGreaterThan(0);\n });\n // We expect it to have been called twice (1. initial mount, 2. retry click)\n expect(api.getConsolidatedSettings).toHaveBeenCalledTimes(2);\n });\n\n // @UX_FEEDBACK: Toast notifications on save success/failure\n it('should show success toast when settings are saved', async () => {\n api.getConsolidatedSettings.mockResolvedValue(mockSettings);\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n api.updateConsolidatedSettings.mockResolvedValue({});\n\n render(SettingsPage);\n await waitFor(() => expect(screen.getByText('Settings')).toBeTruthy());\n\n // Navigate to Logging tab where the Save button is\n // 'Logging' appears in both the tab and section heading; use getAllByText\n await fireEvent.click(screen.getAllByText('Logging')[0]);\n\n const saveBtn = screen.getByText('Save Logging Config');\n await fireEvent.click(saveBtn);\n\n await waitFor(() => {\n expect(addToast).toHaveBeenCalledWith('Settings saved', 'success');\n });\n });\n\n it('should show error toast when settings save fails', async () => {\n api.getConsolidatedSettings.mockResolvedValue(mockSettings);\n api.requestApi.mockResolvedValue(mockMigrationSettings);\n api.updateConsolidatedSettings.mockRejectedValue(new Error('Save Error'));\n\n render(SettingsPage);\n await waitFor(() => expect(screen.getByText('Settings')).toBeTruthy());\n\n // Navigate to Logging tab where the Save button is\n // 'Logging' appears in both the tab and section heading; use getAllByText\n await fireEvent.click(screen.getAllByText('Logging')[0]);\n\n const saveBtn = screen.getByText('Save Logging Config');\n await fireEvent.click(saveBtn);\n\n await waitFor(() => {\n expect(addToast).toHaveBeenCalledWith('Failed', 'error');\n });\n });\n});\n\n// #endregion SettingsPageUxTest:Module\n" }, { "contract_id": "AutomationPage", @@ -82294,25 +84490,6 @@ "tier_source": "AutoCalculated", "body": "\n\n\n\n\n\n
\n
\n
\n

Automation Policies

\n

Manage scheduled validation rules and execution windows.

\n
\n {#if !showForm}\n \n {/if}\n
\n\n {#if showForm}\n
\n
\n \n |\n

\n {selectedPolicy ? 'Edit Policy' : 'New Policy'}\n

\n
\n showForm = false} \n />\n
\n {:else if isLoading}\n
\n
\n
\n {:else}\n
\n
    \n {#each policies as policy}\n
  • \n
    \n
    \n
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n

    {policy.name}

    \n
    \n {getEnvName(policy.environment_id)}\n \n {policy.dashboard_ids.length} Dashboards\n
    \n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n
    \n
    \n
  • \n {:else}\n
  • \n \n \n \n

    No policies

    \n

    Get started by creating a new automation policy.

    \n
    \n \n
    \n
  • \n {/each}\n
\n
\n\n {#if translationSchedules.length > 0}\n

Translation Schedules

\n
\n
    \n {#each translationSchedules as ts}\n
  • \n
    \n
    \n
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n

    {ts.job_name}

    \n
    \n {ts.cron_expression}\n \n {ts.timezone}\n
    \n
    \n
    \n
    \n \n {ts.is_active ? 'Active' : 'Inactive'}\n \n {#if ts.last_run_at}\n \n Last: {new Date(ts.last_run_at).toLocaleString()}\n \n {/if}\n
    \n
    \n
    \n
  • \n {:else}\n
  • \n No translation schedules configured\n
  • \n {/each}\n
\n
\n {/if}\n {/if}\n
\n\n" }, - { - "contract_id": "handleSuccess:Function", - "contract_type": "Function", - "file_path": "frontend/src/routes/settings/connections/+page.svelte", - "start_line": 24, - "end_line": 34, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "POST": "Triggers the fetchConnections method on the list component.", - "PRE": "listComponent must be bound.", - "PURPOSE": "Refreshes the connection list after a successful creation." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": " // #region handleSuccess:Function [TYPE Function]\n /* @PURPOSE: Refreshes the connection list after a successful creation.\n @PRE: listComponent must be bound.\n @POST: Triggers the fetchConnections method on the list component.\n */\n function handleSuccess() {\n if (listComponent) {\n listComponent.fetchConnections();\n }\n }\n // #endregion handleSuccess:Function\n" - }, { "contract_id": "loadConfigs:Function", "contract_type": "Function", @@ -82548,8 +84725,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::readTabFromUrl", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 42, - "end_line": 46, + "start_line": 41, + "end_line": 45, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82563,8 +84740,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::writeTabToUrl", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 52, - "end_line": 56, + "start_line": 51, + "end_line": 55, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82578,8 +84755,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::normalizeTab", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 64, - "end_line": 68, + "start_line": 63, + "end_line": 67, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82593,8 +84770,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::normalizeLlmSettings", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 78, - "end_line": 82, + "start_line": 77, + "end_line": 81, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82608,8 +84785,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::isDashboardValidationBindingValid", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 99, - "end_line": 107, + "start_line": 98, + "end_line": 106, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82623,8 +84800,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::getProviderById", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 115, - "end_line": 118, + "start_line": 114, + "end_line": 117, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82638,8 +84815,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::normalizeSupersetBaseUrl", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 128, - "end_line": 133, + "start_line": 127, + "end_line": 132, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82653,8 +84830,8 @@ "contract_id": "frontend/src/routes/settings/settings-utils.js::resolveEnvStage", "contract_type": "Function", "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 146, - "end_line": 150, + "start_line": 145, + "end_line": 149, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -82664,21 +84841,6 @@ "tier_source": "AutoCalculated", "body": "/**\n * Classify an environment's deployment stage from its `name` or `url`.\n * Returns one of: `\"PROD\"`, `\"PREPROD\"`, or `\"DEV\"`.\n */" }, - { - "contract_id": "frontend/src/routes/settings/settings-utils.js::createEmptyConnectionDraft", - "contract_type": "Function", - "file_path": "frontend/src/routes/settings/settings-utils.js", - "start_line": 162, - "end_line": 165, - "tier": "TIER_1", - "complexity": 1, - "metadata": {}, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "jsdoc", - "tier_source": "AutoCalculated", - "body": "/**\n * Create a blank connection object suitable for the \"new connection\" form.\n */" - }, { "contract_id": "StorageIndexPage", "contract_type": "Page", @@ -84066,6 +86228,583 @@ "tier_source": "AutoCalculated", "body": "\n\n\n
\n\t
\n\t\t
\n\t\t\t

{$t.translate?.history?.title}

\n\t\t\t

{$t.translate?.history?.subtitle}

\n\t\t
\n\t\t\n\t
\n\n\t\n\t{#if totalMetric()}\n\t\t
\n\t\t\t
\n\t\t\t\t

{$t.translate?.history?.total_runs}

\n\t\t\t\t

{totalMetric().total_runs}

\n\t\t\t
\n\t\t\t
\n\t\t\t\t

{$t.translate?.history?.successful}

\n\t\t\t\t

{totalMetric().successful_runs}

\n\t\t\t
\n\t\t\t
\n\t\t\t\t

{$t.translate?.history?.failed}

\n\t\t\t\t

{totalMetric().failed_runs}

\n\t\t\t
\n\t\t\t
\n\t\t\t\t

{$t.translate?.history?.records}

\n\t\t\t\t

{totalMetric().total_records}

\n\t\t\t
\n\t\t
\n\t{/if}\n\n\t\n\t
\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t
\n\n\t\n\t{#if isLoading}\n\t\t
\n\t\t\t{#each Array(5) as _}\n\t\t\t\t
\n\t\t\t{/each}\n\t\t
\n\n\t\n\t{:else if uxState === 'empty'}\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t

{$t.translate?.history?.no_runs}

\n\t\t\t

{$t.translate?.history?.no_runs_hint}

\n\t\t
\n\n\t\n\t{:else if uxState === 'populated' || uxState === 'detail_open'}\n\t\t
\n\t\t\t{#each runs as run}\n\t\t\t\t openDetail(run)}\n\t\t\t\t\tclass=\"bg-white border border-gray-200 rounded-lg p-3 hover:shadow-sm hover:border-gray-300 transition-all cursor-pointer\"\n\t\t\t\t>\n\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{getJobName(run.job_id)}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{run.status}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{#if run.trigger_type}\n\t\t\t\t\t\t\t\t\t{run.trigger_type}\n\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{run.created_at ? new Date(run.created_at).toLocaleString() : ''}\n\t\t\t\t\t\t\t\t{_('translate.history.records_label').replace('{count}', run.total_records || 0)}\n\t\t\t\t\t\t\t\t{_('translate.history.ok_label').replace('{count}', run.successful_records || 0)}\n\t\t\t\t\t\t\t\t{_('translate.history.fail_label').replace('{count}', run.failed_records || 0)}\n\t\t\t\t\t\t\t\t{#if run.created_by}\n\t\t\t\t\t\t\t\t\t{_('translate.history.by_label').replace('{user}', run.created_by)}\n\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{#if run.target_languages && run.target_languages.length > 0}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{#each run.target_languages as lang}\n\t\t\t\t\t\t\t\t\t\t{lang}\n\t\t\t\t\t\t\t\t\t{/each}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
e.stopPropagation()}>\n\t\t\t\t\t\t\t{#if run.status === 'PENDING' || run.status === 'RUNNING'}\n\t\t\t\t\t\t\t\t handleCancelRun(run.id)}\n\t\t\t\t\t\t\t\t\tdisabled={cancellingRunId === run.id}\n\t\t\t\t\t\t\t\t\tclass=\"px-2 py-1 text-xs bg-red-100 text-red-700 rounded hover:bg-red-200 disabled:opacity-50 transition-colors\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{cancellingRunId === run.id\n\t\t\t\t\t\t\t\t\t\t? ($t.translate?.run?.cancelling || '...')\n\t\t\t\t\t\t\t\t\t\t: ($t.translate?.run?.cancel || 'Cancel')}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t{#if run.status === 'FAILED'}\n\t\t\t\t\t\t\t\t handleRetryRun(run.id)}\n\t\t\t\t\t\t\t\t\tdisabled={retryingRunId === run.id}\n\t\t\t\t\t\t\t\t\tclass=\"px-2 py-1 text-xs bg-amber-100 text-amber-700 rounded hover:bg-amber-200 disabled:opacity-50 transition-colors\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{retryingRunId === run.id\n\t\t\t\t\t\t\t\t\t\t? ($t.translate?.run?.retrying || '...')\n\t\t\t\t\t\t\t\t\t\t: ($t.translate?.run?.retry_failed || 'Retry')}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t{#if run.status === 'COMPLETED' && (run.skipped_records || 0) > 0}\n\t\t\t\t\t\t\t\t handleDownloadSkipped(run.id)}\n\t\t\t\t\t\t\t\t\tclass=\"text-xs text-primary hover:text-primary-hover\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{$t.translate?.history?.skipped_csv}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t{/each}\n\t\t
\n\n\t\t\n\t\t
\n\t\t\t

{_('translate.history.showing').replace('{count}', runs.length).replace('{total}', total)}

\n\t\t\t
\n\t\t\t\t { currentPage--; loadRuns(); }}\n\t\t\t\t\tdisabled={currentPage <= 1}\n\t\t\t\t\tclass=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50\"\n\t\t\t\t>\n\t\t\t\t\t{$t.translate?.history?.previous}\n\t\t\t\t\n\t\t\t\t { currentPage++; loadRuns(); }}\n\t\t\t\t\tdisabled={currentPage * pageSize >= total}\n\t\t\t\t\tclass=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50\"\n\t\t\t\t>\n\t\t\t\t\t{$t.translate?.history?.next}\n\t\t\t\t\n\t\t\t
\n\t\t
\n\t{/if}\n\n\t\n\t{#if uxState === 'detail_open' && selectedRunDetail}\n\t\t
\n\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t

{$t.translate?.history?.run_detail}

\n\t\t\t\t\t\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.status}

\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{selectedRunDetail.status}\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.trigger}

\n\t\t\t\t\t\t

{selectedRunDetail.trigger_type || 'manual'}

\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.started}

\n\t\t\t\t\t\t

{selectedRunDetail.started_at ? new Date(selectedRunDetail.started_at).toLocaleString() : '-'}

\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.completed}

\n\t\t\t\t\t\t

{selectedRunDetail.completed_at ? new Date(selectedRunDetail.completed_at).toLocaleString() : '-'}

\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{selectedRunDetail.total_records || 0}

\n\t\t\t\t\t\t

{$t.translate?.history?.total}

\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{selectedRunDetail.successful_records || 0}

\n\t\t\t\t\t\t

{$t.translate?.history?.success}

\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{selectedRunDetail.failed_records || 0}

\n\t\t\t\t\t\t

{$t.translate?.history?.failed}

\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

{selectedRunDetail.skipped_records || 0}

\n\t\t\t\t\t\t

{$t.translate?.history?.skipped}

\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.language_stats && Object.keys(selectedRunDetail.language_stats).length > 0}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.run?.per_language}

\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{#each Object.entries(selectedRunDetail.language_stats) as [lang, stats]}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t{lang}\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t{_('translate.run.translated_label').replace('{count}', stats.translated_rows)}\n\t\t\t\t\t\t\t\t\t\t{_('translate.run.failed_label').replace('{count}', stats.failed_rows)}\n\t\t\t\t\t\t\t\t\t\t{_('translate.run.skipped_label').replace('{count}', stats.skipped_rows)}\n\t\t\t\t\t\t\t\t\t\t{_('translate.run.tokens_label').replace('{count}', stats.token_count)}\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/each}\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t{#if selectedRunDetail.status === 'PENDING' || selectedRunDetail.status === 'RUNNING'}\n\t\t\t\t\t\t handleCancelRun(selectedRunDetail.id)}\n\t\t\t\t\t\t\tdisabled={cancellingRunId === selectedRunDetail.id}\n\t\t\t\t\t\t\tclass=\"px-4 py-2 text-sm bg-destructive text-white rounded-lg hover:bg-destructive-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{cancellingRunId === selectedRunDetail.id\n\t\t\t\t\t\t\t\t? ($t.translate?.run?.cancelling || 'Cancelling...')\n\t\t\t\t\t\t\t\t: ($t.translate?.run?.cancel || 'Cancel')}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t\t{#if selectedRunDetail.status === 'FAILED'}\n\t\t\t\t\t\t handleRetryRun(selectedRunDetail.id)}\n\t\t\t\t\t\t\tdisabled={retryingRunId === selectedRunDetail.id}\n\t\t\t\t\t\t\tclass=\"px-4 py-2 text-sm bg-amber-600 text-white rounded-lg hover:bg-amber-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{retryingRunId === selectedRunDetail.id\n\t\t\t\t\t\t\t\t? ($t.translate?.run?.retrying || 'Retrying...')\n\t\t\t\t\t\t\t\t: ($t.translate?.run?.retry_failed || 'Retry Failed')}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.config_snapshot}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.config_snapshot}

\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
{JSON.stringify(selectedRunDetail.config_snapshot, null, 2)}
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.config_hash || selectedRunDetail.dict_snapshot_hash}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.snapshots}

\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{#if selectedRunDetail.config_hash}\n\t\t\t\t\t\t\t\t
Config: {selectedRunDetail.config_hash}
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t{#if selectedRunDetail.dict_snapshot_hash}\n\t\t\t\t\t\t\t\t
Dict: {selectedRunDetail.dict_snapshot_hash}
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t{#if selectedRunDetail.key_hash}\n\t\t\t\t\t\t\t\t
Key: {selectedRunDetail.key_hash}
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.events && selectedRunDetail.events.length > 0}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.events.replace('{count}', selectedRunDetail.events.length)}

\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{#each selectedRunDetail.events as evt}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{evt.event_type}\n\t\t\t\t\t\t\t\t\t|\n\t\t\t\t\t\t\t\t\t{evt.created_at ? new Date(evt.created_at).toLocaleString() : ''}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/each}\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.error_message}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.error}

\n\t\t\t\t\t\t

{selectedRunDetail.error_message}

\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\n\t\t\t\t\n\t\t\t\t{#if selectedRunDetail.superset_execution_id}\n\t\t\t\t\t
\n\t\t\t\t\t\t

{$t.translate?.history?.superset_query_id}

\n\t\t\t\t\t\t

{selectedRunDetail.superset_execution_id}

\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\t\t\t
\n\t\t
\n\t{/if}\n
\n\n" }, + { + "contract_id": "ValidationTaskList", + "contract_type": "Page", + "file_path": "frontend/src/routes/validation/+page.svelte", + "start_line": 1, + "end_line": 399, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PARAM": "{string} status", + "PURPOSE": "Validation task list page with status filter, task cards, and create/duplicate/delete actions.", + "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" + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "unknown_tag", + "tag": "PARAM", + "message": "@PARAM is not defined in axiom_config.yaml tags", + "detail": null + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "RATIONALE", + "message": "@RATIONALE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RATIONALE", + "message": "@RATIONALE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "REJECTED", + "message": "@REJECTED is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "REJECTED", + "message": "@REJECTED is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "invalid_enum_value", + "tag": "TYPE", + "message": "@TYPE value '{'idle'|'loading'|'empty'|'populated'|'error'|'filtered_empty'}' is not in allowed enum", + "detail": { + "allowed": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Tombstone", + "Skill", + "Agent" + ], + "value": "{'idle'|'loading'|'empty'|'populated'|'error'|'filtered_empty'}" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_STATE", + "message": "@UX_STATE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_STATE", + "message": "@UX_STATE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n

{$t.validation?.tasks_title || 'Validation Tasks'}

\n

{$t.validation?.last_run_status || 'Monitor and validate dashboard quality'}

\n
\n \n \n \n \n {$t.validation?.new_task || 'New Task'}\n \n
\n\n \n
\n {#each statusPills as pill (pill.value)}\n filterByStatus(pill.value)}\n class=\"px-3 py-1.5 text-sm rounded-full border transition-colors\n {statusFilter === pill.value\n ? 'bg-blue-50 border-blue-300 text-blue-700'\n : 'bg-white border-gray-200 text-gray-600 hover:border-gray-300'}\"\n >\n {pill.label}\n ({pill.count})\n \n {/each}\n
\n\n \n {#if isLoading}\n
\n {#each Array(3) as _, i (i)}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n {/each}\n
\n\n \n {:else if uxState === 'error'}\n
\n

{error}

\n \n {$t.validation?.retry || 'Retry'}\n \n
\n\n \n {:else if uxState === 'empty'}\n
\n \n \n \n

{$t.validation?.no_tasks || 'No validation tasks yet. Create your first task to start monitoring dashboards.'}

\n \n {$t.validation?.create_task_cta || 'Create Task'}\n \n
\n\n \n {:else if uxState === 'filtered_empty'}\n
\n \n \n \n

{$t.validation?.no_tasks_filtered || 'No tasks match your filters.'}

\n filterByStatus('')}\n class=\"text-blue-600 hover:text-blue-700 text-sm font-medium\"\n >\n {$t.validation?.clear_filters || 'Clear filters'}\n \n
\n\n \n {:else if uxState === 'populated'}\n
\n {#each tasks as task (task.id)}\n \n handleNavToConfig(task.id)}\n onkeydown={(e) => { if (e.key === 'Enter') handleNavToConfig(task.id); }}\n role=\"button\"\n tabindex=\"0\"\n class=\"bg-white border border-gray-200 rounded-xl p-4 hover:shadow-md hover:border-gray-300 transition-all cursor-pointer\"\n >\n
\n
\n
\n

{task.name}

\n \n {task.is_active !== false ? ($t.validation?.active || 'Active') : ($t.validation?.inactive || 'Inactive')}\n \n
\n
\n {#if task.dashboard_id}\n \n {$t.validation?.dashboard || 'Dashboard'}: {task.dashboard_id?.substring(0, 16)}...\n \n {/if}\n {#if task.environment_id}\n {$t.validation?.environment || 'Env'}: {task.environment_id?.substring(0, 12)}...\n {/if}\n {#if task.last_run_status}\n \n {$t.validation?.last_run || 'Last run'}:\n \n {task.last_run_status}\n \n \n {/if}\n {#if task.last_run_at}\n {new Date(task.last_run_at).toLocaleString()}\n {/if}\n {#if task.provider_id}\n {$t.validation?.provider || 'LLM'}: {task.provider_id?.substring(0, 12)}...\n {/if}\n {#if task.schedule_days?.length}\n \n {$t.validation?.scheduled || 'Scheduled'}\n \n {:else}\n \n {$t.validation?.manual_only || 'Manual only'}\n \n {/if}\n
\n
\n \n
e.stopPropagation()}>\n handleRunNow(task.id)}\n disabled={runningTasks[task.id]}\n class=\"p-2 text-gray-400 hover:text-blue-600 rounded-lg hover:bg-blue-50 transition-colors disabled:opacity-50\"\n title={$t.validation?.run_now || 'Run Now'}\n >\n \n \n \n \n \n handleDuplicate(task.id)}\n class=\"p-2 text-gray-400 hover:text-blue-600 rounded-lg hover:bg-blue-50 transition-colors\"\n title={$t.validation?.duplicate_task || 'Duplicate'}\n >\n \n \n \n \n {#if showDeleteConfirm === task.id}\n
\n handleDelete(task.id)}\n class=\"px-2 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700\"\n >\n {$t.validation?.confirm_delete || 'Delete'}\n \n { showDeleteConfirm = null; deleteWithRuns = false; }}\n class=\"px-2 py-1 text-xs bg-gray-200 text-gray-700 rounded hover:bg-gray-300\"\n >\n {$t.validation?.cancel_delete || 'Cancel'}\n \n
\n {:else}\n { showDeleteConfirm = task.id; deleteWithRuns = false; }}\n class=\"p-2 text-gray-400 hover:text-red-600 rounded-lg hover:bg-red-50 transition-colors\"\n title={$t.common?.delete || 'Delete'}\n >\n \n \n \n \n {/if}\n
\n
\n {#if showDeleteConfirm === task.id}\n
\n \n
\n {/if}\n
\n {/each}\n
\n\n \n {#if total > pageSize}\n
\n

\n {($t.validation?.showing || 'Showing {count} of {total}')\n .replace('{count}', String(tasks.length))\n .replace('{total}', String(total))}\n

\n
\n { currentPage--; loadTasks(); }}\n disabled={currentPage <= 1}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.previous || 'Previous'}\n \n { currentPage++; loadTasks(); }}\n disabled={currentPage * pageSize >= total}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.next || 'Next'}\n \n
\n
\n {/if}\n {/if}\n\n\n" + }, + { + "contract_id": "ValidationTaskConfig", + "contract_type": "Page", + "file_path": "frontend/src/routes/validation/[id]/+page.svelte", + "start_line": 1, + "end_line": 699, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "Validation task configuration page with Config and History tabs. Handles new and edit modes.", + "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" + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "RATIONALE", + "message": "@RATIONALE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RATIONALE", + "message": "@RATIONALE is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "REJECTED", + "message": "@REJECTED is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "REJECTED", + "message": "@REJECTED is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "invalid_enum_value", + "tag": "TYPE", + "message": "@TYPE value '{'idle'|'loading'|'configured'|'saving'|'error'|'not_found'}' is not in allowed enum", + "detail": { + "allowed": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Tombstone", + "Skill", + "Agent" + ], + "value": "{'idle'|'loading'|'configured'|'saving'|'error'|'not_found'}" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_FEEDBACK", + "message": "@UX_FEEDBACK is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_FEEDBACK", + "message": "@UX_FEEDBACK is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_REACTIVITY", + "message": "@UX_REACTIVITY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_REACTIVITY", + "message": "@UX_REACTIVITY is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_RECOVERY", + "message": "@UX_RECOVERY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_RECOVERY", + "message": "@UX_RECOVERY is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_STATE", + "message": "@UX_STATE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_STATE", + "message": "@UX_STATE is forbidden for contract type 'Page' at C4", + "detail": { + "actual_complexity": 4, + "contract_type": "Page" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n {pageTitle}\n\n\n
\n \n
\n
\n

\n {isNewTask ? ($t.validation?.new_task || 'New Validation Task') : ($t.validation?.edit_task || 'Edit Validation Task')}\n

\n {#if !isNewTask && task}\n

{$t.validation?.created_at || 'Created'}: {new Date(task.created_at || task.created_on).toLocaleString()}

\n {/if}\n
\n
\n {#if !isNewTask}\n \n {#if isRunning}\n \n \n \n \n {$t.validation?.running || 'Running...'}\n {:else}\n {$t.validation?.run_now || 'Run Now'}\n {/if}\n \n {/if}\n \n {$t.validation?.cancel || 'Cancel'}\n \n \n {isSaving ? ($t.validation?.saving || 'Saving...') : ($t.validation?.save || 'Save')}\n \n
\n
\n\n \n {#if uxState === 'loading'}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n \n {:else if uxState === 'error'}\n
\n

{error || $t.validation?.load_task_failed || 'Failed to load task.'}

\n
\n \n {$t.validation?.retry || 'Retry'}\n \n \n {$t.validation?.back || 'Back'}\n \n
\n
\n\n \n {:else if uxState === 'not_found'}\n
\n

{$t.validation?.task_not_found || 'Task not found'}

\n

{$t.validation?.task_not_found_desc || 'The task you are looking for does not exist or has been deleted.'}

\n \n {$t.validation?.go_back || 'Go back'}\n \n
\n\n \n {:else if uxState === 'configured' || uxState === 'saving'}\n \n
\n \n
\n\n \n {#if !isNewTask && providerId && !isProviderMultimodal}\n
\n

\n \n \n \n {$t.validation?.provider_multimodal_required || 'Dashboard validation requires a multimodal LLM provider (supports images).'}\n

\n
\n {/if}\n\n \n {#if activeTab === 'config'}\n
\n \n
\n

{$t.validation?.task_name || 'Basic Info'}

\n
\n
\n \n \n {#if validationErrors.name}\n

{validationErrors.name}

\n {/if}\n
\n
\n
\n\n \n
\n

{$t.validation?.dashboard || 'Dashboard & Environment'}

\n
\n
\n \n { dashboardId = ''; searchDashboards(''); }}\n class=\"w-full px-3 py-2 border rounded-lg text-sm {validationErrors.environment_id ? 'border-red-300 bg-red-50' : 'border-gray-300'}\"\n >\n \n {#each environments as env (env.id)}\n \n {/each}\n \n {#if validationErrors.environment_id}\n

{validationErrors.environment_id}

\n {/if}\n
\n
\n \n \n \n {#each dashboards as d (d.id)}\n \n {/each}\n \n {#if validationErrors.dashboard_id}\n

{validationErrors.dashboard_id}

\n {/if}\n {#if dashboardsLoading}\n

Loading...

\n {/if}\n
\n
\n
\n\n \n
\n

{$t.validation?.llm_provider || 'LLM Provider'}

\n
\n \n \n \n {#each llmProviders as p (p.id)}\n \n {/each}\n \n {#if validationErrors.provider_id}\n

{validationErrors.provider_id}

\n {/if}\n {#if providerId && !isProviderMultimodal}\n

\n \n \n \n {$t.validation?.provider_multimodal_required || 'Dashboard validation requires a multimodal LLM provider.'}\n

\n {/if}\n
\n
\n\n \n
\n
\n

{$t.validation?.schedule || 'Schedule'}

\n (showSchedule = !showSchedule)}\n class=\"text-sm text-blue-600 hover:text-blue-700 font-medium\"\n >\n {showSchedule\n ? ($t.validation?.schedule_collapse || 'Hide schedule')\n : ($t.validation?.schedule_expand || 'Configure schedule')}\n \n
\n\n {#if !showSchedule}\n

{$t.validation?.manual_only || 'Manual only — runs triggered by user.'}

\n {:else}\n
\n
\n \n \n
\n {#each DAY_LABELS as day, idx (day)}\n toggleDay(idx)}\n class=\"px-3 py-1.5 text-sm rounded-lg border transition-colors\n {scheduleDays.includes(idx)\n ? 'bg-blue-100 border-blue-300 text-blue-700'\n : 'bg-white border-gray-200 text-gray-600 hover:border-gray-300'}\"\n >\n {$t.validation?.[DAY_KEYS[idx]] || day}\n \n {/each}\n
\n
\n\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n {/if}\n
\n\n \n
\n \n
\n
\n\n \n {:else if activeTab === 'history'}\n
\n {#if runsLoading}\n
\n {#each Array(3) as _, i (i)}\n
\n {/each}\n
\n {:else if runs.length === 0}\n
\n

{$t.validation?.run_history_empty || 'No runs for this task yet.'}

\n
\n {:else}\n
\n \n \n \n \n \n \n \n \n \n \n \n {#each runs as run (run.id)}\n \n \n \n \n \n \n \n {/each}\n \n
{$t.validation?.status || 'Status'}{$t.validation?.summary || 'Summary'}{$t.validation?.issues || 'Issues'}{$t.validation?.timestamp || 'Timestamp'}{$t.validation?.actions || 'Actions'}
\n \n {run.status || 'UNKNOWN'}\n \n \n {run.summary || '-'}\n \n {run.issues_count ?? run.issues ?? '-'}\n \n {run.created_at || run.completed_at ? new Date(run.created_at || run.completed_at).toLocaleString() : '-'}\n \n handleNavToReport(run.task_id)}\n class=\"text-blue-600 hover:text-blue-700 text-sm font-medium\"\n >\n {$t.validation?.view_report || 'View Report'}\n \n
\n
\n\n \n {#if runsTotal > runsPageSize}\n
\n

\n {($t.validation?.showing || 'Showing {count} of {total}')\n .replace('{count}', String(runs.length))\n .replace('{total}', String(runsTotal))}\n

\n
\n { runsPage--; loadRunHistory(); }}\n disabled={runsPage <= 1}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.previous || 'Previous'}\n \n { runsPage++; loadRunHistory(); }}\n disabled={runsPage * runsPageSize >= runsTotal}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.next || 'Next'}\n \n
\n
\n {/if}\n {/if}\n
\n {/if}\n {/if}\n
\n\n" + }, + { + "contract_id": "ValidationHistory", + "contract_type": "Page", + "file_path": "frontend/src/routes/validation/history/+page.svelte", + "start_line": 1, + "end_line": 405, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Validation run history page with filters, metrics summary, and run cards.", + "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" + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "RATIONALE", + "message": "@RATIONALE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RATIONALE", + "message": "@RATIONALE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "REJECTED", + "message": "@REJECTED is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "REJECTED", + "message": "@REJECTED is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "invalid_enum_value", + "tag": "TYPE", + "message": "@TYPE value '{'idle'|'loading'|'empty'|'filtered_empty'|'populated'|'error'}' is not in allowed enum", + "detail": { + "allowed": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Tombstone", + "Skill", + "Agent" + ], + "value": "{'idle'|'loading'|'empty'|'filtered_empty'|'populated'|'error'}" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_STATE", + "message": "@UX_STATE is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_STATE", + "message": "@UX_STATE is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n

{$t.validation?.history_title || 'Validation History'}

\n

{$t.validation?.last_run || 'Review past validation runs'}

\n
\n { currentPage = 1; applyFilters(); }}\n class=\"px-4 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors\"\n >\n \n \n \n {$t.common?.refresh || 'Refresh'}\n \n
\n\n \n
\n
\n \n \n \n \n \n \n
\n \n {$t.validation?.apply || 'Apply'}\n \n \n \n \n \n \n
\n
\n
\n\n \n {#if isLoading}\n
\n
\n {#each Array(3) as _, i (i)}\n
\n {/each}\n
\n\n \n {:else if uxState === 'error'}\n
\n

{error}

\n \n {$t.validation?.retry || 'Retry'}\n \n
\n\n \n {:else if uxState === 'empty'}\n
\n \n \n \n

{$t.validation?.no_runs || 'No validation runs yet. Create a task and run it.'}

\n
\n\n \n {:else if uxState === 'filtered_empty'}\n
\n \n \n \n

{$t.validation?.no_runs_filtered || 'No runs match your filters.'}

\n \n {$t.validation?.clear_filters || 'Clear filters'}\n \n
\n\n \n {:else if uxState === 'populated'}\n \n
\n
\n

{$t.validation?.total_runs || 'Total runs'}

\n

{totalRuns}

\n
\n
\n

{$t.validation?.passed || 'Passed'}

\n

{passedCount}

\n
\n
\n

{$t.validation?.failed || 'Failed'}

\n

{failedCount}

\n
\n
\n

{$t.validation?.warn_rate || 'Warn rate'}

\n

{warnRate}%

\n
\n
\n\n \n
\n {#each runs as run (run.id)}\n
\n
\n
\n
\n {getTaskName(run.task_id)}\n \n {run.status || 'UNKNOWN'}\n \n {#if Array.isArray(run.issues) && run.issues.length > 0}\n \n {$t.validation?.issues || 'Issues'}: {run.issues.length}\n \n {/if}\n
\n {#if run.summary}\n

{run.summary}

\n {/if}\n
\n {run.created_at ? new Date(run.created_at).toLocaleString() : '-'}\n {$t.validation?.dashboard || 'Dashboard'}: {run.dashboard_id || getTaskName(run.task_id)}\n
\n
\n
e.stopPropagation()}>\n handleNavToReport(run.task_id)}\n class=\"px-3 py-1.5 text-xs text-blue-600 hover:text-blue-700 font-medium rounded-lg hover:bg-blue-50 transition-colors\"\n >\n {$t.validation?.view_report || 'View Report'}\n \n {#if showDeleteConfirm === run.id}\n
\n handleDeleteRun(run.id)}\n class=\"px-2 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700\"\n >\n {$t.validation?.confirm_delete || 'Delete'}\n \n (showDeleteConfirm = null)}\n class=\"px-2 py-1 text-xs bg-gray-200 text-gray-700 rounded hover:bg-gray-300\"\n >\n {$t.validation?.cancel_delete || 'Cancel'}\n \n
\n {:else}\n (showDeleteConfirm = run.id)}\n class=\"p-2 text-gray-400 hover:text-red-600 rounded-lg hover:bg-red-50 transition-colors\"\n title={$t.common?.delete || 'Delete'}\n >\n \n \n \n \n {/if}\n
\n
\n
\n {/each}\n
\n\n \n
\n

\n {($t.validation?.showing || 'Showing {count} of {total}')\n .replace('{count}', String(runs.length))\n .replace('{total}', String(total))}\n

\n
\n { currentPage--; loadRuns(); }}\n disabled={currentPage <= 1}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.previous || 'Previous'}\n \n { currentPage++; loadRuns(); }}\n disabled={currentPage * pageSize >= total}\n class=\"px-3 py-1.5 text-sm border border-gray-200 rounded-lg disabled:opacity-50 hover:bg-gray-50\"\n >\n {$t.validation?.next || 'Next'}\n \n
\n
\n {/if}\n
\n\n" + }, { "contract_id": "GitServiceContractTests", "contract_type": "Module", @@ -85017,180 +87756,6 @@ "tier_source": "AutoCalculated", "body": "/**\n * @purpose Updates logging configuration.\n * @param {Object} configData - Logging config (level, task_log_level, enable_belief_state).\n * @returns {Promise}\n * @relation CALLS -> backend.src.api.routes.settings.update_logging_config\n */" }, - { - "contract_id": "ConnectionService", - "contract_type": "Service", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 1, - "end_line": 54, - "tier": "TIER_1", - "complexity": 2, - "metadata": { - "COMPLEXITY": 2, - "PURPOSE": "Service for Connection Management API — list, create, and delete connection configurations." - }, - "relations": [], - "schema_warnings": [ - { - "code": "tag_not_for_contract_type", - "tag": "COMPLEXITY", - "message": "@COMPLEXITY is not allowed for contract type 'Service'", - "detail": { - "actual_type": "Service", - "allowed_types": [ - "Module", - "Function", - "Class", - "Component", - "Block", - "Skill", - "Agent" - ] - } - }, - { - "code": "tag_forbidden_by_complexity", - "tag": "COMPLEXITY", - "message": "@COMPLEXITY is forbidden for contract type 'Service' at C2", - "detail": { - "actual_complexity": 2, - "contract_type": "Service" - } - }, - { - "code": "tag_not_for_contract_type", - "tag": "PURPOSE", - "message": "@PURPOSE is not allowed for contract type 'Service'", - "detail": { - "actual_type": "Service", - "allowed_types": [ - "Module", - "Function", - "Class", - "Component", - "Block", - "ADR", - "Skill", - "Agent" - ] - } - }, - { - "code": "tag_forbidden_by_complexity", - "tag": "PURPOSE", - "message": "@PURPOSE is forbidden for contract type 'Service' at C2", - "detail": { - "actual_complexity": 2, - "contract_type": "Service" - } - } - ], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "// #region ConnectionService [C:2] [TYPE Service] [SEMANTICS connection, service, api, crud, database]\n// @BRIEF Service for Connection Management API — list, create, and delete connection configurations.\n\n/**\n * Service for interacting with the Connection Management API.\n */\n\nimport { requestApi } from '../lib/api';\n\nconst API_BASE = '/settings/connections';\n\n// #region getConnections:Function [TYPE Function]\n/* @PURPOSE: Fetch a list of saved connections.\n @PRE: None.\n @POST: Returns a promise resolving to an array of connections.\n*/\n/**\n * Fetch a list of saved connections.\n * @returns {Promise} List of connections.\n */\nexport async function getConnections() {\n return requestApi(API_BASE);\n}\n// #endregion getConnections:Function\n\n// #region createConnection:Function [TYPE Function]\n/* @PURPOSE: Create a new connection configuration.\n @PRE: connectionData must be a valid object.\n @POST: Returns a promise resolving to the created connection.\n*/\n/**\n * Create a new connection configuration.\n * @param {Object} connectionData - The connection data.\n * @returns {Promise} The created connection instance.\n */\nexport async function createConnection(connectionData) {\n return requestApi(API_BASE, 'POST', connectionData);\n}\n// #endregion createConnection:Function\n\n// #region deleteConnection:Function [TYPE Function]\n/* @PURPOSE: Delete a connection configuration.\n @PRE: connectionId must be a valid string.\n @POST: Returns a promise that resolves when deletion is complete.\n*/\n/**\n * Delete a connection configuration.\n * @param {string} connectionId - The ID of the connection to delete.\n */\nexport async function deleteConnection(connectionId) {\n return requestApi(`${API_BASE}/${connectionId}`, 'DELETE');\n}\n// #endregion deleteConnection:Function\n// #endregion ConnectionService\n" - }, - { - "contract_id": "getConnections:Function", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 12, - "end_line": 24, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "POST": "Returns a promise resolving to an array of connections.", - "PRE": "None.", - "PURPOSE": "Fetch a list of saved connections." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "// #region getConnections:Function [TYPE Function]\n/* @PURPOSE: Fetch a list of saved connections.\n @PRE: None.\n @POST: Returns a promise resolving to an array of connections.\n*/\n/**\n * Fetch a list of saved connections.\n * @returns {Promise} List of connections.\n */\nexport async function getConnections() {\n return requestApi(API_BASE);\n}\n// #endregion getConnections:Function\n" - }, - { - "contract_id": "frontend/src/services/connectionService.js::getConnections", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 17, - "end_line": 21, - "tier": "TIER_1", - "complexity": 1, - "metadata": {}, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "jsdoc", - "tier_source": "AutoCalculated", - "body": "/**\n * Fetch a list of saved connections.\n * @returns {Promise} List of connections.\n */" - }, - { - "contract_id": "createConnection:Function", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 26, - "end_line": 39, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "POST": "Returns a promise resolving to the created connection.", - "PRE": "connectionData must be a valid object.", - "PURPOSE": "Create a new connection configuration." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "// #region createConnection:Function [TYPE Function]\n/* @PURPOSE: Create a new connection configuration.\n @PRE: connectionData must be a valid object.\n @POST: Returns a promise resolving to the created connection.\n*/\n/**\n * Create a new connection configuration.\n * @param {Object} connectionData - The connection data.\n * @returns {Promise} The created connection instance.\n */\nexport async function createConnection(connectionData) {\n return requestApi(API_BASE, 'POST', connectionData);\n}\n// #endregion createConnection:Function\n" - }, - { - "contract_id": "frontend/src/services/connectionService.js::createConnection", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 31, - "end_line": 36, - "tier": "TIER_1", - "complexity": 1, - "metadata": {}, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "jsdoc", - "tier_source": "AutoCalculated", - "body": "/**\n * Create a new connection configuration.\n * @param {Object} connectionData - The connection data.\n * @returns {Promise} The created connection instance.\n */" - }, - { - "contract_id": "deleteConnection:Function", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 41, - "end_line": 53, - "tier": "TIER_1", - "complexity": 1, - "metadata": { - "POST": "Returns a promise that resolves when deletion is complete.", - "PRE": "connectionId must be a valid string.", - "PURPOSE": "Delete a connection configuration." - }, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "region", - "tier_source": "AutoCalculated", - "body": "// #region deleteConnection:Function [TYPE Function]\n/* @PURPOSE: Delete a connection configuration.\n @PRE: connectionId must be a valid string.\n @POST: Returns a promise that resolves when deletion is complete.\n*/\n/**\n * Delete a connection configuration.\n * @param {string} connectionId - The ID of the connection to delete.\n */\nexport async function deleteConnection(connectionId) {\n return requestApi(`${API_BASE}/${connectionId}`, 'DELETE');\n}\n// #endregion deleteConnection:Function\n" - }, - { - "contract_id": "frontend/src/services/connectionService.js::deleteConnection", - "contract_type": "Function", - "file_path": "frontend/src/services/connectionService.js", - "start_line": 46, - "end_line": 50, - "tier": "TIER_1", - "complexity": 1, - "metadata": {}, - "relations": [], - "schema_warnings": [], - "anchor_syntax": "jsdoc", - "tier_source": "AutoCalculated", - "body": "/**\n * Delete a connection configuration.\n * @param {string} connectionId - The ID of the connection to delete.\n */" - }, { "contract_id": "GitUtils", "contract_type": "Module", @@ -86757,6623 +89322,6642 @@ } ], "file_hashes": { - "backend/src/plugins/translate/__tests__/test_preview.py": 13085659611728720229, - "venv/lib/python3.13/site-packages/pyasn1/codec/ber/encoder.py": 8912119133548489544, - "venv/lib/python3.13/site-packages/git/objects/submodule/base.py": 10140490301897269395, - "venv/lib/python3.13/site-packages/pydantic/deprecated/decorator.py": 8609500261161560793, - "backend/conftest.py": 16521922883434363388, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/__init__.py": 13749066369790839334, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_packbits.py": 7592956764084658562, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_is_monotonic.py": 4626065848596214108, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_export_format.py": 17862222951776199694, - "venv/lib/python3.13/site-packages/git/objects/blob.py": 8972374723153211283, - "venv/lib/python3.13/site-packages/pillow.libs/libbrotlidec-b57ddf63.so.1.2.0": 10032590058372320813, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_select_dtypes.py": 3530442956913622572, - "venv/lib/python3.13/site-packages/websockets/asyncio/server.py": 885415484558949506, - "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.py": 14696841109142419143, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_hist_box_by.py": 16197297231683144299, - "venv/lib/python3.13/site-packages/yaml/constructor.py": 8731384179016992045, - "venv/lib/python3.13/site-packages/pygments/lexers/webassembly.py": 17811970490091406867, - "backend/src/plugins/translate/dictionary.py": 2903767700173238799, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_dialect.py": 4700488504252803159, - "backend/git_repos/remote/test-repo.git/objects/c5/b992984fe856bd81206304a881faa3087937cf": 2441623644664166468, - "frontend/build/_app/immutable/assets/0.DWB1eHi4.css": 9171035187624906932, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/secrets.py": 17816662030600756342, - "backend/git_repos/remote/test-repo.git/objects/8c/4ea7958b7a7e140d27e1e7d8d1f9912fdf5992": 5862166356451798197, - "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pygments/lexers/grammar_notation.py": 9009644754106884095, - "venv/lib/python3.13/site-packages/pip/_internal/commands/index.py": 16715578868094112894, - "venv/lib/python3.13/site-packages/numpy/lib/_datasource.pyi": 5894423389796456573, - "venv/lib/python3.13/site-packages/pandas/core/internals/__init__.py": 1377108808392195313, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asof.py": 17616601748321325187, - "venv/lib/python3.13/site-packages/pandas/io/parsers/readers.py": 7899068668225389287, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/char.pyi": 1639810799219814643, - "venv/lib/python3.13/site-packages/pygments/lexers/spice.py": 1376126320935115350, - "backend/src/plugins/translate/metrics.py": 16289306156708185830, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/METADATA": 11557342107649194148, - "venv/lib/python3.13/site-packages/websockets/extensions/__init__.py": 13067201313921664210, - "venv/lib/python3.13/site-packages/websockets/legacy/exceptions.py": 16025779645869134942, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/__init__.py": 14571251344510763303, - "venv/lib/python3.13/site-packages/cryptography/x509/certificate_transparency.py": 11337143186866439208, - "venv/lib/python3.13/site-packages/numpy/_core/_dtype.pyi": 17662618580381221543, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_comparisons.py": 2764694394636775220, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py": 3369246520501764730, - "venv/lib/python3.13/site-packages/httpcore/_exceptions.py": 6716590711697088732, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/functions.py": 16567226076808693246, - "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft_umath.cpython-313-x86_64-linux-gnu.so": 16443444849116065961, - "venv/lib/python3.13/site-packages/uvicorn/protocols/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f": 13432803601367981068, - "backend/alembic.ini": 8897071018956157084, - "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector.py": 15458248567257759500, - "venv/lib/python3.13/site-packages/jaraco/classes/properties.py": 6976928770004942858, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunc_config.pyi": 11754104063443791746, - "venv/lib/python3.13/site-packages/requests/auth.py": 912521029864094489, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_interval.py": 2911379732293827726, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_datetimes.py": 7889573945417063183, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation": 5398883285871046811, - "venv/lib/python3.13/site-packages/authlib/common/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_indexing.py": 3841182456456779012, - "venv/lib/python3.13/site-packages/git/types.py": 13960696584646279283, - "frontend/src/routes/dashboards/health/__tests__/health_page.integration.test.js": 11653729504599199718, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py": 9623344347519683527, - "venv/lib/python3.13/site-packages/pygments/lexers/ooc.py": 14540210212631538007, - "venv/lib/python3.13/site-packages/pandas/core/window/common.py": 17956497339875932377, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py": 6712732248328458871, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_array_ops.py": 6709502157317299163, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_as_unit.py": 8492383355919959393, - "backend/src/services/__tests__/test_encryption_manager.py": 5925253324895194576, - "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_time.py": 10463741033950978270, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/__init__.py": 6327819603201859020, - "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/hybrid.py": 14287665090144592501, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_hashing.py": 11119284926039008503, - "venv/lib/python3.13/site-packages/PIL/_binary.py": 14039167720582222043, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_missing.py": 7034102519042351965, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_period.py": 3419297908709788013, - "venv/lib/python3.13/site-packages/pygments/lexers/parsers.py": 12372594608244797844, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_abstract_interface.py": 17625870734108222276, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/RECORD": 2688648742701423549, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.py": 17277594393032382485, - "venv/lib/python3.13/site-packages/jsonschema/tests/_suite.py": 6307666366417438489, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_na_values.py": 13527837495439739279, - "venv/lib/python3.13/site-packages/pandas/core/tools/times.py": 6560679305255812809, - "venv/lib/python3.13/site-packages/pandas/io/formats/css.py": 11288129826285529457, - "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/__init__.py": 14268033439436797364, - "venv/lib/python3.13/site-packages/PIL/ImageChops.py": 16368812693381154921, - "venv/lib/python3.13/site-packages/numpy/strings/__init__.py": 6523674574341354095, - "frontend/src/routes/dashboards/[id]/components/DashboardTaskHistory.svelte": 8800115118935646769, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90": 13174951794239860144, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/__init__.py": 15487893533770969571, - "frontend/build/_app/immutable/nodes/7.Db8qHvn3.js": 5936859630254124070, - "venv/lib/python3.13/site-packages/pyasn1/type/error.py": 1479878696626082697, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/jwe.py": 10478268710546063196, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_orm_types.py": 5508682532707462217, - "venv/lib/python3.13/site-packages/pandas/util/_tester.py": 1033951890304257539, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py": 16386268386376675175, - "venv/lib/python3.13/site-packages/numpy/tests/test_configtool.py": 8208415015478205502, - "venv/lib/python3.13/site-packages/pandas/tests/test_register_accessor.py": 16661086720613729974, - "venv/lib/python3.13/site-packages/pandas/io/xml.py": 326466573926392764, - "venv/lib/python3.13/site-packages/pygments/lexers/tls.py": 3552078393009383412, - "venv/lib/python3.13/site-packages/pip/_vendor/certifi/cacert.pem": 15624463015628939254, - "venv/lib/python3.13/site-packages/pip/_vendor/distro/__init__.py": 11414161642984633362, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_series.py": 2980850649986213051, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion": 2607512361823362698, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_value_counts.py": 5534713464063604301, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_pad.pyi": 14755435694146003896, - "venv/lib/python3.13/site-packages/pandas/tests/tools/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/cddl.py": 1303059539145221713, - "backend/src/api/routes/translate/_router.py": 4164547666727936398, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi": 1846673463183660140, - "frontend/src/lib/components/layout/__tests__/test_sidebar.svelte.js": 1424894894434906249, - "backend/src/plugins/git/llm_extension.py": 9347391649685791102, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/__init__.py": 6532094538918910232, - "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/wsproto_impl.py": 3072714633272661847, - "venv/lib/python3.13/site-packages/packaging/licenses/__init__.py": 15879493360260891293, + "venv/lib/python3.13/site-packages/pydantic/v1/error_wrappers.py": 5701679786078971939, "venv/lib/python3.13/site-packages/jsonschema/tests/typing/test_all_concrete_validators_match_protocol.py": 14824388798676578409, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_internals.py": 10472508540875131797, - "venv/lib/python3.13/site-packages/websockets/speedups.pyi": 10322382420215791091, - "venv/lib/python3.13/site-packages/pygments/lexers/algebra.py": 9651893228421050246, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py": 2516476609539242190, - "venv/lib/python3.13/site-packages/numpy/_array_api_info.pyi": 13283968924732680159, - "venv/lib/python3.13/site-packages/pydantic/_internal/_namespace_utils.py": 5237766366340181382, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/redis.py": 11313520438600819390, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_compare.py": 3079569478684646491, - "backend/src/api/routes/clean_release.py": 1984604735131504761, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_ratio.py": 940213488194452623, - "venv/lib/python3.13/site-packages/git/db.py": 6680123567509774609, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/background.py": 2105814165112049750, - "backend/src/plugins/translate/preview_prompt_builder.py": 2354938052590494405, - "venv/lib/python3.13/site-packages/pygments/lexers/eiffel.py": 8964563077187051946, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h": 5001035774408914877, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_mrecords.py": 15952147778503828707, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_indexing.py": 16623126293364224089, - "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/signals.py": 13677199634497673845, - "venv/lib/python3.13/site-packages/PIL/TiffTags.py": 8688883943071546469, - "venv/lib/python3.13/site-packages/pygments/__init__.py": 14493583771211110135, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_operators.py": 12686786829906210592, + "venv/lib/python3.13/site-packages/pandas/_testing/contexts.py": 11714205921752896137, "venv/lib/python3.13/site-packages/pip/_vendor/pygments/regexopt.py": 16073437303824961930, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/index_tricks.py": 10051261976498916957, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_constructors.py": 16197656939536784142, - "backend/src/api/routes/assistant/_llm_planner.py": 444517242115816139, - "venv/lib/python3.13/site-packages/numpy/f2py/__init__.py": 7470157159992827389, - "venv/lib/python3.13/site-packages/urllib3/_base_connection.py": 14495079097019980154, - "venv/lib/python3.13/site-packages/pydantic/parse.py": 13750341403702794392, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/wheel.py": 828222664427570058, - "venv/lib/python3.13/site-packages/passlib/tests/test_win32.py": 13932956220195912963, - "venv/lib/python3.13/site-packages/pydantic/validate_call_decorator.py": 11130572937843915026, - "venv/lib/python3.13/site-packages/bcrypt/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/h11/_writers.py": 8585823094975171480, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.cpython-313-x86_64-linux-gnu.so": 15960606468596245469, - "venv/lib/python3.13/site-packages/referencing/jsonschema.py": 14596871117484757502, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/scoping.py": 18223258186431020473, - "frontend/src/lib/components/dataset-review/LaunchConfirmationPanel.svelte": 14399834101283315718, - "venv/lib/python3.13/site-packages/starlette/convertors.py": 17839747154274354605, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_index.py": 10837492069089787028, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_algos.py": 5356470832688354593, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_amd64_unix.h": 16679226724722970205, - "venv/lib/python3.13/site-packages/pyasn1/type/constraint.py": 16776615503418773283, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/WHEEL": 7454950858448014158, - "venv/lib/python3.13/site-packages/click/utils.py": 13475604420010022458, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_unittests.py": 18157503533859249155, - "venv/lib/python3.13/site-packages/numpy/random/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/PIL/MicImagePlugin.py": 13540523615822507963, - "venv/lib/python3.13/site-packages/numpy/random/_common.pyi": 5094115692952609118, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/pkg_resources.py": 14271077832999370068, - "backend/src/plugins/translate/__tests__/test_scheduler.py": 11257332466578758156, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_alter_axes.py": 11338712836362534969, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/util.py": 955993052529739164, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_methods.py": 12694335778731418517, - "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.pyi": 9243829615414967057, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core": 10616484054735611337, - "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/__init__.py": 12911374670789466961, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_sort_values.py": 15072305514178699398, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_parser.py": 3540203683732744499, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/__init__.py": 15130871412783076140, - "backend/src/plugins/translate/_utils.py": 10016440264788256359, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/vectorized.cpython-313-x86_64-linux-gnu.so": 5441755022198996487, - "venv/lib/python3.13/site-packages/pandas/compat/numpy/function.py": 18405870240333383757, - "venv/lib/python3.13/site-packages/fastapi/middleware/trustedhost.py": 4285622102799027823, - "venv/lib/python3.13/site-packages/pandas/io/formats/excel.py": 797619981868084011, - "venv/lib/python3.13/site-packages/greenlet/greenlet_cpython_compat.hpp": 8396413256279803400, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_legacy.py": 12735901522735836481, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_extension.py": 17245018204352082978, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi": 16934250836612138541, - "venv/lib/python3.13/site-packages/pandas/errors/__init__.py": 13444371880185740908, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_union_categoricals.py": 6843679254735807, - "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_py.py": 6428078990080243608, - "venv/lib/python3.13/site-packages/numpy/ma/testutils.pyi": 3899348061346041413, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarinherit.py": 15240535501243623986, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reset_index.py": 14490875921264161445, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_convert.py": 13349243029437881949, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/common.py": 2075178842766962782, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_header.py": 3564391095263545879, - "venv/lib/python3.13/site-packages/yaml/__init__.py": 11044333164208875121, - "frontend/src/routes/translate/dictionaries/+page.svelte": 1038433841421198720, - "frontend/src/components/git/CommitModal.svelte": 4151596094672629211, - "backend/src/services/reports/__tests__/test_report_normalizer.py": 5179524010104259469, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/models.py": 11521700876708601977, - "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pxd": 9126772093305708921, - "frontend/src/lib/stores/sidebar.js": 8409084311045055153, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_indexing_slow.py": 12558235638488427077, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/RECORD": 8956798822782402202, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/status_codes.py": 17005213506461710202, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/dml.py": 17308908394336670576, - "venv/bin/pip": 13861749540792881808, - "venv/lib/python3.13/site-packages/attr/__init__.pyi": 13203080513025719049, - "venv/lib/python3.13/site-packages/jose/backends/cryptography_backend.py": 2875270748627611635, - "venv/lib/python3.13/site-packages/pandas/tests/extension/date/array.py": 18073740473413382768, - "venv/lib/python3.13/site-packages/pygments/lexers/comal.py": 769727871242464458, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.pyi": 12925006572914814268, - "backend/git_repos/remote/test-repo.git/hooks/fsmonitor-watchman.sample": 14381968406977928721, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/version.py": 6401479036177132374, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-2.csv": 16611724551361692999, - "venv/lib/python3.13/site-packages/pydantic/v1/annotated_types.py": 12925825196690299531, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_ufunc.py": 3326502989311831856, - "venv/lib/python3.13/site-packages/passlib/tests/test_pwd.py": 10089138951415591061, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/RECORD": 17985800801793506250, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/stride_tricks.pyi": 5844806555773292985, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_na_scalar.py": 13950899907067372014, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_raises.py": 9678418010293693275, - "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pygments/lexers/matlab.py": 1880915927722177654, - "frontend/src/lib/components/dataset-review/__tests__/us2_semantic_workspace.ux.test.js": 3550956860258259058, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/__init__.py": 4781700006554860887, - "venv/lib/python3.13/site-packages/h11/__init__.py": 222801976520197308, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_common.py": 10797243274520625867, - "frontend/src/components/git/GitWorkspacePanel.svelte": 15810952071932060330, - "venv/lib/python3.13/site-packages/pandas/tests/frame/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/METADATA": 6656194161182818439, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token_validator.py": 2932866595454490527, - "venv/lib/python3.13/site-packages/pygments/formatter.py": 11156733836937309465, - "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.pyi": 10638891136586198429, - "frontend/src/components/git/GitOperationsPanel.svelte": 5140779139910068800, - "venv/lib/python3.13/site-packages/ecdsa/test_pyecdsa.py": 14542286382742044648, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/resources.py": 11533706401259147051, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_utils.pyi": 3708905060001289515, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unique.py": 6234921572794573905, - "frontend/src/lib/components/reports/__tests__/fixtures/reports.fixtures.js": 10647302793388244094, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_logical.py": 6818185860296232476, - "frontend/vite.config.js": 982595057268821071, - "backend/tests/test_dashboards_api.py": 2278794209397518464, - "venv/lib/python3.13/site-packages/pygments/lexers/_asy_builtins.py": 1665617945818958781, - "venv/lib/python3.13/site-packages/websockets/speedups.c": 11800200877763464246, - "venv/lib/python3.13/site-packages/pip/_internal/utils/direct_url_helpers.py": 6075890513530296650, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py": 5247208668583898949, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_formats.py": 18080627205081311773, - "venv/lib/python3.13/site-packages/pyasn1/codec/native/encoder.py": 120921270972591880, - "venv/lib/python3.13/site-packages/secretstorage/collection.py": 17903258621904912493, - "backend/src/plugins/translate/prompt_builder.py": 9619706108488955349, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.pyi": 2700568594438441246, - "venv/lib/python3.13/site-packages/_pytest/stepwise.py": 3527630676691417317, - "venv/lib/python3.13/site-packages/psycopg2/tz.py": 9966680685796585198, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py": 17927903035152872556, - "venv/lib/python3.13/site-packages/pip/__pip-runner__.py": 1138979712722199296, - "venv/lib/python3.13/site-packages/PIL/JpegImagePlugin.py": 10621639599916796689, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_sequence.py": 3721630758772772345, - "venv/lib/python3.13/site-packages/pandas/io/spss.py": 864838144958947906, - "venv/lib/python3.13/site-packages/charset_normalizer/version.py": 9948878594498587774, - "venv/lib/python3.13/site-packages/pygments/lexers/make.py": 5345282370426217663, - "frontend/build/_app/immutable/chunks/DXUsjDzY.js": 18242831136557949498, - "backend/src/models/dataset_review_pkg/_mapping_models.py": 8898456326244890685, - "venv/lib/python3.13/site-packages/pydantic/tools.py": 8931184638883701008, - "venv/lib/python3.13/site-packages/pandas/_libs/reshape.pyi": 88721900806893992, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_series.py": 16418555817529711079, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_reductions.py": 2816859231048302619, - "venv/lib/python3.13/site-packages/pip/_internal/network/cache.py": 10606522397693824641, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/__init__.py": 10834852742917144496, - "backend/src/api/routes/assistant/_history.py": 6437021555836617855, - "venv/lib/python3.13/site-packages/fastapi/encoders.py": 1914192268055730299, - "backend/src/plugins/translate/plugin.py": 9225230324052126034, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_deprecations.py": 6015734648984591027, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/wgsl.py": 9718384325049172855, - "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/smmap/__init__.py": 4557520096828426601, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/themes.py": 6451091097727599550, - "venv/lib/python3.13/site-packages/pandas/core/indexes/multi.py": 9115751979327393200, - "venv/lib/python3.13/site-packages/PIL/FtexImagePlugin.py": 8196606399875185931, - "venv/lib/python3.13/site-packages/pip/_internal/models/candidate.py": 3099785363867247334, - "frontend/src/routes/datasets/review/+page.svelte": 12909115647298935839, - "frontend/src/components/git/ConflictResolver.svelte": 2318922269446496715, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/json.py": 15085143436056608404, - "venv/lib/python3.13/site-packages/rsa/asn1.py": 3861968161559322784, - "venv/lib/python3.13/site-packages/pip/_internal/req/req_set.py": 534498057184394558, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/types.py": 13384984564922916167, - "venv/lib/python3.13/site-packages/idna/__init__.py": 6489437464172324468, - "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/__init__.py": 1229691061011958769, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_is_homogeneous_dtype.py": 15378147393056707851, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/rule.py": 5318344538761246105, - "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_to_numpy.py": 14845850776625255794, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/einsumfunc.pyi": 8902765738896588686, - "venv/lib/python3.13/site-packages/pandas/_libs/internals.cpython-313-x86_64-linux-gnu.so": 2008633361686956377, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/__init__.py": 11157967642611612522, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked_shared.py": 8453174300922339015, - "venv/lib/python3.13/site-packages/pygments/styles/lightbulb.py": 12433916113773598760, - "backend/src/services/notifications/__init__.py": 13930898146447654299, - "venv/lib/python3.13/site-packages/pandas/_libs/ops_dispatch.pyi": 16176428602589420913, - "venv/lib/python3.13/site-packages/pandas/core/groupby/base.py": 16888506204910366302, - "backend/alembic/versions/543d43d752b8_migrate_old_dictionary_entries_and_.py": 10988663686444687907, - "venv/lib/python3.13/site-packages/pandas/core/arrays/masked.py": 13977195666947626206, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets.py": 4499538899492148499, - "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.py": 338595621218646492, - "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml.py": 6906547816798138000, - "venv/lib/python3.13/site-packages/keyring/util/__init__.py": 9635016046220094473, - "venv/lib/python3.13/site-packages/pydantic/v1/color.py": 14545509649623975912, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_day.py": 6371851881186970754, - "venv/lib/python3.13/site-packages/pygments/lexers/perl.py": 17014528337020572681, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_csky_gcc.h": 12929785267195988209, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets.py": 10923534235697247269, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/type_check.pyi": 1599910480066368464, - "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/LICENSE": 6989336036499641077, - "frontend/src/components/tools/DebugTool.svelte": 17267560034225794881, - "backend/src/api/routes/git/_merge_routes.py": 2019590524299108754, - "venv/lib/python3.13/site-packages/pandas/tests/resample/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/urllib3/http2/connection.py": 1661620860881397554, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/exceptions.py": 2873060848310644552, - "venv/lib/python3.13/site-packages/passlib/tests/sample1b.cfg": 2872366861156549016, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_nanfunctions.py": 2356468092336024365, - "venv/lib/python3.13/site-packages/pip/_vendor/certifi/core.py": 2300277198409164253, - "frontend/src/routes/settings/settings-utils.js": 6465823001530600927, - "frontend/build/_app/immutable/nodes/4.BvNwW8AT.js": 8636697565127397423, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/fromnumeric.pyi": 6708743411405679061, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_extint128.py": 11074657869101074458, - "venv/lib/python3.13/site-packages/websockets/sync/connection.py": 2791040669094103200, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_categorical.py": 1329115818264527103, - "venv/lib/python3.13/site-packages/bcrypt/__init__.py": 11415155211917181362, - "venv/lib/python3.13/site-packages/annotated_types/__init__.py": 7367790549779882749, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/naming.py": 14503932124671438340, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/__init__.py": 16146480198665866916, - "venv/lib/python3.13/site-packages/httpcore/_sync/connection.py": 1539337414493486168, - "frontend/e2e/tests/settings.e2e.js": 14741334477359695649, - "frontend/src/lib/ui/index.ts": 6883965364006817450, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/METADATA": 13633829318759752611, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pycparser/ply/ctokens.py": 1599952198962458730, - "venv/lib/python3.13/site-packages/more_itertools/__init__.pyi": 16479506520351014608, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/queue.py": 7820997545569991670, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_apply.py": 11248068903302454630, - "frontend/build/_app/immutable/chunks/CNlOpchA.js": 745984356029155492, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_timedeltaindex.py": 2359681317403710563, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/authorization_server.py": 4427151727224472650, - "venv/lib/python3.13/site-packages/pydantic_settings/py.typed": 15130871412783076140, - "backend/src/plugins/translate/service_bulk_replace.py": 5355744069308185607, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/request.py": 10484280068366411541, - "venv/lib/python3.13/site-packages/gitdb/db/git.py": 13552203494737962026, - "venv/lib/python3.13/site-packages/pydantic/v1/dataclasses.py": 7833468513057242440, - "venv/lib/python3.13/site-packages/pygments/style.py": 17393199235575070210, - "venv/lib/python3.13/site-packages/pandas/core/arrays/timedeltas.py": 7318851108932357510, - "venv/lib/python3.13/site-packages/httpcore/_api.py": 16499985295426060327, - "frontend/src/components/git/DeploymentModal.svelte": 16301125393395343650, - "backend/git_repos/remote/test-repo.git/hooks/push-to-checkout.sample": 4825338927654285910, - "backend/src/services/dataset_review/clarification_pkg/_helpers.py": 9331845075873070265, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_size.py": 12449835577388069407, - "venv/lib/python3.13/site-packages/pygments/lexers/other.py": 6893672181003034910, - "frontend/src/services/__tests__/gitService.test.js": 12845562082447336909, - "venv/lib/python3.13/site-packages/attr/converters.pyi": 17675091788614033166, - "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/tests/test_lazyloading.py": 17465787495701737655, - "venv/lib/python3.13/site-packages/passlib/tests/test_utils_handlers.py": 556092537518149789, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get.py": 6509102681661636928, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/pretty.py": 2448541115957861214, - "venv/lib/python3.13/site-packages/rsa/py.typed": 11041940105507257053, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh26681.f90": 1515497186927052106, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connectionpool.py": 10453724680327835821, - "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/RECORD": 11111103193315065053, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/constructors.py": 7587476800569414769, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/git/objects/submodule/root.py": 5322248117564025370, - "backend/src/scripts/seed_permissions.py": 17005340106913955508, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/__init__.py": 371829636800613137, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_normalize.py": 3203921571999101793, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_replace.py": 8165088653532047247, - "venv/lib/python3.13/site-packages/_pytest/terminal.py": 885450969703476729, - "venv/lib/python3.13/site-packages/jaraco/functools/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpcore/_async/connection.py": 2155744160496556069, - "venv/lib/python3.13/site-packages/apscheduler/triggers/interval.py": 3964550092873794670, - "venv/lib/python3.13/site-packages/gitdb/util.py": 645937410168583692, - "venv/lib/python3.13/site-packages/numpy/tests/test__all__.py": 10689265249302359388, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/METADATA": 9458019064618635438, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/packaging/_structures.py": 13086687542872305890, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/__init__.py": 15130871412783076140, - "backend/src/plugins/translate/dictionary_entries.py": 11394786590056973146, - "venv/lib/python3.13/site-packages/six.py": 948867418687428421, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/state.py": 10500170103357297551, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_npfuncs.py": 13987318550267921389, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/hooks.py": 9888227370911151341, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/ecdsa/_compat.py": 13034064768731879065, - "venv/lib/python3.13/site-packages/pluggy/_manager.py": 18202550145040079612, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/test_astype.py": 10171766562093740708, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_character.py": 17168707712220699738, - "venv/lib/python3.13/site-packages/PIL/ImageQt.py": 6607270889359138659, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape_base.pyi": 10291383658131961346, - "venv/lib/python3.13/site-packages/pygments/styles/rainbow_dash.py": 12236746494379891602, - "backend/tests/services/clean_release/test_publication_service.py": 17277940125978730159, - "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/__init__.py": 1798074863773727377, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_period.py": 10309599277099605395, - "backend/src/plugins/translate/__tests__/__init__.py": 2490542523242946173, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_integrity.py": 12010564145080323987, - "venv/lib/python3.13/site-packages/dateutil/tz/_factories.py": 7538654189286887518, - "venv/lib/python3.13/site-packages/pluggy/_warnings.py": 2664977718908223842, - "venv/lib/python3.13/site-packages/httpcore/_async/http11.py": 7565741048880549265, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/mock.py": 14010776046610111182, - "frontend/src/lib/stores/__tests__/test_taskDrawer.js": 13582869875796637016, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta_range.py": 15081095442418142820, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_extension_array_equal.py": 16119106336497630796, - "venv/lib/python3.13/site-packages/pygments/lexers/smithy.py": 10789533877863290582, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_str.py": 149688376805129532, - "venv/lib/python3.13/site-packages/jeepney/low_level.py": 6546206679858571608, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90": 15012692484070385863, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.pyi": 3145980717589050713, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_append.py": 17016125916761365423, - "venv/lib/python3.13/site-packages/authlib/oauth2/base.py": 12948318231066662045, - "venv/lib/python3.13/site-packages/pygments/lexers/configs.py": 7712797939104760185, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/__init__.py": 15130871412783076140, - "frontend/build/_app/immutable/chunks/DU4MtuMl.js": 14717365893620949586, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/sphinxext.py": 2403717774564798878, - "venv/lib/python3.13/site-packages/pandas/compat/_constants.py": 3909166275649444824, - "venv/lib/python3.13/site-packages/pandas/tseries/frequencies.py": 2262381949755250516, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_arithmetic.py": 17449383588949771785, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pxd": 13413785818999584986, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/criterion.py": 2042509334195547606, - "venv/lib/python3.13/site-packages/jsonschema/__init__.py": 6925762200139836824, - "venv/lib/python3.13/site-packages/numpy/lib/mixins.py": 7404729635424818497, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.py": 1472021608501071055, - "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.py": 5570375156851166818, - "venv/lib/python3.13/site-packages/passlib/tests/test_context_deprecated.py": 7876919198015151018, + "venv/lib/python3.13/site-packages/pyasn1/type/base.py": 6801504886392649787, + "venv/lib/python3.13/site-packages/starlette/middleware/trustedhost.py": 8302185291610019926, + "backend/src/services/dataset_review/orchestrator_pkg/_helpers.py": 3718757635506173013, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv": 16333455295913164408, + "venv/lib/python3.13/site-packages/passlib/ifc.py": 14479133654556657428, + "venv/lib/python3.13/site-packages/pygments/lexers/ul4.py": 9580182474451220952, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_counting.py": 5628494712451120258, + "venv/lib/python3.13/site-packages/ecdsa/keys.py": 10281170640484982154, + "backend/tests/test_task_persistence.py": 1764267414712263025, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/transforms.py": 3773159138960141434, + "venv/lib/python3.13/site-packages/pip/_internal/operations/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.pyi": 11310761736182213265, "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_repeat.py": 9155935990114743583, - "venv/lib/python3.13/site-packages/uvicorn/loops/uvloop.py": 5385425357504191161, - "venv/lib/python3.13/site-packages/jeepney/io/blocking.py": 4699555965372200059, - "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.py": 503331864022631297, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_round.py": 7912161077874611432, - "venv/lib/python3.13/site-packages/pandas/tests/test_algos.py": 11860014896449369497, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_matrix_linalg.py": 2858987911347541177, - "venv/lib/python3.13/site-packages/pygments/token.py": 6987328478153445584, - "backend/src/plugins/translate/preview_session_ops.py": 14499196532448992687, - "venv/lib/python3.13/site-packages/pandas/core/computation/api.py": 17919983681396223380, - "venv/lib/python3.13/site-packages/pandas/core/frame.py": 2630807744775247533, - "venv/lib/python3.13/site-packages/attr/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/macos.py": 17442393555211213147, - "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.pyi": 5269136485429780038, - "venv/lib/python3.13/site-packages/pydantic/v1/class_validators.py": 6471688474853407718, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/scalars.py": 3468820466230647963, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.pyi": 3595910367556664837, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv": 3026156288992132911, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_reshape.py": 5572426834735088916, - "venv/lib/python3.13/site-packages/numpy/_core/tests/_locales.py": 18178500267053825979, - "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_dict.py": 4937173601709369119, - "venv/lib/python3.13/site-packages/PIL/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/carbon.py": 6753624244809529841, - "frontend/src/routes/admin/settings/+page.svelte": 15536865086528222650, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_delitem.py": 14336697139511118920, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90": 5518911932373565642, - "backend/src/core/auth/logger.py": 9289916075840905359, - "venv/lib/python3.13/site-packages/pandas/core/accessor.py": 1188716996113179524, - "venv/lib/python3.13/site-packages/pandas/io/excel/_calamine.py": 13354427767660487637, - "venv/lib/python3.13/site-packages/websockets/server.py": 16599051743322571790, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_file_buffer_url.py": 15377043158761455858, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/__init__.py": 3619091571279924576, - "venv/lib/python3.13/site-packages/pandas/io/json/_json.py": 1393095374713367445, - "venv/lib/python3.13/site-packages/pip/_vendor/__init__.py": 11734104142988812647, - "venv/lib/python3.13/site-packages/charset_normalizer/models.py": 9917300217816275821, - "venv/lib/python3.13/site-packages/pygments/lexer.py": 3658450949169647228, - "backend/src/services/notifications/providers.py": 12897444612423813747, - "backend/src/dependencies.py": 9481683691730170837, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/env.py": 1254612137164491329, - "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/RECORD": 4857922668040624663, - "venv/lib/python3.13/site-packages/pandas/core/reshape/melt.py": 14109947554124551986, - "venv/lib/python3.13/site-packages/sqlalchemy/pool/base.py": 16951268065271931235, - "venv/lib/python3.13/site-packages/pandas/tests/test_sorting.py": 10751098438703044961, - "venv/lib/python3.13/site-packages/websockets/legacy/framing.py": 12759022769700230409, - "venv/lib/python3.13/site-packages/pip/_internal/commands/help.py": 4175797322922912326, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_category.py": 3944898528119364040, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/common.py": 2075178842766962782, + "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.pyi": 15848834171197104301, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/websockets/asyncio/connection.py": 17044409627448400723, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/matrix.pyi": 15667024840812783911, + "venv/lib/python3.13/site-packages/pandas/_testing/_hypothesis.py": 12298650110193262367, "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh25211.f": 1486878017876900890, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_html.py": 7947998260347730581, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/RECORD": 1164466882742493155, + "venv/lib/python3.13/site-packages/PIL/PcdImagePlugin.py": 922809545463280224, + "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.pyi": 18290764713161282980, + "venv/lib/python3.13/site-packages/pygments/styles/lightbulb.py": 12433916113773598760, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_constructors.py": 9478848417896027917, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/redis.py": 11313520438600819390, + "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.py": 12771179468704314203, + "frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js": 15091004230843271151, + "venv/lib/python3.13/site-packages/cryptography/x509/general_name.py": 4481582226129488535, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_conversion.py": 12184280074522274780, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py": 16768579082462294745, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/licenses/COPYING": 14459782230785388765, + "venv/lib/python3.13/site-packages/starlette/_exception_handler.py": 9892172656847200124, + "build.sh": 14606128418937696284, + "venv/lib/python3.13/site-packages/cffi/pkgconfig.py": 16057517851163939571, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_mips_unix.h": 17373389962405490482, + "venv/lib/python3.13/site-packages/pydantic/root_model.py": 20625057828723317, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/block.f": 10727418304254548946, + "frontend/src/lib/components/layout/__tests__/test_breadcrumbs.svelte.js": 1250794495161202602, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unique.py": 6234921572794573905, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.pyi": 1521384724035973688, + "venv/lib/python3.13/site-packages/gitdb/exc.py": 13975852664048821278, + "venv/lib/python3.13/site-packages/pandas/core/apply.py": 17080038932032802984, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_md4.py": 15270721044910698449, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_common.py": 10797243274520625867, + "venv/lib/python3.13/site-packages/git/index/fun.py": 18338379518768926372, + "venv/lib/python3.13/site-packages/pip/_internal/network/cache.py": 10606522397693824641, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/__init__.py": 6489437464172324468, + "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.py": 6205675182996213576, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/halffloat.h": 16913381775994652343, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py": 7906029092844029127, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/METADATA": 7727489762869155085, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_smoke.py": 7476432112986643847, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/__init__.py": 3619091571279924576, + "venv/lib/python3.13/site-packages/uvicorn/server.py": 15714008348292243019, + "venv/lib/python3.13/site-packages/_pytest/__init__.py": 3769333500910148571, + "venv/lib/python3.13/site-packages/pygments/formatters/groff.py": 6480830447984073574, + "frontend/build/_app/immutable/assets/9.tn0RQdqM.css": 15130871412783076140, + "backend/src/services/clean_release/audit_service.py": 3614108458934359126, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/WHEEL": 13232065379159720345, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/__init__.py": 8558541715982163200, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ufuncobject.h": 5112456258078662871, + "backend/git_repos/remote/test-repo.git/objects/a1/3525f5f44e26d8fbec3226bd488d14793575a2": 3742572048019652365, + "venv/lib/python3.13/site-packages/authlib/integrations/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/_philox.cpython-313-x86_64-linux-gnu.so": 9916143171057774705, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/__init__.py": 2635182244050911910, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi": 4376871621615688626, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_polynomial.pyi": 9134949577567498894, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/RECORD": 12598309574903741388, + "backend/src/plugins/translate/service_inline_correction.py": 11066393548140180037, + "venv/lib/python3.13/site-packages/PIL/ImageQt.py": 6607270889359138659, + "backend/tests/test_core_scheduler.py": 6589618269087393661, + "venv/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py": 7733356903092860495, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_ndarray_backed.py": 10097812802469682233, + "venv/lib/python3.13/site-packages/numpy/typing/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/io/sas/__init__.py": 8095743504390517992, + "frontend/build/_app/immutable/chunks/D_JM-145.js": 3165451337751856519, + "backend/src/plugins/llm_analysis/__tests__/test_client_headers.py": 5527172390260032966, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_dtypes.py": 6831042272921908068, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_editable.py": 14352954849821931255, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/__main__.py": 487896753130729554, + "frontend/src/lib/ui/Button.svelte": 921807193049478213, + "backend/src/core/superset_profile_lookup.py": 5518507735632088337, + "venv/lib/python3.13/site-packages/gitdb/test/test_example.py": 3039934065817753241, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_equals.py": 18261810467289276844, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_generic.py": 1297407268239966429, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_values.py": 12064896795288302730, + "venv/lib/python3.13/site-packages/pygments/lexers/_stata_builtins.py": 18053452765493556047, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/_pytest/runner.py": 5772610501857496741, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply.py": 8103417303073393969, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/row.py": 9763935103055608874, + "venv/lib/python3.13/site-packages/numpy/_core/_methods.pyi": 9155045948490225716, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/__init__.py": 13331622784664204066, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/models.py": 16636119441941357281, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/wheel.py": 13979536782410081712, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/recarray_from_file.fits": 15116318600514274152, + "venv/lib/python3.13/site-packages/pandas/compat/_optional.py": 12714208019736797073, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/uts46data.py": 1867240043777383728, + "venv/lib/python3.13/site-packages/passlib/handlers/sha1_crypt.py": 5752556581809938954, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_matrix_linalg.py": 2858987911347541177, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_pydatetime.py": 1129954411080617001, + "venv/lib/python3.13/site-packages/pandas/io/parquet.py": 14415622950469421518, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/url.py": 9692934100602135106, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_linalg.py": 2939739913218718132, + "venv/lib/python3.13/site-packages/jsonschema/__main__.py": 18136546137047911521, + "venv/lib/python3.13/site-packages/fastapi/responses.py": 6092572095549573593, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/METADATA": 4954909612926293404, + "venv/lib/python3.13/site-packages/authlib/jose/errors.py": 15231759002942436632, + "venv/lib/python3.13/site-packages/pydantic/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_na_scalar.py": 13950899907067372014, + "venv/lib/python3.13/site-packages/numpy/_typing/__init__.py": 18242238390157333247, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/resource_protector.py": 14354891358060085360, + "venv/lib/python3.13/site-packages/httpcore/_synchronization.py": 10997080307461682786, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_dtype.py": 12210524152630532747, + "frontend/src/routes/settings/EnvironmentsTab.svelte": 1326318857426265025, + "frontend/src/components/git/useGitManager.js": 5317184945628692154, + "frontend/build/_app/immutable/chunks/C61pgZQY.js": 3641743244229229084, + "backend/src/models/config.py": 7631082065091961320, + "backend/src/api/routes/assistant/_resolvers.py": 6365921685100086434, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_pipe.py": 8255917221095334212, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/sqlalchemy.py": 811968833735951956, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex.tpl": 8820045022551446255, + "venv/lib/python3.13/site-packages/pandas/core/computation/expressions.py": 10684284531040203747, + "frontend/src/lib/components/assistant/__tests__/assistant_confirmation.integration.test.js": 12582020574293031526, + "venv/lib/python3.13/site-packages/secretstorage/dhcrypto.py": 8860116996905452758, + "frontend/build/_app/immutable/nodes/20.DcXwE2jD.js": 12036759984214418945, + "venv/lib/python3.13/site-packages/pip/_internal/cli/main.py": 9304034369762028739, + "backend/alembic/versions/c4a3a2f74bfe_add_missing_columns_needs_review_.py": 4320606555167902916, + "venv/lib/python3.13/site-packages/pydantic/_internal/_namespace_utils.py": 5237766366340181382, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/models.py": 6924198551176217533, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/datonly.f90": 10495925225338237742, + "venv/lib/python3.13/site-packages/fastapi/utils.py": 15402403831700548944, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/create.py": 16693261531832306870, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_array_utils.py": 14682148205379122638, + "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.py": 503331864022631297, + "venv/lib/python3.13/site-packages/pandas/tests/frame/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/lib.cpython-313-x86_64-linux-gnu.so": 6452315003728497116, + "backend/src/core/migration_engine.py": 3310429374293524108, + "venv/lib/python3.13/site-packages/pydantic_settings/main.py": 17272314000918984790, + "backend/src/services/clean_release/preparation_service.py": 10596397721803950912, + "venv/lib/python3.13/site-packages/keyring/backends/libsecret.py": 11621088556661567306, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/appengine.py": 16194997685865850655, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h": 10634781863364525895, + "venv/lib/python3.13/site-packages/pip/_internal/utils/glibc.py": 12335359492756627313, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_convert_dtypes.py": 13612212066710266457, + "venv/lib/python3.13/site-packages/greenlet/__init__.py": 3447613556981242475, + "venv/lib/python3.13/site-packages/greenlet/_greenlet.cpython-313-x86_64-linux-gnu.so": 6036818030377883416, + "venv/lib/python3.13/site-packages/passlib/handlers/cisco.py": 15004707325761459775, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dtypes.py": 4985057130807802395, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libk5crypto-b1f99d5c.so.3.1": 10669523137596317954, + "venv/lib/python3.13/site-packages/jose/utils.py": 1926138853970725083, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/integration.py": 3085827906490477329, + "venv/lib/python3.13/site-packages/numpy/core/overrides.py": 11228841530565061867, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_floats.py": 3064615530495290792, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_setitem.py": 14920902525192671548, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas.py": 9446226619493404132, + "venv/lib/python3.13/site-packages/PIL/ImageText.py": 15322496455608242001, + "venv/lib/python3.13/site-packages/urllib3/_collections.py": 3440910792774742262, + "frontend/src/lib/components/reports/ReportCard.svelte": 13714680961668469204, + "backend/src/core/plugin_base.py": 11649432288706102843, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv": 13695545125848146013, + "venv/lib/python3.13/site-packages/passlib/handlers/fshp.py": 13298827601291507295, + "venv/lib/python3.13/site-packages/_pytest/timing.py": 14080119171718125986, + "backend/src/core/database.py": 14562394756039123793, + "venv/lib/python3.13/site-packages/numpy/fft/_helper.pyi": 9546918341939102632, + "venv/lib/python3.13/site-packages/pandas/io/sas/sasreader.py": 12766780210114366112, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py": 15060063324909302240, + "backend/src/core/__tests__/test_throttled_scheduler.py": 10949494963069000037, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/comparisons.py": 7327629888601690759, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/RECORD": 3649834117451110628, + "venv/lib/python3.13/site-packages/pygments/lexers/srcinfo.py": 16466766917840327610, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_asymmetric.py": 6903778603779934572, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/logging.py": 2426447364230673649, + "venv/lib/python3.13/site-packages/numpy/lib/_iotools.py": 10522826373041592861, + "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pxd": 14261507718442469988, + "venv/lib/python3.13/site-packages/fastapi/middleware/gzip.py": 436886407566263171, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24008.f": 3872245077994936272, + "venv/lib/python3.13/site-packages/numpy/_core/defchararray.py": 15550230459945996915, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-2.csv": 16611724551361692999, + "venv/lib/python3.13/site-packages/requests/cookies.py": 4997226307650350876, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_missing.py": 2976310411820303374, + "venv/lib/python3.13/site-packages/ecdsa/eddsa.py": 15966858338456571506, + "venv/lib/python3.13/site-packages/dateutil/_common.py": 12492546559232079071, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pycparser/ply/__init__.py": 5040371336745852622, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/code.py": 9700811903057180696, + "venv/lib/python3.13/site-packages/pycparser/c_parser.py": 3954138286651284327, + "venv/lib/python3.13/site-packages/numpy/_pytesttester.py": 17737911110576747508, + "venv/lib/python3.13/site-packages/pygments/lexers/_googlesql_builtins.py": 12251289884604745945, + "venv/lib/python3.13/site-packages/pygments/lexers/_cl_builtins.py": 16540712925368297957, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_find_common_type.py": 9581516171321396333, + "venv/lib/python3.13/site-packages/pygments/formatter.py": 11156733836937309465, + "venv/lib/python3.13/site-packages/pandas/core/indexers/utils.py": 5861072573716897447, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/common.py": 10996276696597806957, + "backend/src/scripts/clean_release_tui.py": 11100359353752859553, + "backend/src/api/routes/dashboards/_helpers.py": 16683849709430404975, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_as_unit.py": 4283520188709399244, + "venv/lib/python3.13/site-packages/numpy/ma/mrecords.pyi": 8945514863366384484, + "backend/src/services/clean_release/__tests__/test_stages.py": 15353751625742444422, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/wheel.py": 3531093454660385247, + "venv/lib/python3.13/site-packages/pydantic/v1/decorator.py": 6124748023704700724, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/scalars.pyi": 17683675356659300769, + "venv/lib/python3.13/site-packages/websockets/sync/messages.py": 15699091325918681038, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_msvc.h": 2465089365642299646, + "venv/lib/python3.13/site-packages/passlib/registry.py": 5050675058011850564, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_stack_unstack.py": 3737891757817696405, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/__init__.py": 17194870661869873083, + "venv/bin/pytest": 2593802493707545818, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_api.py": 7131036004750554905, + "venv/lib/python3.13/site-packages/pandas/plotting/_core.py": 6766059152026241747, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/mod.py": 2054876501774773382, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_missing.py": 6224750552277937853, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta_range.py": 15081095442418142820, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/aiomysql.py": 12999962380333482189, + "venv/lib/python3.13/site-packages/httpx/_transports/mock.py": 13564349939188292363, + "venv/lib/python3.13/site-packages/jose/constants.py": 10880650415673457194, + "venv/lib/python3.13/site-packages/rapidfuzz/_common_py.py": 15410157970973169427, + "venv/lib/python3.13/site-packages/numpy/random/_common.cpython-313-x86_64-linux-gnu.so": 12834724130890991478, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/styled.py": 8726407298858811635, + "venv/lib/python3.13/site-packages/passlib/handlers/bcrypt.py": 8125664010268654055, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/util.py": 955993052529739164, + "venv/lib/python3.13/site-packages/anyio/_core/_eventloop.py": 6853955946028131785, + "venv/lib/python3.13/site-packages/pydantic/_internal/_docs_extraction.py": 5210114991139191634, + "venv/lib/python3.13/site-packages/pygments/styles/monokai.py": 12381683616720952636, + "venv/lib/python3.13/site-packages/pygments/lexers/_lua_builtins.py": 12653747099659257203, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/exceptions.py": 11303331612406662162, + "frontend/src/lib/api/translate/dictionaries.js": 13928848549982189213, + "venv/lib/python3.13/site-packages/ecdsa/_version.py": 17707102226558781833, + "backend/_convert_defs.py": 208535643309836247, + "venv/lib/python3.13/site-packages/numpy/matlib.py": 112839038090033740, + "venv/bin/pip3.13": 13861749540792881808, + "backend/src/core/auth/oauth.py": 9925908783612235042, + "backend/src/core/auth/__init__.py": 16435384828055133073, + "venv/lib/python3.13/site-packages/pandas/io/api.py": 8275376846208437741, + "venv/lib/python3.13/site-packages/jaraco/context/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/arrays/floating.py": 1215586266958421991, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asof.py": 17616601748321325187, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_transpose.py": 1686867045869336370, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_astype.py": 6578539240745332772, + "venv/lib/python3.13/site-packages/fastapi/security/http.py": 8465565118555441408, + "venv/lib/python3.13/site-packages/tzlocal/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/__init__.py": 1856412417337875350, + "venv/lib/python3.13/site-packages/numpy.libs/libscipy_openblas64_-096271d3.so": 14338208504131470036, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/AUTHORS": 2987771679926243782, + "venv/lib/python3.13/site-packages/pandas/core/internals/ops.py": 4740509262379451243, + "venv/lib/python3.13/site-packages/anyio/abc/_streams.py": 8089057973257658396, + "venv/lib/python3.13/site-packages/anyio/_backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.py": 17817123894903120316, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop_duplicates.py": 5874427993953991216, + "venv/lib/python3.13/site-packages/pygments/lexers/textedit.py": 14872291021083255414, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv": 8710594949902856122, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_dst.py": 12243642467695371088, + "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimelike.py": 4356700619632833878, + "frontend/src/components/backups/BackupManager.svelte": 15237659305406789107, + "venv/lib/python3.13/site-packages/_pytest/doctest.py": 6126919596776592278, + "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.py": 1590647503660777156, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/encoder.py": 4790267438222037867, + "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.py": 1731362089136926666, + "venv/lib/python3.13/site-packages/pandas/core/sparse/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/alias_generators.py": 5991580234179623842, + "backend/src/api/routes/assistant/_dataset_review_dispatch.py": 10108558091463171824, + "venv/lib/python3.13/site-packages/_pytest/config/compat.py": 13175516717549204627, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/sdist.py": 9490366272695301385, + "venv/lib/python3.13/site-packages/authlib/jose/jwk.py": 13560749074922587626, + "venv/lib/python3.13/site-packages/_pytest/_code/__init__.py": 6211607282116942091, + "venv/lib/python3.13/site-packages/pandas/tests/strings/conftest.py": 12065119814157197510, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_uninstall.py": 3515239440812977025, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/expression.py": 15511250785671695359, + "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.py": 11397521081216402594, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/plugin.py": 18006138132596504101, + "venv/lib/python3.13/site-packages/idna/idnadata.py": 200840860629525970, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/accessor.py": 8373575175447947401, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_mask.py": 9654897363729130542, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/__init__.py": 8807410829260170597, + "venv/lib/python3.13/site-packages/pyasn1/type/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pydantic/deprecated/tools.py": 16466182352694741629, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_numeric.py": 18037815278545274402, + "venv/lib/python3.13/site-packages/httpx/_types.py": 12461152436147308761, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarraytypes.h": 6765088137325865789, + "venv/lib/python3.13/site-packages/greenlet/TBrokenGreenlet.cpp": 10822436772777706192, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_datetime64.py": 16272266806084058743, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_get_dummies.py": 14871264482622327003, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapper.py": 16715864918034312591, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/cryptography/utils.py": 18088508841978595788, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/array.py": 7437107031079833232, + "venv/lib/python3.13/site-packages/pygments/lexers/php.py": 17636450950688953288, + "venv/lib/python3.13/site-packages/pygments/lexers/snobol.py": 414946539602526513, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/passlib/tests/test_context.py": 15195609282700801214, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_convert_dtypes.py": 5005259275646154894, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pyodbc.py": 11271266527234292020, + "venv/lib/python3.13/site-packages/pygments/lexers/stata.py": 7249891970174867363, + "backend/src/plugins/translate/executor.py": 15866803979457728942, + "backend/src/plugins/translate/preview_prompt_builder.py": 2354938052590494405, + "backend/src/plugins/translate/dictionary_correction.py": 18051915404774774954, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_validate.py": 12789481642730855139, + "merge_kilo.py": 4282227344165325430, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/WHEEL": 1598805043198466373, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_salsa.py": 1756536674254931838, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqlconnector.py": 17538029557373507617, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/twodim_base.pyi": 10156504423258357540, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE": 16499431172938528491, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_type_check.py": 3935091606923106753, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_join.py": 11910166566689889389, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_dt_accessor.py": 2229616362327032253, + "venv/lib/python3.13/site-packages/pandas/core/ops/dispatch.py": 7041711677358147534, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_index_col.py": 17604191644943383567, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/_typing.py": 10524021526716767489, + "venv/lib/python3.13/site-packages/pydantic/generics.py": 15019381413806459410, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_quantile.py": 17110581927381599978, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/RECORD": 8971487317739420905, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_arrow_compat.py": 17818294260710640443, + "venv/lib/python3.13/site-packages/pygments/styles/manni.py": 11853576691280294949, + "backend/src/api/routes/__tests__/test_reports_openapi_conformance.py": 17043883737206361151, + "venv/lib/python3.13/site-packages/itsdangerous/signer.py": 3694661094753475840, + "backend/src/models/dataset_review_pkg/_profile_models.py": 9621392840420324583, + "backend/src/services/clean_release/artifact_catalog_loader.py": 7672031618376179570, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py": 5728866271812501558, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/LICENSE": 6581019367004699816, + "venv/lib/python3.13/site-packages/pandas/_libs/window/aggregations.pyi": 6072607880689125113, + "backend/src/plugins/translate/__tests__/test_inline_correction.py": 3644785257160613130, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/mypy.py": 823265492261272631, + "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.pyi": 7674087576653964854, + "backend/src/plugins/translate/orchestrator_planner.py": 1630348739588568408, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/WHEEL": 11630459739183915695, + "docker/nginx.ssl.conf": 12350396037548059686, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_rolling.py": 11118160360072677569, + "backend/src/plugins/debug.py": 2035734953696955393, + "venv/lib/python3.13/site-packages/pandas/core/ops/invalid.py": 10186546927135277579, + "frontend/src/services/toolsService.js": 1568142461283466080, + "backend/src/core/utils/superset_context_extractor/_templates.py": 6790136732701012567, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_crackfortran.py": 10278720705326601943, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_setops.py": 15196593522537569500, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_assignability.pyi": 1718610984396277997, + "venv/lib/python3.13/site-packages/PIL/_binary.py": 14039167720582222043, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_results.py": 18145930285449734975, + "venv/lib/python3.13/site-packages/pygments/cmdline.py": 15628499088643246809, + "backend/src/api/routes/dashboards/_projection.py": 1559143255780155174, + "venv/lib/python3.13/site-packages/passlib/utils/binary.py": 13123975436674239306, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/WHEEL": 2357997949040430835, + "frontend/src/lib/components/translate/TermCorrectionPopup.svelte": 5276611147503580165, + "frontend/src/routes/admin/settings/+page.svelte": 15536865086528222650, + "venv/lib/python3.13/site-packages/ecdsa/test_rw_lock.py": 1572802971060634697, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/descriptor_props.py": 7044852927393650707, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90": 11945588837236968550, + "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.pyi": 2029639875417260268, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90": 7589258200398878529, + "venv/lib/python3.13/site-packages/PIL/PaletteFile.py": 4104323659569809769, + "backend/tests/scripts/test_clean_release_tui_v2.py": 16893299982170941753, + "venv/lib/python3.13/site-packages/pandas/plotting/_misc.py": 10202078355301731720, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_stringdtype.py": 8381476847196129074, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_gen_files.py": 11149423183253618378, + "venv/lib/python3.13/site-packages/cffi/_imp_emulation.py": 17246725564704952212, + "venv/lib/python3.13/site-packages/pygments/formatters/_mapping.py": 13335227913146542481, + "backend/src/services/__tests__/test_llm_provider.py": 13082073379648782691, + "frontend/build/_app/immutable/nodes/36.DcuDEthp.js": 13924137868633939936, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/__init__.py": 10470644151952252331, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.py": 12636954896699095212, + "backend/git_repos/remote/test-repo.git/hooks/pre-push.sample": 8029776382195911768, + "venv/lib/python3.13/site-packages/pillow.libs/libpng16-4a38ea05.so.16.53.0": 13136089038268964667, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_reductions.py": 1713831062142840146, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/resource_protector.py": 9147671710440653567, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/vectorized.pyi": 15498895254516573071, + "venv/lib/python3.13/site-packages/httpcore/_backends/trio.py": 8394426709857317737, + "backend/git_repos/remote/test-repo.git/objects/ed/0432f88f5f7d95b26ecde34345abe741dd9db2": 13426916511127204463, + "venv/lib/python3.13/site-packages/pydantic/v1/errors.py": 11245135449608452720, + "venv/lib/python3.13/site-packages/pydantic/plugin/_loader.py": 792663962985957671, + "venv/lib/python3.13/site-packages/fastapi/params.py": 14263655860695381481, + "venv/lib/python3.13/site-packages/numpy/_typing/_add_docstring.py": 14657346268890680694, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_factorize.py": 5585211699185937865, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/__init__.py": 16532856661318424631, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timedeltas.cpython-313-x86_64-linux-gnu.so": 17089839649971421164, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_reductions.py": 8258332365408303156, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/PIL/ImtImagePlugin.py": 17599267755504817169, + "frontend/build/_app/immutable/chunks/DiYpmdlT.js": 17238224188429722519, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py": 6712732248328458871, + "venv/lib/python3.13/site-packages/itsdangerous/__init__.py": 6969210114978365656, + "venv/lib/python3.13/site-packages/pygments/lexers/css.py": 517586374264113606, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/requests.py": 6703055041957748929, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numeric.pyi": 17005748821769179511, + "backend/src/plugins/translate/prompt_builder.py": 9619706108488955349, + "venv/lib/python3.13/site-packages/iniconfig/_parse.py": 11418441008427032090, + "venv/lib/python3.13/site-packages/cffi/commontypes.py": 11198107299826138465, + "venv/lib/python3.13/site-packages/gitdb/db/mem.py": 15823812455996199993, + "venv/lib/python3.13/site-packages/python_multipart/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py": 1246582552828542841, + "venv/lib/python3.13/site-packages/pygments/lexers/jsx.py": 13855228003748707341, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/claims.py": 12645788445743898136, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.c": 11535375410441493281, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/token_validator.py": 13917237710752731397, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayprint.py": 13335063050941743734, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiprocessing.py": 5522490547285108448, + "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.py": 4154852745131464543, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/accessors.py": 12743680296510533030, + "venv/lib/python3.13/site-packages/passlib/tests/sample1b.cfg": 2872366861156549016, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_downcast.py": 10399746645741452200, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_duplicate_labels.py": 10663105616336167414, + "venv/lib/python3.13/site-packages/pandas/__init__.py": 793698514004377486, + "venv/lib/python3.13/site-packages/dateutil/tz/_common.py": 9009072600471223066, + "venv/lib/python3.13/site-packages/pygments/lexers/phix.py": 16775285097768256238, + "venv/lib/python3.13/site-packages/pygments/lexers/data.py": 9365024327689738663, + "venv/lib/python3.13/site-packages/pyasn1/compat/integer.py": 7365270971777550573, + "venv/lib/python3.13/site-packages/httpx/_main.py": 1812303705973265093, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_index.py": 10837492069089787028, + "venv/lib/python3.13/site-packages/anyio/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/tests/test_hosts.py": 8284535274820610802, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f": 3980077223827767077, + "venv/lib/python3.13/site-packages/greenlet/TPythonState.cpp": 12828594265749606443, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/twisted.py": 16059862619165885730, + "venv/lib/python3.13/site-packages/_pytest/freeze_support.py": 494952714451267295, + "venv/lib/python3.13/site-packages/pygments/lexers/roboconf.py": 1335271183806115470, + "venv/lib/python3.13/site-packages/smmap/buf.py": 18231775424238352734, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_round.py": 14996007456708990295, + "frontend/src/components/tasks/LogFilterBar.svelte": 5318774167984892372, + "venv/lib/python3.13/site-packages/pandas/_libs/reshape.cpython-313-x86_64-linux-gnu.so": 10639750501333255943, + "backend/src/api/routes/dashboards/_listing_routes.py": 1750634467656242702, + "venv/lib/python3.13/site-packages/_pytest/config/findpaths.py": 7867603756389940562, + "frontend/e2e/e2e-nohealth.mjs": 5921562935931064381, + "venv/lib/python3.13/site-packages/itsdangerous/encoding.py": 205863946173486958, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/pytestplugin.py": 1591034895268415944, + "venv/lib/python3.13/site-packages/pygments/style.py": 17393199235575070210, + "venv/lib/python3.13/site-packages/httpcore/_sync/interfaces.py": 1532245423878428608, + "docker/backend.entrypoint.sh": 1034669340368151691, + "venv/lib/python3.13/site-packages/pandas/io/formats/console.py": 10370334487585281127, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/asymmetric_key.py": 14948661854506285135, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timezones.py": 8042029178538467146, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_npfuncs.py": 13987318550267921389, + "venv/lib/python3.13/site-packages/pygments/lexers/rita.py": 8105458520706587972, + "venv/lib/python3.13/site-packages/jeepney/tests/test_wrappers.py": 4813328996575597980, + "venv/lib/python3.13/site-packages/pandas/io/orc.py": 12754290195886557668, + "frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js": 13047006106880121194, + "venv/lib/python3.13/site-packages/pygments/lexers/devicetree.py": 9820277168995231927, + "backend/src/services/dataset_review/event_logger.py": 8083530196989488371, + "backend/git_repos/remote/test-repo.git/hooks/pre-commit.sample": 102291230237676317, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/RECORD": 963865046004908868, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_compat.h": 6512969159139431485, + "venv/lib/python3.13/site-packages/gitdb/const.py": 14122142034887286559, + "venv/lib/python3.13/site-packages/dotenv/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/pandas/tests/io/generate_legacy_storage_files.py": 11015954144633661960, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_ccalendar.py": 8819357623337533489, + "venv/lib/python3.13/site-packages/pygments/lexers/smalltalk.py": 6113431347120223592, + "backend/src/core/migration/risk_assessor.py": 1061977005072298440, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/cache.py": 15037055977924167732, + "venv/lib/python3.13/site-packages/cffi/lock.py": 13507686939203117974, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arithmetic.py": 3209727509456212551, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/endpoint.py": 18260428408051728802, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot.py": 334735766122314163, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_cumulative.py": 15644124412739892167, + "venv/lib/python3.13/site-packages/numpy/_core/memmap.pyi": 14124415711399771715, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/expressions.py": 8015786996064244656, + "venv/lib/python3.13/site-packages/pandas/core/indexes/period.py": 1181348384346239378, + "venv/lib/python3.13/site-packages/pandas/tests/resample/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/lib/components/health/HealthMatrix.svelte": 13165441444996153191, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/RECORD": 2963644632913976754, + "scripts/scan_secrets.sh": 599173385111063848, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/array.py": 8065856342131357421, + "venv/lib/python3.13/site-packages/itsdangerous/url_safe.py": 13454753900702274266, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/modeline.py": 6194365452131561478, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/scope.py": 4096190764836489091, + "venv/lib/python3.13/site-packages/pip/_internal/models/link.py": 7172346414535657925, + "venv/lib/python3.13/site-packages/pandas/api/internals.py": 5188134630996087511, + "venv/lib/python3.13/site-packages/pygments/lexers/gcodelexer.py": 13712494327007684318, + "frontend/src/routes/dashboards/[id]/components/DashboardLinkedResources.svelte": 8279080994517688482, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_subclass.py": 16342917051908786497, + "backend/src/plugins/llm_analysis/__tests__/test_screenshot_service.py": 17792688368296989200, + "backend/src/plugins/llm_analysis/scheduler.py": 14673660738877638091, + "backend/tests/test_translate_scheduler.py": 14274816721941617887, + "backend/git_repos/remote/test-repo.git/HEAD": 12394318939628232491, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_to_numpy.py": 14845850776625255794, + "venv/lib/python3.13/site-packages/fastapi/background.py": 16533963020573865222, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_readers.py": 2136472634307645842, + "backend/src/api/routes/git/_repo_operations_routes.py": 5819532622410034169, + "venv/lib/python3.13/site-packages/PIL/_webp.cpython-313-x86_64-linux-gnu.so": 11070012119632935103, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/_cryptography_key.py": 388489172928969873, + "frontend/src/components/RepositoryDashboardGrid.svelte": 14921738329941705036, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi": 16042272072158438261, + "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.pyi": 17639497083041129225, + "venv/lib/python3.13/site-packages/referencing/retrieval.py": 11921179805977833120, + "venv/lib/python3.13/site-packages/passlib/handlers/__init__.py": 3424087230285514388, + "venv/lib/python3.13/site-packages/git/db.py": 6680123567509774609, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_indexing.py": 9862204223281834360, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_qcut.py": 8972418112914954758, + "backend/src/api/routes/assistant/_command_parser.py": 2745692387994130159, + "venv/lib/python3.13/site-packages/pydantic/v1/fields.py": 3948219773415054006, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_has_cy.py": 11979732417254560424, + "backend/git_repos/remote/test-repo.git/objects/d8/3fe0db1279ef07c4c4f3de4156a629373b4057": 7507193819578792576, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iloc.py": 7586049606891014270, + "venv/lib/python3.13/site-packages/passlib/hash.py": 5238710192614935875, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_str_accessor.py": 4066094997616994612, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex.py": 8772423071604000084, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_matplotlib.py": 12775850858284584296, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/theme.py": 14225878259183479398, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90": 2174121054736811903, + "venv/lib/python3.13/site-packages/pandas/tests/test_downstream.py": 5635510753354256507, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_liboffsets.py": 14705822637347212540, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/pyproject.py": 12684373765476932108, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90": 8048650253889213460, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_deprecated_kwargs.py": 10379929935087904974, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_style.tpl": 3352086677417301397, + "venv/lib/python3.13/site-packages/pandas/core/arrays/boolean.py": 8821671562937866269, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_index_new.py": 796607958391882182, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/events.py": 15099787454570172797, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/tornado.py": 6491136785917169991, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_groupby.py": 2738671407653333726, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_grouping.py": 5994909693214299971, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_object_arr.py": 4725156416161661681, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.py": 5221550291012182443, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/infer.py": 12541904372617915365, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/__init__.py": 10261654903106416888, + "venv/lib/python3.13/site-packages/pygments/lexers/modula2.py": 6575895980250662093, + "venv/lib/python3.13/site-packages/pandas/_testing/_warnings.py": 5640964566228306285, + "venv/lib/python3.13/site-packages/attr/__init__.pyi": 13203080513025719049, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/watchfilesreload.py": 13062440477475586751, + "frontend/src/routes/datasets/review/+page.svelte": 12909115647298935839, + "venv/lib/python3.13/site-packages/pandas/tests/extension/date/__init__.py": 16789767433439616593, + "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.py": 9654828595008925976, + "frontend/src/routes/admin/settings/llm/+page.svelte": 3079157958329647867, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/offsets.pyi": 13173581775000480811, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timedeltas.pyi": 3783371827926657291, + "frontend/src/assets/svelte.svg": 13872699371039797074, + "frontend/src/lib/stores/taskDrawer.js": 6659505033581293370, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/token.py": 6987328478153445584, + "venv/lib/python3.13/site-packages/pygments/lexers/macaulay2.py": 8022891778577314212, + "backend/src/api/routes/translate/_dictionary_routes.py": 5480137091791704976, + "backend/src/services/dataset_review/orchestrator_pkg/_commands.py": 15474996500928063708, + "venv/lib/python3.13/site-packages/keyring/http.py": 1408024724330078009, + "venv/lib/python3.13/site-packages/numpy/random/_sfc64.pyi": 3536657185495782642, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py": 16550134594771291234, + "backend/src/plugins/git/llm_extension.py": 9347391649685791102, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_extension_array_equal.py": 16119106336497630796, + "venv/lib/python3.13/site-packages/anyio/abc/_sockets.py": 15042495744291042062, + "venv/lib/python3.13/site-packages/pandas/tests/construction/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py": 16610770935842519289, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_pickle.py": 3419420815386925630, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/METADATA": 15987199384245264478, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/client_mixin.py": 17980753662107479779, + "venv/lib/python3.13/site-packages/numpy/lib/__init__.pyi": 1537495515469182226, + "backend/src/plugins/translate/__tests__/test_dictionary_utils.py": 12007616543185225081, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot_multilevel.py": 9830258607305392103, + "frontend/src/routes/tools/debug/+page.svelte": 8699044541980877686, + "frontend/src/components/DashboardGrid.svelte": 17669234585849525689, + "venv/lib/python3.13/site-packages/jaraco/classes/ancestry.py": 11742194518360056470, + "venv/lib/python3.13/site-packages/iniconfig/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py": 3177255974394221645, + "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.pyi": 3111521453255595221, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/installed.py": 18153165899841229597, + "backend/src/schemas/profile.py": 7950698901810733002, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz": 17626265752554406355, + "venv/lib/python3.13/site-packages/numpy/_core/_methods.py": 16805668769357938792, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_dropna.py": 3620959914439334511, + "frontend/src/lib/components/ui/MultiSelect.svelte": 1475503303018683038, + "venv/lib/python3.13/site-packages/passlib/utils/compat/_ordered_dict.py": 14248790502300368024, + "venv/lib/python3.13/site-packages/fastapi/routing.py": 466387159689567541, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/editable_legacy.py": 8145740626773638218, + "venv/lib/python3.13/site-packages/dotenv/__main__.py": 16883579879172186355, + "venv/lib/python3.13/site-packages/numpy/f2py/__version__.py": 8588600299261398598, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf": 10179237442840865225, + "venv/lib/python3.13/site-packages/pandas/core/computation/expr.py": 13085709365673019494, + "venv/lib/python3.13/site-packages/git/objects/commit.py": 12317865358846331802, + "venv/lib/python3.13/site-packages/PIL/_imagingcms.pyi": 12476347428820346383, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/style.py": 12654125988995362593, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_fillna.py": 16297834601116528166, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/click/shell_completion.py": 5858110451169927373, + "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/__init__.py": 1229691061011958769, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/panel.py": 17832701246248000383, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/LICENSE": 16510279186416777136, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_slp_switch.py": 16490710972475154509, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_encs.py": 9703572751543253904, + "venv/lib/python3.13/site-packages/numpy/ma/core.pyi": 4829891173366130328, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_tooltip.py": 853808724844451770, + "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.py": 2490579175967301457, + "backend/src/services/reports/__tests__/test_report_normalizer.py": 5179524010104259469, + "backend/src/core/task_manager/context.py": 17543992255093146942, + "backend/git_repos/remote/test-repo.git/objects/4e/227f4d8289ea657ae813b1460f979ae4b676b3": 5659284628452785331, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/core.py": 14576109242055156193, + "venv/lib/python3.13/site-packages/attrs/setters.py": 5775359015245600592, + "venv/lib/python3.13/site-packages/pip/_internal/models/__init__.py": 13482731985065116750, + "venv/lib/python3.13/site-packages/apscheduler/triggers/calendarinterval.py": 12481650996882675949, + "dist/docker/backend.1.2.1.tar.xz": 10352037330818810014, + "venv/lib/python3.13/site-packages/psycopg2/tz.py": 9966680685796585198, + "venv/lib/python3.13/site-packages/pip/_internal/models/installation_report.py": 14534544543677907640, + "venv/lib/python3.13/site-packages/passlib/apps.py": 4633269405597895766, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_amd64_unix.h": 16679226724722970205, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90": 13315882216322269383, + "venv/lib/python3.13/site-packages/pandas/core/tools/times.py": 6560679305255812809, + "venv/lib/python3.13/site-packages/pandas/core/interchange/buffer.py": 12961802206383700922, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append.py": 13152738905565588661, + "venv/lib/python3.13/site-packages/pandas/tests/apply/conftest.py": 13798335354961261346, + "venv/lib/python3.13/site-packages/urllib3/util/request.py": 9432067988603015849, + "venv/lib/python3.13/site-packages/keyring/compat/properties.py": 1562771115138037410, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/licenses/LICENSE": 7959949171752474553, + "venv/lib/python3.13/site-packages/psycopg2/_ipaddress.py": 12332672835751787869, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas_xport.py": 16525568795475918874, + "frontend/src/lib/stores/activity.js": 14023344642294459631, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/METADATA": 15876173086384975957, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/shared.py": 1162754506656505196, + "venv/lib/python3.13/site-packages/pygments/lexers/graphics.py": 13783143864729682444, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_stride_tricks.py": 1064774375151677743, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexing.py": 9988098331562906950, + "venv/lib/python3.13/site-packages/pip/_internal/utils/_jaraco_text.py": 9046755357011730699, + "venv/lib/python3.13/site-packages/dotenv/parser.py": 17651523026132242005, + "venv/lib/python3.13/site-packages/smmap/test/test_mman.py": 8977119225749253844, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_time_grouper.py": 3203729024111501071, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE": 4123064337800029995, + "venv/lib/python3.13/site-packages/websockets/client.py": 5229500079651465772, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_names.py": 10037208029090713121, + "venv/lib/python3.13/site-packages/httpx/_utils.py": 4836536051177895209, + "venv/lib/python3.13/site-packages/PIL/_imagingft.pyi": 1385456134120145584, + "venv/lib/python3.13/site-packages/numpy/_core/_asarray.py": 3468915833437229425, + "venv/lib/python3.13/site-packages/greenlet/greenlet_thread_support.hpp": 7773996382104849037, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_api.py": 6439927798101672423, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_constructors.py": 7466113171256856591, + "venv/lib/python3.13/site-packages/pandas/_typing.py": 17795648994662434211, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ext.py": 8361831054662096695, "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_np_datetime.py": 18363183516409621205, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/engines.py": 10876954465293959720, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_copy.py": 3114918520437707410, - "venv/lib/python3.13/site-packages/anyio/streams/memory.py": 11762722143503428823, - "venv/lib/python3.13/site-packages/pandas/_libs/hashing.cpython-313-x86_64-linux-gnu.so": 16124435225170610034, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming_py.py": 16133454512601432815, + "venv/lib/python3.13/site-packages/pydantic/_internal/_internal_dataclass.py": 13206778611516171760, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_timedelta.py": 17052461094717926538, + "venv/lib/python3.13/site-packages/anyio/pytest_plugin.py": 4165280709813718099, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_re.py": 1296579393600719224, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/__init__.py": 16434403703599680307, + "venv/lib/python3.13/site-packages/pygments/styles/onedark.py": 17580335614588531275, + "venv/lib/python3.13/site-packages/urllib3/fields.py": 9503202008440141421, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_histograms.py": 47631283818191049, + "frontend/build/_app/immutable/entry/start.bTuMC3Dl.js": 6019693168465456384, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/device_code.py": 6712610002227849281, + "backend/git_repos/remote/test-repo.git/objects/8c/4ea7958b7a7e140d27e1e7d8d1f9912fdf5992": 5862166356451798197, + "venv/lib/python3.13/site-packages/packaging/_elffile.py": 9546225990833172494, + "venv/lib/python3.13/site-packages/urllib3/connectionpool.py": 7493427857878469165, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_astype.py": 11995587502880659624, + "venv/lib/python3.13/site-packages/jsonschema/_keywords.py": 949562792260528762, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval.py": 8549680643865283913, + "venv/lib/python3.13/site-packages/requests/hooks.py": 9888227370911151341, + "venv/lib/python3.13/site-packages/websockets/connection.py": 5168795926684067030, + "backend/src/plugins/translate/__tests__/test_dictionary.py": 4341966549214032934, + "frontend/e2e/tests/login.e2e.js": 16303843677272482041, + "backend/tests/core/test_mapping_service.py": 6888870177029085220, + "venv/lib/python3.13/site-packages/pandas/tests/test_register_accessor.py": 16661086720613729974, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py": 256154392957334831, + "backend/git_repos/remote/test-repo.git/hooks/prepare-commit-msg.sample": 7530253302780245896, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadb.py": 3109042476851791996, + "venv/lib/python3.13/site-packages/pyasn1/codec/streaming.py": 13202773554072937140, + "venv/lib/python3.13/site-packages/pygments/formatters/svg.py": 11686316844190214147, + "venv/lib/python3.13/site-packages/pandas/io/excel/_base.py": 1251545894005373734, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/test_indexing.py": 2274965639578580723, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/conftest.py": 17514079438846557943, + "venv/lib/python3.13/site-packages/dateutil/utils.py": 7067026915090881998, + "venv/lib/python3.13/site-packages/pandas/_libs/internals.pyi": 11662356720550765508, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/__init__.py": 16123561007855424016, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg.py": 8023549900603235601, + "venv/lib/python3.13/site-packages/pandas/io/excel/_util.py": 6664989864423807444, + "venv/lib/python3.13/site-packages/pandas/tseries/__init__.py": 2648641118117738895, + "venv/lib/python3.13/site-packages/numpy/linalg/__init__.py": 15647756307608142577, + "venv/lib/python3.13/site-packages/numpy/core/_dtype.py": 2806449741844148191, + "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.py": 16539612003028676816, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-2.csv": 4052796393463357888, + "frontend/e2e/tests/smoke.e2e.js": 11130903009452044456, + "venv/lib/python3.13/site-packages/numpy/random/__init__.pyi": 13833571330152615376, + "venv/lib/python3.13/site-packages/fastapi/param_functions.py": 14585101566697773072, + "venv/lib/python3.13/site-packages/starlette/staticfiles.py": 11256974306202558529, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polyutils.pyi": 3841660741524427413, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_datetimelike.py": 10294379314868108649, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dtype.py": 5553691086633215767, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/METADATA": 1862765380818895200, + "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.py": 10803011906582324302, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_chaining_and_caching.py": 11784574265874608859, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_orc.py": 1248059610437937895, + "venv/lib/python3.13/site-packages/attr/validators.pyi": 15579625896285277321, + "backend/git_repos/remote/test-repo.git/objects/c5/b992984fe856bd81206304a881faa3087937cf": 2441623644664166468, + "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.pyi": 6534825471013879522, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi": 2777456956260371820, + "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django.py": 3210697476292094384, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth2_client.py": 6742098857947604729, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/__init__.py": 4870269250323682576, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/unrolled.py": 12651425412640834530, + "venv/lib/python3.13/site-packages/jeepney/wrappers.py": 15234251727654692435, + "frontend/build/_app/immutable/assets/AssistantChatPanel.D4L5jlt0.css": 10724144138366384732, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_find_replace.py": 262184394614748386, + "venv/lib/python3.13/site-packages/pygments/lexers/_mapping.py": 12987629396101138833, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.pyx": 649821942746469002, + "venv/lib/python3.13/site-packages/_pytest/monkeypatch.py": 2635774457434545573, + "venv/lib/python3.13/site-packages/ecdsa/test_malformed_sigs.py": 2606295770491528880, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_isoc.py": 4923640657296076239, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/_typing.py": 17598638528781632158, + "venv/lib/python3.13/site-packages/numpy/random/_mt19937.cpython-313-x86_64-linux-gnu.so": 85866616759631810, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_loc.py": 17839380711970027363, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_factorize.py": 17995673140216929494, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/__init__.py": 14522970260621605208, + "venv/lib/python3.13/site-packages/git/objects/blob.py": 8972374723153211283, + "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.py": 8786558894094307341, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_nat.py": 18428782698385974380, + "venv/lib/python3.13/site-packages/httpx/_transports/wsgi.py": 11981127094916412794, + "docker/nginx.conf": 14595959129793115016, + "venv/lib/python3.13/site-packages/requests/adapters.py": 17161109043243436200, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_astype.py": 563689238486630866, + "frontend/src/lib/stores/__tests__/mocks/environment.js": 16653269108049932073, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/base.py": 16891437410462671317, + "frontend/src/components/git/ConflictResolver.svelte": 2318922269446496715, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/base.py": 16714704323747942110, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pycparser/plyparser.py": 5251740466238035035, + "frontend/build/_app/immutable/nodes/34.Bo9XKqls.js": 1288499880603706148, + "venv/lib/python3.13/site-packages/numpy/core/einsumfunc.py": 3484247123731380377, + "venv/lib/python3.13/site-packages/tzlocal/utils.py": 7893867974548929154, + "venv/lib/python3.13/site-packages/numpy/_core/_rational_tests.cpython-313-x86_64-linux-gnu.so": 13475521165331256711, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlrd.py": 9982457234958102003, + "venv/lib/python3.13/site-packages/referencing/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_initialstub_already_started.py": 5562030563802006923, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv": 10950201682596097452, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.asm": 16630507336149184509, + "venv/lib/python3.13/site-packages/sqlalchemy/event/attr.py": 5971663429221923939, + "venv/lib/python3.13/site-packages/PIL/IcnsImagePlugin.py": 1870235606309784691, + "backend/src/api/routes/__tests__/test_dashboards.py": 226265424558878456, + "venv/lib/python3.13/site-packages/websockets/legacy/__init__.py": 12332512329533591682, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/pyasn1/type/univ.py": 7163437624197683039, + "venv/lib/python3.13/site-packages/pygments/lexers/mojo.py": 8616283481592061285, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f": 13517753924061311074, + "venv/lib/python3.13/site-packages/pandas/io/stata.py": 14370692318835340323, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/WHEEL": 18203500019759199992, + "backend/src/services/clean_release/stages/__init__.py": 11595548160903612178, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_ints.py": 5616705208267050659, + "venv/lib/python3.13/site-packages/cffi/api.py": 5325821560978502135, + "backend/src/api/routes/admin.py": 235004514833998579, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/__init__.py": 2397613800206300456, + "venv/lib/python3.13/site-packages/passlib/crypto/des.py": 14699826058580193499, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_dtype.py": 1647214604678171565, + "venv/lib/python3.13/site-packages/pip/_internal/cli/progress_bars.py": 7584699216537478969, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_subclass.py": 10949229764696473939, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filters/__init__.py": 835924536855006596, + "frontend/src/routes/datasets/__tests__/DatasetPreview.test.js": 12281160027416292128, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test__exceptions.py": 12099001631178696189, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_nonkeyword_arguments.py": 11676809974120007408, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_typing.py": 17589387690638097975, + "venv/lib/python3.13/site-packages/pandas/core/construction.py": 10646956189518908985, + "venv/lib/python3.13/site-packages/git/exc.py": 14278238357119816365, + "venv/lib/python3.13/site-packages/pydantic/_migration.py": 17982816821930887921, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/__init__.py": 3969805865048730851, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/WHEEL": 5076688779572520166, + "venv/lib/python3.13/site-packages/numpy/__config__.py": 15794735729525094396, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/METADATA": 6438256145634479451, + "venv/lib/python3.13/site-packages/pandas/core/accessor.py": 1188716996113179524, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_cython.py": 2933400021016349431, + "frontend/src/lib/components/dataset-review/SemanticLayerReview.svelte": 10805621354490209991, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_like.py": 2778905818573625118, + "venv/lib/python3.13/site-packages/PIL/_imagingtk.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/numpy/_pytesttester.pyi": 5750506937526308405, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_laguerre.py": 7475592201750602042, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/events.py": 10224214051422678828, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/auto.py": 12818217385551437286, + "venv/lib/python3.13/site-packages/starlette/formparsers.py": 9019779181100355515, + "venv/lib/python3.13/site-packages/pandas/io/parsers/readers.py": 7899068668225389287, + "venv/lib/python3.13/site-packages/sqlalchemy/event/__init__.py": 16182540084654095394, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_argsort.py": 7320661835159648143, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_array.py": 11271807719833350332, + "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.pyi": 18193727720492050602, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pygments/lexers/ml.py": 7510453371068494792, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_replace.py": 4953527309376861139, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_policy.py": 13856626567322091253, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_sorting.py": 10523740688498427929, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937.py": 7299586490442539723, + "backend/tests/test_translate_jobs.py": 16585154497956900995, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/METADATA": 13695483537390128881, + "venv/lib/python3.13/site-packages/passlib/utils/compat/__init__.py": 17369882236606423129, + "venv/lib/python3.13/site-packages/h11/_receivebuffer.py": 4631433251046338381, + "venv/lib/python3.13/site-packages/_pytest/mark/expression.py": 1821437025841201912, + "venv/lib/python3.13/site-packages/pandas/_version.py": 3480474785419232091, + "venv/lib/python3.13/site-packages/pygments/styles/gruvbox.py": 9489017112545247388, + "venv/lib/python3.13/site-packages/jsonschema/_typing.py": 13152346021901861822, + "dist/docker/frontend.1.2.0.tar.xz": 2118312929856113798, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authorization_server.py": 13696038495666024258, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js": 10530710876604536879, + "venv/lib/python3.13/site-packages/httpx/_client.py": 1063593889704982038, + "venv/lib/python3.13/site-packages/gitdb/fun.py": 55226330810782184, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_printing.py": 1901396869745313303, + "backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py": 11718998093543631478, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_skew_kurt.py": 15225601437354712351, + "backend/src/plugins/storage/plugin.py": 17070362975404691950, + "venv/lib/python3.13/site-packages/pillow.libs/libXau-154567c4.so.6.0.0": 4340972632724893052, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_asfreq.py": 6162659555626011770, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_categorical.py": 18254320571347851153, + "venv/lib/python3.13/site-packages/httpcore/_backends/auto.py": 10488908050307887802, + "venv/lib/python3.13/site-packages/pygments/lexers/teal.py": 10004159499175716139, + "venv/lib/python3.13/site-packages/pandas/core/util/numba_.py": 3535857372998653863, + "frontend/src/routes/translate/dictionaries/+page.svelte": 1038433841421198720, + "venv/lib/python3.13/site-packages/cffi/_cffi_include.h": 13094899814611950155, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml.py": 6906547816798138000, + "venv/lib/python3.13/site-packages/pycparser/c_ast.py": 5942107079119742, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/yara.py": 17510792615476493957, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_scrypt.py": 8106466515670064013, + "venv/lib/python3.13/site-packages/websockets/cli.py": 14049106025886056110, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/proxy.py": 13008557041076030198, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/converter.py": 9041278869295701566, + "venv/lib/python3.13/site-packages/cryptography/x509/verification.py": 1079694784860492682, + "venv/lib/python3.13/site-packages/urllib3/http2/connection.py": 1661620860881397554, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/statreload.py": 5018382301336802445, + "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.py": 17192211156810267818, + "frontend/build/index.html": 16213508127396580150, + "backend/src/plugins/translate/superset_executor.py": 5480256123348033488, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_numpyconfig.h": 18150055639397773687, + "venv/lib/python3.13/site-packages/pygments/lexers/jsonnet.py": 1314044008440065525, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_hist_box_by.py": 16197297231683144299, + "venv/lib/python3.13/site-packages/cryptography/x509/extensions.py": 10197248868682803019, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/cache_key.py": 11118819065204404106, + "venv/lib/python3.13/site-packages/pygments/lexers/foxpro.py": 14032656072384708293, + "venv/lib/python3.13/site-packages/pip/_internal/utils/unpacking.py": 106471890743211548, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/__init__.py": 16146480198665866916, + "venv/lib/python3.13/site-packages/_pytest/unittest.py": 10848803633530338204, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/METADATA": 6656194161182818439, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini": 1071371630695963467, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/screen.py": 6933591906297023845, + "venv/lib/python3.13/site-packages/pandas/core/arrays/string_.py": 14865733321317939478, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_frame.py": 9378623452601244234, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/provider.py": 16463243654123731993, + "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.pyi": 9206355685192026844, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexerrors.py": 4434868847540549873, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.py": 7446626038222262489, + "venv/lib/python3.13/site-packages/psycopg2/errors.py": 10441360078612452560, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_unique.py": 3148372351781648868, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npy": 9694707264403109829, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_setops.py": 14246225281428284850, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args.py": 5821040955806257450, + "backend/src/services/clean_release/report_builder.py": 6953311294119437848, + "venv/lib/python3.13/site-packages/pygments/styles/staroffice.py": 11694998942433220413, + "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.py": 338595621218646492, + "frontend/src/lib/components/reports/__tests__/reports_filter_performance.test.js": 10583581505638859039, + "frontend/build/_app/immutable/nodes/11.nar5mT8y.js": 13453147673342899405, + "frontend/vitest.config.js": 142965001777137074, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_latex.py": 15077617224435782028, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/__init__.py": 17630019785411546070, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_pairwise.py": 2673370322448160842, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90": 15981076495193915107, + "venv/lib/python3.13/site-packages/authlib/deprecate.py": 3563885283090710443, + "venv/lib/python3.13/site-packages/pygments/lexers/tact.py": 1164971357219795420, + "venv/lib/python3.13/site-packages/jeepney/io/trio.py": 11859775321483330469, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/json.py": 6429651405841289922, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/INSTALLER": 17282701611721059870, + "backend/src/services/clean_release/repositories/approval_repository.py": 15069637305272665109, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_all_methods.py": 18227706645906325527, + "venv/lib/python3.13/site-packages/pandas/io/sql.py": 12592024569011796790, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_methods.py": 14881910898871057761, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_monotonic.py": 14648437502004398715, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/array.py": 1919242530821725197, + "venv/lib/python3.13/site-packages/websockets/speedups.cpython-313-x86_64-linux-gnu.so": 10941658763526595989, + "venv/lib/python3.13/site-packages/pip/_internal/cli/parser.py": 1064209424435927674, + "venv/lib/python3.13/site-packages/numpy/_configtool.pyi": 9670892208858157218, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_timestamp_method.py": 11393911418463808195, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pymysql.py": 12923876736367229454, + "venv/lib/python3.13/site-packages/PIL/Hdf5StubImagePlugin.py": 15654153796225833950, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/METADATA": 16700674024421191168, + "venv/lib/python3.13/site-packages/pip/_internal/utils/filesystem.py": 7716285033598020316, + "venv/lib/python3.13/site-packages/numpy/_typing/_scalars.py": 17701938912160369190, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/RECORD": 11604408378998955169, + "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.py": 17277594393032382485, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/__init__.py": 308178910015974550, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timezones.pyi": 17528421279543420867, + "venv/lib/python3.13/site-packages/pandas/core/ops/mask_ops.py": 16152832446926420035, + "venv/lib/python3.13/site-packages/pandas/_libs/properties.cpython-313-x86_64-linux-gnu.so": 7092136701092358552, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_categorical.py": 12897027063618569795, + "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.pyi": 84606125837677197, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/base.py": 3250660921154829815, + "venv/lib/python3.13/site-packages/sqlalchemy/schema.py": 16029542421991709659, + "venv/lib/python3.13/site-packages/pandas/core/window/online.py": 13551140636252302201, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/pager.py": 18072372651585577904, + "venv/lib/python3.13/site-packages/PIL/ImagePath.py": 18323293175183057101, + "venv/lib/python3.13/site-packages/numpy/lib/format.pyi": 11752225430594536662, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/httpcore/_sync/connection.py": 1539337414493486168, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/missing.py": 11241703105777668183, + "venv/lib/python3.13/site-packages/sqlalchemy/util/concurrency.py": 1325673503812009695, + "venv/lib/python3.13/site-packages/httpx/_transports/asgi.py": 12335675489870745729, + "venv/lib/python3.13/site-packages/pandas/core/indexes/range.py": 3838277376774246164, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py": 17908437937265384125, + "venv/lib/python3.13/site-packages/httpcore/__init__.py": 5897259569277532401, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/METADATA": 14126682758562488244, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/__init__.py": 11709551233929312136, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_utils.py": 4612923732868929770, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/WHEEL": 15858869568085970864, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_types.py": 651959450717569029, + "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.pyi": 3661113433078225952, + "venv/lib/python3.13/site-packages/cryptography/x509/oid.py": 13909847799728532602, + "venv/lib/python3.13/site-packages/pygments/__main__.py": 13200500591994479045, + "venv/lib/python3.13/site-packages/pygments/lexers/unicon.py": 1155454077052833821, + "venv/lib/python3.13/site-packages/passlib/handlers/scram.py": 12281469744083867450, + "venv/lib/python3.13/site-packages/pygments/lexers/smithy.py": 10789533877863290582, + "backend/src/core/encryption_key.py": 5870186928729062534, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_gcs.py": 7733247456252965901, + "backend/src/plugins/backup.py": 9775992510122456201, + "venv/lib/python3.13/site-packages/pip/_internal/models/selection_prefs.py": 14700113736620314923, + "venv/lib/python3.13/site-packages/pygments/lexers/_scheme_builtins.py": 5722444920479775453, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE": 4274653168153720331, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/WHEEL": 5179340427739743287, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_set.py": 534498057184394558, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi": 1846673463183660140, + "venv/lib/python3.13/site-packages/authlib/oidc/registration/claims.py": 4161520263207458028, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_list_accessor.py": 8613662386779664039, + "venv/lib/python3.13/site-packages/pygments/formatters/html.py": 1918541918263449443, + "venv/lib/python3.13/site-packages/httpx/_multipart.py": 2181282475656908730, + "backend/tests/test_translate_executor_filter.py": 11717560360659156703, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/crud.py": 805684028038896506, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.pyi": 6616985736007157309, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_comparison.py": 4611207880323503098, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_limited_api.py": 15788485008764560845, + "venv/lib/python3.13/site-packages/sqlalchemy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/reshape/merge.py": 300205528811693975, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/unistring.py": 18037463865539157041, + "venv/lib/python3.13/site-packages/pygments/lexers/felix.py": 2334148799642808111, + "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.pyi": 16573082220135508510, + "venv/lib/python3.13/site-packages/pydantic/tools.py": 8931184638883701008, + "venv/lib/python3.13/site-packages/fastapi/templating.py": 10760135144345238340, + "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector_cpp.cpython-313-x86_64-linux-gnu.so": 16337157355618216738, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/__init__.py": 18019562641348687547, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.py": 6142062990691556076, + "venv/lib/python3.13/site-packages/pandas/core/col.py": 4221271461723119525, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename_axis.py": 13193478481758930128, + "venv/lib/python3.13/site-packages/websockets/asyncio/router.py": 15039562376314233669, + "venv/lib/python3.13/site-packages/pandas/_testing/compat.py": 10172779814048259850, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/cymysql.py": 5570881524647789741, + "venv/lib/python3.13/site-packages/PIL/PcxImagePlugin.py": 1691405132377495336, + "venv/lib/python3.13/site-packages/certifi/cacert.pem": 14727832973577663826, + "venv/lib/python3.13/site-packages/pip/_internal/configuration.py": 2563100675379605810, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/console.py": 10217327186846649646, + "venv/lib/python3.13/site-packages/idna/intranges.py": 12536174834761591006, + "venv/lib/python3.13/site-packages/pillow.libs/liblzma-61b1002e.so.5.8.2": 11405063484938458842, + "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.py": 11621577915097515056, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_modules.py": 16835987029123241300, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_can_hold_element.py": 5406431247116557833, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_delete.py": 5958440386632506587, + "frontend/src/lib/auth/store.ts": 14669655798912377598, + "venv/lib/python3.13/site-packages/PIL/_imaging.cpython-313-x86_64-linux-gnu.so": 1425926264271197601, + "venv/lib/python3.13/site-packages/click/core.py": 16793133181718891193, + "venv/lib/python3.13/site-packages/fastapi/_compat/model_field.py": 392699021682253569, + "venv/lib/python3.13/site-packages/h11/_events.py": 13800479928851716538, + "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.py": 12251264586530536622, + "venv/lib/python3.13/site-packages/pygments/lexers/actionscript.py": 8829560731160428621, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv": 12896264205153363031, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_routines.py": 4860173574365060471, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/validator.py": 11486125578281617670, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_api.py": 5813060676255093777, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_snap.py": 4515844385819802784, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_style.py": 14810883299259169406, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/REQUESTED": 15130871412783076140, + "frontend/src/lib/api/datasetReview.js": 3023829599261929428, + "frontend/src/components/git/BranchSelector.svelte": 12975425183125935169, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_union_categoricals.py": 6843679254735807, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray_misc.pyi": 16219573290116396099, + "frontend/src/routes/datasets/__tests__/StatsBar.test.js": 14838932138074212145, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/block_docstring/foo.f": 2489756567993745076, + "venv/lib/python3.13/site-packages/numpy/random/_sfc64.cpython-313-x86_64-linux-gnu.so": 17186695607612591922, + "venv/lib/python3.13/site-packages/authlib/jose/util.py": 14843923624043422219, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_info.py": 10615285239043745712, + "backend/src/api/routes/translate/_metrics_routes.py": 13468336445030118059, + "backend/tests/test_storage_audit_fixes.py": 13290928649795578073, + "venv/lib/python3.13/site-packages/fastapi/testclient.py": 2606236077497278662, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_attr_equal.py": 5612259834202470413, + "venv/bin/activate.fish": 5275961582873298085, + "venv/lib/python3.13/site-packages/ecdsa/numbertheory.py": 13538480862642502330, + "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimes.py": 14331984919364185787, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_base.py": 8678387511873412922, + "frontend/build/_app/immutable/chunks/Bk3a6kW_.js": 3389547072030174822, + "venv/lib/python3.13/site-packages/ecdsa/rfc6979.py": 11564966030899162026, + "venv/lib/python3.13/site-packages/h11/_version.py": 9334144031400715479, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_overrides.py": 92685611709898742, + "venv/lib/python3.13/site-packages/py.py": 16248211404003181569, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_dialect.py": 6294522482440261756, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/base.py": 10205051944814316388, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/control.py": 2034518223411945438, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/asyncmy.py": 11808138763443525443, + "venv/lib/python3.13/site-packages/click/_compat.py": 14451519072991457993, + "venv/lib/python3.13/site-packages/pandas/core/interchange/from_dataframe.py": 8278998381856028462, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_indexing.py": 17106010337164216722, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/lexers/_css_builtins.py": 17478340487186531268, + "venv/lib/python3.13/site-packages/anyio/_core/_asyncio_selector_thread.py": 1760597191437520000, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_arithmetic.py": 17449383588949771785, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarinherit.py": 15240535501243623986, + "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.cpython-313-x86_64-linux-gnu.so": 9380059465932560412, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_color.py": 3700828402084646308, + "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.pyi": 18395688193449688360, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_callback.py": 1689177048527329209, + "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.py": 2953876934840155920, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/METADATA": 4975169119201255384, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_reductions.py": 14432782234851468060, + "backend/src/api/routes/translate/_job_routes.py": 15469484615259714480, + "venv/lib/python3.13/site-packages/urllib3/response.py": 1987354357306756790, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_cpp_exception.py": 11851283355840567373, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/jupyter.py": 4446535289156468239, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_invalid.py": 2762344062554575805, + "venv/lib/python3.13/site-packages/pygments/styles/colorful.py": 15708848112363953394, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_series_equal.py": 1223890028205011021, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_construction.py": 6564829381134214401, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_conversion.pyi": 11580106670226366710, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/starlette/_utils.py": 8384087194580626069, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_inspect.py": 10573558345297891848, + "venv/lib/python3.13/site-packages/python_multipart/decoders.py": 14252672585219598429, + "backend/src/models/dataset_review_pkg/_semantic_models.py": 3910791744304398663, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_take.py": 9847808489301498487, + "frontend/src/lib/components/layout/__tests__/sidebarNavigation.test.js": 8459006438402290167, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/claims.py": 14794441479740527265, + "backend/src/plugins/translate/orchestrator_config.py": 1227864697811313446, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/__init__.py": 6654484356035994666, + "venv/lib/python3.13/site-packages/pandas/io/excel/_pyxlsb.py": 10035587889954731645, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/setitem.py": 9552868454186447925, + "frontend/src/lib/components/reports/__tests__/report_detail.integration.test.js": 4193615240297330385, + "frontend/src/components/storage/FileList.svelte": 11661146151896000393, + "venv/lib/python3.13/site-packages/pycparser/yacctab.py": 18018314512916353707, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py": 18069619555394133945, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_copy.py": 11335108864615756235, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexer.py": 14400766876373764268, + "backend/src/services/clean_release/manifest_builder.py": 10633987497931832162, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/enumerated.py": 16623643153933348755, + "venv/lib/python3.13/site-packages/passlib/tests/test_win32.py": 13932956220195912963, + "venv/lib/python3.13/site-packages/starlette/endpoints.py": 3379755567024530053, + "venv/lib/python3.13/site-packages/uvicorn/loops/auto.py": 13086005977087619545, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_boxplot_method.py": 7635131059308651529, + "frontend/playwright-report/index.html": 14077910029911296246, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/mean_.py": 3641008929910474457, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/LICENSE": 8423899413955829149, + "venv/lib/python3.13/site-packages/pandas/core/indexes/extension.py": 7193879749426425951, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_put.py": 8547660958963625817, + "venv/lib/python3.13/site-packages/pandas/core/internals/construction.py": 893951849732478990, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/METADATA": 2810323639884879396, + "venv/lib/python3.13/site-packages/greenlet/TGreenlet.hpp": 6993553444981671786, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/oracledb.py": 7158791242292470472, + "venv/lib/python3.13/site-packages/pygments/lexers/basic.py": 12723021007042054402, + "venv/lib/python3.13/site-packages/more_itertools/__init__.py": 9858612105173082060, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_format.py": 1947585389944838076, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_typst.py": 14619529283550788275, + "venv/lib/python3.13/site-packages/pygments/lexers/ldap.py": 17455983150181177257, + "venv/lib/python3.13/site-packages/pygments/lexers/archetype.py": 8995143180482517233, + "merge_spec.py": 5285945727297582371, + "frontend/build/_app/immutable/chunks/2dOUpm6k.js": 11811637653151731489, + "backend/src/api/routes/assistant/_history.py": 6437021555836617855, + "backend/src/api/routes/git_schemas.py": 9243114525622127446, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/roles.py": 5448455900674232810, + "venv/lib/python3.13/site-packages/jsonschema/_types.py": 9250091433305395923, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/__init__.py": 14186136918454802843, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/apps.py": 4219758952914498116, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/__init__.py": 14481526616887213120, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/METADATA": 13633829318759752611, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/pydantic/_internal/_discriminated_union.py": 1818179910730401509, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_symbol.py": 10792387279408528886, + "venv/lib/python3.13/site-packages/passlib/handlers/roundup.py": 3844280972451753019, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.pyi": 16976386782787920450, + "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimelike.py": 394614958716301173, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_nlargest.py": 1423106021399469694, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_halfyear.py": 587199217232946404, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_split_partition.py": 2715491071550545667, + "venv/lib/python3.13/site-packages/pygments/lexers/_ada_builtins.py": 16331776886501464264, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo77.f": 7353666717928699883, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libselinux-0922c95c.so.1": 16516617710645376769, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py": 2375452080667815941, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_mask.py": 5451866071307236899, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_describe.py": 11923715539897559626, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_constructors.py": 1697610790604400105, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_polynomial.py": 3049262771098624825, + "venv/lib/python3.13/site-packages/pandas/core/computation/ops.py": 18250656489649699560, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_set_value.py": 4166411740676564820, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_combine_concat.py": 3201068805128232483, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/METADATA": 5628172948035858892, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bus.py": 4260827599660763641, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/METADATA": 12747626683405487434, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress_bar.py": 15595912766961891283, + "venv/lib/python3.13/site-packages/fastapi/security/utils.py": 2616633862993539558, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_cumulative.py": 16283954014170928273, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/METADATA": 15225661995655327539, + "venv/lib/python3.13/site-packages/pygments/lexers/make.py": 5345282370426217663, + "venv/lib/python3.13/site-packages/pip/_internal/utils/compatibility_tags.py": 15862649917149158291, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/base.py": 13454394827268856575, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/rapidfuzz/process.py": 3870006735299537016, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/apps.py": 14151733532064278336, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/diagnose.py": 17275977405061138181, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_clip.py": 8087139801274517318, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_ufunc.py": 5025605639221470838, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/shape.py": 13410030168622484801, + "venv/lib/python3.13/site-packages/httpcore/_sync/connection_pool.py": 8159971229245441880, + "venv/lib/python3.13/site-packages/pygments/lexers/julia.py": 13516407944275342328, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libldap-2974a1ba.so.2.0.200": 13590569080612602445, + "venv/lib/python3.13/site-packages/gitdb/__init__.py": 15381521749253695923, + "venv/lib/python3.13/site-packages/pip/_internal/commands/download.py": 7533669665002975823, + "venv/lib/python3.13/site-packages/numpy/random/_pickle.pyi": 16081120364372391381, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/endpoints.py": 18334891787808122725, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/console.py": 3540660073442483692, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename.py": 16148017223289654683, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_formats.py": 18080627205081311773, + "venv/lib/python3.13/site-packages/pillow.libs/liblcms2-cc10e42f.so.2.0.17": 4221600618602131476, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_elements_constructors.py": 9279447066034364952, "venv/lib/python3.13/site-packages/PIL/JpegPresets.py": 12342262642420923471, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro_py.py": 11991492232381887787, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/RECORD": 15574202654585730126, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_missing.py": 3991199131191840903, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/ecdsa/ecdh.py": 12596317261561755793, + "frontend/src/lib/stores/__tests__/test_activity.js": 15599963775430388097, + "backend/src/schemas/validation.py": 11881058653924000699, + "backend/src/services/reports/report_service.py": 17586405613867657190, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.py": 17112989332785349705, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_resolution.py": 6076761538303762297, + "backend/src/services/clean_release/__tests__/test_source_isolation.py": 17714198919084455758, + "backend/src/services/profile_utils.py": 3954310438409803447, + "venv/lib/python3.13/site-packages/pluggy/_hooks.py": 6941854999025808196, + "backend/git_repos/remote/test-repo.git/objects/00/fcf77cecdf261aef91eda792ab3384a3339922": 1527330822006618217, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_is_full.py": 9577318758326279694, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/METADATA": 3618776395694990076, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/binding.py": 17078280153372356796, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/METADATA": 6502714564886871819, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta.py": 7742506012012398830, + "venv/lib/python3.13/site-packages/numpy/ma/__init__.pyi": 1855615156913010107, + "venv/lib/python3.13/site-packages/PIL/GifImagePlugin.py": 16073125611077200693, + "venv/lib/python3.13/site-packages/jose/jws.py": 11592462993417182096, + "frontend/src/lib/components/translate/TranslationPreview.svelte": 3234775946311369733, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/licenses/LICENSE": 3996324383113221529, + "venv/lib/python3.13/site-packages/greenlet/greenlet_refs.hpp": 8525862687669040510, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_iterrows.py": 3791886201566670087, + "venv/lib/python3.13/site-packages/_pytest/compat.py": 10046464101087327473, + "venv/lib/python3.13/site-packages/pydantic/_internal/_validators.py": 2939255306814626438, + "venv/lib/python3.13/site-packages/pandas/api/extensions/__init__.py": 882327406374020760, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/RECORD": 8201759541483070364, + "venv/lib/python3.13/site-packages/websockets/sync/connection.py": 2791040669094103200, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/__init__.py": 9083396324667433335, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/linalg.pyi": 7217817172953767893, + "venv/lib/python3.13/site-packages/PIL/PngImagePlugin.py": 5076219228736706283, + "venv/lib/python3.13/site-packages/git/index/util.py": 5022401275553420722, + "venv/lib/python3.13/site-packages/gitdb/utils/encoding.py": 1668793658272579497, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/default_styles.py": 4469204219504675080, + "venv/pyvenv.cfg": 2513607356761047446, + "backend/src/services/reports/normalizer.py": 11408466232944555336, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_numba.py": 6409810497251251179, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.py": 183817263146423033, + "venv/lib/python3.13/site-packages/pip/_internal/commands/help.py": 4175797322922912326, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_array_ops.py": 6709502157317299163, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_argparse.py": 11111699418217357084, + "venv/lib/python3.13/site-packages/charset_normalizer/api.py": 9172704759115759638, + "venv/lib/python3.13/site-packages/numpy/_core/_operand_flag_tests.cpython-313-x86_64-linux-gnu.so": 12296711931541109624, + "backend/src/plugins/translate/_llm_http.py": 15686826696693103176, + "venv/lib/python3.13/site-packages/fastapi/openapi/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_format.py": 5231304674283854194, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/fixed_string.f90": 8654788371538544793, + "venv/lib/python3.13/site-packages/dateutil/tz/__init__.py": 9617254832690762236, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/RECORD": 17985800801793506250, + "venv/lib/python3.13/site-packages/pygments/lexers/xorg.py": 14591144191879110061, + "backend/tests/services/dataset_review/test_superset_matrix.py": 5114797134613078913, + "venv/lib/python3.13/site-packages/cffi/parse_c_type.h": 9889309594462820068, + "venv/lib/python3.13/site-packages/numpy/fft/__init__.pyi": 10354990065626209946, + "backend/src/core/utils/dataset_mapper.py": 1606029474387636183, + "backend/src/plugins/llm_analysis/models.py": 3600633137673071517, + "venv/lib/python3.13/site-packages/ecdsa/test_jacobi.py": 1249543655136186433, + "venv/lib/python3.13/site-packages/fastapi/_compat/main.py": 13016492818231995760, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/__init__.py": 4752355175318979033, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period.py": 9715843209581883915, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.pyi": 9003794318682878317, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/assertion.py": 5287436128235488464, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/protocol.py": 932296179250981622, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/modes.py": 6832635056228445650, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90": 8680230823849248800, + "frontend/src/components/EnvSelector.svelte": 3937920133889630193, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reshaping.py": 18085648077811502689, + "frontend/build/_app/immutable/nodes/16.SU4ykNaQ.js": 13055744988522722486, "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_freq_attr.py": 17290447066681837965, + "backend/src/services/clean_release/candidate_service.py": 8516915994721977806, + "backend/src/api/routes/assistant/_routes.py": 438564212453429233, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/__init__.py": 9482393721453335937, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/clsregistry.py": 1589692649837935355, + "venv/lib/python3.13/site-packages/pygments/lexers/dsls.py": 11696359794961833087, + "venv/lib/python3.13/site-packages/numpy/_core/_internal.py": 13056946834347643109, + "venv/lib/python3.13/site-packages/passlib/tests/__main__.py": 16477180140297957650, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/RECORD": 10036839994791510159, + "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/__init__.py": 15130871412783076140, + "dist/docker/ss-tools.1.1.0.tar.xz": 14627825683119220800, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray.pyi": 14369009813591437391, + "venv/lib/python3.13/site-packages/jsonschema/protocols.py": 847332300543820834, + "venv/lib/python3.13/site-packages/requests/help.py": 1885413874621672882, + "venv/lib/python3.13/site-packages/ecdsa/_compat.py": 13034064768731879065, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pipe.py": 7400355977900310233, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/utils/filetypes.py": 4415340223268174913, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_excel.py": 5467043641314706635, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_cumulative.py": 8178093067175155877, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.pyi": 9282436354926617898, + "venv/lib/python3.13/site-packages/pandas/core/computation/engines.py": 1889823242704769952, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.py": 3762934316884129514, + "venv/lib/python3.13/site-packages/pluggy/_manager.py": 18202550145040079612, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py": 6509914623926583629, + "venv/lib/python3.13/site-packages/jose/jwk.py": 2781217726458801910, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_validate.py": 2133732492454460539, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_empty.py": 13006241382741353569, + "backend/src/plugins/translate/preview_response_parser.py": 15690759478655959205, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/zookeeper.py": 4318643109309626098, + "venv/lib/python3.13/site-packages/pandas/_libs/groupby.pyi": 6154952803757623626, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.cpython-313-x86_64-linux-gnu.so": 1211491156495529145, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_records.py": 12217508428903265797, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_two_greenlets.py": 11156275429806391390, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/METADATA": 3474626408138844944, + "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_version.py": 849232015288488204, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_hashtable.py": 7762405492052106717, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_ratio.py": 940213488194452623, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_processors.py": 16557117595879208702, + "venv/lib/python3.13/site-packages/pygments/lexers/matlab.py": 1880915927722177654, + "venv/lib/python3.13/site-packages/pygments/lexers/graphviz.py": 15677908982985025500, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo77.f": 12000068001851270396, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_repeat.py": 11360772447747837958, + "venv/lib/python3.13/site-packages/yaml/__init__.py": 11044333164208875121, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/_arrow_utils.py": 17808805047762566525, + "venv/lib/python3.13/site-packages/sqlalchemy/log.py": 10101221585967121334, + "venv/lib/python3.13/site-packages/pygments/styles/emacs.py": 4540417536507245024, + "backend/src/services/__tests__/test_rbac_permission_catalog.py": 5190751380981933250, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/__init__.py": 13841777369501476946, + "frontend/src/lib/components/reports/__tests__/fixtures/reports.fixtures.js": 10647302793388244094, + "frontend/build/_app/immutable/nodes/22.BSKyKb5v.js": 13377678180488845490, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_util.py": 6573034224727513309, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_value_counts.py": 15633881149834196174, + "venv/lib/python3.13/site-packages/pygments/styles/friendly.py": 13799024964803741891, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_pickle.py": 2910383574326146698, + "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.py": 3001896031623204147, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/pyodbc.py": 4146960201984489604, + "venv/lib/python3.13/site-packages/pandas/core/window/expanding.py": 14141093310397856286, + "venv/lib/python3.13/site-packages/pip/_internal/models/direct_url.py": 4619204214785230341, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/plugin_base.py": 2880434680251108786, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_na_values.py": 13527837495439739279, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi": 13061638961405460334, + "venv/lib/python3.13/site-packages/pygments/lexers/installers.py": 5083244110640899732, + "backend/git_repos/remote/test-repo.git/hooks/pre-merge-commit.sample": 10013699873067956556, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/dtypes.pyi": 15114028503984522176, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_overlaps.py": 8287716909793575347, + "frontend/build/_app/immutable/chunks/C6AbqTCJ.js": 13749317683500891666, + "venv/lib/python3.13/site-packages/_pytest/logging.py": 10972553724755511468, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py": 11185011314498348980, + "backend/git_repos/remote/test-repo.git/objects/3e/05ec6ef6504483c4bc7d00f0d0272c38ec661f": 11182016264585388842, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/argon2.py": 15389474901714096890, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_unary.py": 2573825678342936734, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_datetime.py": 1678885152993000592, + "venv/lib/python3.13/site-packages/click/testing.py": 15973659312284678327, + "venv/lib/python3.13/site-packages/rsa/randnum.py": 13958355153634534526, + "venv/lib/python3.13/site-packages/pandas/tests/api/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_shift.py": 14681514853406253657, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_astype.py": 15768655715952923925, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/_writer.py": 15053365792216907149, + "frontend/svelte.config.js": 8473636210766821560, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_interpolate.py": 6154072863387383113, + "venv/lib/python3.13/site-packages/numpy/_utils/__init__.py": 7731065084036767848, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py": 9627328185578406121, + "venv/lib/python3.13/site-packages/numpy/lib/npyio.py": 6782361985454523908, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_testing/_io.py": 14264259716673715185, + "venv/lib/python3.13/site-packages/pygments/lexers/wgsl.py": 9718384325049172855, + "venv/lib/python3.13/site-packages/fastapi/cli.py": 13972351579061154035, + "venv/lib/python3.13/site-packages/jaraco/classes/properties.py": 6976928770004942858, + "venv/lib/python3.13/site-packages/starlette/__init__.py": 3252794766897205870, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_equals.py": 6429101196875333574, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_asof.py": 8656532774394927388, + "venv/lib/python3.13/site-packages/pandas/io/formats/string.py": 14718123345899686696, + "venv/lib/python3.13/site-packages/_pytest/faulthandler.py": 13329320306353718649, + "frontend/src/lib/components/translate/TranslationRunResult.svelte": 3992997916593732645, + "frontend/src/components/git/GitManager.svelte": 2759220622954168718, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_common_basic.py": 1945891789924713537, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/sessions.py": 5400174351499383072, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufuncs.pyi": 1808147181379894521, + "frontend/src/components/TaskHistory.svelte": 7819646903874958430, + "backend/git_repos/remote/test-repo.git/hooks/fsmonitor-watchman.sample": 14381968406977928721, + "backend/git_repos/remote/test-repo.git/objects/5a/82ef700fef88b69cd480e4025283809496ee20": 7003383965314354150, + "venv/lib/python3.13/site-packages/requests/api.py": 12339139862411341381, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/METADATA": 14608873187265321271, + "venv/lib/python3.13/site-packages/pandas/io/formats/info.py": 215303194287834907, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/memmap.pyi": 2834143910417841603, + "venv/lib/python3.13/site-packages/pandas/core/groupby/numba_.py": 15997665748332235683, + "venv/lib/python3.13/site-packages/pygments/lexers/mime.py": 7768464764849718825, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_easter.py": 3397863170068576196, + "frontend/build/_app/immutable/chunks/D78XyA0Q.js": 5460557046065155963, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_range.py": 9900908262700749861, + "backend/src/services/rbac_permission_catalog.py": 8206280020500996966, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_get_numeric_data.py": 5896318696417090902, + "venv/lib/python3.13/site-packages/charset_normalizer/__main__.py": 8887772289570078278, + "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.py": 18402126171936308228, + "frontend/build/_app/immutable/nodes/24.DBmsYGXH.js": 14500145410736690111, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/repr.py": 839417422880281122, + "venv/lib/python3.13/site-packages/idna/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/tokens_mixins.py": 9923721909178724437, + "venv/lib/python3.13/site-packages/_pytest/pathlib.py": 9719734558816066453, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/RECORD": 173225030102092319, + "frontend/eslint.config.js": 14296985543214702398, + "backend/src/core/task_manager/lifecycle.py": 1696300129247014205, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_shape_base.py": 4117141349022217163, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_py.py": 6518425342376455821, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_algos.py": 5356470832688354593, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_setops.py": 17350958906336246626, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator": 6870991911243684132, + "venv/lib/python3.13/site-packages/idna/uts46data.py": 5698404064763638591, + "venv/lib/python3.13/site-packages/numpy/matlib.pyi": 8017902013455539981, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_clipboard.py": 12674078499544938252, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunc_config.pyi": 2005481648919369399, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/METADATA": 1266134223155266488, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/specifiers.py": 12284901056355482991, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_filter.py": 2388681477981649268, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_finalize.py": 12539815426478689538, + "venv/lib/python3.13/site-packages/apscheduler/triggers/date.py": 9545774812177853725, + "venv/lib/python3.13/site-packages/numpy/lib/scimath.pyi": 18165025261847276375, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict_of_blocks.py": 11646835537993064324, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/offsets.cpython-313-x86_64-linux-gnu.so": 6726636942028566415, + "frontend/src/routes/settings/+page.svelte": 1600542308917432302, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/base.py": 7855217087916771270, + "venv/lib/python3.13/site-packages/passlib/tests/test_totp.py": 9150389741890748343, + "venv/lib/python3.13/site-packages/PIL/report.py": 9428754440615681790, + "venv/lib/python3.13/site-packages/PIL/PdfParser.py": 13710342183037972042, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_style.py": 6849613206971398029, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_api_info.pyi": 7887489694871300469, + "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.pyi": 9935587108964614958, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/toml.py": 2225382735669153136, + "venv/lib/python3.13/site-packages/pandas/core/groupby/categorical.py": 16588862198627920420, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqldb.py": 2138006249556140141, + "backend/git_repos/remote/test-repo.git/objects/99/38d17c3f4199e53e4d4ebc253fe9c840caa505": 8414792171590415839, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/__init__.py": 10072943986583771248, + "venv/lib/python3.13/site-packages/apscheduler/executors/gevent.py": 17122637996105344344, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/padding.py": 11244071766694094554, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_comparison.py": 5348781442514871089, + "venv/lib/python3.13/site-packages/dateutil/parser/_parser.py": 9443336890192151397, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reset_index.py": 14490875921264161445, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_riscv_unix.h": 8607317131295864391, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/METADATA": 14158024963562115116, + "venv/lib/python3.13/site-packages/_pytest/config/__init__.py": 12787579251203510616, + "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.pyi": 5269136485429780038, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein_py.py": 11350239659973489646, + "venv/lib/python3.13/site-packages/jose/backends/_asn1.py": 14123487576864105793, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_extras.py": 16160090335191788104, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/six.py": 1161259802604920635, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5support-d0bcff84.so.0.1": 16819924515291719993, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/__init__.py": 6532094538918910232, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_take.py": 1216902953519121176, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_indexing.py": 4334578480714520407, + "venv/lib/python3.13/site-packages/pandas/tests/extension/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jeepney/tests/test_low_level.py": 3579024079580951234, + "venv/lib/python3.13/site-packages/httpx/_content.py": 1301854837767395687, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_produces_warning.py": 750781117570375777, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_map.py": 4761668276463940924, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_julian_date.py": 6868080396693831272, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/base.py": 13634605726041717070, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/types.py": 356973910046950951, + "venv/lib/python3.13/site-packages/httpcore/_async/__init__.py": 491192949420297153, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape.pyi": 2188930129299348535, + "venv/lib/python3.13/site-packages/pygments/lexers/openscad.py": 13045825115225232396, + "frontend/src/lib/components/layout/TaskDrawer.svelte": 11803999908168836613, + "frontend/build/_app/immutable/nodes/14.oojF1MKZ.js": 4314347373047993584, + "venv/lib/python3.13/site-packages/pygments/styles/stata_dark.py": 324072437809944751, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_ufunclike.py": 13752381070039804384, + "backend/src/models/translate.py": 17253774670319669066, + "backend/src/plugins/translate/_run_source.py": 11569137727611732019, + "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_gather.py": 3634138701088855517, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/resolution.py": 5132658725516243311, + "backend/src/core/utils/superset_context_extractor/_base.py": 2165790563924045511, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/WHEEL": 6514509858522675228, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/__init__.py": 3247870839323520754, + "venv/lib/python3.13/site-packages/pygments/lexers/qvt.py": 1895735583818227972, + "venv/lib/python3.13/site-packages/pygments/lexers/rust.py": 8605690716125176329, + "venv/lib/python3.13/site-packages/requests/__init__.py": 2604491098990438229, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq_py.py": 16054175754674285311, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex_like.py": 13803156447991282315, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE": 1126906383149772681, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_coercion.py": 3339075591248270762, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/RECORD": 9974324769263969827, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/__init__.py": 16150188643076000414, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_util.py": 13997184496924925110, + "venv/lib/python3.13/site-packages/urllib3/util/util.py": 12490259045660543460, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/__init__.py": 10834852742917144496, + "venv/lib/python3.13/site-packages/pytest/__main__.py": 8747175113746141224, + "backend/src/core/__init__.py": 8673978627093182792, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertsql.py": 4633484475514351889, + "venv/lib/python3.13/site-packages/rsa/core.py": 13203947234024924497, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/certs.py": 13366788049827102313, + "venv/lib/python3.13/site-packages/_pytest/reports.py": 13930709338396699351, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/licenses/LICENSE": 9235234428907927646, + "venv/lib/python3.13/site-packages/pandas/core/util/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_cli.py": 3173259257428855556, + "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.py": 2215312866861772848, + "venv/lib/python3.13/site-packages/pandas/core/tools/timedeltas.py": 7221393731712061943, + "venv/lib/python3.13/site-packages/pandas/tests/config/test_config.py": 4630144191929135452, + "venv/lib/python3.13/site-packages/numpy/_core/printoptions.py": 3897105663572772838, + "venv/lib/python3.13/site-packages/pandas/io/excel/_calamine.py": 13354427767660487637, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/METADATA": 14036738037171597049, + "venv/lib/python3.13/site-packages/pygments/styles/sas.py": 12363791134941577382, + "venv/lib/python3.13/site-packages/pygments/lexers/bdd.py": 5389493859905397060, + "frontend/src/lib/i18n/index.ts": 17142521634407341070, + "backend/src/api/routes/tasks.py": 2917461791850604633, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/__version__.py": 14138134075118474134, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__main__.py": 11917862648584782420, + "venv/lib/python3.13/site-packages/pydantic/v1/generics.py": 1150594223414883339, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937_regressions.py": 8981142329261965538, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_categorical.py": 8844412630511751140, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_core_functionalities.py": 10449747865888948579, + "venv/lib/python3.13/site-packages/PIL/ImagePalette.py": 9227837918026991107, + "venv/lib/python3.13/site-packages/yaml/reader.py": 9873075843010693205, + "backend/tests/services/clean_release/test_policy_resolution_service.py": 3471271299977247598, + "venv/lib/python3.13/site-packages/starlette/authentication.py": 10905269573809129547, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_droplevel.py": 2071197388394658690, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reset_index.py": 5946666595195952693, + "venv/lib/python3.13/site-packages/attr/_funcs.py": 5302917072419624193, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_formats.py": 9738552308554950419, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_formats.py": 13752366280743004410, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data": 9599129816090399315, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/syntax.py": 18070449217682341495, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_ordered.py": 13827016781743929164, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/bar.py": 12859947592168238832, + "venv/lib/python3.13/site-packages/pandas/core/frame.py": 2630807744775247533, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_diff.py": 7420674239386436885, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_indexing.py": 16291207621268530224, + "venv/lib/python3.13/site-packages/pygments/lexers/gleam.py": 5161116162065925222, + "frontend/src/lib/ui/Select.svelte": 11354509509920497811, + "venv/lib/python3.13/site-packages/requests/status_codes.py": 17005213506461710202, + "venv/lib/python3.13/site-packages/websockets/http11.py": 11022534176398053082, + "venv/lib/python3.13/site-packages/pip/_internal/cli/status_codes.py": 9143625681947330756, + "venv/lib/python3.13/site-packages/cryptography/x509/name.py": 15338066443257445241, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_infer_objects.py": 6769980076977692890, + "venv/lib/python3.13/site-packages/pandas/tests/generic/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jaraco/classes/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/typing_inspection/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/smmap/test/test_util.py": 5634593621291240094, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayprint.pyi": 2053388407376896377, + "venv/lib/python3.13/site-packages/requests/_internal_utils.py": 4091305333167213279, + "venv/lib/python3.13/site-packages/numpy/core/umath.py": 4476812261188108155, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_util.py": 16024147572807865219, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_frame_equal.py": 12459816298158655274, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.cpython-313-x86_64-linux-gnu.so": 6011605826065363427, + "venv/lib/python3.13/site-packages/pip/_internal/utils/misc.py": 17461379236189029253, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/bitwise_ops.pyi": 15598239133239520456, + "venv/lib/python3.13/site-packages/PIL/SunImagePlugin.py": 7661622930404688367, + "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/test-failed-1.png": 5297796663331551625, + "venv/lib/python3.13/site-packages/keyring/testing/util.py": 11195868112805409554, + "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_generation_shared.py": 23345689300073549, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_indexing.py": 546024765756472196, + "backend/src/models/dataset_review_pkg/_execution_models.py": 14035769184235191693, + "frontend/e2e/tests/git.e2e.js": 5892730242199126550, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/cffi/_shimmed_dist_utils.py": 4824806157907607487, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/WHEEL": 9131187629260560775, + "backend/src/plugins/translate/scheduler.py": 13413202759986193820, + "venv/lib/python3.13/site-packages/anyio/streams/memory.py": 11762722143503428823, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_extension.py": 4831602527247293866, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_.py": 644667973700652263, + "venv/lib/python3.13/site-packages/fastapi/concurrency.py": 17937688838625807004, + "venv/lib/python3.13/site-packages/click/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/psycopg2/extensions.py": 14197445323992851566, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/apscheduler/executors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets.py": 10923534235697247269, + "venv/lib/python3.13/site-packages/passlib/utils/md4.py": 4521366665754877351, + "venv/lib/python3.13/site-packages/pydantic/v1/typing.py": 13467331592583800299, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_api.py": 16743710460729009914, + "venv/lib/python3.13/site-packages/sqlalchemy/event/api.py": 987321343916500337, + "venv/lib/python3.13/site-packages/pandas/compat/_constants.py": 3909166275649444824, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py": 5946672289916692272, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_base.py": 15292769510056833117, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/macos.py": 17442393555211213147, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_freq_attr.py": 7685756734926749093, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/apps.py": 10758062668702044519, + "venv/lib/python3.13/site-packages/starlette/middleware/wsgi.py": 12506262030845301606, + "venv/lib/python3.13/site-packages/pygments/lexers/dns.py": 17149871769553794654, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/utils.py": 617314300548081590, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/misc/extended_precision.pyi": 6541258584648209609, + "venv/lib/python3.13/site-packages/numpy/_core/strings.pyi": 1981676808027146409, + "backend/src/plugins/translate/dictionary_entries.py": 11394786590056973146, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_dtypes.py": 2313400030798822026, + "venv/lib/python3.13/site-packages/pandas/tests/window/conftest.py": 10673264126684571493, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/markers.py": 8297667990263004097, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_repr.py": 13147587049887075335, + "frontend/src/components/git/GitInitPanel.svelte": 3002620133377315800, + "frontend/build/_app/immutable/nodes/18.BOhnophJ.js": 1849546302677188034, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_einsum.py": 17286384318722237180, + "venv/lib/python3.13/site-packages/httpcore/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.py": 5735043585893007971, + "frontend/build/_app/immutable/chunks/ekAQZlRA.js": 18344355808596370815, + "backend/src/core/task_manager/graph.py": 1566662881946484762, + "backend/src/services/llm_prompt_templates.py": 16187535610068299149, + "backend/src/plugins/translate/preview_token_estimator.py": 254295902082954386, + "venv/lib/python3.13/site-packages/pytest/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/TExceptionState.cpp": 17617354576371846109, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_cumulative.py": 11752712818547022872, + "venv/lib/python3.13/site-packages/pandas/tests/tools/__init__.py": 15130871412783076140, + "backend/src/api/routes/git/_deps.py": 8233286973979159721, + "venv/lib/python3.13/site-packages/pydantic/color.py": 1007422551673129827, + "venv/lib/python3.13/site-packages/pandas/compat/numpy/__init__.py": 1037113402100731082, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/token.py": 11655733747403312358, + "venv/lib/python3.13/site-packages/pyasn1/type/namedval.py": 8273171503516887681, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_filters.py": 17271344092069736999, + "venv/lib/python3.13/site-packages/httpcore/_sync/http_proxy.py": 14037211594707072958, + "frontend/src/components/tasks/TaskLogPanel.svelte": 4685456099513280294, + "venv/lib/python3.13/site-packages/pip/_internal/utils/temp_dir.py": 8657533190026387896, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_iloc.py": 16160558158155038350, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.cpython-313-x86_64-linux-gnu.so": 12473903676666680134, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation": 13992741783834278677, + "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.py": 12796890117561096360, + "venv/lib/python3.13/site-packages/httpcore/_utils.py": 3255581092836273826, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_old_base.py": 191359377446257900, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_internal/models/wheel.py": 10473287225032326206, + "frontend/src/routes/translate/dictionaries/[id]/+page.svelte": 17719561272401762626, + "venv/lib/python3.13/site-packages/keyring/cli.py": 10996746519742056101, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/WHEEL": 7414522633964952515, + "venv/lib/python3.13/site-packages/pygments/lexers/usd.py": 934820244673741695, + "venv/lib/python3.13/site-packages/pip/_internal/index/package_finder.py": 12631116673181479779, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_values.py": 834951665649981397, + "venv/lib/python3.13/site-packages/numpy/core/__init__.py": 10397294636564169377, + "frontend/build/_app/immutable/nodes/17.yX4KZQxj.js": 13162492380863525642, + "venv/lib/python3.13/site-packages/pandas/_config/dates.py": 3863381688916127265, + "venv/lib/python3.13/site-packages/_pytest/hookspec.py": 387790426108810884, + "backend/src/plugins/translate/_batch_sizer.py": 13074277127276828485, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/METADATA": 9586902338916246692, + "venv/lib/python3.13/site-packages/apscheduler/executors/debug.py": 14072221218785494847, + "venv/lib/python3.13/site-packages/charset_normalizer/__init__.py": 12412600648990392633, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_pandas.py": 10894229569442891394, + "backend/tests/test_constants_audit_fixes.py": 18298690956132739779, + "venv/lib/python3.13/site-packages/pandas/_libs/internals.cpython-313-x86_64-linux-gnu.so": 2008633361686956377, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_logical.py": 6818185860296232476, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/__init__.py": 2791238481813240414, + "frontend/src/components/TaskList.svelte": 3024343043730631288, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npz": 9481735723557962988, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_cpp.cpython-313-x86_64-linux-gnu.so": 10263790384087091349, + "venv/lib/python3.13/site-packages/pandas/_config/config.py": 1494288055210911451, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/relationships.py": 8401569216905291119, + "venv/lib/python3.13/site-packages/pygments/lexers/sophia.py": 15971500155124949058, + "frontend/src/app.html": 10207534912546549080, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/licenses/LICENSE": 17020744174398828059, + "backend/src/core/task_manager/__init__.py": 15991802770215124472, + "venv/lib/python3.13/site-packages/attr/__init__.py": 14436902698244718082, + "venv/lib/python3.13/site-packages/numpy/lib/user_array.py": 14003456655595459585, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py": 9888795404090331319, + "venv/lib/python3.13/site-packages/websockets/sync/__init__.py": 15130871412783076140, + "docker/frontend.Dockerfile": 13262735279052210084, + "venv/lib/python3.13/site-packages/pandas/core/series.py": 11618272682977710696, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/token_endpoint.py": 6118770923176099889, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/_pytest/helpconfig.py": 3033477806668470951, + "venv/lib/python3.13/site-packages/pluggy/__init__.py": 8269188363563356631, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_dict.py": 16252265723192124609, + "backend/src/api/routes/validation/__tests__/test_validation_api.py": 9582367280498409855, + "venv/lib/python3.13/site-packages/pygments/lexers/special.py": 4972294202790455038, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/METADATA": 6596896092754256988, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_py.py": 6428078990080243608, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE": 1641332741515411734, + "venv/lib/python3.13/site-packages/greenlet/tests/test_tracing.py": 10227316489696807112, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/packages.py": 11689856177725665974, + "venv/lib/python3.13/site-packages/pandas/_libs/indexing.cpython-313-x86_64-linux-gnu.so": 13188040757764159731, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/char.pyi": 13143560686049627445, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_arrow_string_mixins.py": 16862663427780315543, + "venv/lib/python3.13/site-packages/pandas/io/excel/_odswriter.py": 17220892094904423676, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_to_timestamp.py": 17572983799929378095, + "venv/lib/python3.13/site-packages/numpy/_core/lib/pkgconfig/numpy.pc": 14713682399742251335, + "backend/src/api/routes/assistant/_schemas.py": 4855661257485426649, + "backend/src/plugins/translate/orchestrator.py": 2899451611486868631, + "venv/lib/python3.13/site-packages/sqlalchemy/__init__.py": 9751988289698484530, + "backend/src/plugins/__init__.py": 17194112070692432889, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.py": 15426828792217499138, + "venv/lib/python3.13/site-packages/cryptography/x509/__init__.py": 4066756344049307453, + "venv/lib/python3.13/site-packages/referencing/tests/test_exceptions.py": 10846225989746274213, + "venv/lib/python3.13/site-packages/pydantic/errors.py": 3506829204186508192, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-2.csv": 14641856424618845798, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi": 17458894097215345719, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jws_algs.py": 11920621906391796226, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_frame.py": 4303613319747945709, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_shift.py": 9952689832827833247, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polybase.pyi": 3404315099794022355, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/lambdas.py": 13377298868598623228, + "venv/lib/python3.13/site-packages/git/refs/__init__.py": 16246686106073400519, + "venv/lib/python3.13/site-packages/dateutil/tz/win.py": 8427821225251397364, + "venv/lib/python3.13/site-packages/websockets/legacy/client.py": 4032878587330592478, + "venv/lib/python3.13/site-packages/pydantic/config.py": 1450073446492183677, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/_internal/_utils.py": 10936299012115637790, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_fillna.py": 7244491410004453166, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_mangle_dupes.py": 15613858733226279352, + "venv/lib/python3.13/site-packages/multipart/decoders.py": 11346752866822986212, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_function.py": 13492077564015386528, + "backend/src/api/routes/storage.py": 17448492494022569347, + "venv/lib/python3.13/site-packages/pygments/lexers/_tsql_builtins.py": 829193091321611630, + "venv/lib/python3.13/site-packages/pandas/core/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth1/__init__.py": 3692257288065292607, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.APACHE": 11041304845352917971, + "venv/lib/python3.13/site-packages/rapidfuzz/process_py.py": 17563673072076876125, + "venv/lib/python3.13/site-packages/pandas/core/arrays/integer.py": 7775055011080964709, + "venv/lib/python3.13/site-packages/click/formatting.py": 6694583529073729642, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows_renderer.py": 1076842273781909680, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.pyi": 6546751036506752550, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py": 15753279711312689193, + "venv/lib/python3.13/site-packages/pandas/core/arrays/timedeltas.py": 7318851108932357510, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation": 4826455560768665215, + "venv/lib/python3.13/site-packages/PIL/ImageFile.py": 15765130658900167517, + "venv/lib/python3.13/site-packages/pygments/lexers/_openedge_builtins.py": 4979988747924637739, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/licenses/LICENSE": 13479831069780783137, + "frontend/src/routes/translate/[id]/+page.svelte": 1911443262444004956, + "venv/lib/python3.13/site-packages/PIL/WalImageFile.py": 12442826195371137238, + "venv/lib/python3.13/site-packages/pillow.libs/libfreetype-ee1c40c4.so.6.20.4": 12301510769231120312, + "venv/lib/python3.13/site-packages/pandas/io/json/_normalize.py": 15938855324762935595, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_chebyshev.py": 8054411443686791426, + "venv/lib/python3.13/site-packages/PIL/TarIO.py": 13651401276968618561, + "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.py": 546976622482819095, + "venv/lib/python3.13/site-packages/pygments/lexers/praat.py": 54226477748516386, + "venv/lib/python3.13/site-packages/pygments/lexers/_luau_builtins.py": 13690910306072616818, + "venv/lib/python3.13/site-packages/pygments/lexers/bqn.py": 11823648528816858738, + "backend/src/api/routes/__tests__/test_assistant_authz.py": 13343271902390197049, + "backend/src/plugins/translate/preview_constants.py": 12447768695944862994, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_index_as_string.py": 13421551616136437100, + "backend/src/plugins/translate/dictionary_import_export.py": 12639118203353044308, + "frontend/src/routes/login/+page.svelte": 18430869485200259448, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/__init__.py": 4781700006554860887, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py": 15644105878811738516, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/automap.py": 4672057253309608464, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_analytics.py": 8155550493311083506, + "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.cpython-313-x86_64-linux-gnu.so": 13917011878259810696, + "venv/bin/py.test": 2593802493707545818, + "venv/lib/python3.13/site-packages/pillow.libs/libwebp-d8b9687f.so.7.2.0": 116215608212382352, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_regression.py": 4611768764484593979, + "frontend/src/routes/settings/MigrationMappingsTable.svelte": 4467573699012255407, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_aix.h": 8706347224105630468, + "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending_distributions.py": 209769687436320665, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/common.py": 11384497819737275399, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/entities.py": 8001287806688585081, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_unary.py": 7128845965976836334, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_linux.h": 15772978805500070727, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/compiler.py": 11662494978292401568, + "venv/lib/python3.13/site-packages/h11/_state.py": 11398755254809751139, + "backend/src/plugins/translate/service.py": 11825307511971639412, + "venv/lib/python3.13/site-packages/pygments/formatters/img.py": 18230180171537565208, + "venv/lib/python3.13/site-packages/httpcore/_backends/base.py": 5491727479625093183, + "venv/lib/python3.13/site-packages/pygments/lexers/sas.py": 6128008194712914874, + "venv/lib/python3.13/site-packages/pandas/_libs/hashing.cpython-313-x86_64-linux-gnu.so": 16124435225170610034, + "venv/lib/python3.13/site-packages/certifi/core.py": 7472627735517449185, + "venv/lib/python3.13/site-packages/starlette/exceptions.py": 15978811612997200737, + "frontend/src/lib/components/reports/reportTypeProfiles.js": 10752964062056890725, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/WHEEL": 9788895026336324100, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string.py": 3834067244989779682, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/secrets.py": 17816662030600756342, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/jsonschema/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/styles/_mapping.py": 11752660241391232497, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/char.f90": 12203871998988759364, + "venv/lib/python3.13/site-packages/pygments/util.py": 4815334059917765852, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py": 5995058808539530576, + "venv/lib/python3.13/site-packages/greenlet/tests/test_gc.py": 6383305344377882524, + "venv/lib/python3.13/site-packages/pydantic/type_adapter.py": 10162988530225478692, + "venv/lib/python3.13/site-packages/pandas/tests/computation/test_eval.py": 2921337784087808487, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_numba.py": 203614377324678234, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/version.py": 3699343596421001359, + "venv/lib/python3.13/site-packages/pandas/core/computation/api.py": 17919983681396223380, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/signature.py": 3614545297259098566, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py": 5324490103277723813, + "venv/lib/python3.13/site-packages/gitdb/db/base.py": 3375449584942578385, + "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.py": 7029935879540617057, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_protocols.py": 5019018645804313814, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/accumulate.py": 5780225603819849877, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arithmetic.py": 14858832264660410908, + "venv/lib/python3.13/site-packages/pygments/lexers/haxe.py": 1915270891525929751, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_index_tricks.py": 4676293127859087991, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_join.py": 1131792466825856990, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/key_set.py": 8485970749081951741, + "venv/lib/python3.13/site-packages/pygments/lexers/resource.py": 8057351545636349791, + "venv/bin/activate.csh": 14513616043256836238, + "frontend/src/lib/components/layout/TopNavbar.svelte": 16593656019460608311, + "backend/src/api/routes/git/_gitea_routes.py": 14644218433873522624, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/traceback.py": 2535227583726271746, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_engines.py": 2790877023773269276, + "venv/lib/python3.13/site-packages/pip/__main__.py": 574438877257676911, + "backend/src/plugins/llm_analysis/__init__.py": 9254812131558249924, + "backend/src/plugins/translate/_text_cleaner.py": 13161219043687449729, + "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.cpython-313-x86_64-linux-gnu.so": 17652852308919396403, + "venv/lib/python3.13/site-packages/pandas/_version_meson.py": 4875297137037630519, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/live.py": 8586058300967410643, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ma.pyi": 6467636381637286867, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/utils.h": 3920393832993063886, + "venv/lib/python3.13/site-packages/pandas/_libs/json.pyi": 10989301892466547548, + "venv/lib/python3.13/site-packages/numpy/lib/_datasource.py": 18136853038949826147, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_indexing.py": 1926721846569184112, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_is_monotonic.py": 12899848089975919515, + "venv/lib/python3.13/site-packages/pandas/tests/extension/date/array.py": 18073740473413382768, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/provision.py": 7362363963464621570, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/RECORD": 6488682447051657004, + "venv/lib/python3.13/site-packages/pygments/lexers/numbair.py": 17382646010399794697, + "backend/tests/test_log_persistence.py": 11073909507089982937, + "venv/lib/python3.13/site-packages/greenlet/tests/test_stack_saved.py": 7767924647054186572, + "venv/lib/python3.13/site-packages/pip/_internal/commands/completion.py": 4435231315212798769, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayscalars.h": 16142050006935459679, + "venv/lib/python3.13/site-packages/pycparser/ply/cpp.py": 1665654017894222868, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_python_parser_only.py": 12231449578582108346, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/licenses/LICENSE": 11986475601091748012, + "venv/lib/python3.13/site-packages/pygments/styles/dracula.py": 12379322008538174078, + "backend/tests/core/migration/test_dry_run_orchestrator.py": 5158126098685923841, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/__init__.py": 5118993772178969104, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_rewrite_warning.py": 4895919872954538758, + "venv/lib/python3.13/site-packages/uvicorn/protocols/utils.py": 6147480543268737542, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_overlap.py": 4202716587079637350, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/parameters.py": 5104015814292812973, + "backend/src/api/routes/reports.py": 5647380957044157360, + "venv/lib/python3.13/site-packages/numpy/lib/_version.pyi": 10804755840730584157, + "venv/lib/python3.13/site-packages/referencing/_core.py": 14744795336121513230, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_resolution.py": 18198858926948468112, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/request.py": 10484280068366411541, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/setup.py": 5482352991573617756, + "venv/lib/python3.13/site-packages/h11/_util.py": 9362339074207904329, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/licenses/LICENSE": 6653202620765194772, + "venv/lib/python3.13/site-packages/sqlalchemy/exc.py": 6372950288664776625, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90": 3492659529812762861, + "venv/lib/python3.13/site-packages/tzlocal/unix.py": 995019116408448073, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_constructors.py": 2786493777737472376, + "backend/git_repos/remote/test-repo.git/refs/heads/master": 12485529318667335076, + "backend/src/services/clean_release/mappers.py": 8684357784135236729, + "venv/lib/python3.13/site-packages/pygments/styles/arduino.py": 4578385147314541233, + "venv/lib/python3.13/site-packages/uvicorn/__main__.py": 6086938803696646644, + "venv/lib/python3.13/site-packages/pandas/tests/test_take.py": 17628004130770326677, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_header.py": 3564391095263545879, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_update.py": 9098258267671647783, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/_internal_utils.py": 4091305333167213279, + "venv/lib/python3.13/site-packages/_pytest/debugging.py": 16135285365306979060, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/writeonly.py": 14213960431308620600, + "venv/lib/python3.13/site-packages/greenlet/greenlet_compiler_compat.hpp": 465436185632243991, + "venv/lib/python3.13/site-packages/numpy/lib/mixins.py": 7404729635424818497, + "venv/lib/python3.13/site-packages/pygments/lexers/console.py": 18266795648198475028, + "venv/lib/python3.13/site-packages/pandas/io/xml.py": 326466573926392764, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__iotools.py": 6260912730310453037, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_where.py": 3272402211717453881, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_skiprows.py": 8764515842253490735, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/__init__.py": 15340047930888693984, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.pyi": 3595910367556664837, + "venv/lib/python3.13/site-packages/cryptography/fernet.py": 10137792148038140630, + "venv/lib/python3.13/site-packages/uvicorn/_types.py": 3339389597716220585, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/LICENSE": 16343563559291870811, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategy_options.py": 16342048970907383117, + "venv/lib/python3.13/site-packages/PIL/PalmImagePlugin.py": 13008868719182630239, + "venv/lib/python3.13/site-packages/gitdb/db/ref.py": 1176701624460337371, + "backend/src/services/dataset_review/clarification_pkg/_helpers.py": 9331845075873070265, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/common.py": 14578909424716153057, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_align.py": 6050248183327934780, + "venv/lib/python3.13/site-packages/pygments/lexers/wren.py": 6259586056260713984, + "venv/lib/python3.13/site-packages/ecdsa/ssh.py": 17010933326090778158, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core": 6622984507059115517, + "venv/lib/python3.13/site-packages/numpy/_core/tests/_natype.py": 12013743717306900860, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/interfaces.py": 5371646629319169153, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_log_render.py": 18076931145915444473, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_item.py": 17619314877770917080, + "venv/lib/python3.13/site-packages/pygments/lexers/rego.py": 16022844238903541738, + "venv/lib/python3.13/site-packages/pandas/_libs/reshape.pyi": 88721900806893992, + "venv/lib/python3.13/site-packages/pygments/lexers/automation.py": 8021926838024836904, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_missing.py": 7034102519042351965, + "backend/src/services/clean_release/repositories/report_repository.py": 17952038790457725175, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/RECORD": 7914594107698271488, + "backend/git_repos/remote/test-repo.git/refs/heads/feature/test": 7714224145564125988, + "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.py": 11758491058846790938, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/util.py": 10640907133050862176, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/utils.py": 2959395751217827103, + "frontend/src/components/llm/DocPreview.svelte": 25645090129568414, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append_common.py": 2377351120083195530, + "frontend/src/routes/migration/mappings/+page.svelte": 4566398049366943407, + "venv/lib/python3.13/site-packages/gitdb/db/pack.py": 13460574575424209609, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkeyutils-dfe70bd6.so.1.5": 9414227432578104677, + "venv/lib/python3.13/site-packages/pygments/styles/material.py": 14325514369696961874, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/passlib/utils/pbkdf2.py": 15802959653228956404, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/conftest.py": 9673372914396625461, + "venv/lib/python3.13/site-packages/pandas/tests/test_algos.py": 11860014896449369497, "venv/lib/python3.13/site-packages/pygments/formatters/terminal.py": 14380579279194052030, "run_clean_tui.sh": 14305120550349644601, - "venv/lib/python3.13/site-packages/anyio/abc/_testing.py": 16484863782452886547, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_astype.py": 11386658862732393123, - "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/__init__.py": 63497920264089252, - "venv/lib/python3.13/site-packages/pandas/core/arrays/_mixins.py": 14293848457775268010, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/__init__.py": 15130871412783076140, - "frontend/src/lib/components/layout/__tests__/test_breadcrumbs.svelte.js": 1250794495161202602, - "frontend/build/_app/immutable/chunks/Bbsm9eoK.js": 15498683014087735706, - "venv/lib/python3.13/site-packages/pip/_internal/models/link.py": 7172346414535657925, - "backend/src/api/routes/__tests__/test_git_status_route.py": 6682904773087475636, - "backend/src/plugins/translate/__tests__/test_dictionary_prompt_builder.py": 12854863376472707556, - "venv/lib/python3.13/site-packages/iniconfig/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/_libs/arrays.pyi": 12629806207276576877, - "venv/lib/python3.13/site-packages/pandas/tests/internals/test_internals.py": 2049484047553296860, - "venv/lib/python3.13/site-packages/numpy/_core/records.pyi": 14194354215405544730, - "venv/lib/python3.13/site-packages/rsa/parallel.py": 4968566722541778371, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_constructors.py": 6515602441449955627, - "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.py": 15031197044862908440, - "venv/lib/python3.13/site-packages/anyio/_core/_contextmanagers.py": 1258491775823080427, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_getitem.py": 8414677531950073373, - "venv/lib/python3.13/site-packages/requests/certs.py": 16052880877156864882, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_extract.py": 14547819021277949280, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_pickle.py": 3419420815386925630, - "venv/lib/python3.13/site-packages/pygments/styles/default.py": 13992125975366109635, - "backend/src/core/superset_client/_datasets_preview.py": 12644037069207561202, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/errors.py": 12777931960088171310, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/LICENSE": 2032205056284080825, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_logical_ops.py": 16166386974005224415, - "venv/lib/python3.13/site-packages/pandas/core/arrays/_ranges.py": 2572903460327860111, - "venv/lib/python3.13/site-packages/starlette/routing.py": 16063812008141874150, - "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.pyi": 3814281717779245045, - "venv/lib/python3.13/site-packages/numpy/_typing/_extended_precision.py": 4201820494689784136, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi": 7801211423226951223, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_seed_sequence.py": 7687465232954593311, - "venv/lib/python3.13/site-packages/pandas/_libs/tslib.pyi": 16170606956605100142, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/json.py": 14738429697319670035, - "venv/lib/python3.13/site-packages/pip/_internal/cli/command_context.py": 9426036980437931533, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py": 13570990531070630950, - "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_des.py": 7198931807116651263, - "venv/lib/python3.13/site-packages/passlib/handlers/scrypt.py": 10089372287597257402, - "venv/lib/python3.13/site-packages/pygments/lexers/agile.py": 5686162551416231457, - "backend/src/plugins/__init__.py": 17194112070692432889, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/kuin.py": 2818054539831699366, - "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.pyi": 16573082220135508510, - "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending.pyx": 756189645898997788, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__main__.py": 11917862648584782420, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_endian.h": 2761502363895204652, - "venv/lib/python3.13/site-packages/jeepney/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_table.tpl": 17198355067645888735, - "venv/lib/python3.13/site-packages/pygments/styles/igor.py": 2291640843781128270, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/concat.py": 14737724508458849795, - "venv/lib/python3.13/site-packages/PIL/_webp.pyi": 18222325750818585549, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_autocorr.py": 1092316868398391792, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/protocol.py": 932296179250981622, - "frontend/src/routes/datasets/[id]/+page.svelte": 14911166036063098761, - "venv/lib/python3.13/site-packages/pip/_internal/utils/subprocess.py": 3095012838116670328, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90": 8999550841368314739, - "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.pyi": 2744889206277418389, - "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.pyi": 3573629536236108391, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get_value.py": 389530025760539462, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/contains.py": 3098087827310439993, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/python3.npy": 4957143805477405905, - "venv/lib/python3.13/site-packages/pandas/core/computation/ops.py": 18250656489649699560, - "venv/lib/python3.13/site-packages/gitdb/test/test_base.py": 16305779366785148795, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_expanding.py": 9047466276603454007, - "venv/lib/python3.13/site-packages/pandas/tests/extension/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nunique.py": 8450574751331186943, - "venv/lib/python3.13/site-packages/pygments/lexers/maple.py": 7402467573829618534, - "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.py": 18402126171936308228, - "venv/lib/python3.13/site-packages/numpy/lib/array_utils.pyi": 14646405559193539455, - "frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js": 6561454515118560091, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_groupby_shift_diff.py": 1210657479716368827, - "venv/lib/python3.13/site-packages/pygments/formatters/pangomarkup.py": 17135620955205945255, - "backend/src/plugins/translate/preview_review.py": 5584592578627646560, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_py.py": 13809503317864539103, - "backend/alembic_test.db": 14995253579408279707, - "venv/lib/python3.13/site-packages/cryptography/exceptions.py": 5173540025160237758, - "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE": 14610443802372107702, - "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/__init__.py": 4870269250323682576, - "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.cpython-313-x86_64-linux-gnu.so": 1211491156495529145, - "venv/lib/python3.13/site-packages/yaml/_yaml.cpython-313-x86_64-linux-gnu.so": 16990140871649227895, - "venv/lib/python3.13/site-packages/git/diff.py": 6691274015605451565, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_concat.py": 10207975532842927134, - "frontend/src/lib/components/dataset-review/ExecutionMappingReview.svelte": 6341989866442424314, - "venv/lib/python3.13/site-packages/passlib/tests/test_utils_pbkdf2.py": 17016810698578473773, - "venv/lib/python3.13/site-packages/pandas/core/strings/accessor.py": 14021462534679430426, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_item_selection.py": 1027989019709029615, - "venv/lib/python3.13/site-packages/anyio/abc/_resources.py": 8330687082933028623, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/terminal_theme.py": 13727399800263579809, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90": 8079594129222364031, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_dtypes.py": 481191723198819568, - "venv/lib/python3.13/site-packages/httpcore/_sync/interfaces.py": 1532245423878428608, - "venv/lib/python3.13/site-packages/pygments/lexers/phix.py": 16775285097768256238, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/cast.py": 342228968652072052, - "backend/src/models/__tests__/test_clean_release.py": 8187870494226758184, - "venv/lib/python3.13/site-packages/jsonschema/_format.py": 8987698648383779883, - "venv/lib/python3.13/site-packages/pip/_internal/models/installation_report.py": 14534544543677907640, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/connection.py": 5582413226288987808, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ctypeslib.pyi": 8623725566434725526, - "backend/tests/scripts/test_clean_release_cli.py": 13978106497618764226, - "venv/lib/python3.13/site-packages/pygments/styles/emacs.py": 4540417536507245024, - "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/WHEEL": 7314207500206292683, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_where.py": 14167991754625133668, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/__init__.py": 14571251344510763303, - "frontend/build/_app/immutable/chunks/AokmZN-I.js": 16413474655951004736, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_non_unique.py": 15286893322149413712, - "backend/src/plugins/translate/__tests__/test_text_cleaner.py": 8349602354072854086, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_datetime.py": 13781712980921881470, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE": 12064892310002036996, - "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/extending.py": 9859383893070793914, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/region.py": 12579403230062395563, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/fromnumeric.py": 3792079757208879362, - "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/WHEEL": 8954358347596196608, - "venv/lib/python3.13/site-packages/pip/_internal/req/constructors.py": 17485271035479378662, - "venv/lib/python3.13/site-packages/rpds/__init__.py": 5862197328247012275, - "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE": 14316979437290727897, - "venv/lib/python3.13/site-packages/attr/_typing_compat.pyi": 2823472697859409877, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayobject.py": 13337664596833150958, - "venv/lib/python3.13/site-packages/pip/_internal/operations/prepare.py": 13514839972066861359, - "venv/lib/python3.13/site-packages/pandas/tests/extension/json/__init__.py": 7877061921210840955, - "venv/lib/python3.13/site-packages/pygments/lexers/qlik.py": 3881663935630350152, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatter.py": 16499277113779414101, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_defmatrix.py": 2982572083770917411, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_function.py": 13492077564015386528, - "venv/lib/python3.13/site-packages/pandas/core/sorting.py": 689057022713741051, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_setops.py": 8622608042929141013, - "backend/src/core/utils/superset_context_extractor/_templates.py": 6790136732701012567, - "venv/lib/python3.13/site-packages/fastapi/requests.py": 14587947416691824903, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_string.py": 9224234539232195189, - "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/sqlalchemy/util/deprecations.py": 7020540470348910770, - "backend/src/core/utils/async_network.py": 840981454868177222, - "venv/lib/python3.13/site-packages/gitdb/test/test_pack.py": 7518388297247535189, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/appengine.py": 16194997685865850655, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_constructors.py": 3440572832185940666, - "backend/src/models/__tests__/test_models.py": 1386812925656974657, - "venv/lib/python3.13/site-packages/pydantic/errors.py": 3506829204186508192, - "backend/alembic/README": 17625003422504608299, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/models.py": 3567900447243180991, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arrow_compat.py": 12986187285988432338, - "venv/lib/python3.13/site-packages/click/globals.py": 18353671282454331523, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/azure.py": 13529763490186254462, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_where.py": 16584772339591698754, - "venv/lib/python3.13/site-packages/pydantic/config.py": 1450073446492183677, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_find_replace.py": 262184394614748386, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_exceptions.py": 12145393002202744314, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/METADATA": 5628172948035858892, - "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/METADATA": 3814104793342833872, - "venv/lib/python3.13/site-packages/PIL/GifImagePlugin.py": 16073125611077200693, - "venv/lib/python3.13/site-packages/jose/exceptions.py": 8562012933958941039, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/datonly.f90": 10495925225338237742, - "frontend/src/lib/auth/__tests__/permissions.test.js": 13555349356008297952, - "backend/src/services/clean_release/publication_service.py": 1882863137548904782, - "backend/src/plugins/translate/__tests__/test_dictionary_correction.py": 17508858180216288123, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odswriter.py": 5134385709728943904, - "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.py": 4154852745131464543, - "backend/git_repos/remote/test-repo.git/objects/aa/ea042a37c6f7bd010d91db93951328da7f01cc": 11936716919619613939, - "venv/lib/python3.13/site-packages/charset_normalizer/md.cpython-313-x86_64-linux-gnu.so": 1835299664481804968, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/__init__.py": 697601512486720554, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi": 11733449165276720901, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/METADATA": 6438256145634479451, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_astype.py": 4854809596041987380, - "venv/lib/python3.13/site-packages/pillow.libs/libavif-01e67780.so.16.3.0": 13947441788826399574, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_mask.py": 5451866071307236899, - "venv/lib/python3.13/site-packages/pandas/tests/api/test_types.py": 8889829773923216769, - "frontend/src/routes/git/+page.svelte": 14169430923974356254, - "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/jeepney/tests/test_bindgen.py": 8637878018232418583, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_can_hold_element.py": 5406431247116557833, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_take.py": 3281943380342853080, - "venv/lib/python3.13/site-packages/greenlet/tests/test_version.py": 6317733744899804292, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/printing.py": 8681519649669408795, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_bar.py": 7791068963246005463, - "backend/src/services/dataset_review/repositories/session_repository.py": 4058785536575367912, - "venv/lib/python3.13/site-packages/packaging/_elffile.py": 9546225990833172494, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_delitem.py": 16538190861492829338, - "venv/lib/python3.13/site-packages/keyring/backends/null.py": 12740996416911604870, - "venv/lib/python3.13/site-packages/numpy/_typing/_dtype_like.py": 1598511035344858524, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/conftest.py": 12368472226536104037, - "venv/lib/python3.13/site-packages/sqlalchemy/connectors/aioodbc.py": 2018840826888846321, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_convert_dtypes.py": 5005259275646154894, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_set_value.py": 17480833128128893268, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg_catalog.py": 15726448028057859831, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/base.py": 3628510830969664111, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/core.py": 2199607970842512780, - "venv/lib/python3.13/site-packages/pydantic/v1/schema.py": 10008526732895436361, - "venv/lib/python3.13/site-packages/numpy/tests/test_public_api.py": 11741922758622705449, - "venv/lib/python3.13/site-packages/numpy/fft/tests/test_pocketfft.py": 18025182347224285050, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_repr.py": 11737029058271003097, - "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np126.pkl.gz": 9677994062701347206, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/METADATA": 10241403930811743893, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply.py": 12349190935180702377, - "venv/lib/python3.13/site-packages/anyio/streams/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/__init__.py": 2331213407497901634, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_numpy_array_equal.py": 2089426719574307767, - "venv/lib/python3.13/site-packages/sqlalchemy/event/base.py": 18238453132776154057, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_pickle.py": 8705060420848529055, - "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/RECORD": 12598309574903741388, - "venv/lib/python3.13/site-packages/click/_compat.py": 14451519072991457993, - "frontend/src/routes/datasets/review/ReviewWorkspaceHeader.svelte": 15302107925819930527, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_polynomial.pyi": 9134949577567498894, - "backend/src/plugins/translate/sql_generator.py": 900251269659959067, - "frontend/src/routes/settings/connections/+page.svelte": 276661107137418305, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.py": 15511055314565873928, - "venv/lib/python3.13/site-packages/numpy/exceptions.py": 10981418339663118022, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_copy.py": 12902342280706372953, - "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.pyi": 12144531601504755948, - "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/licenses/LICENSE": 6653202620765194772, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_invalid.py": 2762344062554575805, - "venv/lib/python3.13/site-packages/rapidfuzz/utils_py.py": 12341806772632276946, - "venv/lib/python3.13/site-packages/_pytest/skipping.py": 10561585274103209115, - "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/parameter.py": 2793853093222900337, - "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/base.py": 15872835330892203433, - "venv/lib/python3.13/site-packages/cffi/_embedding.h": 9441285871823018603, - "venv/lib/python3.13/site-packages/passlib/utils/compat/__init__.py": 17369882236606423129, - "venv/lib/python3.13/site-packages/pandas/_libs/writers.cpython-313-x86_64-linux-gnu.so": 6878855127769203372, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_constructors.py": 17392287676196409733, - "venv/lib/python3.13/site-packages/attrs/exceptions.py": 2871247302586505373, - "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/METADATA": 2624107638694809013, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_range.py": 3544406211185340973, - "venv/lib/python3.13/site-packages/pygments/lexers/ecl.py": 12886695201994337568, - "venv/lib/python3.13/site-packages/keyring/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/descriptor_props.py": 7044852927393650707, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/models.py": 16636119441941357281, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/candidates.py": 5951912505933673835, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/connection.py": 15405047955974108860, - "venv/bin/py.test": 2593802493707545818, - "venv/lib/python3.13/site-packages/keyring/devpi_client.py": 3445890176686211982, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_csv.py": 10737444103906389448, - "backend/src/plugins/translate/preview_prompt_helpers.py": 14303328860208074708, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_conversion_utils.py": 1567199588622767277, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_compression.py": 3167245427092658522, - "backend/src/core/utils/superset_compilation_adapter.py": 4974836712746468095, - "venv/lib/python3.13/site-packages/pygments/lexers/fantom.py": 1986459352773446836, - "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/WHEEL": 3749476255729626245, - "venv/lib/python3.13/site-packages/PIL/_imagingft.pyi": 1385456134120145584, - "venv/lib/python3.13/site-packages/referencing/tests/test_retrieval.py": 10782087416909177703, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_fsspec.py": 6936167344144998172, - "venv/lib/python3.13/site-packages/fastapi/dependencies/utils.py": 7687214523082385505, - "venv/lib/python3.13/site-packages/pygments/formatters/img.py": 18230180171537565208, - "venv/lib/python3.13/site-packages/pygments/lexers/tal.py": 447505725492547461, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_categorical.py": 9615571808720893016, - "venv/lib/python3.13/site-packages/passlib/ext/django/__init__.py": 11713862539944289631, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/token_validator.py": 13917237710752731397, - "venv/lib/python3.13/site-packages/pygments/styles/coffee.py": 17584414468786822371, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/warnings.py": 2552021607611112605, - "venv/lib/python3.13/site-packages/cffi/pkgconfig.py": 16057517851163939571, - "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/__init__.py": 8705044848308260480, - "venv/lib/python3.13/site-packages/smmap/test/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/fastapi/openapi/models.py": 1680354178147364813, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/constant_time.py": 2499026008403328245, - "frontend/src/lib/components/assistant/__tests__/assistant_confirmation.integration.test.js": 12582020574293031526, - "venv/lib/python3.13/site-packages/sqlalchemy/util/topological.py": 11586868018611359415, - "venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py": 13206297306768491360, - "venv/lib/python3.13/site-packages/pygments/lexers/meson.py": 14659991367778746658, - "frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js": 2331331717663585059, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py": 6973859422068490274, - "venv/lib/python3.13/site-packages/passlib/handlers/ldap_digests.py": 8658529184965699766, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.pyi": 16164841755339571545, - "venv/lib/python3.13/site-packages/pluggy/__init__.py": 8269188363563356631, - "venv/lib/python3.13/site-packages/idna/compat.py": 9758194415584776667, - "venv/lib/python3.13/site-packages/pygments/lexers/webidl.py": 8097260111959278117, - "venv/lib/python3.13/site-packages/git/refs/symbolic.py": 14996822770181935589, - "venv/lib/python3.13/site-packages/anyio/_backends/_trio.py": 4764555436057754985, - "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.py": 1094797446508902066, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_cpp.cpython-313-x86_64-linux-gnu.so": 10263790384087091349, - "venv/lib/python3.13/site-packages/pip/_internal/commands/inspect.py": 1401259241736437656, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/__init__.py": 11850945878149145990, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_factorize.py": 17995673140216929494, - "venv/lib/python3.13/site-packages/jaraco/classes/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/ecdsa/ecdh.py": 12596317261561755793, - "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/RECORD": 7363618870628306370, - "venv/lib/python3.13/site-packages/fastapi/_compat/v2.py": 15078491685917047095, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_array.py": 12514884344165043136, - "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_utils.py": 2329717399120006435, - "venv/lib/python3.13/site-packages/pydantic/__init__.py": 11536052293866174672, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/PIL/BmpImagePlugin.py": 16682567630621529903, - "venv/lib/python3.13/site-packages/pip/_internal/utils/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numerictypes.pyi": 15443101937711720707, - "venv/lib/python3.13/site-packages/yaml/nodes.py": 3463622922914760653, - "venv/lib/python3.13/site-packages/itsdangerous/__init__.py": 6969210114978365656, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex_like.py": 1407890639206728014, - "venv/lib/python3.13/site-packages/uvicorn/main.py": 5843333502356171120, - "venv/lib/python3.13/site-packages/pandas/_libs/sas.cpython-313-x86_64-linux-gnu.so": 16309838137741124637, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/operators.py": 2468046993343796128, - "venv/lib/python3.13/site-packages/pygments/formatters/latex.py": 7514533384468139434, - "venv/lib/python3.13/site-packages/starlette/background.py": 10232175205397808417, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi": 8666343427862784832, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_io.py": 4199750143323741326, - "venv/lib/python3.13/site-packages/pygments/lexers/sieve.py": 15757825442941567629, - "frontend/src/routes/storage/backups/+page.svelte": 3437582895363203695, - "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.pyi": 8916922961301555974, - "venv/lib/python3.13/site-packages/pygments/formatters/irc.py": 2133711525226123259, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/RECORD": 15865206372525596795, - "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.py": 1590647503660777156, - "venv/lib/python3.13/site-packages/starlette/authentication.py": 10905269573809129547, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py": 8864112842559211971, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/asyncmy.py": 11808138763443525443, - "frontend/src/routes/dashboards/health/+page.svelte": 5234355531444674267, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_constructors.py": 11786151805350138436, - "frontend/build/_app/immutable/chunks/BWuq2W7N.js": 17816481472338018959, - "backend/src/api/routes/git/_repo_operations_routes.py": 5819532622410034169, - "backend/src/api/routes/translate/__init__.py": 6357999798616465776, - "venv/lib/python3.13/site-packages/numpy/core/multiarray.py": 18368443598659711836, - "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.py": 12636954896699095212, - "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/RECORD": 14375680579341422646, - "venv/lib/python3.13/site-packages/pandas/_libs/indexing.cpython-313-x86_64-linux-gnu.so": 13188040757764159731, - "venv/lib/python3.13/site-packages/pandas/_config/localization.py": 11197430792343731762, - "venv/lib/python3.13/site-packages/numpy/random/_common.pxd": 3402284125943848851, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-2.csv": 7063857529719738394, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_partial_slicing.py": 15567512240469921599, - "venv/lib/python3.13/site-packages/pygments/lexers/gdscript.py": 12775803139854052838, - "venv/lib/python3.13/site-packages/packaging/_musllinux.py": 2568338440457080365, - "venv/lib/python3.13/site-packages/jsonschema/_utils.py": 14237077105384631097, - "venv/lib/python3.13/site-packages/pandas/core/groupby/indexing.py": 18009437216172136227, - "venv/lib/python3.13/site-packages/pandas/tests/construction/test_extract_array.py": 3100523370314150013, - "frontend/src/routes/profile/+page.svelte": 17979719303737794427, - "frontend/build/_app/immutable/chunks/DsnmJJEf.js": 17416107759626312632, - "backend/src/services/clean_release/compliance_orchestrator.py": 10585043190405940115, - "backend/git_repos/remote/test-repo.git/objects/a7/49f11fad695dff77faf1708c7320867d0be1df": 4641609158325033031, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_api.py": 7131036004750554905, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_asfreq.py": 12721047184483392773, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarbuffer.py": 16859789411010045795, - "venv/lib/python3.13/site-packages/numpy/_core/_internal.pyi": 6840742333427164920, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_print.py": 598821365691498702, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period_range.py": 9598872514187524706, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_counting.py": 5628494712451120258, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_convert_dtypes.py": 13612212066710266457, - "frontend/src/lib/components/reports/__tests__/report_detail.integration.test.js": 4193615240297330385, - "venv/lib/python3.13/site-packages/tzlocal/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/RECORD": 3288669175908898843, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo77.f": 16250175448122328648, - "frontend/src/routes/settings/automation/+page.svelte": 17397435134589275932, - "venv/lib/python3.13/site-packages/authlib/common/urls.py": 13627272625165922482, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/module_data_docstring.f90": 18245403117623015312, - "venv/lib/python3.13/site-packages/charset_normalizer/api.py": 9172704759115759638, - "venv/lib/python3.13/site-packages/jeepney/tests/secrets_introspect.xml": 10717038359151125278, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/claims.py": 11853156183819186599, - "frontend/build/_app/immutable/chunks/BLdlpp5i.js": 11984092703547102139, - "venv/lib/python3.13/site-packages/pydantic/type_adapter.py": 10162988530225478692, - "venv/lib/python3.13/site-packages/numpy/_core/records.py": 11414828908088050950, - "backend/src/api/routes/git/__init__.py": 14824479456728364642, - "venv/lib/python3.13/site-packages/pandas/tests/config/test_config.py": 4630144191929135452, - "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.pyi": 5892973170789971535, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.py": 5221550291012182443, - "frontend/build/_app/immutable/nodes/13.uOTGQxsu.js": 12543968595061548876, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/licenses/LICENSE": 16147999986886816451, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.py": 4265012785873472600, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/well_known.py": 7183795183137931709, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/default_styles.py": 4469204219504675080, - "venv/lib/python3.13/site-packages/referencing/tests/test_jsonschema.py": 9815500901482570619, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_shift.py": 9952689832827833247, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo90.f90": 2435648607844815947, - "venv/lib/python3.13/site-packages/passlib/crypto/digest.py": 15890463288512025688, - "venv/lib/python3.13/site-packages/passlib/tests/backports.py": 17098448557554464521, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_usecols_basic.py": 16382444980424010514, - "venv/lib/python3.13/site-packages/fastapi/security/http.py": 8465565118555441408, - "venv/lib/python3.13/site-packages/pandas/_libs/window/aggregations.pyi": 6072607880689125113, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_transpose.py": 1686867045869336370, - "venv/lib/python3.13/site-packages/click/types.py": 6491651131669287534, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/engine.py": 2652248727360250985, - "venv/lib/python3.13/site-packages/yaml/scanner.py": 8554164423030397366, - "venv/lib/python3.13/site-packages/websockets/connection.py": 5168795926684067030, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/vectorized.pyi": 15498895254516573071, - "venv/lib/python3.13/site-packages/charset_normalizer/md.py": 2029760700380476138, - "venv/lib/python3.13/site-packages/websockets/legacy/handshake.py": 376095144657994920, - "venv/lib/python3.13/site-packages/pydantic/deprecated/tools.py": 16466182352694741629, - "venv/lib/python3.13/site-packages/ecdsa/test_malformed_sigs.py": 2606295770491528880, - "venv/lib/python3.13/site-packages/websockets/speedups.cpython-313-x86_64-linux-gnu.so": 10941658763526595989, - "venv/lib/python3.13/site-packages/httpcore/_async/__init__.py": 491192949420297153, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/registration.py": 14639972512303032712, - "venv/lib/python3.13/site-packages/passlib/handlers/bcrypt.py": 8125664010268654055, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/parameters.py": 1647490964392525933, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_strings.py": 7379299916213794543, - "venv/lib/python3.13/site-packages/pygments/lexers/_luau_builtins.py": 13690910306072616818, - "venv/lib/python3.13/site-packages/pydantic/deprecated/parse.py": 819235411736647763, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/reporters.py": 10760889726586439724, - "venv/lib/python3.13/site-packages/pydantic_settings/utils.py": 14396350455520958703, - "venv/lib/python3.13/site-packages/packaging/pylock.py": 15346942039643310253, - "venv/lib/python3.13/site-packages/pandas/core/reshape/merge.py": 300205528811693975, - "backend/src/api/routes/connections.py": 6022659034509664689, - "venv/lib/python3.13/site-packages/pandas/_libs/index.pyi": 17679349633640606985, - "backend/src/plugins/git_plugin.py": 11912463343289116491, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/rec.pyi": 14615751247243515028, - "venv/lib/python3.13/site-packages/PIL/ImagePath.py": 18323293175183057101, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv": 601782991752922510, - "backend/tests/test_translate_corrections.py": 1228642484417924184, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/__init__.py": 14571251344510763303, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarraytypes.h": 6765088137325865789, - "venv/lib/python3.13/site-packages/passlib/handlers/des_crypt.py": 15304795681178011265, - "backend/src/api/routes/__tests__/test_tasks_logs.py": 17724385243163092479, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/tornado.py": 6491136785917169991, - "backend/src/models/filter_state.py": 6470311179852241297, - "venv/lib/python3.13/site-packages/numpy/_core/_operand_flag_tests.cpython-313-x86_64-linux-gnu.so": 12296711931541109624, - "backend/src/api/routes/migration.py": 6030566471113208264, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np121.pkl.gz": 4708588000144933291, - "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.pyi": 3661113433078225952, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayprint.py": 5912583751693302370, - "venv/lib/python3.13/site-packages/sqlalchemy/event/registry.py": 2857989070743633709, - "venv/lib/python3.13/site-packages/_pytest/mark/__init__.py": 9343015549300275714, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_cython_aggregations.py": 10818895573637904764, - "venv/lib/python3.13/site-packages/pandas/core/ops/__init__.py": 4049432353810047365, - "venv/lib/python3.13/site-packages/pandas/io/sas/sas_xport.py": 16525568795475918874, - "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp_impl.cpython-313-x86_64-linux-gnu.so": 11767771662042404251, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/windows.py": 16452996247375488034, - "frontend/src/pages/Dashboard.svelte": 3653104499351855122, - "venv/lib/python3.13/site-packages/pandas/core/flags.py": 4690844374637430013, - "venv/lib/python3.13/site-packages/pygments/lexers/solidity.py": 5071425960622305629, - "venv/lib/python3.13/site-packages/numpy/version.py": 1497063540123613501, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_laguerre.py": 7475592201750602042, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_orc.py": 1248059610437937895, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/core.py": 14576109242055156193, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_coercion.py": 3551994404797560483, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_monotonic.py": 11817523305776951162, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_setops.py": 17350958906336246626, - "backend/src/models/dashboard.py": 8479838979214366697, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_sh_gcc.h": 3574353221233465215, - "backend/src/plugins/git/__init__.py": 2144831474780401625, - "backend/src/core/async_superset_client.py": 5842980152216372100, - "frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js": 13047006106880121194, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_deprecations.py": 16124509063246256847, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_hashtable.py": 2620207240930665390, - "venv/lib/python3.13/site-packages/pillow.libs/libXau-154567c4.so.6.0.0": 4340972632724893052, - "venv/lib/python3.13/site-packages/numpy/_typing/_scalars.py": 17701938912160369190, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/common.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/util.py": 4815334059917765852, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/chararray.pyi": 17340224970247832290, - "merge_kilo.py": 4282227344165325430, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py": 7906029092844029127, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/datasource.pyi": 16752667877866430577, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_repr.py": 16609300578827398344, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_legacy.py": 9226692984248279094, - "venv/lib/python3.13/site-packages/pydantic/_internal/_utils.py": 10936299012115637790, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress.py": 5951745251426856398, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cython.py": 14695721638531081573, - "venv/lib/python3.13/site-packages/passlib/tests/utils.py": 15403198680231294263, - "venv/lib/python3.13/site-packages/numpy/typing/tests/test_runtime.py": 12534621594420844770, - "frontend/build/_app/immutable/nodes/37.D-RPsxP5.js": 9256582747431738102, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/cli.py": 6382193953727339271, - "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/trace.zip": 14597002665264983691, - "venv/lib/python3.13/site-packages/pydantic/v1/json.py": 16596969681914729251, - "venv/lib/python3.13/site-packages/pygments/styles/gh_dark.py": 7717523746712391809, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/__init__.py": 15130871412783076140, - "backend/src/core/logger/__tests__/test_logger.py": 11665830455325390168, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_table.tpl": 8706980975714184465, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_api.py": 5813060676255093777, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-1.csv": 2202360898679162333, - "backend/src/models/dataset_review_pkg/_clarification_models.py": 13264800784251426725, - "venv/lib/python3.13/site-packages/pip/_internal/distributions/__init__.py": 1343779312297539596, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_where.py": 3272402211717453881, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_rowcount.py": 6682800584070485197, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/locators.py": 7638945613579396718, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/annotation.py": 15855576199737688124, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_shift.py": 8547819448301023303, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npy": 17303060773267383537, - "backend/git_repos/remote/test-repo.git/objects/d8/3fe0db1279ef07c4c4f3de4156a629373b4057": 7507193819578792576, - "backend/src/models/__tests__/test_report_models.py": 18076243829002249148, - "venv/lib/python3.13/site-packages/websockets/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/typing.py": 6661252174518316760, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_http_headers.py": 13187746870209705951, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/codec.py": 14814999235499530522, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/METADATA": 1862765380818895200, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/mod.py": 2054876501774773382, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/METADATA": 13776251749114562660, - "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.pyi": 6534825471013879522, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_base.py": 16710163879060522196, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/__init__.py": 16434403703599680307, - "venv/lib/python3.13/site-packages/pygments/lexers/graphics.py": 13783143864729682444, - "backend/src/models/report.py": 9185954411073383239, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_partial.py": 15129217814262096441, - "backend/src/plugins/translate/__init__.py": 12400577052797809611, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_construction.py": 13953424340346625390, - "venv/lib/python3.13/site-packages/pip/_internal/network/utils.py": 13421242949994555055, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90": 2657057181044959432, - "venv/lib/python3.13/site-packages/pydantic/v1/typing.py": 13467331592583800299, - "venv/lib/python3.13/site-packages/PIL/MpegImagePlugin.py": 7726254767528154514, - "venv/lib/python3.13/site-packages/PIL/SpiderImagePlugin.py": 12234762087257163606, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/LICENSE": 6774760218010069963, - "venv/lib/python3.13/site-packages/numpy/random/__init__.py": 11732100564412485633, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pygments/lexers/func.py": 12257919753150082714, - "venv/lib/python3.13/site-packages/passlib/handlers/phpass.py": 16489430001449160264, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/dax.py": 10868881057512002309, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_value_counts.py": 15633881149834196174, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py": 4301355720042319835, - "backend/src/core/auth/security.py": 8289703096420999159, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex.py": 16348619731902304844, - "venv/lib/python3.13/site-packages/httpcore/_backends/trio.py": 8394426709857317737, - "venv/lib/python3.13/site-packages/anyio/abc/_subprocesses.py": 4297459042599291531, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/apply.py": 3906017176873949738, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_nditer.py": 8341339612899904236, - "venv/lib/python3.13/site-packages/attr/_version_info.py": 3850449653182103457, - "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/RECORD": 9964194961227523130, - "venv/lib/python3.13/site-packages/pydantic/deprecated/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/core/computation/expressions.py": 10684284531040203747, - "frontend/src/components/llm/DocPreview.svelte": 25645090129568414, - "venv/lib/python3.13/site-packages/dotenv/__main__.py": 16883579879172186355, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/core/fromnumeric.py": 2136433423902202138, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/align.py": 6078666505647454830, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_repr.py": 13147587049887075335, - "venv/lib/python3.13/site-packages/websockets/asyncio/client.py": 5694225754072131767, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_types.py": 4083297168618981717, - "venv/lib/python3.13/site-packages/numpy/_core/multiarray.pyi": 3494871767602648807, - "venv/lib/python3.13/site-packages/psycopg2/_psycopg.cpython-313-x86_64-linux-gnu.so": 13471342289207537479, - "backend/git_repos/remote/test-repo.git/hooks/prepare-commit-msg.sample": 7530253302780245896, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/einsumfunc.py": 9944042006439149561, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_repr.py": 7552782621374439569, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/repr.py": 839417422880281122, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_transpose.py": 17983160984979323393, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py": 15294662527620994511, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_level_values.py": 12490886203425393290, - "backend/src/api/auth.py": 6636844886257776670, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pyodbc.py": 11271266527234292020, - "venv/lib/python3.13/site-packages/pip/_internal/utils/compat.py": 1841193561752758336, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ma.pyi": 6467636381637286867, - "venv/lib/python3.13/site-packages/numpy/core/_utils.py": 14108063453670701289, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arrayterator.py": 1646530870049791291, - "venv/lib/python3.13/site-packages/pandas/core/common.py": 14578909424716153057, - "venv/lib/python3.13/site-packages/pygments/lexers/felix.py": 2334148799642808111, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/serialize.py": 11139432164346742421, - "venv/lib/python3.13/site-packages/numpy/ma/core.py": 338350463523585845, - "venv/lib/python3.13/site-packages/anyio/pytest_plugin.py": 4165280709813718099, - "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.py": 546976622482819095, - "venv/lib/python3.13/site-packages/pandas/tests/series/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.cpython-313-x86_64-linux-gnu.so": 18139875206371157315, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/misc.py": 6571241778569465264, - "venv/lib/python3.13/site-packages/pandas/api/indexers/__init__.py": 17431573013142626187, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/RECORD": 16558021503346615951, - "venv/lib/python3.13/site-packages/uvicorn/middleware/asgi2.py": 5355343704425405009, - "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_gen_files.py": 11149423183253618378, - "venv/lib/python3.13/site-packages/websockets/__init__.py": 4916307256304054040, - "venv/lib/python3.13/site-packages/packaging/requirements.py": 2896326326372719999, - "venv/lib/python3.13/site-packages/pip/_internal/req/req_dependency_group.py": 10505346210114745037, - "venv/lib/python3.13/site-packages/numpy/lib/_iotools.py": 10522826373041592861, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh17797.f90": 17319074662077763768, - "venv/lib/python3.13/site-packages/numpy/tests/test_ctypeslib.py": 9592016432737074765, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.py": 14034239842770171660, - "venv/lib/python3.13/site-packages/dotenv/main.py": 7408889670575271484, - "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/WHEEL": 8600534672961461758, - "venv/lib/python3.13/site-packages/greenlet/TUserGreenlet.cpp": 16258622236210473101, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/websockets/streams.py": 15786581670248099415, - "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.pyi": 15864712173815045309, - "venv/lib/python3.13/site-packages/pandas/util/version/__init__.py": 3844072588696074141, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_setops.py": 10550603120090683350, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_iloc.py": 16160558158155038350, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_stata.py": 3030675968330529905, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args.py": 5821040955806257450, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_keywords.py": 11487954623214475915, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_results.py": 18145930285449734975, - "backend/src/services/superset_lookup_service.py": 16520439978260397080, - "backend/tests/test_translate_history.py": 14504549443376034614, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/requirements.py": 13215932786801020434, - "backend/src/core/task_manager/lifecycle.py": 14300570861650299636, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_string.py": 15542851215119662814, - "frontend/build/_app/immutable/nodes/11.KsItOBh4.js": 4087665907116502716, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_asfreq.py": 6162659555626011770, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/binding.py": 17078280153372356796, - "venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py": 4857114071347950833, - "frontend/src/components/tasks/TaskResultPanel.svelte": 7735278333136205649, - "venv/lib/python3.13/site-packages/yaml/events.py": 745772917931702910, - "venv/bin/activate": 14735074000123383125, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/nested_secrets.py": 15691917061715429369, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_utils.py": 15197339054699289627, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_monotonic.py": 14648437502004398715, - "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/test_uuid.py": 13955678427426850807, - "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.py": 548928042543500365, - "venv/lib/python3.13/site-packages/pandas/io/html.py": 2727247063231114153, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/unix.py": 13808187640638677050, - "venv/lib/python3.13/site-packages/pygments/lexers/_vim_builtins.py": 6842381248727719900, - "venv/lib/python3.13/site-packages/httpx/_transports/default.py": 8391302827983907910, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_pydatetime.py": 1129954411080617001, - "venv/lib/python3.13/site-packages/attr/validators.pyi": 15579625896285277321, - "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_regression.py": 5652583095949741238, - "venv/lib/python3.13/site-packages/numpy/__config__.py": 15794735729525094396, - "venv/lib/python3.13/site-packages/pandas/_libs/algos.pyi": 22405377601029952, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_retain_attributes.py": 16210262356844956764, - "frontend/build/_app/immutable/chunks/DA-mqwbe.js": 17228797594481881608, - "frontend/eslint.config.js": 14296985543214702398, - "backend/src/schemas/__init__.py": 8700952869915187087, - "venv/lib/python3.13/site-packages/dotenv/cli.py": 7952654621986067973, - "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/referencing/tests/test_core.py": 8280983300775878144, - "venv/lib/python3.13/site-packages/pandas/_libs/window/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numeric_only.py": 13610631681447961840, - "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/apscheduler/__init__.py": 8652514118183227412, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/parameters.py": 12219404446503940066, - "venv/lib/python3.13/site-packages/passlib/utils/des.py": 2650106381178222229, - "venv/lib/python3.13/site-packages/fastapi/testclient.py": 2606236077497278662, - "venv/lib/python3.13/site-packages/PIL/ContainerIO.py": 7551929914241379005, - "venv/lib/python3.13/site-packages/packaging/version.py": 13470993734108007779, - "frontend/src/components/storage/FileList.svelte": 11661146151896000393, - "backend/src/services/profile_utils.py": 3954310438409803447, - "venv/lib/python3.13/site-packages/urllib3/poolmanager.py": 15431313180245757657, - "venv/lib/python3.13/site-packages/jeepney/fds.py": 16573439672758641560, - "backend/src/schemas/auth.py": 12332369795585412464, - "frontend/src/services/git-utils.js": 12982149055119314642, - "backend/src/plugins/translate/orchestrator_lang_stats.py": 5713612003349083382, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_mask.py": 9654897363729130542, - "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.pyi": 12052895927933479005, - "venv/lib/python3.13/site-packages/websockets/__main__.py": 11948055520555854616, - "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.pyi": 9291444594181042963, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_processors.py": 16557117595879208702, - "venv/lib/python3.13/site-packages/numpy/random/_pcg64.pyi": 14785496840737986355, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_arithmetic.py": 4858019700859362660, - "venv/lib/python3.13/site-packages/pygments/lexers/shell.py": 3842338968014057744, - "backend/alembic/versions/c4a3a2f74bfe_add_missing_columns_needs_review_.py": 4320606555167902916, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_localize.py": 18409231586451494605, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_json_table_schema_ext_dtype.py": 13021437050542691118, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_numba.py": 6409810497251251179, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_period.py": 15671388508498441412, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/ddl.py": 5006132143435653867, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_envs.py": 5657151394155576509, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_federal.py": 16758212916399857971, - "venv/lib/python3.13/site-packages/pygments/lexers/sgf.py": 6802546617450210439, - "venv/lib/python3.13/site-packages/starlette/status.py": 16192064443996706569, - "frontend/build/_app/immutable/chunks/nvuMiq_x.js": 15230412160727535217, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_formats.py": 13752366280743004410, - "backend/src/core/utils/__init__.py": 12454773556575864508, - "venv/lib/python3.13/site-packages/jose/backends/rsa_backend.py": 13507186353881931758, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/profiling.py": 16030397164203895281, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/AUTHORS": 3558407083075395848, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/METADATA": 8985010079096958084, - "venv/lib/python3.13/site-packages/pygments/lexers/asn1.py": 15030988816882821134, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_csv.py": 6678500392137188521, - "backend/tests/core/test_migration_engine.py": 7419155921858935534, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_hour.py": 13754646634123368797, - "venv/lib/python3.13/site-packages/pluggy/_callers.py": 1042673447718196223, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py": 6067836157632573182, - "venv/lib/python3.13/site-packages/pydantic/decorator.py": 6984214881365537811, - "venv/lib/python3.13/site-packages/cffi/_shimmed_dist_utils.py": 4824806157907607487, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_timer.py": 8196003526646080498, - "venv/lib/python3.13/site-packages/attr/_cmp.pyi": 14443711863388606665, - "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/METADATA": 16700674024421191168, - "venv/lib/python3.13/site-packages/httpx/_decoders.py": 14478643473006178492, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_axis.py": 4097534573847151853, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_chaining_and_caching.py": 15814259766479305290, - "venv/lib/python3.13/site-packages/git/exc.py": 14278238357119816365, - "frontend/playwright-report/index.html": 14077910029911296246, - "venv/lib/python3.13/site-packages/anyio/streams/stapled.py": 9733127303038397237, - "venv/lib/python3.13/site-packages/pandas/io/sas/sas_constants.py": 14492427939536692313, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/utils.py": 9959199071030996679, - "venv/lib/python3.13/site-packages/fastapi/concurrency.py": 17937688838625807004, - "venv/lib/python3.13/site-packages/pygments/lexers/hdl.py": 6772823608124143123, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/warnings_and_errors.py": 11172336980866895356, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/__init__.py": 2397613800206300456, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_constructors.py": 9767900500541600486, - "venv/lib/python3.13/site-packages/jose/__init__.py": 15575670403380555945, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_quarter.py": 11099677280196239755, - "venv/lib/python3.13/site-packages/charset_normalizer/cli/__main__.py": 2148876100501691980, - "venv/lib/python3.13/site-packages/httpx/_transports/__init__.py": 5931944625631942279, - "venv/lib/python3.13/site-packages/_pytest/raises.py": 8188402179490363767, - "venv/lib/python3.13/site-packages/authlib/common/security.py": 2291133227104016684, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_linux.h": 15772978805500070727, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/__init__.py": 1197579313959289096, - "venv/lib/python3.13/site-packages/pip/_internal/models/direct_url.py": 4619204214785230341, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_frequencies.py": 14039315221824123200, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_real.py": 5283415082530228716, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fromnumeric.pyi": 8671744104085911610, - "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.py": 5564496700647900501, - "frontend/playwright.config.js": 1601415616693761429, - "venv/lib/python3.13/site-packages/h11/py.typed": 12358286306858197118, - "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.cpp": 7360124705400993707, - "venv/lib/python3.13/site-packages/pygments/lexers/gleam.py": 5161116162065925222, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/errors.py": 12935154705443176852, - "backend/src/core/utils/fileio.py": 8925306729946909050, - "venv/lib/python3.13/site-packages/pygments/styles/friendly.py": 13799024964803741891, - "backend/src/core/task_manager/persistence.py": 17734987286155732710, - "venv/lib/python3.13/site-packages/pandas/io/parsers/python_parser.py": 7297059565749331767, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_concat.py": 1351478313334379336, - "venv/lib/python3.13/site-packages/pandas/_libs/lib.pyi": 3049004444338566197, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_regression.py": 16293647824734937323, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_any_index.py": 10800968419286329268, - "venv/lib/python3.13/site-packages/pandas/core/indexes/frozen.py": 1419685664276640120, - "venv/lib/python3.13/site-packages/websockets/version.py": 5853118844880112885, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append_common.py": 2377351120083195530, - "venv/lib/python3.13/site-packages/starlette/middleware/errors.py": 1337979724602864440, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi": 13061638961405460334, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_astype.py": 1961831758405941258, - "frontend/src/components/git/GitMergeDialog.svelte": 17029360862035548928, - "venv/lib/python3.13/site-packages/pygments/lexers/savi.py": 95400050302239274, - "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/LICENSE": 16174281248426886206, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_finfo.py": 17174674209412768422, - "frontend/src/lib/stores/activity.js": 14023344642294459631, - "backend/src/api/routes/tasks.py": 2917461791850604633, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/base.py": 10200916670889920659, - "venv/lib/python3.13/site-packages/pygments/lexers/procfile.py": 3860651022061090738, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_api.py": 13319208721442328400, - "venv/lib/python3.13/site-packages/keyring/backends/chainer.py": 12526770797516553385, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_inf.py": 8659210689723088321, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-1.csv": 5708101386018266998, - "backend/src/plugins/translate/_run_service.py": 1705461175389858266, - "backend/test.db": 15130871412783076140, - "venv/lib/python3.13/site-packages/gitdb/stream.py": 3035738824550231197, - "venv/lib/python3.13/site-packages/rpds/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.f": 18215492757907465667, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarmath.py": 9762951701352556447, - "docker/backend.Dockerfile": 4384294014726084339, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/METADATA": 3448868793744358515, - "venv/lib/python3.13/site-packages/starlette/middleware/gzip.py": 4321371046149637632, - "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/WHEEL": 7454950858448014158, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/__init__.py": 15735839022111230173, - "venv/lib/python3.13/site-packages/pandas/core/apply.py": 17080038932032802984, - "venv/lib/python3.13/site-packages/numpy/core/overrides.pyi": 1968648615494204783, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_categorical.py": 9923236395692943732, - "backend/src/core/__tests__/test_throttled_scheduler.py": 10949494963069000037, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/abc.py": 6227782083136374888, - "venv/lib/python3.13/site-packages/pygments/lexers/promql.py": 8929925488296216854, - "frontend/src/routes/settings/EnvironmentsTab.svelte": 1326318857426265025, - "venv/lib/python3.13/site-packages/pandas/core/tools/__init__.py": 15130871412783076140, - "backend/tests/test_log_persistence.py": 11073909507089982937, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_win_type.py": 18105114803686556748, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/block_docstring/foo.f": 2489756567993745076, - "venv/lib/python3.13/site-packages/pip/_internal/commands/lock.py": 14782882714168174465, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90": 6208802899442270399, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_datetimelike.py": 15246580603900811749, - "venv/lib/python3.13/site-packages/numpy/core/numerictypes.py": 5776941405348611027, - "venv/lib/python3.13/site-packages/numpy/lib/_version.py": 15294708923334674060, - "venv/lib/python3.13/site-packages/greenlet/greenlet_msvc_compat.hpp": 12504008513945919250, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_promote.py": 16601872688404846307, - "venv/lib/python3.13/site-packages/pycparser/yacctab.py": 18018314512916353707, - "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/code.py": 9700811903057180696, - "venv/lib/python3.13/site-packages/pygments/lexers/haskell.py": 8011341851439354724, - "frontend/src/components/RepositoryDashboardGrid.svelte": 14921738329941705036, - "frontend/build/_app/immutable/chunks/CA1pzeTf.js": 4029128264487796302, - "venv/lib/python3.13/site-packages/pygments/lexers/json5.py": 9736695186548899403, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_encoding.py": 6622474614967398246, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.BSD": 3858254215169937333, - "venv/lib/python3.13/site-packages/PIL/McIdasImagePlugin.py": 14137545069906812251, - "backend/src/services/llm_provider.py": 18361253887642486050, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/filesize.py": 13234856188049714485, - "venv/lib/python3.13/site-packages/pandas/_testing/contexts.py": 11714205921752896137, - "venv/lib/python3.13/site-packages/rapidfuzz/_common_py.py": 15410157970973169427, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/build_tracker.py": 9389444024234384408, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/box.py": 14303526978791498662, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ufuncobject.h": 5112456258078662871, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/securetransport.py": 12104888897121018676, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/METADATA": 3618776395694990076, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_npfuncs.py": 6132674295193898715, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_nonkeyword_arguments.py": 11676809974120007408, - "venv/lib/python3.13/site-packages/PIL/_avif.pyi": 18222325750818585549, - "venv/lib/python3.13/site-packages/pygments/lexers/archetype.py": 8995143180482517233, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/plugin_base.py": 2880434680251108786, - "venv/lib/python3.13/site-packages/pygments/lexers/lilypond.py": 1088755646568511197, - "venv/lib/python3.13/site-packages/pydantic/env_settings.py": 18250976255197243083, - "frontend/src/lib/api/datasetReview.js": 3023829599261929428, - "venv/lib/python3.13/site-packages/greenlet/greenlet_internal.hpp": 13173115501223013762, - "venv/lib/python3.13/site-packages/pyasn1/codec/ber/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/pillow.libs/libpng16-4a38ea05.so.16.53.0": 13136089038268964667, - "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.pyi": 362674842164060822, - "venv/lib/python3.13/site-packages/numpy/__init__.pxd": 13527602429695748857, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayscalars.h": 16142050006935459679, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h": 7896028550808252043, - "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_numeric.py": 18037815278545274402, - "backend/src/plugins/translate/__tests__/test_lang_detect.py": 2328877106785068272, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/certs.py": 13366788049827102313, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi": 16312114056447366970, - "backend/tests/test_resource_hubs.py": 3990299394875930767, - "venv/lib/python3.13/site-packages/git/config.py": 1724894144987553201, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_style.py": 6849613206971398029, - "frontend/src/lib/components/health/PolicyForm.svelte": 16556369076015031814, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_drop.py": 11341278355685583133, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_query_eval.py": 17613800806748649144, - "venv/lib/python3.13/site-packages/PIL/PdfImagePlugin.py": 16082854250442815862, - "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/licenses/LICENSE": 8438117004702803716, - "venv/lib/python3.13/site-packages/_pytest/config/exceptions.py": 3199245296954654462, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/RECORD": 17545477863793260029, - "venv/lib/python3.13/site-packages/numpy/lib/introspect.py": 5706729538356302335, - "venv/lib/python3.13/site-packages/pandas/_libs/testing.pyi": 16691791330088523786, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/ma/LICENSE": 6723325434476453127, - "venv/lib/python3.13/site-packages/httpcore/_backends/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.pyi": 7674087576653964854, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_limited_api.py": 15788485008764560845, - "venv/lib/python3.13/site-packages/pygments/lexers/slash.py": 8320676560518108343, - "backend/src/api/routes/dashboards/_detail_routes.py": 12522696473630508473, - "backend/src/services/clean_release/repositories/audit_repository.py": 9617813121624417458, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_numpy.py": 9825804096508014886, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/provision.py": 7362363963464621570, - "venv/lib/python3.13/site-packages/apscheduler/util.py": 11440701924954413440, - "venv/lib/python3.13/site-packages/pyasn1/type/base.py": 6801504886392649787, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_pickle.py": 4216445955812104014, - "venv/lib/python3.13/site-packages/cffi/__init__.py": 13427266446746498548, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/syntax.py": 18070449217682341495, - "backend/src/services/clean_release/__tests__/test_stages.py": 15353751625742444422, - "venv/lib/python3.13/site-packages/pip/_internal/distributions/base.py": 16714704323747942110, - "venv/lib/python3.13/site-packages/pydantic/_internal/_model_construction.py": 694471028676746110, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/providers.py": 7267821734584612032, - "venv/lib/python3.13/site-packages/_pytest/setuponly.py": 10959102379908419762, - "venv/lib/python3.13/site-packages/jsonschema/protocols.py": 847332300543820834, - "venv/lib/python3.13/site-packages/pandas/core/sample.py": 11913688303879867963, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_align.py": 10284128457194204574, - "venv/lib/python3.13/site-packages/pandas/tests/libs/test_hashtable.py": 7762405492052106717, - "frontend/src/lib/auth/permissions.js": 12787489292887903923, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/collections.py": 16114931075157411913, - "frontend/src/lib/components/dataset-review/CompiledSQLPreview.svelte": 4866254539173481462, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numerictypes.py": 5719374287454872555, - "frontend/src/lib/components/translate/TranslationRunResult.svelte": 3992997916593732645, - "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.pyi": 9206355685192026844, - "frontend/src/types/dashboard.ts": 9718666955722367566, - "frontend/src/lib/stores/__tests__/assistantChat.test.js": 11822882112255142537, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py": 5324490103277723813, - "venv/lib/python3.13/site-packages/ecdsa/test_eddsa.py": 1785854649532849946, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata.py": 2021612995853910808, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/styled.py": 8726407298858811635, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/dml.py": 6567627855667533645, - "venv/lib/python3.13/site-packages/sqlalchemy/exc.py": 6372950288664776625, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/__init__.py": 12975130533860125272, - "frontend/build/_app/immutable/nodes/10.CpNiMhPr.js": 1754671220917742591, - "backend/tests/scripts/test_clean_release_tui_v2.py": 16893299982170941753, - "venv/lib/python3.13/site-packages/pycparser/c_ast.py": 5942107079119742, - "venv/lib/python3.13/site-packages/rpds/__init__.pyi": 12037474523494903587, - "venv/lib/python3.13/site-packages/itsdangerous/url_safe.py": 13454753900702274266, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_value_attrspec.py": 7741590618654448240, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c": 5472633890472031814, - "venv/lib/python3.13/site-packages/PIL/_imagingtk.cpython-313-x86_64-linux-gnu.so": 1708198947135304326, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_overlaps.py": 8287716909793575347, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/base.py": 14908084548919567658, - "venv/lib/python3.13/site-packages/numpy/fft/__init__.pyi": 10354990065626209946, - "venv/lib/python3.13/site-packages/attr/exceptions.py": 11532465891810816417, - "venv/lib/python3.13/site-packages/charset_normalizer/cd.py": 8687667152597941021, - "merge_spec.py": 5285945727297582371, - "venv/lib/python3.13/site-packages/PIL/PcdImagePlugin.py": 922809545463280224, - "venv/lib/python3.13/site-packages/numpy.libs/libquadmath-96973f99-934c22de.so.0.0.0": 5098713761946118139, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/styles/dracula.py": 12379322008538174078, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_loongarch64_linux.h": 6566098590441297326, - "venv/lib/python3.13/site-packages/passlib/handlers/scram.py": 12281469744083867450, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_sorting.py": 10523740688498427929, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo77.f": 4046503346951676582, - "backend/git_repos/remote/test-repo.git/objects/ae/8d2f5dec5d421b2d6cc1eebaad6d2ef901a90d": 15877648001251681939, - "venv/lib/python3.13/site-packages/pytest_asyncio/__init__.py": 8162213292669110211, - "venv/lib/python3.13/site-packages/_pytest/_py/path.py": 8464061867075119556, - "venv/lib/python3.13/site-packages/_pytest/_argcomplete.py": 3586514420674089892, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/scalar_string.f90": 15018631706178918578, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isna.py": 18394053826166267096, - "venv/lib/python3.13/site-packages/psycopg2/errors.py": 10441360078612452560, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd_module.py": 7122050193390298178, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_errors.py": 3301889847545579393, - "venv/lib/python3.13/site-packages/pandas/io/excel/_odfreader.py": 2760916559416783928, - "venv/lib/python3.13/site-packages/urllib3/exceptions.py": 9687187566231423953, - "frontend/src/routes/translate/history/+page.svelte": 9504117584329454876, - "backend/src/api/__init__.py": 5287505122015708040, - "backend/src/models/dataset_review_pkg/_execution_models.py": 14035769184235191693, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_indexing.py": 14717641281147152159, - "venv/lib/python3.13/site-packages/pygments/lexers/supercollider.py": 15306357945850389082, - "frontend/src/routes/storage/repos/+page.svelte": 3849368960648953479, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_insert.py": 6970975909565157982, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/compat.py": 9758194415584776667, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_iteration.py": 2118501258411211851, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv": 8710594949902856122, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dtype.py": 5553691086633215767, - "venv/lib/python3.13/site-packages/jose/jwt.py": 3405491994268385178, - "venv/lib/python3.13/site-packages/attrs/setters.py": 5775359015245600592, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_sparse.py": 14343335524508450058, - "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.cpython-313-x86_64-linux-gnu.so": 13917011878259810696, - "venv/lib/python3.13/site-packages/anyio/lowlevel.py": 11919467357746648592, - "venv/lib/python3.13/site-packages/anyio/_core/_subprocesses.py": 7271614043537119143, - "venv/lib/python3.13/site-packages/numpy/ma/__init__.py": 214772578978182427, - "venv/lib/python3.13/site-packages/authlib/oidc/core/models.py": 1370998944213578392, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_misc.pyi": 7544619194032232861, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90": 4990763135487995517, - "venv/lib/python3.13/site-packages/numpy/_core/_multiarray_tests.cpython-313-x86_64-linux-gnu.so": 442168371609469538, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_snap.py": 4515844385819802784, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_resolution.py": 9651416588266430520, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_csv.py": 571991535656576735, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_pytables_missing.py": 12154582133989896069, - "venv/lib/python3.13/site-packages/pandas/io/formats/style_render.py": 13586834368514801953, - "venv/lib/python3.13/site-packages/pygments/lexers/robotframework.py": 11507713622179102496, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_aix.h": 13316272821279308986, - "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_encs.py": 9703572751543253904, - "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/__init__.py": 6758781485387665020, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/config.py": 10707678943298497676, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/response.py": 15004896908941411698, - "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimelike.py": 394614958716301173, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/METADATA": 6596896092754256988, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/prompt.py": 9561640601516933380, - "venv/lib/python3.13/site-packages/pydantic/alias_generators.py": 5991580234179623842, - "venv/lib/python3.13/site-packages/attr/_next_gen.py": 16353246941851015420, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler_py.py": 16189204441438239231, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ma.py": 15912582628112164509, - "venv/lib/python3.13/site-packages/anyio/to_process.py": 16627578499791368365, - "venv/lib/python3.13/site-packages/websockets/frames.py": 4901850477414613953, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/rec.pyi": 9140655366667421698, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv": 12358602501260667480, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/memory.py": 9947113720821563254, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/__init__.py": 10920760520224795596, - "venv/lib/python3.13/site-packages/pandas/core/window/__init__.py": 15180240812077877933, - "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/WHEEL": 14929202952940710322, - "venv/lib/python3.13/site-packages/fastapi/_compat/v1.py": 9776181748061371513, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_re.py": 1296579393600719224, - "venv/lib/python3.13/site-packages/greenlet/TGreenlet.cpp": 4121171004360760212, - "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.py": 5260748170237305627, - "venv/lib/python3.13/site-packages/typing_inspection/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi": 13016654355866474644, - "venv/lib/python3.13/site-packages/_pytest/config/findpaths.py": 7867603756389940562, - "venv/lib/python3.13/site-packages/numpy/_core/printoptions.pyi": 16758392990920041462, - "venv/lib/python3.13/site-packages/pandas/compat/numpy/__init__.py": 1037113402100731082, - "venv/lib/python3.13/site-packages/pillow.libs/libtiff-295fd75c.so.6.2.0": 17866578820357536656, - "venv/lib/python3.13/site-packages/jaraco/context/__init__.py": 10975097417056278427, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/endpoint.py": 13389763148720370546, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/RECORD": 16342326945648353387, - "venv/lib/python3.13/site-packages/requests/packages.py": 7733041271118298220, - "venv/lib/python3.13/site-packages/numpy/_core/shape_base.pyi": 10225243791643474943, - "venv/lib/python3.13/site-packages/greenlet/TThreadStateCreator.hpp": 9887867766190459665, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_constructors.py": 2786493777737472376, - "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_to_xml.py": 8477770807916990981, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_block_internals.py": 17935662848672401507, - "frontend/src/lib/ui/Select.svelte": 11354509509920497811, - "frontend/src/routes/datasets/review/[id]/__tests__/dataset_review_workspace.ux.test.js": 4105775024258653726, - "frontend/build/_app/immutable/nodes/2.BU8wqGgg.js": 6294847122565605073, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_ordered.py": 13827016781743929164, - "venv/lib/python3.13/site-packages/pandas/tests/extension/list/array.py": 8065856342131357421, - "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.pyi": 9629457630163613604, - "venv/lib/python3.13/site-packages/packaging/__init__.py": 5479277484104486860, - "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.py": 7365943844063702766, - "frontend/build/_app/immutable/nodes/28.QOb2SnBY.js": 5137088104621923471, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/offsets.cpython-313-x86_64-linux-gnu.so": 6726636942028566415, - "venv/lib/python3.13/site-packages/pandas/api/executors/__init__.py": 16954693181142010028, - "venv/lib/python3.13/site-packages/pygments/lexers/berry.py": 4540479522141160472, - "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.pyi": 8607205990821121708, - "frontend/build/_app/immutable/entry/app.CvbxKUco.js": 16925898304891491045, - "venv/lib/python3.13/site-packages/cryptography/x509/base.py": 9124948989225782039, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_get.py": 10255752806860493777, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/base.py": 11386927749822539057, - "venv/lib/python3.13/site-packages/jeepney/io/tests/test_trio.py": 7459901627473962540, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers.py": 4940305787631493030, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/rethinkdb.py": 16413299263077970925, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/fields.py": 10090313990429695520, - "venv/lib/python3.13/site-packages/jsonschema/_typing.py": 13152346021901861822, - "venv/lib/python3.13/site-packages/pandas/io/excel/_openpyxl.py": 6676451564208867775, - "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/licenses/LICENSE": 13479831069780783137, - "venv/lib/python3.13/site-packages/pandas/_libs/properties.pyi": 9268470215750269699, - "venv/bin/fastapi": 12400009726251862770, - "backend/src/plugins/translate/service_inline_correction.py": 11066393548140180037, - "venv/lib/python3.13/site-packages/attr/_config.py": 1864824728504480204, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi": 10784666243744187693, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f": 13517753924061311074, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_scalar_compat.py": 10534925655070162459, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/RECORD": 18294169019244826301, - "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/fields.py": 8923326131649837922, - "venv/lib/python3.13/site-packages/pydantic/deprecated/class_validators.py": 2200511838255373813, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunc_config.pyi": 2005481648919369399, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/_internal/_internal_dataclass.py": 13206778611516171760, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/RECORD": 2024211292009381421, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_dtype.py": 12210524152630532747, - "venv/lib/python3.13/site-packages/pygments/lexers/c_like.py": 13004061780700827047, - "venv/lib/python3.13/site-packages/numpy/random/_sfc64.cpython-313-x86_64-linux-gnu.so": 17186695607612591922, - "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.py": 6205675182996213576, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.pyi": 2700568594438441246, - "venv/lib/python3.13/site-packages/pandas/core/computation/parsing.py": 3084943521520476999, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_astype.py": 7497268667246913350, - "venv/lib/python3.13/site-packages/httpx/_types.py": 12461152436147308761, - "frontend/e2e/fixtures/global-setup.js": 1597253740213759490, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.asm": 16630507336149184509, - "frontend/src/routes/settings/StorageSettings.svelte": 1953157077500445570, - "backend/src/api/routes/assistant/__init__.py": 14959302162073618175, - "frontend/src/lib/auth/store.ts": 14669655798912377598, - "backend/src/services/git/_url.py": 15729080796864187707, - "venv/lib/python3.13/site-packages/greenlet/greenlet.h": 16216120538647882082, - "venv/lib/python3.13/site-packages/PIL/_imagingmorph.cpython-313-x86_64-linux-gnu.so": 11171810899664471137, - "venv/lib/python3.13/site-packages/pyasn1/type/namedtype.py": 1859990775875190116, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_truncate.py": 6478126371906156409, - "venv/lib/python3.13/site-packages/jsonschema/_legacy_keywords.py": 16481666133229715822, - "backend/git_repos/remote/test-repo.git/objects/22/91d2eb86d77accf7401f8952778809cd1aa4d4": 5120428041118096941, - "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini": 16151597765994697599, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/np_datetime.cpython-313-x86_64-linux-gnu.so": 7840846965295537844, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/modules.py": 9023244176010175562, - "venv/lib/python3.13/site-packages/_pytest/main.py": 931018496411984909, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_data.py": 2397937327057341, - "venv/lib/python3.13/site-packages/authlib/jose/errors.py": 15231759002942436632, - "venv/lib/python3.13/site-packages/pandas/api/interchange/__init__.py": 181911269762882069, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_aggregate.py": 15038915958422670700, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/properties.py": 5799883762127872919, - "venv/lib/python3.13/site-packages/pygments/lexers/bdd.py": 5389493859905397060, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_two_greenlets.py": 11156275429806391390, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jws_algs.py": 11920621906391796226, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_numpy.py": 222383250675686477, - "venv/lib/python3.13/site-packages/ecdsa/der.py": 9374566189581725372, - "backend/tests/test_storage_audit_fixes.py": 13290928649795578073, - "venv/lib/python3.13/site-packages/numpy/_core/getlimits.py": 7842717073693731093, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_reductions.py": 14432782234851468060, - "venv/lib/python3.13/site-packages/authlib/jose/util.py": 14843923624043422219, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/authorization_server.py": 17967809814827547139, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/cryptography/utils.py": 18088508841978595788, - "venv/lib/python3.13/site-packages/numpy/_core/shape_base.py": 3996519099530770308, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/types.py": 12298292195929126306, - "venv/lib/python3.13/site-packages/pygments/styles/paraiso_dark.py": 3976779833379189837, - "venv/lib/python3.13/site-packages/urllib3/_version.py": 839747992523118887, - "venv/lib/python3.13/site-packages/pygments/lexers/_scheme_builtins.py": 5722444920479775453, - "venv/lib/python3.13/site-packages/pygments/scanner.py": 5640381644804445932, - "backend/src/plugins/translate/_batch_insert.py": 12482635271028646257, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_html.py": 12040484325988635032, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_timedeltas.py": 4118671843063545221, - "venv/lib/python3.13/site-packages/pillow.libs/liblzma-61b1002e.so.5.8.2": 11405063484938458842, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_extension.py": 4831602527247293866, - "venv/lib/python3.13/site-packages/passlib/handlers/fshp.py": 13298827601291507295, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_datetimes.py": 8863748366184419339, - "venv/lib/python3.13/site-packages/starlette/applications.py": 13591448461234020757, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator": 6616723520993329538, - "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.py": 2490579175967301457, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/package_data.py": 3078502124870585867, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py": 12264234876933578367, - "venv/lib/python3.13/site-packages/pip/_internal/network/lazy_wheel.py": 12936988990566680659, - "venv/lib/python3.13/site-packages/keyring/credentials.py": 14515496037842724455, - "frontend/build/_app/immutable/chunks/BSG9OZdS.js": 11840425241292690352, - "frontend/build/_app/immutable/chunks/Bqz-gzay.js": 1272988762853580208, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/__init__.py": 13331622784664204066, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/RECORD": 6518517239543344179, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/WHEEL": 13347410390513723930, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npz": 12369168483236619421, - "venv/lib/python3.13/site-packages/numpy/_core/_internal.py": 13056946834347643109, - "venv/lib/python3.13/site-packages/pandas/io/orc.py": 12754290195886557668, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/base.py": 14734745827490220667, - "venv/lib/python3.13/site-packages/pygments/lexers/ldap.py": 17455983150181177257, - "venv/lib/python3.13/site-packages/pygments/lexers/go.py": 11118104397271513417, - "backend/src/core/superset_client/_dashboards_crud.py": 8511586546743986158, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_read_fwf.py": 13684564756628524738, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/chararray.pyi": 9683985931409244216, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_kurt.py": 2898715045429898166, - "backend/src/plugins/translate/__tests__/test_dictionary_utils.py": 12007616543185225081, - "backend/src/plugins/translate/__tests__/test_inline_correction.py": 3644785257160613130, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval.py": 1228451182688768814, - "venv/lib/python3.13/site-packages/pandas/io/formats/_color_data.py": 15614976586613738953, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/dependency.py": 7300594038182867460, - "venv/lib/python3.13/site-packages/authlib/oidc/registration/__init__.py": 9448552677419908109, - "venv/lib/python3.13/site-packages/pip/_internal/req/req_file.py": 5180401483285462901, - "venv/lib/python3.13/site-packages/_pytest/runner.py": 5772610501857496741, - "venv/lib/python3.13/site-packages/pandas/core/methods/selectn.py": 13552176539021625776, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/METADATA": 1266134223155266488, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_xs.py": 1897144171324167738, - "venv/lib/python3.13/site-packages/pandas/tests/extension/conftest.py": 16886862391161243448, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_month.py": 14597470286884431085, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_datetime.py": 4179112383995346046, - "venv/lib/python3.13/site-packages/packaging/licenses/_spdx.py": 16440031845441362300, - "venv/lib/python3.13/site-packages/numpy/_typing/_char_codes.py": 14162745886150625150, - "frontend/src/components/DynamicForm.svelte": 12658559315809907844, - "venv/lib/python3.13/site-packages/numpy/py.typed": 15130871412783076140, - "backend/git_repos/remote/test-repo.git/hooks/sendemail-validate.sample": 8058833260784074657, - "backend/git_repos/remote/test-repo.git/objects/a1/3525f5f44e26d8fbec3226bd488d14793575a2": 3742572048019652365, - "venv/lib/python3.13/site-packages/_pytest/assertion/util.py": 16957445183087315124, - "frontend/src/lib/components/reports/ReportDetailPanel.svelte": 16014663571033060148, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_numpy.py": 9663734591667845940, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_pipe.py": 8255917221095334212, - "venv/lib/python3.13/site-packages/httpcore/_utils.py": 3255581092836273826, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.cpython-313-x86_64-linux-gnu.so": 12473903676666680134, - "venv/lib/python3.13/site-packages/starlette/datastructures.py": 12097180838087229563, - "venv/lib/python3.13/site-packages/pygments/lexers/praat.py": 54226477748516386, - "backend/src/core/superset_client/_datasets.py": 2090690091334332797, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hi77.f": 10617763407280454334, - "venv/lib/python3.13/site-packages/websockets/asyncio/connection.py": 17044409627448400723, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/fetch.py": 13937019222549208796, - "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/WHEEL": 8600534672961461758, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssltransport.py": 8148652555908329980, - "venv/lib/python3.13/site-packages/pandas/_libs/indexing.pyi": 90995502095752726, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop.py": 17940792593116540139, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/provision.py": 2676876852726658063, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/meson.build": 8784756284679859367, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_css.py": 17765129030290410902, - "venv/lib/python3.13/site-packages/pandas/core/computation/engines.py": 1889823242704769952, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_algs.py": 2479791018067637690, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_libgroupby.py": 9985769511561272200, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ma.pyi": 8186102816080813799, - "venv/lib/python3.13/site-packages/pandas/core/sparse/api.py": 9094651265692218821, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv": 13695545125848146013, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/models.py": 17356033861792227817, - "venv/lib/python3.13/site-packages/pandas/tests/strings/conftest.py": 12065119814157197510, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.cpython-313-x86_64-linux-gnu.so": 6011605826065363427, - "venv/lib/python3.13/site-packages/PIL/QoiImagePlugin.py": 17663704273100331654, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append.py": 13152738905565588661, - "venv/lib/python3.13/site-packages/PIL/XVThumbImagePlugin.py": 7472134175570205454, - "backend/src/core/utils/superset_context_extractor/_recovery.py": 4103343657420503831, - "backend/src/services/security_badge_service.py": 6269749758059921511, - "backend/git_repos/remote/test-repo.git/HEAD": 12394318939628232491, - "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.py": 9409852116555866847, - "venv/lib/python3.13/site-packages/secretstorage/defines.py": 9590959702075554048, - "venv/lib/python3.13/site-packages/pygments/lexers/tlb.py": 1169242051301155885, - "venv/lib/python3.13/site-packages/jeepney/wrappers.py": 15234251727654692435, - "venv/lib/python3.13/site-packages/requests/cookies.py": 4997226307650350876, - "venv/lib/python3.13/site-packages/numpy/typing/tests/test_typing.py": 10311989961588249147, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby.py": 16180421154734310873, - "venv/lib/python3.13/site-packages/pandas/api/internals.py": 5188134630996087511, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/ec_key.py": 5961540064444749833, - "venv/lib/python3.13/site-packages/numpy/random/__init__.pxd": 7355772669172093814, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/bazaar.py": 5630511062945201327, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/structs.py": 4479429145468072604, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/recfunctions.py": 18330899924171767482, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/conftest.py": 25473177671450048, - "frontend/src/routes/settings/__tests__/settings_page.integration.test.js": 8641041148256525929, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/twodim_base.pyi": 10156504423258357540, - "venv/lib/python3.13/site-packages/passlib/tests/test_apps.py": 10454136535890937237, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f": 13562390882286135024, - "backend/git_repos/remote/test-repo.git/objects/e9/1109abe29d5228675fecd6fc38a097147c090d": 15716642455993350072, - "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/unrolled.py": 12651425412640834530, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/evaluator.py": 6348022789899831255, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_halfyear.py": 9376272342364384767, - "venv/lib/python3.13/site-packages/pygments/lexers/teal.py": 10004159499175716139, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c": 17333399794446198412, - "venv/lib/python3.13/site-packages/numpy/_typing/_add_docstring.py": 14657346268890680694, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/token.py": 11655733747403312358, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_util.py": 6573034224727513309, - "venv/lib/python3.13/site-packages/pandas/tests/test_col.py": 14781555956509956371, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_at_time.py": 15352346149584081864, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunc_config.py": 14728417910466146460, - "venv/lib/python3.13/site-packages/pygments/lexers/dylan.py": 16246299896150112270, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_analytics.py": 4510712334676848202, - "venv/lib/python3.13/site-packages/pygments/lexers/srcinfo.py": 16466766917840327610, - "frontend/src/lib/api/translate/corrections.js": 3619404083693055292, - "venv/lib/python3.13/site-packages/pip/_internal/utils/glibc.py": 12335359492756627313, - "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.pyi": 5879290708972838025, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray.pyi": 14369009813591437391, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_numba.py": 203614377324678234, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.pyi": 14233146512272397376, - "venv/lib/python3.13/site-packages/pandas/core/computation/eval.py": 3176226283265954028, - "venv/lib/python3.13/site-packages/pip/_internal/network/auth.py": 6159841209618753296, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/device_code.py": 6712610002227849281, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/constrain.py": 6513876973118703677, - "venv/lib/python3.13/site-packages/urllib3/connectionpool.py": 7493427857878469165, - "venv/lib/python3.13/site-packages/click/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_subclass.py": 10949229764696473939, - "venv/lib/python3.13/site-packages/numpy/_array_api_info.py": 9709101823494959741, - "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/utils.py": 2959395751217827103, - "venv/lib/python3.13/site-packages/secretstorage/dhcrypto.py": 8860116996905452758, - "venv/lib/python3.13/site-packages/_pytest/assertion/truncate.py": 14000392306994773741, - "venv/lib/python3.13/site-packages/referencing/exceptions.py": 2535322334430110414, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_functions.py": 16376319335326812580, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pipe.py": 7400355977900310233, - "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_records.py": 12217508428903265797, - "frontend/build/_app/immutable/chunks/CjNbyeiE.js": 13814062364361575028, - "backend/src/services/reports/report_service.py": 17586405613867657190, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_melt.py": 15663807247682146566, - "scripts/build_offline_docker_bundle.sh": 9577721838839060974, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/jws.py": 7505219131537941130, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/util.py": 4815334059917765852, - "venv/lib/python3.13/site-packages/git/compat.py": 16843345645628515492, - "venv/lib/python3.13/site-packages/authlib/oidc/registration/claims.py": 4161520263207458028, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_clipboard.py": 12674078499544938252, - "backend/src/services/git/_sync.py": 14233419521256437438, - "venv/lib/python3.13/site-packages/pip/_internal/commands/completion.py": 4435231315212798769, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py": 18229054440703471493, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/timeout.py": 1807228452024740476, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npy": 9694707264403109829, - "venv/lib/python3.13/site-packages/rapidfuzz/utils.py": 5682627611354455144, - "frontend/src/routes/migration/__tests__/migration_dashboard.ux.test.js": 17118608261683412409, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/jwk.py": 6458001384702613165, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_formats.py": 12299393760307251036, - "venv/lib/python3.13/site-packages/PIL/ImageGrab.py": 11114379915762058868, - "frontend/src/components/tools/MapperTool.svelte": 5334953422209152843, - "frontend/src/routes/settings/+page.ts": 3719008513710037840, - "venv/lib/python3.13/site-packages/websockets/extensions/permessage_deflate.py": 12957105912018691390, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/METADATA": 12747626683405487434, - "venv/lib/python3.13/site-packages/pandas/io/formats/style.py": 13235403689320479165, - "backend/src/services/git/_merge.py": 3056385620903925104, - "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_cpp.cpython-313-x86_64-linux-gnu.so": 14187094676876471848, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex.py": 8772423071604000084, - "backend/tests/test_logger.py": 11506419828617508917, - "venv/lib/python3.13/site-packages/pygments/lexers/lisp.py": 11872331622183590758, - "venv/lib/python3.13/site-packages/greenlet/greenlet_exceptions.hpp": 8819301638282185623, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.py": 17993169044119596860, - "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/METADATA": 6960169108624303030, - "venv/lib/python3.13/site-packages/jeepney/bus_messages.py": 5871341372541525842, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_types.py": 651959450717569029, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpcre-9513aab5.so.1.2.0": 12298861477332583668, - "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/LICENSE": 8423899413955829149, - "venv/lib/python3.13/site-packages/greenlet/TThreadStateDestroy.cpp": 13749797532421836328, - "venv/lib/python3.13/site-packages/pip/_internal/index/sources.py": 11609272011565024668, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi": 16042272072158438261, - "venv/lib/python3.13/site-packages/numpy/lib/scimath.py": 7616377937400918724, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/aead.py": 8740476942925346444, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/dtype.pyi": 465999539608816848, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/strings.pyi": 402863478592154500, - "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.pyi": 10077265709692546934, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_numpyconfig.h": 18150055639397773687, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_setitem.py": 15731267129055947469, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/validator_creation.py": 2745563768861102999, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_lexsort.py": 10394832796613968484, - "venv/lib/python3.13/site-packages/passlib/handlers/mysql.py": 11165762635383041460, - "venv/lib/python3.13/site-packages/anyio/_core/_fileio.py": 4507100568401692983, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_count.py": 16947194157984708529, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_insert.py": 17383986803728810587, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_box_unbox.py": 7579587620530953711, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_array.py": 11271807719833350332, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_reflection.py": 10520778598547003532, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/query.py": 3867868366067025348, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/__init__.py": 10357835306532281617, - "venv/lib/python3.13/site-packages/pygments/styles/monokai.py": 12381683616720952636, - "venv/lib/python3.13/site-packages/pygments/lexers/pawn.py": 18127303119414402594, - "venv/lib/python3.13/site-packages/psycopg2/extras.py": 7510107741729866600, - "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/__init__.py": 1923528231486706442, - "venv/lib/python3.13/site-packages/pygments/lexers/_tsql_builtins.py": 829193091321611630, - "backend/src/core/task_manager/graph.py": 1566662881946484762, - "venv/lib/python3.13/site-packages/pygments/lexers/fortran.py": 6859638690245583968, - "backend/src/services/__tests__/test_llm_plugin_persistence.py": 16769242892960874042, - "backend/git_repos/remote/test-repo.git/objects/4e/227f4d8289ea657ae813b1460f979ae4b676b3": 5659284628452785331, - "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe.py": 16525846817331842080, - "venv/lib/python3.13/site-packages/requests/models.py": 9104898985870652256, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/__init__.py": 15130871412783076140, - "frontend/build/_app/immutable/nodes/15.D9krAkIH.js": 4821898373396948445, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/base.py": 5294446834530589760, - "venv/lib/python3.13/site-packages/fastapi/responses.py": 6092572095549573593, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_tools.py": 13994164937603424236, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/_typing.py": 10524021526716767489, - "frontend/src/lib/components/translate/__tests__/test_bulk_replace_modal.svelte.js": 6802604718120565742, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_exceptions.py": 15290185665769490169, - "backend/src/schemas/dataset_review_pkg/_dtos.py": 13301885458265748263, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_count.py": 9186538441380080087, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/factory.py": 3042005457138956499, - "venv/lib/python3.13/site-packages/jeepney/auth.py": 10565040329507087892, - "venv/lib/python3.13/site-packages/pip/_internal/utils/misc.py": 17461379236189029253, - "backend/tests/services/clean_release/test_policy_resolution_service.py": 3471271299977247598, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/__init__.py": 11526998905763262175, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_datetimeindex.py": 14816894350435545024, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_setops.py": 15196593522537569500, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_format.py": 5231304674283854194, - "venv/lib/python3.13/site-packages/pandas/util/_test_decorators.py": 17930801441803090445, - "venv/lib/python3.13/site-packages/pandas/io/json/_table_schema.py": 3103776773020058805, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polynomial.py": 777287409151500309, - "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py": 5995058808539530576, - "frontend/src/routes/+layout.ts": 8392799000856778740, - "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/licenses/LICENSE": 14524289631770661180, - "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.py": 16859854811012717088, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_series_equal.py": 1223890028205011021, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_nat.py": 7400568652984772972, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_rewrite_warning.py": 4895919872954538758, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_map.py": 10769974470610467636, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/METADATA": 11419135077900073883, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval_pyarrow.py": 3849382723890414899, - "venv/lib/python3.13/site-packages/pip/_internal/distributions/installed.py": 18153165899841229597, - "venv/lib/python3.13/site-packages/starlette/_exception_handler.py": 9892172656847200124, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/plugin.py": 18006138132596504101, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_replace.py": 18039668944453454689, - "venv/lib/python3.13/site-packages/starlette/responses.py": 14081178833432955042, - "venv/lib/python3.13/site-packages/requests/adapters.py": 17161109043243436200, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_api.py": 5287018911951723034, - "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.py": 12251264586530536622, - "venv/lib/python3.13/site-packages/pygments/lexers/_mql_builtins.py": 2376212048709413586, - "venv/lib/python3.13/site-packages/pandas/_libs/groupby.cpython-313-x86_64-linux-gnu.so": 14931394220112658268, - "backend/src/schemas/profile.py": 7950698901810733002, - "venv/lib/python3.13/site-packages/numpy/core/_dtype.py": 2806449741844148191, - "venv/lib/python3.13/site-packages/PIL/BdfFontFile.py": 10811640174253687845, - "backend/src/models/dataset_review_pkg/_enums.py": 2243691494729792539, - "backend/tests/services/dataset_review/test_superset_matrix.py": 5114797134613078913, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/type_check.pyi": 9177256991985898824, - "backend/src/services/dataset_review/__init__.py": 15781509495698823404, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90": 5799106109999071412, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/__init__.py": 8632038387100622009, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_frame.py": 2169381747938271444, - "backend/src/services/reports/__tests__/test_report_service.py": 7145268223824508607, - "venv/lib/python3.13/site-packages/numpy/random/_mt19937.pyi": 15904463104068500379, - "venv/lib/python3.13/site-packages/pygments/lexers/theorem.py": 15666523910367201285, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/request.py": 17642741955458391050, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli/py.typed": 9796674040111366709, - "backend/src/api/routes/git/_router.py": 8701683910668868827, - "frontend/src/lib/components/layout/__tests__/sidebarNavigation.test.js": 8459006438402290167, - "venv/lib/python3.13/site-packages/pandas/core/groupby/categorical.py": 16588862198627920420, - "venv/lib/python3.13/site-packages/pandas/io/parsers/base_parser.py": 15148258424429418380, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_repr.py": 5577699046802107144, - "venv/lib/python3.13/site-packages/pygments/formatters/bbcode.py": 8614391937525677922, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/recarray_from_file.fits": 15116318600514274152, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_interp_fillna.py": 5530041283991655415, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/util.py": 9373891872370603585, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/named_types.py": 6099185243355915896, - "venv/lib/python3.13/site-packages/jsonschema/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/greenlet/tests/test_extension_interface.py": 11693583111513457974, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/flatiter.pyi": 9598576095384661517, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/common.py": 16314033415206173235, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/conftest.py": 8406022190801970256, - "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/exc.py": 1448374203226983757, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/index.py": 15694995431926521471, - "venv/lib/python3.13/site-packages/pygments/lexers/modula2.py": 6575895980250662093, - "frontend/src/lib/components/ui/MultiSelect.svelte": 1475503303018683038, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_astype.py": 15384141282611151560, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/containers.py": 5969831151685016772, - "venv/lib/python3.13/site-packages/pluggy/_tracing.py": 7276210024011809655, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated": 11193150813314469394, - "venv/lib/python3.13/site-packages/apscheduler/triggers/base.py": 1170652622104554892, - "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraypad.pyi": 12178766981280242620, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv": 6674536825156196036, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timestamps.cpython-313-x86_64-linux-gnu.so": 13209491675968970365, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_ops.py": 16346030307660048773, - "venv/lib/python3.13/site-packages/pandas/_libs/json.cpython-313-x86_64-linux-gnu.so": 2436285663630821963, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_unicode_ddl.py": 2569618488804767890, - "venv/lib/python3.13/site-packages/pygments/styles/trac.py": 13968346768164381833, - "frontend/src/services/storageService.js": 14408290095426695791, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_openid.py": 5670082466989878756, - "venv/bin/activate.fish": 5275961582873298085, - "venv/lib/python3.13/site-packages/pygments/lexers/floscript.py": 944042220740663491, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/__init__.py": 237070345717942041, - "venv/lib/python3.13/site-packages/secretstorage/py.typed": 15130871412783076140, - "backend/src/plugins/translate/service_utils.py": 15103456860964805370, - "venv/lib/python3.13/site-packages/_pytest/_code/source.py": 9488112979192923739, - "venv/lib/python3.13/site-packages/numpy/_core/defchararray.py": 15550230459945996915, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arraymethod.py": 14421188237635557797, - "frontend/svelte.config.js": 8473636210766821560, - "venv/lib/python3.13/site-packages/ecdsa/test_der.py": 7117444285097824495, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/__init__.py": 12849371269359608058, - "backend/git_repos/remote/test-repo.git/objects/d5/0298a42699f39e4601c0aa23eab07bcb0703c7": 1966124163198751340, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py": 2609365889369107154, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_fillna.py": 7244491410004453166, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_item.py": 17619314877770917080, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_duplicated.py": 14676058112867601208, - "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.pyi": 14181518821845356636, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/baked.py": 6911138208603240867, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hashes.py": 8545380307201732345, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/LICENSE": 4672913476475760762, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_hour.py": 14128508606361694814, - "venv/lib/python3.13/site-packages/more_itertools/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/click/_termui_impl.py": 3296085065310341855, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/__version__.py": 14138134075118474134, - "venv/lib/python3.13/site-packages/httpcore/_sync/__init__.py": 7676937747094511752, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/integration.py": 12670848015915724967, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/__init__.py": 96341051676048910, - "venv/lib/python3.13/site-packages/pillow.libs/libwebpmux-7f11e5ce.so.3.1.2": 13105940093474848953, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_na_indexing.py": 8712547126522523899, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/expression.py": 15511250785671695359, - "venv/lib/python3.13/site-packages/pygments/styles/material.py": 14325514369696961874, - "venv/lib/python3.13/site-packages/pygments/lexers/_googlesql_builtins.py": 12251289884604745945, - "venv/lib/python3.13/site-packages/numpy/dtypes.py": 14128421398870718692, - "venv/lib/python3.13/site-packages/pygments/styles/paraiso_light.py": 15941591873059208999, - "venv/lib/python3.13/site-packages/pygments/styles/autumn.py": 8750937312198920971, - "backend/src/services/clean_release/stages/no_external_endpoints.py": 11899278509901673808, - "venv/lib/python3.13/site-packages/pluggy/_version.py": 7195758686717994475, - "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet_trash.py": 6191655521667576604, - "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/_core/__init__.pyi": 2783897020308040960, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py": 4383854709657749855, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_drop_duplicates.py": 12601598844977346213, - "backend/src/api/routes/dataset_review_pkg/_routes.py": 11040245149296528009, - "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.py": 11393954913234866059, - "venv/lib/python3.13/site-packages/sqlalchemy/event/api.py": 987321343916500337, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/provision.py": 8707620698060818654, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_equals.py": 6429101196875333574, - "venv/lib/python3.13/site-packages/requests/__version__.py": 6677532709758546816, - "venv/lib/python3.13/site-packages/PIL/WmfImagePlugin.py": 15685062825106444247, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_values.py": 834951665649981397, - "venv/lib/python3.13/site-packages/cryptography/__init__.py": 641702726372647770, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_constructors.py": 9478848417896027917, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pymysql.py": 12923876736367229454, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/WHEEL": 16784970174376303810, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/starlette/__init__.py": 3252794766897205870, - "venv/lib/python3.13/site-packages/referencing/tests/test_exceptions.py": 10846225989746274213, - "venv/lib/python3.13/site-packages/greenlet/tests/test_cpp.py": 10982107081267457286, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_logical.py": 6242457515917145500, - "venv/lib/python3.13/site-packages/_pytest/config/argparsing.py": 11156052029258891503, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/gh19161.f90": 7691871466158049079, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename_axis.py": 13193478481758930128, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resampler_grouper.py": 8388490036390951341, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_os.h": 7883047506449405400, - "venv/lib/python3.13/site-packages/pandas/tests/io/conftest.py": 5864037534050136837, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rank.py": 5817408252050193538, - "venv/lib/python3.13/site-packages/anyio/streams/file.py": 15232345967545920863, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.pyf": 4660465266594480405, - "venv/lib/python3.13/site-packages/pandas/io/json/__init__.py": 12333505155070172626, - "venv/lib/python3.13/site-packages/pygments/formatters/_mapping.py": 13335227913146542481, - "backend/src/core/task_manager/__tests__/test_task_logger.py": 1651218524520477084, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_datetime.py": 7862725028865965163, - "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/METADATA": 732041908491732594, - "venv/lib/python3.13/site-packages/uvicorn/protocols/http/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/dotenv/parser.py": 17651523026132242005, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_dtypes.py": 6831042272921908068, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/multiarray.pyi": 17232959648651278910, - "venv/lib/python3.13/site-packages/pygments/lexers/verifpal.py": 9190813166686923928, - "venv/lib/python3.13/site-packages/PIL/XbmImagePlugin.py": 12256750478268246137, - "venv/lib/python3.13/site-packages/fastapi/_compat/main.py": 13016492818231995760, - "backend/src/api/routes/__tests__/test_reports_api.py": 8830242634438523357, - "backend/src/plugins/translate/__tests__/test_executor.py": 17557965511167209685, - "backend/tests/core/migration/test_dry_run_orchestrator.py": 5158126098685923841, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/key_set.py": 8485970749081951741, - "build.sh": 14606128418937696284, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_missing.py": 6224750552277937853, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_constructors.py": 13890224577680389718, - "venv/lib/python3.13/site-packages/pygments/lexers/ncl.py": 14838368780033177943, - "venv/lib/python3.13/site-packages/PIL/IptcImagePlugin.py": 14329453455296600824, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_format.py": 16150524965028369071, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/attr/setters.pyi": 6670509359139243236, - "venv/lib/python3.13/site-packages/greenlet/tests/test_generator.py": 14156412320760444199, - "venv/lib/python3.13/site-packages/pip/_internal/commands/debug.py": 13528633965821062950, - "venv/lib/python3.13/site-packages/anyio/streams/buffered.py": 8916188172110578587, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/scalars.pyi": 3130685119595923378, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.pyf": 1361426175133186231, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.pyi": 13083543811193933305, - "venv/lib/python3.13/site-packages/pip/_internal/index/package_finder.py": 12631116673181479779, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarrayobject.h": 7320510589635636690, - "venv/lib/python3.13/site-packages/numpy/_core/function_base.pyi": 8343632640078378312, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_clip.py": 13498704233745189154, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval.py": 18040371224712437126, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/palette.py": 17383863392192572184, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_base.py": 8678387511873412922, - "venv/lib/python3.13/site-packages/urllib3/filepost.py": 3814725067598042920, - "venv/lib/python3.13/site-packages/_pytest/_io/wcwidth.py": 13515196388826152383, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_sample.py": 4641567828238191927, - "venv/lib/python3.13/site-packages/pygments/lexers/forth.py": 17623561228839319663, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937.py": 7299586490442539723, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/types.py": 16795741817129898714, - "venv/lib/python3.13/site-packages/gitdb/test/test_util.py": 541144638852210407, - "venv/lib/python3.13/site-packages/uvicorn/_types.py": 3339389597716220585, - "frontend/src/lib/components/translate/TranslationRunProgress.svelte": 18041933754930100165, - "frontend/src/routes/datasets/review/[id]/+page.svelte": 3248469759382215571, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/__init__.py": 9106887608906281686, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_compat.py": 6032546839876195115, - "backend/src/api/routes/translate/_correction_routes.py": 12437040676784563126, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/pyproject.py": 12684373765476932108, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_accuracy.py": 3904008607472505376, - "backend/src/plugins/translate/_text_cleaner.py": 13161219043687449729, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/introspection.py": 5447179017910128771, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numeric.py": 14451517189908259173, - "frontend/src/lib/ui/PageHeader.svelte": 3800784212388586861, - "venv/lib/python3.13/site-packages/pyasn1/type/char.py": 16518487114777185541, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_groupby.py": 2738671407653333726, - "venv/lib/python3.13/site-packages/greenlet/tests/test_weakref.py": 6780204527427742510, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/__init__.py": 17454177076687312424, - "venv/lib/python3.13/site-packages/fastapi/_compat/model_field.py": 392699021682253569, - "venv/lib/python3.13/site-packages/greenlet/TBrokenGreenlet.cpp": 10822436772777706192, - "venv/lib/python3.13/site-packages/pandas/core/arrays/_arrow_string_mixins.py": 16862663427780315543, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_excel.py": 5467043641314706635, - "frontend/build/_app/immutable/entry/start.DDuW0Ahn.js": 18063630425247458311, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/util.py": 2176177435997659667, - "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_generation_shared.py": 23345689300073549, - "venv/lib/python3.13/site-packages/pandas/core/ops/common.py": 17314999825118928100, - "backend/src/schemas/dataset_review_pkg/_composites.py": 1898056130177244572, - "venv/lib/python3.13/site-packages/pip/_internal/utils/deprecation.py": 7435269308988385470, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_regression.py": 4611768764484593979, - "venv/lib/python3.13/site-packages/pandas/_libs/ops_dispatch.cpython-313-x86_64-linux-gnu.so": 5284769758475394095, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timedeltas.py": 1175883320586860493, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_join.py": 4213933887062089605, - "venv/lib/python3.13/site-packages/uvicorn/__init__.py": 11517239807926185665, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/base.py": 7110726987481713080, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py": 16768579082462294745, - "venv/lib/python3.13/site-packages/sqlalchemy/util/_collections.py": 7772437080414835462, - "venv/lib/python3.13/site-packages/pygments/lexers/_cl_builtins.py": 16540712925368297957, - "venv/lib/python3.13/site-packages/websockets/asyncio/router.py": 15039562376314233669, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_pickle.py": 2910383574326146698, - "venv/lib/python3.13/site-packages/urllib3/contrib/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/setup.py": 5482352991573617756, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/char.f90": 12203871998988759364, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.cpython-313-x86_64-linux-gnu.so": 13104135217735363438, - "venv/lib/python3.13/site-packages/pydantic_settings/__init__.py": 4374954204580208673, - "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/RECORD": 963865046004908868, - "venv/lib/python3.13/site-packages/PIL/Image.py": 13615925856053031482, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/claims.py": 12645788445743898136, - "venv/lib/python3.13/site-packages/pandas/tests/window/conftest.py": 10673264126684571493, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_datetime_index.py": 15448494560143263150, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_dt_accessor.py": 2229616362327032253, - "frontend/src/routes/+layout.svelte": 2748734957389681795, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi": 11455144434558323236, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/columns.py": 8488246354818721406, - "venv/lib/python3.13/site-packages/authlib/oauth2/__init__.py": 13682931764896414722, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/segment.py": 2555584120510872966, - "venv/lib/python3.13/site-packages/_pytest/pytester.py": 5423287282155948827, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/linalg.pyi": 269481015135399748, - "venv/lib/python3.13/site-packages/numpy/_configtool.pyi": 9670892208858157218, - "venv/lib/python3.13/site-packages/pandas/_libs/interval.pyi": 15698173755300703836, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_interaction.py": 12216477658994324787, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape_base.pyi": 5046405609030418900, - "venv/lib/python3.13/site-packages/pandas/api/typing/aliases.py": 11194270368147942988, - "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.py": 11397521081216402594, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_parse_dates.py": 5344929031479212951, - "venv/lib/python3.13/site-packages/pip/_internal/models/target_python.py": 422323125651848065, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv": 8929553891827331780, - "venv/lib/python3.13/site-packages/pydantic_core/__init__.py": 10563134104783445328, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/mypy.ini": 4763385838822685881, - "venv/lib/python3.13/site-packages/PIL/PaletteFile.py": 4104323659569809769, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_riscv_unix.h": 8607317131295864391, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/cookies.py": 4997226307650350876, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/spinner.py": 5564789578696016201, - "venv/lib/python3.13/site-packages/gitdb/exc.py": 13975852664048821278, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_factorize.py": 861897342553280506, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py": 8530403239168529668, - "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/RECORD": 1556051687830913019, - "venv/lib/python3.13/site-packages/numpy/_core/_rational_tests.cpython-313-x86_64-linux-gnu.so": 13475521165331256711, - "venv/lib/python3.13/site-packages/numpy/f2py/__main__.py": 12567751646090102167, - "venv/lib/python3.13/site-packages/click/termui.py": 7022374827798605437, - "venv/lib/python3.13/site-packages/pip/_internal/exceptions.py": 2252826732781519645, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/comparisons.py": 7327629888601690759, - "venv/lib/python3.13/site-packages/pygments/lexers/textedit.py": 14872291021083255414, - "venv/lib/python3.13/site-packages/pygments/lexers/compiled.py": 8215290039991205531, - "venv/lib/python3.13/site-packages/pandas/io/parsers/c_parser_wrapper.py": 5841064965672872661, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_classes.py": 1440926036579216168, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_multiarray.py": 3592197154340095431, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_repeat.py": 11360772447747837958, - "venv/lib/python3.13/site-packages/pygments/lexers/xorg.py": 14591144191879110061, - "venv/lib/python3.13/site-packages/pip/_internal/utils/appdirs.py": 539688259643447487, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/strings.pyi": 15361498560917514616, - "venv/lib/python3.13/site-packages/passlib/utils/binary.py": 13123975436674239306, - "frontend/build/_app/immutable/nodes/6.PYYYnfkZ.js": 4978533201542652494, - "backend/src/core/superset_client/_charts.py": 8811593556038212857, - "venv/lib/python3.13/site-packages/pydantic/dataclasses.py": 12384956801113860889, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_resolution.py": 6076761538303762297, - "venv/lib/python3.13/site-packages/click/shell_completion.py": 5858110451169927373, - "venv/lib/python3.13/site-packages/numpy/core/defchararray.py": 11371045148957547088, - "venv/lib/python3.13/site-packages/ecdsa/test_jacobi.py": 1249543655136186433, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_indexing.py": 4334578480714520407, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parse_iso8601.py": 9100947620267156161, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nbit_base_example.pyi": 8571452382806614924, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_accessor.py": 10074496835594855786, - "frontend/build/_app/immutable/chunks/BV5UmENj.js": 192787178839312155, - "backend/src/services/clean_release/repositories/candidate_repository.py": 14784344453820731941, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_printing.py": 1901396869745313303, - "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pyi": 15790738442952696034, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_cte.py": 9274103293201050794, - "venv/lib/python3.13/site-packages/pygments/lexers/_lua_builtins.py": 12653747099659257203, - "venv/lib/python3.13/site-packages/jeepney/io/tests/test_threading.py": 6656552495241857519, - "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.pyi": 15067467792538416274, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/base_key.py": 10402800587070352851, - "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/client_mixin.py": 17980753662107479779, - "venv/lib/python3.13/site-packages/pandas/core/internals/ops.py": 4740509262379451243, - "backend/src/plugins/llm_analysis/__tests__/test_client_headers.py": 5527172390260032966, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_typing.py": 17589387690638097975, - "venv/lib/python3.13/site-packages/git/refs/head.py": 16271128287606894569, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_category.py": 3944898528119364040, - "venv/lib/python3.13/site-packages/pygments/lexers/verification.py": 16645885125604874183, - "backend/src/api/routes/__init__.py": 7861712296282676167, - "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.cpython-313-x86_64-linux-gnu.so": 17856848989827220388, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_argon2.py": 11345706437113628133, - "venv/lib/python3.13/site-packages/pygments/styles/pastie.py": 15784474766258831882, - "venv/lib/python3.13/site-packages/_pytest/config/__init__.py": 12787579251203510616, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/jupyter.py": 4446535289156468239, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_util.py": 13997184496924925110, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_compression.py": 8061288329598682752, - "venv/lib/python3.13/site-packages/git/repo/fun.py": 9019364012746153312, - "venv/lib/python3.13/site-packages/fastapi/types.py": 3867821246650502267, - "frontend/src/lib/Counter.svelte": 4002153662176313030, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_select.py": 7083040959665006634, - "venv/lib/python3.13/site-packages/pandas/io/formats/console.py": 10370334487585281127, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/types.py": 356973910046950951, - "venv/lib/python3.13/site-packages/pandas/core/internals/concat.py": 12151675567885981464, - "venv/lib/python3.13/site-packages/authlib/__init__.py": 8957417237987377675, - "venv/lib/python3.13/site-packages/apscheduler/triggers/calendarinterval.py": 12481650996882675949, - "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/__init__.py": 15991623390785635773, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.cpython-313-x86_64-linux-gnu.so": 16927263232848238698, - "frontend/build/_app/immutable/chunks/Dcj7gy5B.js": 15455424043173091479, - "venv/lib/python3.13/site-packages/pygments/lexers/jvm.py": 897669925284011089, - "venv/lib/python3.13/site-packages/pydantic_core/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py": 18069619555394133945, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv": 10950201682596097452, - "backend/src/api/routes/__tests__/test_datasets.py": 12111592699382758436, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_add_prefix_suffix.py": 4815518357936092237, - "venv/lib/python3.13/site-packages/git/refs/remote.py": 4391983355222612205, - "venv/lib/python3.13/site-packages/passlib/handlers/pbkdf2.py": 16686685453577026643, - "venv/lib/python3.13/site-packages/pip/_vendor/typing_extensions.py": 10158933506062403688, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/cells.py": 8299309127027168194, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_sparc_sun_gcc.h": 2915128971664712180, - "backend/git_repos/remote/test-repo.git/objects/00/fcf77cecdf261aef91eda792ab3384a3339922": 1527330822006618217, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_index.py": 1551768441102117466, - "backend/src/api/routes/__tests__/test_connections_routes.py": 1035231993594112504, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_datetime.py": 1678885152993000592, - "frontend/build/favicon.png": 16740551781088792605, - "backend/src/api/routes/assistant/_resolvers.py": 6365921685100086434, - "frontend/src/lib/toasts.js": 199299975383904134, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/__init__.py": 16532856661318424631, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_complex.py": 11732242536199439023, - "venv/lib/python3.13/site-packages/fastapi/staticfiles.py": 4094330072433302614, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename.py": 16148017223289654683, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_from_scalar.py": 16520136036631155842, - "backend/git_repos/remote/test-repo.git/hooks/pre-rebase.sample": 15693225890270078290, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_astype.py": 4023134352880775277, - "backend/src/services/dataset_review/event_logger.py": 8083530196989488371, - "backend/git_repos/remote/test-repo.git/objects/52/ec4a78c629329b8b572ec9d5205271c111baac": 18054296544295201561, - "venv/lib/python3.13/site-packages/pandas/core/methods/to_dict.py": 4653628436393663485, - "venv/lib/python3.13/site-packages/pydantic/main.py": 14086938579850319884, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/WHEEL": 7414522633964952515, - "backend/src/core/auth/oauth.py": 9925908783612235042, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/challenge.py": 6388445104761482746, - "venv/lib/python3.13/site-packages/pandas/io/formats/html.py": 11849941990375030601, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_timestamp.py": 12253372102602993034, - "venv/lib/python3.13/site-packages/pygments/lexers/special.py": 4972294202790455038, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/__init__.py": 11121941644106061453, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/gitdb/utils/encoding.py": 1668793658272579497, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_get_dummies.py": 16112674981222844375, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90": 12508663906609241323, - "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/RECORD": 17341460504914308184, - "backend/src/api/routes/assistant/_command_parser.py": 2745692387994130159, - "venv/lib/python3.13/site-packages/anyio/_core/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/iniconfig/__init__.py": 12623265899068631092, - "venv/lib/python3.13/site-packages/authlib/oidc/core/util.py": 5364455058429522633, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_msvc.h": 2465089365642299646, - "venv/lib/python3.13/site-packages/pip/_internal/models/pylock.py": 16697828625021519459, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/smmap/util.py": 13276170835044840023, - "venv/lib/python3.13/site-packages/jsonschema/tests/typing/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nlargest_nsmallest.py": 11049656379959696695, - "venv/lib/python3.13/site-packages/git/objects/submodule/__init__.py": 12958523219496107878, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/numerictypes.pyi": 15565573472138344755, - "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini": 1071371630695963467, - "venv/lib/python3.13/site-packages/pandas/tests/internals/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authorization_server.py": 13696038495666024258, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/__init__.py": 6654484356035994666, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_period.py": 6047041810867211174, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/index_tricks.pyi": 11463747060334597941, - "frontend/build/_app/immutable/nodes/1.B8nCIAvJ.js": 2236375157633244640, - "backend/git_repos/remote/test-repo.git/objects/99/38d17c3f4199e53e4d4ebc253fe9c840caa505": 8414792171590415839, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_longtable.tpl": 12723621983797415444, - "venv/lib/python3.13/site-packages/httpx/_transports/asgi.py": 12335675489870745729, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_value_counts.py": 9352540710376306520, - "venv/lib/python3.13/site-packages/pyasn1/type/tag.py": 13912273274509186651, - "venv/lib/python3.13/site-packages/pygments/lexers/sql.py": 15566262873151658034, - "venv/lib/python3.13/site-packages/pygments/lexers/smv.py": 8253688483040957894, - "venv/lib/python3.13/site-packages/requests/structures.py": 2668010839316715865, - "backend/src/api/routes/git/_helpers.py": 3960455954241740267, - "venv/lib/python3.13/site-packages/more_itertools/more.pyi": 4844596605492825806, - "venv/lib/python3.13/site-packages/pygments/lexers/data.py": 9365024327689738663, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_year.py": 17441853503700184299, - "frontend/src/lib/api/translate/target-schema.js": 10665479411127476571, - "venv/lib/python3.13/site-packages/typing_inspection/introspection.py": 13916695705179237047, - "venv/lib/python3.13/site-packages/websockets/http11.py": 11022534176398053082, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_index.py": 14187428934500390688, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/highway/LICENSE": 15636145745140922094, - "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_impl.py": 12056958946481531279, - "backend/src/plugins/search.py": 888817404897740233, - "venv/lib/python3.13/site-packages/pillow.libs/libsharpyuv-95d8a097.so.0.1.2": 5320647379976541240, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_indexing.py": 7181087459615188551, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_isoc.py": 4923640657296076239, - "venv/lib/python3.13/site-packages/pandas/tests/io/xml/__init__.py": 15130871412783076140, - "frontend/src/services/adminService.js": 6375990585512014277, - "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.py": 1809069379864985298, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE": 4123064337800029995, - "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.pyi": 4729765666018003634, - "venv/lib/python3.13/site-packages/git/refs/log.py": 5175801243332619268, - "venv/lib/python3.13/site-packages/pygments/lexers/_mysql_builtins.py": 16087227298679432006, - "venv/lib/python3.13/site-packages/pandas/core/nanops.py": 18291534943985310005, - "backend/src/api/routes/translate/_dictionary_routes.py": 5480137091791704976, - "venv/lib/python3.13/site-packages/pygments/lexers/_sql_builtins.py": 5906655440517434734, - "venv/lib/python3.13/site-packages/pandas/core/ops/docstrings.py": 3721650738518391256, - "venv/lib/python3.13/site-packages/pycparser/ply/__init__.py": 5040371336745852622, - "venv/lib/python3.13/site-packages/numpy/dtypes.pyi": 6713822658171717369, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/__init__.py": 9820770319106921495, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/base_server.py": 9643197259080504542, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/AUTHORS": 2987771679926243782, - "venv/lib/python3.13/site-packages/pydantic_core/core_schema.py": 8106298745123589494, - "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/__init__.py": 16416360448593978041, - "venv/lib/python3.13/site-packages/itsdangerous/exc.py": 11181421963755661477, - "venv/lib/python3.13/site-packages/_pytest/stash.py": 14430252294763173610, - "venv/lib/python3.13/site-packages/pygments/styles/sas.py": 12363791134941577382, - "venv/lib/python3.13/site-packages/pygments/lexers/tnt.py": 4657130609241407766, - "venv/lib/python3.13/site-packages/passlib/handlers/windows.py": 8969739861295277439, - "venv/lib/python3.13/site-packages/httpx/_transports/mock.py": 13564349939188292363, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/__init__.py": 2635182244050911910, - "venv/lib/python3.13/site-packages/numpy/fft/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/errors/cow.py": 14381282473643980776, - "backend/tests/core/migration/test_archive_parser.py": 1909788158234142574, - "venv/lib/python3.13/site-packages/websockets/imports.py": 1995356703044158461, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/constants.pyi": 15633065380510755171, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi": 4376871621615688626, - "venv/lib/python3.13/site-packages/PIL/ImageMode.py": 2361901066832921091, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_quantile.py": 11273403743157110261, - "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/WHEEL": 12054782055241301457, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/pager.py": 18072372651585577904, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.pyi": 15767546107856827543, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_stack.py": 5316826578695144945, - "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/array.py": 3517673819082574078, - "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/RECORD": 11604408378998955169, - "venv/lib/python3.13/site-packages/rapidfuzz/__init__.py": 12462153783886855740, - "venv/lib/python3.13/site-packages/numpy/lib/introspect.pyi": 12239924839764265507, - "venv/lib/python3.13/site-packages/pandas/core/api.py": 3390809109543982410, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_matmul.py": 16169282225324014901, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/aiomysql.py": 12999962380333482189, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ext.py": 8361831054662096695, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py": 9559295461619813890, - "venv/lib/python3.13/site-packages/dateutil/zoneinfo/rebuild.py": 1813298167468704155, - "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/RECORD": 6349071557579241461, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_infer_objects.py": 6769980076977692890, - "venv/lib/python3.13/site-packages/pandas/core/util/numba_.py": 3535857372998653863, - "venv/lib/python3.13/site-packages/greenlet/TGreenlet.hpp": 6993553444981671786, - "venv/lib/python3.13/site-packages/pygments/lexers/_vbscript_builtins.py": 9882134558469491349, - "frontend/src/routes/settings/notifications/+page.svelte": 14504217413720856827, - "venv/lib/python3.13/site-packages/PIL/_imagingmath.cpython-313-x86_64-linux-gnu.so": 77725273398858074, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log2.csv": 13979868713429167140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_common.py": 3559416690270529904, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_year.py": 1478857009124807836, - "venv/lib/python3.13/site-packages/uvicorn/protocols/http/flow_control.py": 4822804840057360506, - "frontend/src/services/connectionService.js": 16613277497380191542, - "venv/lib/python3.13/site-packages/pygments/lexers/nit.py": 18262907536841158657, - "frontend/build/_app/env.js": 8815854342083926790, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_map.py": 4761668276463940924, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_factorize.py": 5585211699185937865, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_normalize.py": 11373923576259976755, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_indexing.py": 8943385096811168079, - "venv/lib/python3.13/site-packages/pydantic/_internal/_fields.py": 2692892815545218335, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fft.pyi": 14454280827038327842, - "frontend/src/routes/translate/dictionaries/[id]/+page.svelte": 17719561272401762626, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_arrow.py": 10068866425352207113, - "frontend/build/_app/immutable/nodes/14.Dr4It6rP.js": 1926641097276212307, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayterator.py": 3076316311545674897, - "backend/src/core/task_manager/cleanup.py": 8316318318890394605, - "backend/src/plugins/translate/_lang_detect.py": 2125979777533490081, - "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/okp_key.py": 10312614562914096039, - "venv/lib/python3.13/site-packages/websockets/client.py": 5229500079651465772, - "venv/lib/python3.13/site-packages/pandas/_libs/window/aggregations.cpython-313-x86_64-linux-gnu.so": 16327106317503267067, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_period.py": 7727606662611927293, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_common.py": 9446944526144164255, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_nonunique_indexes.py": 15468078561381939405, - "backend/tests/test_translate_executor_filter.py": 11717560360659156703, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_loadtxt.py": 17562784940619942447, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_boxplot_method.py": 7635131059308651529, - "venv/lib/python3.13/site-packages/websockets/http.py": 9406523480132204760, - "venv/lib/python3.13/site-packages/PIL/FpxImagePlugin.py": 18245056799205041866, - "frontend/build/_app/immutable/assets/9.tn0RQdqM.css": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/roboconf.py": 1335271183806115470, - "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_deprecations.py": 14624516389510242394, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_elffile.py": 5728213398707817049, - "venv/lib/python3.13/site-packages/pandas/io/formats/xml.py": 12235904458551067063, - "backend/src/services/clean_release/preparation_service.py": 10596397721803950912, - "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.py": 4440659352851541547, - "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/assertion_client.py": 4261295109880943573, - "venv/lib/python3.13/site-packages/pydantic_settings/exceptions.py": 18300876747412267999, - "venv/lib/python3.13/site-packages/pandas/core/arrays/boolean.py": 8821671562937866269, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_head_tail.py": 1906121476322841736, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/screen.py": 6933591906297023845, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/authorization_server.py": 2913800420669417152, - "venv/lib/python3.13/site-packages/cryptography/x509/name.py": 15338066443257445241, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/var_.py": 12699521091170347311, - "venv/lib/python3.13/site-packages/pandas/core/window/expanding.py": 14141093310397856286, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_matmul.py": 9323220618335072725, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_constructors.py": 6727209833819502644, - "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.pyi": 2104100025130695295, - "venv/lib/python3.13/site-packages/jsonschema/_keywords.py": 949562792260528762, - "venv/lib/python3.13/site-packages/httpx/_content.py": 1301854837767395687, - "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/tokens_mixins.py": 9923721909178724437, - "venv/lib/python3.13/site-packages/pytest_asyncio/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/polynomial/_polytypes.pyi": 7528777458251688517, - "venv/lib/python3.13/site-packages/pip/_internal/locations/base.py": 7966628150470073365, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js": 10530710876604536879, - "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/accessor.py": 8373575175447947401, - "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.py": 151202984060101867, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_api.py": 1910541672533352625, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_row.py": 918740441973901148, - "venv/lib/python3.13/site-packages/sqlalchemy/util/_py_collections.py": 16825222625411635946, - "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/sessions.py": 5400174351499383072, - "venv/lib/python3.13/site-packages/pip/_internal/network/session.py": 293771075394156394, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_quantile.py": 11966156706220948315, - "venv/lib/python3.13/site-packages/pandas/io/formats/printing.py": 3054136648863371285, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/dynamic.py": 15220116196072524330, - "venv/lib/python3.13/site-packages/pandas/core/reshape/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/h11/_version.py": 9334144031400715479, - "backend/src/api/routes/__tests__/test_migration_routes.py": 2319142184353163171, - "venv/lib/python3.13/site-packages/urllib3/http2/probe.py": 4069929463671970243, - "frontend/src/routes/reports/+page.svelte": 17831076184881844976, - "venv/lib/python3.13/site-packages/jsonschema/exceptions.py": 15651767069704734674, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arithmetic.py": 3209727509456212551, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/anyio/abc/_eventloop.py": 2023190981288767991, - "venv/lib/python3.13/site-packages/pydantic/_internal/_repr.py": 1758478941817868344, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename_axis.py": 12432900682994622455, - "backend/src/core/auth/__tests__/test_auth.py": 9487323693897023350, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/git.py": 17060377178521307324, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/bitwise_ops.pyi": 751490187478960891, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/api.py": 13134394673408254097, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.py": 1341849861184131135, - "venv/lib/python3.13/site-packages/_pytest/_io/terminalwriter.py": 16852767249156780980, - "venv/lib/python3.13/site-packages/pandas/core/interchange/buffer.py": 12961802206383700922, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_ticks.py": 11649965080303468085, - "venv/lib/python3.13/site-packages/pandas/io/api.py": 8275376846208437741, - "venv/lib/python3.13/site-packages/pandas/tseries/holiday.py": 1134358927599488799, - "venv/lib/python3.13/site-packages/httpcore/_sync/http_proxy.py": 14037211594707072958, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_astype.py": 15275720655739710249, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/loading.py": 3460142472461437916, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/etcd.py": 4078354986605069279, - "frontend/build/_app/immutable/nodes/3.C5d1X6_s.js": 4931012884794568256, - "venv/lib/python3.13/site-packages/ecdsa/ecdsa.py": 9770689913380927623, - "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/WHEEL": 16223367184831500348, - "backend/src/core/migration/risk_assessor.py": 1061977005072298440, - "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml_dtypes.py": 18293138335799308439, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_common.py": 2265736743367879051, - "venv/lib/python3.13/site-packages/pandas/util/__init__.py": 4070574585004336241, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_period_index.py": 6634414375581820058, - "frontend/build/_app/immutable/chunks/B8AtCuU6.js": 13246100544061806572, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arithmetic.py": 17043958604607035425, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/methods.py": 8059372834301557565, - "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector_cpp.cpython-313-x86_64-linux-gnu.so": 16337157355618216738, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel_py.py": 9112851333217812996, - "venv/lib/python3.13/site-packages/pygments/styles/__init__.py": 18383248976818885498, - "frontend/src/lib/components/layout/__tests__/test_topNavbar.svelte.js": 11053755879172333925, - "frontend/src/components/backups/BackupManager.svelte": 15237659305406789107, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_categorical.py": 8844412630511751140, - "venv/lib/python3.13/site-packages/apscheduler/executors/asyncio.py": 2230610508870117058, - "backend/src/schemas/health.py": 13764741380188041840, - "backend/src/services/health_service.py": 7295235621662158359, - "venv/lib/python3.13/site-packages/rsa/transform.py": 12261738253972114335, - "venv/lib/python3.13/site-packages/pip/_internal/index/collector.py": 7454652626329467900, - "venv/lib/python3.13/site-packages/pydantic/_internal/_core_metadata.py": 5704137311404303574, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90": 5765181406654284736, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_update_delete.py": 1317337950621091021, - "venv/lib/python3.13/site-packages/itsdangerous/serializer.py": 14271229091461164933, - "venv/lib/python3.13/site-packages/pandas/_libs/writers.pyi": 10494773026133244183, - "venv/lib/python3.13/site-packages/sqlalchemy/event/legacy.py": 13465911776953636949, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_is_monotonic.py": 12899848089975919515, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/vyper.py": 6477559246065994199, - "venv/lib/python3.13/site-packages/pygments/lexers/vip.py": 11287963054551122004, - "venv/lib/python3.13/site-packages/_pytest/faulthandler.py": 13329320306353718649, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90": 13943066317159236257, - "venv/lib/python3.13/site-packages/gitdb/test/test_example.py": 3039934065817753241, - "venv/lib/python3.13/site-packages/pandas/core/arrays/floating.py": 1215586266958421991, - "venv/lib/python3.13/site-packages/pygments/lexers/qvt.py": 1895735583818227972, - "frontend/build/_app/immutable/chunks/BsX-ti3M.js": 3696367511864558476, - "backend/src/services/git/_gitea.py": 12631200182530815617, - "frontend/src/routes/admin/settings/llm/+page.svelte": 3079157958329647867, - "backend/src/plugins/debug.py": 2035734953696955393, - "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_datetime.py": 3499461736474530062, - "venv/lib/python3.13/site-packages/keyring/errors.py": 4587094338672775040, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunclike.pyi": 12215374902556647369, - "venv/lib/python3.13/site-packages/uvicorn/supervisors/basereload.py": 14479857245734482609, - "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.py": 15657897994221955882, - "venv/lib/python3.13/site-packages/apscheduler/job.py": 1858376671986108667, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_month.py": 1613806538807726074, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/type_api.py": 10299750173867399533, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/padding.py": 7470483648602195268, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_validate.py": 2133732492454460539, - "venv/lib/python3.13/site-packages/pip/_vendor/distro/__main__.py": 2688850704829116818, - "venv/lib/python3.13/site-packages/uvicorn/py.typed": 15240312484046875203, - "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/core/computation/check.py": 16048939716341154196, - "frontend/src/lib/components/reports/ReportsList.svelte": 15460090587871611258, - "backend/src/core/task_manager/manager.py": 16906644810860988426, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/METADATA": 4868544280955034757, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/WHEEL": 7127684561765977531, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_round.py": 9358309072340573675, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py": 11185011314498348980, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test__version.py": 9037916251087760255, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/misc/extended_precision.pyi": 6541258584648209609, - "venv/lib/python3.13/site-packages/pandas/tseries/api.py": 14785127136180503704, - "frontend/src/components/tasks/LogEntryRow.svelte": 3694709927263161265, - "venv/lib/python3.13/site-packages/pip/_internal/main.py": 13711402795965346761, - "venv/lib/python3.13/site-packages/pandas/tests/computation/test_compat.py": 11655000938111420543, - "venv/lib/python3.13/site-packages/cffi/vengine_cpy.py": 10684192171370688079, - "venv/lib/python3.13/site-packages/numpy/random/_pcg64.cpython-313-x86_64-linux-gnu.so": 5759445712745875888, - "venv/lib/python3.13/site-packages/websockets/extensions/base.py": 2457233337788783873, - "venv/lib/python3.13/site-packages/pandas/tests/util/conftest.py": 11143177766735481660, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iat.py": 3570464615146398178, - "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/METADATA": 10810011740984652381, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/validator.py": 14200019408839159476, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayterator.pyi": 7439348655567232744, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py": 2285778903282667561, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_duplicated.py": 6659959750254523427, - "venv/lib/python3.13/site-packages/pandas/core/tools/timedeltas.py": 7221393731712061943, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.pyi": 12043292763005874815, - "venv/lib/python3.13/site-packages/pygments/lexers/ambient.py": 18106929781201758080, - "backend/src/services/clean_release/mappers.py": 8684357784135236729, - "backend/alembic/versions/b1c2d3e4f5a6_add_source_hash_to_translation_records.py": 4775534557742900399, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/base.py": 17992335652981439676, - "frontend/src/components/tasks/TaskLogPanel.svelte": 4685456099513280294, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_unix.h": 13709837360414450184, - "venv/lib/python3.13/site-packages/certifi/__main__.py": 13417658012431779061, - "venv/lib/python3.13/site-packages/apscheduler/events.py": 10748346950729364899, - "venv/lib/python3.13/site-packages/pandas/core/indexes/period.py": 1181348384346239378, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nlargest.py": 14518132768753249360, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_comparison.py": 5348781442514871089, - "venv/lib/python3.13/site-packages/PIL/ImageFile.py": 15765130658900167517, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/uvicorn/supervisors/statreload.py": 5018382301336802445, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_missing.py": 2976310411820303374, - "frontend/src/components/git/BranchSelector.svelte": 12975425183125935169, - "venv/lib/python3.13/site-packages/httpcore/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/_orm_constructors.py": 4276726508722638048, - "venv/lib/python3.13/site-packages/pandas/core/reshape/api.py": 16364136812252343076, - "frontend/src/routes/tools/backups/+page.svelte": 6796050751535238723, - "venv/lib/python3.13/site-packages/pycparser/_c_ast.cfg": 2649342580905806389, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets2.py": 11100501798741918610, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_like.py": 2778905818573625118, - "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_utils.py": 8668650648802195016, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f": 5913807803369559749, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_console.py": 11657469008721907972, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/WHEEL": 5990830714395966792, - "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_partial_slicing.py": 16219611534574666182, - "venv/lib/python3.13/site-packages/git/remote.py": 1694919255653049944, - "venv/lib/python3.13/site-packages/pip/_internal/commands/freeze.py": 8644678595442275485, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_dtypes_basic.py": 10917162988625838981, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_cov_corr.py": 8117511855230249212, - "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/_gen_files.py": 6273314671315377131, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test__exceptions.py": 12099001631178696189, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine.py": 4446011286411407708, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.pyi": 2700568594438441246, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_truncate.py": 9623613657871046837, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dot.py": 16876560325283070437, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_numba.py": 1668304729617150075, - "venv/lib/python3.13/site-packages/pandas/io/feather_format.py": 13242733585787888812, - "venv/lib/python3.13/site-packages/pandas/core/indexers/__init__.py": 1756397319068017890, - "backend/src/api/routes/dashboards/_router.py": 8641007051243802224, - "backend/src/api/routes/profile.py": 11866770263441371105, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/traversals.py": 1188980668212022868, - "venv/lib/python3.13/site-packages/fastapi/security/base.py": 15674297568104917749, - "venv/lib/python3.13/site-packages/pygments/lexers/bqn.py": 11823648528816858738, - "venv/lib/python3.13/site-packages/passlib/handlers/mssql.py": 2800599582708170195, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_overlaps.py": 2328652590379935311, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexer.py": 14400766876373764268, - "venv/lib/python3.13/site-packages/_pytest/config/compat.py": 13175516717549204627, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/__init__.py": 14522970260621605208, - "venv/lib/python3.13/site-packages/sqlalchemy/util/queue.py": 1289234691048379395, - "venv/lib/python3.13/site-packages/pandas/core/indexing.py": 15507869313676722071, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.pyi": 15420142722808118826, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_numpy.py": 4073641912755651877, - "venv/lib/python3.13/site-packages/pandas/tests/test_expressions.py": 16378925536309828288, - "venv/lib/python3.13/site-packages/psycopg2/_json.py": 9729420372294281405, - "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/METADATA": 10707390829735099042, - "venv/lib/python3.13/site-packages/pygments/styles/inkpot.py": 10516710471319090846, - "venv/lib/python3.13/site-packages/pandas/tests/computation/__init__.py": 15130871412783076140, - "frontend/src/routes/reports/llm/[taskId]/report_page.contract.test.js": 4825093389030464765, - "backend/src/plugins/translate/__tests__/test_sql_generator.py": 4676288356986389564, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_msvc.h": 17581467060937454503, - "venv/lib/python3.13/site-packages/jose/backends/base.py": 12795468809472351388, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_scrypt.py": 8106466515670064013, - "venv/lib/python3.13/site-packages/_pytest/compat.py": 10046464101087327473, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_function.py": 14142346897145169685, - "venv/lib/python3.13/site-packages/jeepney/tests/test_low_level.py": 3579024079580951234, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/WHEEL": 13232065379159720345, - "venv/lib/python3.13/site-packages/websockets/typing.py": 13268801935274185287, - "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/__init__.py": 4290669519959060720, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_function_base.py": 15241999259666702619, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_series.py": 10922287546912569276, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/events.py": 7576713358952064464, - "venv/lib/python3.13/site-packages/pycparser/_ast_gen.py": 5464347629908906775, - "backend/src/core/utils/network.py": 8313622593956890768, - "venv/lib/python3.13/site-packages/authlib/oidc/discovery/__init__.py": 308178910015974550, - "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/assertion.py": 5287436128235488464, - "venv/lib/python3.13/site-packages/fastapi/middleware/gzip.py": 436886407566263171, - "venv/lib/python3.13/site-packages/pandas/_libs/algos.cpython-313-x86_64-linux-gnu.so": 15706331654215762588, - "venv/lib/python3.13/site-packages/_pytest/pastebin.py": 13946273207624603063, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/base.py": 13634605726041717070, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_inspect.py": 10573558345297891848, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_style.tpl": 3352086677417301397, - "venv/lib/python3.13/site-packages/keyring/util/platform_.py": 16978095707950463638, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_object_arr.py": 4725156416161661681, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/greenlet/PyModule.cpp": 3464405102256525511, - "venv/lib/python3.13/site-packages/cffi/backend_ctypes.py": 2042566833861899211, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi": 13850254283540522444, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/RECORD": 7844752443022514265, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nditer.pyi": 2351219156711800159, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufuncs.pyi": 1808147181379894521, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_get_numeric_data.py": 11747933921770969706, - "venv/lib/python3.13/site-packages/multipart/multipart.py": 26386459953377432, - "venv/lib/python3.13/site-packages/pip/_internal/cli/parser.py": 1064209424435927674, - "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE": 5669644120528099197, - "venv/lib/python3.13/site-packages/uvicorn/__main__.py": 6086938803696646644, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/licenses/LICENSE": 3509878235770224233, - "backend/alembic/versions/aa1b2c3d4e5f_drop_deprecated_translate_columns.py": 15433357059529111004, - "venv/lib/python3.13/site-packages/jsonschema/_types.py": 9250091433305395923, - "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.pyi": 13208953770241664384, - "venv/lib/python3.13/site-packages/pandas/io/formats/info.py": 215303194287834907, - "backend/alembic/versions/ed310b33f02c_multi_language_translation_tables.py": 1424919631205944664, - "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/__init__.py": 18036348770966744795, - "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_rolling.py": 11118160360072677569, - "venv/lib/python3.13/site-packages/pandas/_libs/ops.cpython-313-x86_64-linux-gnu.so": 10490009128553397250, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_tz_convert.py": 77283525137564255, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_indexing.py": 17106010337164216722, - "venv/lib/python3.13/site-packages/pip/_vendor/certifi/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/__init__.py": 11009955319062089477, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.py": 13853220736499979380, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/io.py": 11072022722163954973, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/cache.py": 15037055977924167732, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/validator.py": 11486125578281617670, - "venv/lib/python3.13/site-packages/httpcore/_synchronization.py": 10997080307461682786, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_regression.py": 9375525053479844400, - "venv/lib/python3.13/site-packages/PIL/ImageEnhance.py": 3218405223202808764, - "frontend/src/pages/Settings.svelte": 12818597464628135154, - "venv/lib/python3.13/site-packages/ecdsa/curves.py": 812969717084691115, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpcore/_async/connection_pool.py": 932468678264370661, - "venv/lib/python3.13/site-packages/dateutil/utils.py": 7067026915090881998, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.pyi": 13110894861187422750, - "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py": 15753279711312689193, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA": 7788873460115135563, - "venv/lib/python3.13/site-packages/pygments/lexers/dalvik.py": 5549983892200382076, - "backend/src/api/routes/datasets.py": 8495307661445562003, - "backend/src/services/clean_release/__init__.py": 18311663871116449547, - "frontend/src/lib/components/layout/Sidebar.svelte": 8588237337148619706, - "backend/src/services/git/_base.py": 3671238045679556094, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop.py": 15751236355035730554, - "venv/lib/python3.13/site-packages/anyio/streams/tls.py": 4191898645554875562, - "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/METADATA": 13428590545328703138, - "venv/lib/python3.13/site-packages/pandas/core/missing.py": 13332302791063948992, - "venv/lib/python3.13/site-packages/pandas/io/pickle.py": 5418646169167774144, - "venv/lib/python3.13/site-packages/numpy/core/shape_base.py": 17925759824894973734, - "venv/lib/python3.13/site-packages/pillow.libs/libharfbuzz-0692f733.so.0.61230.0": 23110287346167671, - "backend/src/core/__init__.py": 8673978627093182792, - "backend/src/plugins/translate/dictionary_import_export.py": 12639118203353044308, - "venv/lib/python3.13/site-packages/pandas/tests/resample/conftest.py": 1643522609234951699, - "backend/git_repos/remote/test-repo.git/objects/c2/491dfd8c841bacd5f491510f6334aa4a626f00": 6297303620364618482, - "dist/docker/backend.1.2.0.tar.xz": 15111524255417105836, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/histograms.pyi": 2281259341486424755, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py": 6109201994963211857, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90": 6219951399575860362, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/__init__.py": 7062045842767697645, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_serialization.py": 2011519400081029270, - "venv/lib/python3.13/site-packages/pandas/_libs/tslib.cpython-313-x86_64-linux-gnu.so": 10742615805788605480, - "venv/lib/python3.13/site-packages/anyio/_core/_typedattr.py": 17584691045493791349, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/RECORD": 12555714734722889695, - "venv/lib/python3.13/site-packages/pandas/util/_doctools.py": 3766479022075611396, - "venv/lib/python3.13/site-packages/PIL/GdImageFile.py": 16875784236394545058, - "venv/lib/python3.13/site-packages/pygments/lexers/php.py": 17636450950688953288, - "venv/lib/python3.13/site-packages/pip/_internal/utils/virtualenv.py": 14416705841810221305, - "venv/lib/python3.13/site-packages/urllib3/util/ssl_match_hostname.py": 7411350247004265632, "frontend/src/components/MappingTable.svelte": 17937756426921453860, - "venv/lib/python3.13/site-packages/pandas/core/indexes/base.py": 496956059910401121, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_formats.py": 13500155167624433622, - "venv/lib/python3.13/site-packages/referencing/__init__.py": 10093824711214801917, - "backend/src/services/reports/__init__.py": 11818812865847046400, - "backend/alembic/env.py": 17895850402041934744, - "venv/lib/python3.13/site-packages/numpy/_typing/_array_like.py": 2161873439361281488, - "frontend/src/lib/components/dataset-review/ValidationFindingsPanel.svelte": 2403276296409515448, - "venv/lib/python3.13/site-packages/ecdsa/test_sha3.py": 12459459298663975730, - "venv/lib/python3.13/site-packages/keyring/backends/libsecret.py": 11621088556661567306, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_like.pyi": 1968570015765106620, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.pyi": 10947021928755741366, - "venv/lib/python3.13/site-packages/pandas/io/iceberg.py": 13137128885014736233, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/dictionary.py": 9599439750713575741, - "venv/lib/python3.13/site-packages/pytest/__main__.py": 8747175113746141224, - "frontend/src/lib/components/translate/ScheduleConfig.svelte": 14007615494976044075, - "venv/lib/python3.13/site-packages/pandas/tests/internals/test_api.py": 11217428888457119601, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/RECORD": 16874983218652404911, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_constructors.py": 1697610790604400105, - "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/smmap/test/test_tutorial.py": 16309370344201290582, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE": 1641332741515411734, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/help.py": 3124654001287175629, - "venv/lib/python3.13/site-packages/pygments/lexers/asm.py": 13861952972248758785, - "backend/src/core/utils/superset_context_extractor/_parsing.py": 17093712504833649098, - "backend/git_repos/remote/test-repo.git/objects/ed/0432f88f5f7d95b26ecde34345abe741dd9db2": 13426916511127204463, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/RECORD": 5612689057373270213, - "venv/lib/python3.13/site-packages/passlib/handlers/digests.py": 18158237109145814857, - "venv/lib/python3.13/site-packages/authlib/oidc/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/reporter.py": 6510864297510700136, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_iceberg.py": 1726421917529457420, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/parameters.py": 247312908510013930, - "backend/src/plugins/translate/service_datasource.py": 10240814407336170041, - "backend/src/plugins/translate/orchestrator_config.py": 1227864697811313446, - "frontend/src/components/backups/BackupList.svelte": 14417854869668960310, - "venv/lib/python3.13/site-packages/jose/jws.py": 11592462993417182096, - "venv/lib/python3.13/site-packages/cryptography/hazmat/_oid.py": 755042927629281577, - "venv/lib/python3.13/site-packages/passlib/utils/md4.py": 4521366665754877351, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.py": 5933622200264572885, - "venv/lib/python3.13/site-packages/pandas/core/construction.py": 10646956189518908985, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/cx_oracle.py": 10093932131797570986, - "venv/lib/python3.13/site-packages/numpy/_core/overrides.pyi": 13121243505132110607, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/getlimits.pyi": 93747984191461691, - "venv/lib/python3.13/site-packages/pygments/lexers/macaulay2.py": 8022891778577314212, - "venv/bin/keyring": 1488968652276547659, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/groupby.py": 12749730954888633240, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_strings.py": 17398806130402098912, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90": 877982462186396830, - "backend/src/services/clean_release/__tests__/test_preparation_service.py": 4765724405964286078, - "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/METADATA": 15225661995655327539, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_jsonschema_test_suite.py": 12733761462141495972, - "venv/lib/python3.13/site-packages/ecdsa/_rwlock.py": 7971972922423146201, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/revocation.py": 16178499278312777474, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/multiarray.py": 3224049574922696945, - "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.pyi": 1942236362568669510, - "venv/lib/python3.13/site-packages/pandas/tests/reductions/__init__.py": 16150188643076000414, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpq-9b38f5e3.so.5.17": 9680474575710585826, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_astype.py": 4975959187621745360, - "venv/lib/python3.13/site-packages/click/formatting.py": 6694583529073729642, - "venv/lib/python3.13/site-packages/numpy/_core/_simd.pyi": 13553578040186939249, - "venv/lib/python3.13/site-packages/pandas/util/_validators.py": 10201915528715968165, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_numba.py": 8250377774229977284, - "venv/lib/python3.13/site-packages/git/objects/tree.py": 10239027037919781330, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_base.py": 15292769510056833117, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_skew_kurt.py": 15225601437354712351, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_shift.py": 14681514853406253657, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_categorical.py": 10863578845754547294, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_searchsorted.py": 11208047646304753715, - "venv/lib/python3.13/site-packages/keyring/testing/backend.py": 14295829193445781542, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_unsupported.py": 9115440166074553860, - "scripts/generate_financial_arrears_data.py": 15989529185799374517, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test__iotools.py": 6260912730310453037, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/twisted.py": 16059862619165885730, - "venv/lib/python3.13/site-packages/pydantic/deprecated/json.py": 17692639396786690144, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_string.py": 11422235699126032386, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_file_handling.py": 732772718210067599, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/mypy.py": 10034028441785588819, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.pyi": 2101854548535776875, - "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/RECORD": 12015288851076448205, - "venv/lib/python3.13/site-packages/numpy/_core/umath.py": 6132761780113682667, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_pbkdf2.py": 4977067068389993374, - "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/METADATA": 3179724236887811680, - "venv/lib/python3.13/site-packages/httpcore/_backends/auto.py": 10488908050307887802, - "venv/lib/python3.13/site-packages/pygments/formatters/groff.py": 6480830447984073574, - "venv/lib/python3.13/site-packages/pygments/lexers/arturo.py": 4565524340706235725, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_textreader.py": 388955620768371652, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_clip.py": 8087139801274517318, - "frontend/src/lib/ui/LanguageSwitcher.svelte": 3899734183369041614, - "backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py": 18129267641758340444, - "venv/lib/python3.13/site-packages/_pytest/terminalprogress.py": 5490989904517343259, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_unicode.py": 1103608932321322989, - "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/response.py": 9594165377270752433, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/tools.py": 6437315459200419827, - "venv/lib/python3.13/site-packages/pycparser/ply/lex.py": 3393278208465358140, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_numeric.py": 9417128508433693658, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/database.py": 7111764828004587758, - "venv/lib/python3.13/site-packages/pandas/io/sql.py": 12592024569011796790, - "venv/lib/python3.13/site-packages/numpy/lib/_datasource.py": 18136853038949826147, - "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.pyi": 17903213294220335051, - "venv/lib/python3.13/site-packages/keyring/compat/properties.py": 1562771115138037410, - "venv/lib/python3.13/site-packages/numpy/f2py/rules.py": 9322914583460630877, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_semicolon_split.py": 8153770165829451525, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_methods.py": 14881910898871057761, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_pydatetime.py": 16228315407662560992, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py": 1359143503575245224, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/__init__.py": 6489437464172324468, - "venv/lib/python3.13/site-packages/passlib/exc.py": 15559705487889657091, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/events.py": 10224214051422678828, - "venv/lib/python3.13/site-packages/yaml/cyaml.py": 9157893742065554693, - "venv/lib/python3.13/site-packages/pycparser/lextab.py": 16045770806700381661, - "venv/lib/python3.13/site-packages/pygments/lexers/rebol.py": 10460732731157940232, - "frontend/e2e/tests/smoke.e2e.js": 11130903009452044456, - "frontend/build/_app/immutable/chunks/Cg5szaOz.js": 14010439230478307451, - "backend/src/core/utils/superset_context_extractor/__init__.py": 1074191108198498747, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_py_util.py": 12836989066113400538, - "backend/src/core/utils/dataset_mapper.py": 11420365912051387020, - "venv/lib/python3.13/site-packages/psycopg2/extensions.py": 14197445323992851566, - "venv/lib/python3.13/site-packages/jsonschema_specifications/_core.py": 14812112544772987164, - "venv/lib/python3.13/site-packages/greenlet/tests/test_generator_nested.py": 12822240347707346718, - "venv/lib/python3.13/site-packages/pip/_internal/distributions/wheel.py": 13979536782410081712, - "venv/lib/python3.13/site-packages/pip/_internal/commands/show.py": 11839987586497822300, - "venv/lib/python3.13/site-packages/anyio/_core/_eventloop.py": 6853955946028131785, - "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.pyi": 2042169688753984918, - "venv/lib/python3.13/site-packages/uvicorn/loops/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/wrapper.py": 14599195010683170123, - "venv/lib/python3.13/site-packages/attrs/converters.py": 13109003765349201809, - "venv/lib/python3.13/site-packages/numpy/lib/user_array.py": 14003456655595459585, - "venv/lib/python3.13/site-packages/pygments/lexers/codeql.py": 4254046699692048717, - "venv/lib/python3.13/site-packages/authlib/common/encoding.py": 52296066492753953, - "backend/git_repos/remote/test-repo.git/info/exclude": 6403833611826357791, - "venv/lib/python3.13/site-packages/pygments/lexers/pddl.py": 9256112535059995841, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_series.py": 17126297747681689408, - "venv/lib/python3.13/site-packages/pygments/styles/rrt.py": 9490973359165080360, - "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/implicit.py": 5400555157488808948, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/WHEEL": 8600534672961461758, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/base.py": 6348888156686452825, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_cumulative.py": 16283954014170928273, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_all_methods.py": 18227706645906325527, - "venv/lib/python3.13/site-packages/idna/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/io/pytables.py": 17482934215513855928, - "venv/lib/python3.13/site-packages/PIL/GbrImagePlugin.py": 7681313333602257802, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_indexing.py": 5063545640498065297, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_object.py": 9215781825358309147, - "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/METADATA": 2604612822968175379, - "venv/lib/python3.13/site-packages/apscheduler/triggers/combining.py": 1264860868414723829, - "venv/lib/python3.13/site-packages/pillow.libs/libxcb-64009ff3.so.1.1.0": 7322566017497612912, - "venv/lib/python3.13/site-packages/pandas/core/indexes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_dropna.py": 3620959914439334511, - "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE": 1126906383149772681, - "venv/lib/python3.13/site-packages/anyio/abc/_tasks.py": 16839170934610571514, - "venv/lib/python3.13/site-packages/pip/_internal/utils/packaging.py": 15555781487631855604, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arithmetic.pyi": 10265823318697442495, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-1.csv": 9129730764673472086, - "venv/lib/python3.13/site-packages/numpy/_core/printoptions.py": 3897105663572772838, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isin.py": 14387850595546682314, - "venv/lib/python3.13/site-packages/pip/_internal/index/__init__.py": 14829074315307489628, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/matrix.pyi": 15667024840812783911, - "venv/lib/python3.13/site-packages/pandas/core/indexes/api.py": 13750417165301467381, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reduce.py": 14976712507854054776, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/base.py": 13454394827268856575, - "venv/lib/python3.13/site-packages/numpy/core/umath.py": 4476812261188108155, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_inference.py": 16402427186697071465, - "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/licenses/LICENSE": 7959949171752474553, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_operators.py": 12686786829906210592, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/identity.py": 326059526167697655, - "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet.py": 10727595500186011102, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/urllib3/util/request.py": 9432067988603015849, - "venv/lib/python3.13/site-packages/websockets/auth.py": 499195617702591757, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/argon2.py": 15389474901714096890, - "venv/lib/python3.13/site-packages/sqlalchemy/event/attr.py": 5971663429221923939, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/quantile.py": 17341029201525362074, - "venv/lib/python3.13/site-packages/pygments/lexers/_qlik_builtins.py": 1728058904137960444, - "venv/lib/python3.13/site-packages/attr/_cmp.py": 3297594878548179300, - "venv/lib/python3.13/site-packages/pip/py.typed": 10243553515949422671, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/__init__.py": 3577295959173028042, - "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.py": 7446626038222262489, - "venv/lib/python3.13/site-packages/passlib/handlers/roundup.py": 3844280972451753019, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/memmap.pyi": 15629663272474054909, - "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_config.py": 3636377988901907424, - "venv/lib/python3.13/site-packages/attr/_make.py": 2348458829123990579, - "venv/lib/python3.13/site-packages/pip/_internal/utils/hashes.py": 17310331665429541812, - "venv/lib/python3.13/site-packages/pandas/core/computation/scope.py": 16859504937881548797, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_skew.py": 5276102682005383261, - "venv/lib/python3.13/site-packages/anyio/functools.py": 4300781896135050327, - "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/METADATA": 14126682758562488244, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_fillna.py": 9297637486401098611, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_reductions.py": 8258332365408303156, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi": 2777456956260371820, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/orderinglist.py": 10162099108656794338, - "venv/lib/python3.13/site-packages/urllib3/util/util.py": 12490259045660543460, - "venv/lib/python3.13/site-packages/uvicorn/lifespan/off.py": 16254524872582859561, - "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pydantic/v1/decorator.py": 6124748023704700724, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/introspection.py": 14645217065508644154, - "venv/lib/python3.13/site-packages/_pytest/cacheprovider.py": 5114545353355728201, - "venv/lib/python3.13/site-packages/pandas/core/arrays/base.py": 664515424699746697, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_arithmetic.py": 17427754419626622853, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_put.py": 8547660958963625817, - "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.py": 3654583356259850174, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py": 5126234270435358377, - "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.c": 2519219289444051739, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/incfile.f90": 4348588746493647387, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_astype.py": 8633811117672837999, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_skiprows.py": 8764515842253490735, - "venv/lib/python3.13/site-packages/pygments/lexers/pascal.py": 5992422120590352714, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_empty.py": 13006241382741353569, - "frontend/src/components/MissingMappingModal.svelte": 11264881226066623003, - "frontend/src/routes/settings/LoggingSettings.svelte": 1737218883899664063, - "backend/src/plugins/translate/__tests__/test_orthogonal_fixes.py": 264408615924319135, - "frontend/src/types/backup.ts": 1741234034896689348, - "venv/lib/python3.13/site-packages/gitdb/db/base.py": 3375449584942578385, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/__init__.py": 15130871412783076140, - "backend/git_repos/remote/test-repo.git/objects/6a/f2b28e314c04fb4e03476c12d6491213591512": 4526311953587849385, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/groupby.py": 14661033005768429774, - "venv/lib/python3.13/site-packages/annotated_types/test_cases.py": 5123395674810472016, - "venv/lib/python3.13/site-packages/pip/_internal/operations/install/wheel.py": 3531093454660385247, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.py": 15426828792217499138, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi": 9835891299056543360, - "venv/lib/python3.13/site-packages/anyio/abc/__init__.py": 11428476337116642278, - "venv/lib/python3.13/site-packages/starlette/config.py": 16509394679506300256, - "venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py": 10265081145401348863, - "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/scipy_sparse.py": 2091608752719976909, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/modeline.py": 6194365452131561478, - "frontend/build/_app/immutable/nodes/27.DAsxun8j.js": 4855661606729192315, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_ssl_constants.py": 14834514243239777933, - "backend/src/core/superset_profile_lookup.py": 5518507735632088337, - "venv/lib/python3.13/site-packages/_pytest/tmpdir.py": 10834220332037364219, - "venv/lib/python3.13/site-packages/_pytest/_io/saferepr.py": 8025234471485188730, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/auth.py": 912521029864094489, - "venv/lib/python3.13/site-packages/cryptography/x509/extensions.py": 10197248868682803019, - "venv/lib/python3.13/site-packages/rapidfuzz/_utils.py": 14374663810542207121, - "venv/lib/python3.13/site-packages/numpy/lib/__init__.py": 12211229657513986410, - "venv/lib/python3.13/site-packages/pandas/core/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/tests/test_utils.py": 10362977406431569031, - "venv/lib/python3.13/site-packages/pandas/_version_meson.py": 4875297137037630519, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reorder_levels.py": 10996225584998355824, - "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/__init__.py": 4761936067832638585, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayprint.pyi": 2053388407376896377, - "venv/lib/python3.13/site-packages/pygments/lexers/thingsdb.py": 6073447481627395832, - "frontend/src/lib/components/reports/ReportCard.svelte": 13714680961668469204, - "frontend/src/lib/components/dataset-review/SourceIntakePanel.svelte": 13922687579631047714, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/emath.pyi": 3718540478840842664, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/schema.py": 83238111330132033, - "venv/lib/python3.13/site-packages/pandas/core/computation/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timezones.py": 1962830142478494009, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlcipher.py": 11225173272050906977, - "venv/lib/python3.13/site-packages/numpy/_pytesttester.pyi": 5750506937526308405, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_cumulative.py": 11752712818547022872, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_month.py": 8485374160446988786, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_readlines.py": 15928258358116399067, - "venv/lib/python3.13/site-packages/yaml/representer.py": 10550136298978225013, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/umath/svml/LICENSE": 9584102918819171104, - "venv/lib/python3.13/site-packages/pandas/tests/extension/list/test_list.py": 4538625980063375611, - "venv/lib/python3.13/site-packages/pip/_internal/wheel_builder.py": 3893922370396791826, - "venv/lib/python3.13/site-packages/passlib/handlers/django.py": 66638338316838351, - "venv/lib/python3.13/site-packages/dateutil/tz/tz.py": 5258008267965780817, - "venv/lib/python3.13/site-packages/anyio/streams/text.py": 12507591237176920223, - "venv/lib/python3.13/site-packages/pygments/lexers/haxe.py": 1915270891525929751, - "frontend/e2e/helpers/api.helper.js": 12740720187461301874, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/types.py": 1343652083039949282, - "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.pyi": 2667658052734929089, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertsql.py": 4633484475514351889, - "frontend/src/components/tools/ConnectionList.svelte": 13697819455163305485, - "backend/src/core/task_manager/context.py": 17543992255093146942, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/__init__.py": 4752355175318979033, - "frontend/build/_app/immutable/chunks/BuRkO16S.js": 9587040733399939559, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/indexable.py": 4131796922597075758, - "venv/lib/python3.13/site-packages/typing_extensions.py": 8402965285733247527, - "venv/lib/python3.13/site-packages/pip/_internal/commands/__init__.py": 3795218871212151351, - "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/INSTALLER": 17282701611721059870, - "backend/src/core/task_manager/__init__.py": 15991802770215124472, - "venv/lib/python3.13/site-packages/pyasn1/type/opentype.py": 340146737126677655, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcom_err-2abe824b.so.2.1": 12870528025628871295, - "venv/lib/python3.13/site-packages/pygments/lexers/varnish.py": 3608370156692616959, - "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/LICENSE": 6581019367004699816, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/authorization_code.py": 4958605540994687737, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/rsa.py": 5392922995791487437, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/base.py": 13444129650880426353, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/filewrapper.py": 17786759398959482432, - "venv/lib/python3.13/site-packages/numpy/random/_mt19937.cpython-313-x86_64-linux-gnu.so": 85866616759631810, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token.py": 4747545058753492487, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_multiindex.py": 13723677252432338937, - "venv/lib/python3.13/site-packages/pycparser/c_parser.py": 3954138286651284327, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame.py": 16757570551941104401, - "venv/lib/python3.13/site-packages/pandas/core/arrays/period.py": 11560984428402318984, - "backend/src/services/clean_release/__tests__/test_report_builder.py": 14655761033823243898, - "frontend/build/_app/immutable/nodes/8.DVAQ4RBT.js": 14721796119406492715, - "venv/lib/python3.13/site-packages/numpy/_distributor_init.pyi": 1308368231471324581, - "backend/src/models/config.py": 7631082065091961320, - "venv/lib/python3.13/site-packages/passlib/handlers/argon2.py": 835074952952017434, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/conftest.py": 2643915042664055969, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/relationships.py": 8401569216905291119, - "frontend/src/routes/dashboards/[id]/components/DashboardLinkedResources.svelte": 8279080994517688482, - "venv/lib/python3.13/site-packages/jeepney/tests/test_auth.py": 15125055415702968414, - "venv/lib/python3.13/site-packages/idna-3.11.dist-info/RECORD": 11541505360973709787, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__init__.py": 8880435562116660648, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_round.py": 1299086932398824299, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timezones.cpython-313-x86_64-linux-gnu.so": 1137453907225619959, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_s390_unix.h": 5161826643658505126, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_dict_compat.py": 18196543090455290455, - "venv/lib/python3.13/site-packages/PIL/EpsImagePlugin.py": 1824020964179364491, - "venv/bin/jsonschema": 16516374846693491442, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming_py.py": 16133454512601432815, - "venv/lib/python3.13/site-packages/pygments/lexers/_usd_builtins.py": 8671446144574174964, - "frontend/src/components/TaskLogViewer.svelte": 11262767195652916566, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/hybrid.py": 5793056975404534989, - "venv/lib/python3.13/site-packages/pandas/tests/extension/date/__init__.py": 16789767433439616593, - "venv/lib/python3.13/site-packages/keyring/core.py": 2764269590123131634, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/cursor.py": 8074527784886981710, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py": 17908437937265384125, - "venv/lib/python3.13/site-packages/pygments/sphinxext.py": 2768161754523156130, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_transform.py": 5674175311567817854, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/zip-safe": 15240312484046875203, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_string_array.py": 8260883866404398980, - "venv/lib/python3.13/site-packages/pygments/lexers/_mapping.py": 12987629396101138833, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hiworld.f90": 6321872653169140461, - "frontend/src/assets/svelte.svg": 13872699371039797074, - "venv/lib/python3.13/site-packages/keyring/backend_complete.bash": 16589214602970214174, - "venv/lib/python3.13/site-packages/_pytest/assertion/__init__.py": 16392348866405910618, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_version.pyi": 18093228021414910594, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/result.py": 8306497889916212025, - "frontend/src/lib/components/translate/__tests__/test_correction_cell.svelte.js": 2314051239468628554, - "frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js": 15091004230843271151, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_astype.py": 16700461036658228009, - "backend/src/api/routes/git/_gitea_routes.py": 14644218433873522624, - "venv/lib/python3.13/site-packages/charset_normalizer/legacy.py": 1706599349563920562, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/_cmd.py": 14954780419054588164, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_kwarg.py": 10417724544218303733, - "venv/lib/python3.13/site-packages/pandas/io/parsers/arrow_parser_wrapper.py": 11745253171984606573, - "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.pyi": 18193727720492050602, - "venv/lib/python3.13/site-packages/gitdb/test/__init__.py": 18393574323937353933, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_dists.py": 16746363359320577809, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/flatiter.py": 3066469329738423021, - "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.pyi": 14069586330277925998, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timedeltas.cpython-313-x86_64-linux-gnu.so": 17089839649971421164, - "frontend/build/_app/immutable/chunks/CTk7LksI.js": 14741048309207626554, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/conftest.py": 4124267277224879990, - "frontend/src/lib/stores/datasetReviewSession.js": 3915919349382526215, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_style.py": 10405592363651914796, - "backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py": 14275839608126658275, - "backend/src/services/llm_prompt_templates.py": 16187535610068299149, - "venv/lib/python3.13/site-packages/pandas/tests/construction/__init__.py": 15130871412783076140, - "backend/tests/scripts/test_clean_release_tui.py": 14700450036639944764, - "venv/lib/python3.13/site-packages/passlib/tests/sample_config_1s.cfg": 1809713544666311828, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/cffi/setuptools_ext.py": 30796527302561458, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_setops.py": 16240008859650640717, - "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/exceptions.py": 11303331612406662162, - "venv/lib/python3.13/site-packages/pandas/io/sas/__init__.py": 8095743504390517992, - "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.cpython-313-x86_64-linux-gnu.so": 3478629877770507853, - "backend/src/plugins/migration.py": 16213446701284149979, - "venv/lib/python3.13/site-packages/fastapi/routing.py": 466387159689567541, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_version.py": 15336513445621042105, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/_typing.py": 17598638528781632158, - "venv/lib/python3.13/site-packages/cryptography/hazmat/__init__.py": 6534110674636458866, - "venv/lib/python3.13/site-packages/_pytest/_py/error.py": 2257336434271433543, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray_misc.pyi": 16219573290116396099, - "frontend/src/lib/components/reports/reportTypeProfiles.js": 10752964062056890725, - "venv/lib/python3.13/site-packages/_pytest/legacypath.py": 7512065138259788426, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.pyf": 14358606965464506398, - "venv/lib/python3.13/site-packages/tzlocal/__init__.py": 11017072814026497364, - "venv/lib/python3.13/site-packages/pandas/_libs/hashing.pyi": 5241441378073929968, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/nditer.py": 10038360623032425884, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_other.py": 783701524491896337, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/aioodbc.py": 12704729841432715246, - "venv/lib/python3.13/site-packages/pygments/lexers/javascript.py": 16869490851285457857, - "venv/lib/python3.13/site-packages/greenlet/TThreadState.hpp": 15599148954148720463, - "venv/lib/python3.13/site-packages/pandas/_libs/sas.pyi": 873957906443703977, - "backend/src/services/clean_release/stages/data_purity.py": 10459527906317168920, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/metadata.py": 7204343250279221076, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.cpython-313-x86_64-linux-gnu.so": 12654188486128938170, - "backend/src/api/routes/__tests__/test_dashboards.py": 226265424558878456, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_astype.py": 8505605634958454768, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_ops.py": 3875181889032080505, - "venv/lib/python3.13/site-packages/authlib/deprecate.py": 3563885283090710443, - "venv/lib/python3.13/site-packages/websockets/asyncio/compatibility.py": 9716993942839407921, - "backend/src/api/routes/__tests__/test_clean_release_source_policy.py": 15242462571646635922, - "frontend/src/lib/stores/__tests__/sidebar.test.js": 5168138864675110669, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/automap.py": 4672057253309608464, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_produces_warning.py": 750781117570375777, - "venv/lib/python3.13/site-packages/pydantic/deprecated/config.py": 12280996227531856230, - "venv/lib/python3.13/site-packages/numpy/_typing/_shape.py": 12667553664122376205, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexerrors.py": 4434868847540549873, - "backend/tests/test_smoke_plugins.py": 10704454611361370435, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_subplots.py": 4596089143375088346, - "venv/lib/python3.13/site-packages/pip/_internal/models/format_control.py": 12916176880659590456, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/compat.py": 17520043776344667309, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv": 6233924374281534211, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/numeric.py": 12261531924304979741, - "venv/lib/python3.13/site-packages/pandas/core/indexes/category.py": 18192569199634406001, - "venv/lib/python3.13/site-packages/httpx/_auth.py": 1283189552342958900, - "venv/lib/python3.13/site-packages/websockets/asyncio/async_timeout.py": 7267209982032642028, - "venv/lib/python3.13/site-packages/PIL/DcxImagePlugin.py": 11767274218348117481, - "backend/src/models/auth.py": 775632703462705888, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/multiarray.pyi": 6368268452184570195, - "venv/lib/python3.13/site-packages/pandas/tests/test_downstream.py": 5635510753354256507, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayterator.pyi": 15722265241660279277, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/url.py": 9692934100602135106, - "venv/lib/python3.13/site-packages/numpy/random/mtrand.cpython-313-x86_64-linux-gnu.so": 16146459667121787202, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_formats.py": 5259100336852479395, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_api.py": 14120915875574640262, - "frontend/src/components/TaskHistory.svelte": 7819646903874958430, - "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/METADATA": 3474626408138844944, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90": 8048650253889213460, - "frontend/build/_app/immutable/chunks/wGslGEg4.js": 7568691983055374884, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo77.f": 7353666717928699883, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/astype.py": 9925183787411796679, - "venv/lib/python3.13/site-packages/pandas/util/_exceptions.py": 14426860079366867683, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_legendre.py": 18266595775500927868, - "venv/lib/python3.13/site-packages/passlib/handlers/misc.py": 18255658377109333797, - "venv/lib/python3.13/site-packages/numpy/typing/__init__.pyi": 10058149460938883683, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_deprecated_kwargs.py": 10379929935087904974, - "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/WHEEL": 5179340427739743287, - "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_expanding.py": 12504275097476819918, - "venv/lib/python3.13/site-packages/yaml/tokens.py": 2279161238859232338, - "venv/lib/python3.13/site-packages/cffi/verifier.py": 8473599757770867754, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_formats.py": 2601044064677727807, - "venv/lib/python3.13/site-packages/fastapi/_compat/shared.py": 5249003014594464718, - "docker/nginx.ssl.conf": 12350396037548059686, - "venv/lib/python3.13/site-packages/dotenv/__init__.py": 15464030923609356017, - "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_linalg.py": 2939739913218718132, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/RECORD": 11976403473353722969, - "venv/lib/python3.13/site-packages/pyasn1/codec/native/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/METADATA": 15888766579203341778, - "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.py": 15558318749939680074, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_indexing.py": 14461606056665485421, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_copy_deprecation.py": 16045426957636349035, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libldap-2974a1ba.so.2.0.200": 13590569080612602445, - "backend/src/core/plugin_loader.py": 16320603855307510494, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/typst.tpl": 5055419073126793137, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_cpp_exception.py": 11851283355840567373, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py": 15060063324909302240, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_add_prefix_suffix.py": 8367793476246001244, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_constructors.py": 2439700578107653984, - "venv/lib/python3.13/site-packages/PIL/ImageColor.py": 17058618058554970738, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90": 3911644649277659333, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/_mapping.py": 17519715342700184302, - "venv/lib/python3.13/site-packages/PIL/_imagingtk.pyi": 18222325750818585549, - "venv/lib/python3.13/site-packages/jsonschema/cli.py": 9813914882090789748, - "venv/lib/python3.13/site-packages/ecdsa/ssh.py": 17010933326090778158, - "venv/lib/python3.13/site-packages/PIL/ImageText.py": 15322496455608242001, - "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/__init__.py": 17630019785411546070, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/zip-safe": 15240312484046875203, - "venv/lib/python3.13/site-packages/starlette/staticfiles.py": 11256974306202558529, - "venv/lib/python3.13/site-packages/requests/_internal_utils.py": 4091305333167213279, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odf.py": 15484940480924122966, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/base.py": 10205051944814316388, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_warnings.py": 13071210233876253749, - "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/WHEEL": 7454950858448014158, - "frontend/src/lib/components/translate/TranslationMetricsDashboard.svelte": 8577281635452165836, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tz_localize.py": 13699016868476153393, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/status.py": 2214590120238144582, - "backend/src/core/middleware/__init__.py": 13917394130915533209, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein_py.py": 11350239659973489646, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/licenses/COPYING": 15270149301471737292, - "venv/lib/python3.13/site-packages/pandas/core/algorithms.py": 487939626203097713, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_asof.py": 18383318159051131669, - "venv/lib/python3.13/site-packages/sqlalchemy/connectors/pyodbc.py": 4146960201984489604, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_indexing.py": 14552860427542050771, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/rsa_key.py": 7092106298733667895, - "venv/lib/python3.13/site-packages/numpy/ma/README.rst": 13203411621071845216, - "backend/src/plugins/llm_analysis/models.py": 3600633137673071517, - "backend/src/plugins/translate/preview_llm_client.py": 14412557858942627249, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/__init__.py": 11808051681178127650, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polybase.pyi": 3404315099794022355, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/RECORD": 9678861487447993169, - "venv/lib/python3.13/site-packages/ecdsa/_version.py": 17707102226558781833, - "venv/lib/python3.13/site-packages/authlib/integrations/django_client/__init__.py": 14186136918454802843, - "venv/lib/python3.13/site-packages/pygments/lexers/actionscript.py": 8829560731160428621, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_smoke.py": 7476432112986643847, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_coercion.py": 7261787308019145312, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_formats.py": 2743326139283991615, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_tz_localize.py": 14495969595744172955, - "venv/lib/python3.13/site-packages/pandas/tests/generic/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_internal/cli/base_command.py": 10660882478126415399, - "backend/src/plugins/translate/orchestrator_sql_rows.py": 13473935462270832541, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/RECORD": 4487477737768669516, - "venv/lib/python3.13/site-packages/pydantic/_internal/_docs_extraction.py": 5210114991139191634, - "venv/lib/python3.13/site-packages/click/parser.py": 13988544851350599869, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_compare.py": 171535659467902751, - "backend/src/plugins/translate/orchestrator_query.py": 4760681990145471312, - "venv/lib/python3.13/site-packages/pip/_internal/distributions/sdist.py": 9490366272695301385, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_get_numeric_data.py": 5896318696417090902, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_json_table_schema.py": 14454690938977069049, - "venv/lib/python3.13/site-packages/pandas/core/_numba/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_apply.py": 7511915990531229598, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/resolver.py": 2492962412506082234, - "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/hooks.py": 8580161128344266243, - "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.py": 11758491058846790938, - "venv/lib/python3.13/site-packages/numpy/f2py/__version__.pyi": 9759534743796867731, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dlpack.py": 7908102652282922952, - "venv/lib/python3.13/site-packages/httpx/_transports/base.py": 6498990531443644896, - "venv/lib/python3.13/site-packages/pandas/core/window/ewm.py": 12143982379243011357, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_infer_objects.py": 16868563755487479303, - "venv/lib/python3.13/site-packages/pandas/core/internals/api.py": 14632030170441237968, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/inference.py": 2786441797589123900, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py": 7707707044867513457, - "venv/lib/python3.13/site-packages/PIL/_version.py": 3025206805667405876, - "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/RECORD": 7266315886702289726, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-2.csv": 4052796393463357888, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_color.py": 3700828402084646308, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/memmap.pyi": 2834143910417841603, - "venv/lib/python3.13/site-packages/PIL/_typing.py": 17407980360703360848, - "venv/lib/python3.13/site-packages/git/objects/fun.py": 15014209679156260865, - "venv/lib/python3.13/site-packages/urllib3/fields.py": 9503202008440141421, - "frontend/src/lib/stores/taskDrawer.js": 6659505033581293370, - "venv/lib/python3.13/site-packages/pandas/_libs/json.pyi": 10989301892466547548, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_ufunc.py": 669019702416198889, - "frontend/src/lib/api/translate/schedules.js": 8616345664085016472, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_dict.py": 16252265723192124609, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/proxy.py": 13008557041076030198, - "venv/bin/pyrsa-verify": 6762739642629904442, - "venv/lib/python3.13/site-packages/passlib/tests/test_context.py": 15195609282700801214, - "frontend/src/components/auth/ProtectedRoute.svelte": 7705373237339863677, - "backend/src/schemas/settings.py": 7182606947764184429, - "backend/src/services/clean_release/__tests__/test_source_isolation.py": 17714198919084455758, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/halffloat.h": 16913381775994652343, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_utils.pyi": 12312677132342982866, - "venv/lib/python3.13/site-packages/attr/_funcs.py": 5302917072419624193, - "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/parse.py": 2427019397934437210, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/setup.py": 17086801293303202021, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_setops.py": 13440916133402971190, - "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending_distributions.pyx": 15302775787158991386, - "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_timedelta.py": 364160935264757405, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/__init__.py": 3969805865048730851, - "venv/lib/python3.13/site-packages/greenlet/tests/test_stack_saved.py": 7767924647054186572, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd.py": 7577408467041941595, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_get_dummies.py": 14871264482622327003, - "venv/lib/python3.13/site-packages/httpcore/__init__.py": 5897259569277532401, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_filters.py": 17271344092069736999, - "venv/lib/python3.13/site-packages/apscheduler/executors/gevent.py": 17122637996105344344, - "venv/lib/python3.13/site-packages/fastapi/security/open_id_connect_url.py": 3502444317759870079, - "venv/lib/python3.13/site-packages/passlib/tests/__init__.py": 16543763165305017760, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_between.py": 337429135216881486, - "venv/lib/python3.13/site-packages/PIL/Hdf5StubImagePlugin.py": 15654153796225833950, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/auth.py": 13542332344403032059, - "venv/lib/python3.13/site-packages/pygments/lexers/amdgpu.py": 17249439604111838979, - "frontend/src/lib/api/translate/dictionaries.js": 13928848549982189213, - "venv/lib/python3.13/site-packages/attr/_compat.py": 4016698632899969390, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-np0-objarr.npy": 1615546603475261360, - "venv/lib/python3.13/site-packages/httpcore/_async/socks_proxy.py": 9026788710898138090, - "venv/lib/python3.13/site-packages/pygments/plugin.py": 18006138132596504101, - "venv/lib/python3.13/site-packages/pip/_internal/cli/cmdoptions.py": 12107733000019393631, - "venv/lib/python3.13/site-packages/jose/backends/_asn1.py": 14123487576864105793, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_attr_equal.py": 5612259834202470413, - "frontend/build/_app/immutable/nodes/29.BNtnzlh8.js": 13615129204919114468, - "venv/lib/python3.13/site-packages/greenlet/TPythonState.cpp": 12828594265749606443, - "venv/lib/python3.13/site-packages/websockets/exceptions.py": 12048063047468402740, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/dtypes.pyi": 15114028503984522176, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_indexing.py": 11572911419313573163, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_cov_corr.py": 13652339565475304679, - "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/RECORD": 10036839994791510159, - "venv/lib/python3.13/site-packages/jeepney/tests/test_fds.py": 6257376331171761928, - "venv/lib/python3.13/site-packages/pygments/lexers/_julia_builtins.py": 8846111188795315103, - "backend/src/core/superset_client/_databases.py": 7987972129012382620, - "backend/src/services/git/__init__.py": 14011752637167919253, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_util.py": 16024147572807865219, - "venv/lib/python3.13/site-packages/uvicorn/supervisors/watchfilesreload.py": 13062440477475586751, - "frontend/src/lib/components/assistant/__tests__/assistant_first_message.integration.test.js": 16494645867501045726, - "venv/lib/python3.13/site-packages/jaraco/context/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/starlette/requests.py": 4582424111350387010, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/__init__.py": 7316739139609490520, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_numba.py": 1548992314517942530, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_core_functionalities.py": 10449747865888948579, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tolist.py": 8343058000369672317, - "venv/lib/python3.13/site-packages/pygments/regexopt.py": 16073437303824961930, - "venv/lib/python3.13/site-packages/cffi/_cffi_include.h": 13094899814611950155, - "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.py": 2401931196871484449, - "venv/lib/python3.13/site-packages/_pytest/fixtures.py": 1442767529726551116, - "venv/lib/python3.13/site-packages/starlette/templating.py": 9242638124487797988, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_replace.py": 8166203537440976347, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/exceptions.py": 14982764273485726199, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_mixins.py": 12351373879926460719, - "venv/lib/python3.13/site-packages/_pytest/reports.py": 13930709338396699351, - "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_byteswap.py": 5090287710338893350, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_pickle.py": 388513670243918273, - "venv/lib/python3.13/site-packages/pygments/lexers/email.py": 4355246279485460399, - "venv/lib/python3.13/site-packages/pygments/lexers/julia.py": 13516407944275342328, - "venv/lib/python3.13/site-packages/idna/core.py": 7725813731640753267, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_histograms.py": 47631283818191049, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/util.py": 5252158959761945519, - "frontend/src/lib/components/reports/__tests__/report_type_profiles.test.js": 498330292141991614, - "backend/src/services/dataset_review/orchestrator_pkg/_helpers.py": 3718757635506173013, - "venv/lib/python3.13/site-packages/secretstorage/__init__.py": 4535964275649588672, - "venv/lib/python3.13/site-packages/numpy/random/bit_generator.cpython-313-x86_64-linux-gnu.so": 2574035311375507054, - "venv/lib/python3.13/site-packages/pydantic/v1/validators.py": 1060954771151908883, - "backend/src/plugins/translate/preview_executor.py": 7636554040403814604, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/__main__.py": 487896753130729554, - "backend/tests/test_task_manager.py": 1706217361689506763, - "backend/git_repos/remote/test-repo.git/refs/heads/main": 7667767390913789840, - "venv/lib/python3.13/site-packages/sqlalchemy/util/typing.py": 17638587764345605306, - "venv/lib/python3.13/site-packages/pygments/styles/borland.py": 17570558758932580659, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/AB.inc": 10441778083831997423, - "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.pyi": 2029639875417260268, - "venv/lib/python3.13/site-packages/pygments/lexers/sophia.py": 15971500155124949058, - "venv/lib/python3.13/site-packages/pygments/lexers/_scilab_builtins.py": 17453812809700086888, - "frontend/build/_app/immutable/chunks/DPLPFnYm.js": 2792883742193989670, - "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.py": 6617116180936986481, - "backend/src/api/routes/__tests__/test_reports_openapi_conformance.py": 17043883737206361151, - "backend/src/api/routes/mappings.py": 7071183920129492341, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_style.py": 14810883299259169406, - "venv/lib/python3.13/site-packages/git/index/base.py": 641556304637379636, - "venv/lib/python3.13/site-packages/numpy/f2py/setup.cfg": 17974180080760231128, - "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.py": 8786558894094307341, - "venv/lib/python3.13/site-packages/httpcore/_backends/base.py": 5491727479625093183, - "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/RECORD": 7320381591791379627, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_dtypes.py": 13065857166166716628, - "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.pyi": 6546751036506752550, - "venv/lib/python3.13/site-packages/pygments/styles/nord.py": 8469538903422182155, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_abc.py": 10164280045317807365, - "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.py": 15989335816452913951, - "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.py": 4940170059946018356, - "venv/lib/python3.13/site-packages/referencing/typing.py": 8296636464219681747, - "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.py": 893743087939984792, - "venv/lib/python3.13/site-packages/pandas/core/window/online.py": 13551140636252302201, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_grouping.py": 5994909693214299971, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_constructors.py": 7466113171256856591, - "backend/src/services/clean_release/audit_service.py": 3614108458934359126, - "backend/src/services/rbac_permission_catalog.py": 8206280020500996966, - "backend/src/plugins/translate/preview_response_parser.py": 15690759478655959205, - "venv/lib/python3.13/site-packages/gitdb/db/ref.py": 1176701624460337371, - "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/METADATA": 14180973198574731599, - "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/numpy/testing/overrides.pyi": 17408923209056015964, - "venv/lib/python3.13/site-packages/numpy/_typing/_nested_sequence.py": 7827259347937485408, - "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/fastapi/websockets.py": 9910052969532075719, - "venv/lib/python3.13/site-packages/websockets/legacy/__init__.py": 12332512329533591682, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py": 10843527833285941674, - "venv/lib/python3.13/site-packages/more_itertools/__init__.py": 9858612105173082060, - "venv/lib/python3.13/site-packages/_pytest/python.py": 1829073958095716309, - "venv/lib/python3.13/site-packages/_pytest/nodes.py": 515939386237558331, - "venv/lib/python3.13/site-packages/pydantic/_internal/_dataclasses.py": 15256193972947054890, - "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pxd": 14261507718442469988, - "venv/lib/python3.13/site-packages/passlib/utils/pbkdf2.py": 15802959653228956404, - "venv/lib/python3.13/site-packages/pyasn1/type/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/pandas/core/arrays/categorical.py": 15993211255162930859, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_join.py": 17874591841487372992, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_is_monotonic.py": 12769599198035357753, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/interface.py": 3134071530627935964, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_inclusive.py": 1389676378885557519, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_liboffsets.py": 14705822637347212540, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_sparse_accessor.py": 6774374030220202353, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/lambdas.py": 13377298868598623228, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py": 9888795404090331319, - "venv/lib/python3.13/site-packages/urllib3/util/ssl_.py": 11720964010284185952, - "venv/lib/python3.13/site-packages/charset_normalizer/utils.py": 11724147997933584095, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py": 10057637461647348368, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_reindex.py": 15794750188594767026, - "venv/lib/python3.13/site-packages/uvicorn/supervisors/__init__.py": 15971002342788501945, - "venv/lib/python3.13/site-packages/PIL/SunImagePlugin.py": 7661622930404688367, - "venv/lib/python3.13/site-packages/uvicorn/workers.py": 7213290478118197047, - "venv/lib/python3.13/site-packages/pygments/lexers/monte.py": 15158829991357994573, - "venv/lib/python3.13/site-packages/pygments/lexers/mojo.py": 8616283481592061285, - "venv/lib/python3.13/site-packages/pygments/lexers/resource.py": 8057351545636349791, - "venv/lib/python3.13/site-packages/authlib/oauth1/errors.py": 1154126353335030046, - "frontend/src/services/taskService.js": 11368052191249479533, - "backend/src/services/clean_release/source_isolation.py": 18208654007489616188, - "venv/lib/python3.13/site-packages/pygments/lexers/console.py": 18266795648198475028, - "venv/lib/python3.13/site-packages/urllib3/__init__.py": 1854778274753799815, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/infer.py": 12541904372617915365, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/WHEEL": 7145482834744213753, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate.py": 16723865897349422996, - "venv/lib/python3.13/site-packages/pandas/io/sas/sas7bdat.py": 17851617851457266799, - "venv/lib/python3.13/site-packages/_pytest/warning_types.py": 10695097290648045427, - "venv/lib/python3.13/site-packages/_pytest/python_api.py": 12953851690889336092, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py": 16550134594771291234, - "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_algorithms.py": 15219408648894515493, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polyutils.py": 675639791972685455, - "venv/lib/python3.13/site-packages/passlib/hosts.py": 11171402820797380938, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_shift.py": 14026124784027171225, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_constructors.py": 9815164146739254076, - "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/RECORD": 15574202654585730126, - "backend/src/services/clean_release/repositories/policy_repository.py": 10990781278715170404, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/array.py": 13840510238256626632, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/simple.py": 11050636051019777317, - "venv/lib/python3.13/site-packages/pandas/tests/base/__init__.py": 15130871412783076140, - "backend/src/core/cot_logger.py": 12977179701814261121, - "venv/lib/python3.13/site-packages/pandas/_config/display.py": 433650013567734821, - "venv/lib/python3.13/site-packages/numpy/_core/tests/_natype.py": 12013743717306900860, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8693/__init__.py": 11065844267208884531, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_ios.h": 6751259472945638998, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_cli.py": 3173259257428855556, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/LICENSE": 14599279238716790189, - "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth2_session.py": 7076806577412682835, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_unary.py": 8046543893978198672, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_custom_dtypes.py": 12322100282959605055, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/conftest.py": 9673372914396625461, - "venv/lib/python3.13/site-packages/uvicorn/protocols/http/httptools_impl.py": 10367325397209016951, - "frontend/src/lib/components/reports/__tests__/report_card.ux.test.js": 14899927226278257748, - "venv/lib/python3.13/site-packages/_pytest/tracemalloc.py": 5530234062530858720, - "venv/lib/python3.13/site-packages/pandas/_libs/groupby.pyi": 6154952803757623626, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/client.py": 17305914656270781911, - "venv/lib/python3.13/site-packages/pandas/_libs/hashtable.cpython-313-x86_64-linux-gnu.so": 16963890771704942465, - "frontend/build/_app/immutable/chunks/DvPRmPmp.js": 8114859252616489039, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/METADATA": 12295263493152296681, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_null_file.py": 6885565068723353414, - "venv/lib/python3.13/site-packages/PIL/_imaging.pyi": 17119084207765761921, - "venv/lib/python3.13/site-packages/pygments/formatters/__init__.py": 8009871891954370829, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop_duplicates.py": 5874427993953991216, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_compat.py": 4677414058216516380, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_ddl.py": 3690189094298044728, - "venv/lib/python3.13/site-packages/pygments/lexers/inferno.py": 9056274496469409594, - "venv/lib/python3.13/site-packages/passlib/totp.py": 14590474309565233318, - "venv/lib/python3.13/site-packages/pip/_internal/cli/autocompletion.py": 7651919329635563739, - "backend/src/services/clean_release/stages/__init__.py": 11595548160903612178, - "venv/lib/python3.13/site-packages/pandas/_testing/__init__.py": 10127496080404419481, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_astype.py": 7542068949396266883, - "frontend/e2e/e2e-nohealth.mjs": 5921562935931064381, - "venv/lib/python3.13/site-packages/dateutil/rrule.py": 398469817784230512, - "backend/src/services/clean_release/report_builder.py": 6953311294119437848, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90": 9097998998863007705, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_scalar_compat.py": 1306236983392218709, - "venv/lib/python3.13/site-packages/numpy/version.pyi": 5075382895829889457, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dim2.py": 5767600151459095125, - "venv/lib/python3.13/site-packages/numpy/_pytesttester.py": 17737911110576747508, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/json_schema_test_suite.py": 6152158310190822762, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/WHEEL": 5838667082726674838, - "venv/lib/python3.13/site-packages/pygments/lexers/graphql.py": 2307854666015224677, - "venv/lib/python3.13/site-packages/pandas/io/common.py": 12088195203620154171, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_nlargest.py": 1423106021399469694, - "venv/lib/python3.13/site-packages/pygments/styles/arduino.py": 4578385147314541233, - "venv/lib/python3.13/site-packages/websockets/sync/utils.py": 15135020989207191168, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_logical_ops.py": 4438104524064299182, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py": 7421910137064160936, - "frontend/build/_app/immutable/nodes/31.DE1yVSBM.js": 10141074442986077311, - "frontend/src/routes/migration/mappings/+page.svelte": 4566398049366943407, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_sorted.py": 1899608688401238388, - "venv/lib/python3.13/site-packages/pygments/lexers/zig.py": 470431199354307668, - "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators_v1.py": 16723743964226526155, - "venv/lib/python3.13/site-packages/pygments/lexers/foxpro.py": 14032656072384708293, - "venv/lib/python3.13/site-packages/pygments/lexers/scripting.py": 4167168074165473790, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data": 11957232619107868023, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/constants.pyi": 4415188581374004936, - "docker/frontend.Dockerfile": 13262735279052210084, - "venv/lib/python3.13/site-packages/pip/_internal/commands/download.py": 7533669665002975823, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/core/indexers/objects.py": 409599993084996593, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqlconnector.py": 17538029557373507617, - "venv/lib/python3.13/site-packages/PIL/MpoImagePlugin.py": 644327650732339301, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply.py": 8103417303073393969, - "venv/lib/python3.13/site-packages/fastapi/__init__.py": 11054203163075417954, - "venv/lib/python3.13/site-packages/pycparser/c_lexer.py": 10964496587169353564, - "venv/lib/python3.13/site-packages/pygments/styles/solarized.py": 11231143047572616298, - "venv/lib/python3.13/site-packages/pygments/styles/lilypond.py": 12486578704132023691, - "venv/lib/python3.13/site-packages/pandas/core/internals/managers.py": 13547912653290063698, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/charset_normalizer/__main__.py": 8887772289570078278, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/einsumfunc.pyi": 200771351328522379, - "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django_source.py": 15577951591316518967, - "venv/lib/python3.13/site-packages/pydantic/v1/fields.py": 3948219773415054006, - "venv/lib/python3.13/site-packages/starlette/testclient.py": 16088848330558215194, - "venv/lib/python3.13/site-packages/_pytest/warnings.py": 8633394774569709013, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/expression.py": 1248029135284283479, - "venv/lib/python3.13/site-packages/pygments/lexers/yang.py": 7409365668425173823, - "venv/lib/python3.13/site-packages/rsa/common.py": 10921682819204792805, - "venv/lib/python3.13/site-packages/pydantic/types.py": 785880062468926292, - "frontend/static/favicon.svg": 6451919037497541980, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/aws.py": 1364297790170663941, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraysetops.py": 10588903945244480732, - "backend/tests/test_logging_audit_fixes.py": 14806902244422319839, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_range.py": 9900908262700749861, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/common/pythoncapi-compat/COPYING": 3474104874623144155, - "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/expressions.py": 8015786996064244656, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_alpha_unix.h": 2759424570606117942, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufuncs.py": 12732599294816239111, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reshape.py": 10576230966727810832, - "venv/lib/python3.13/site-packages/uvicorn/middleware/message_logger.py": 14825516604555033580, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py": 5728866271812501558, - "venv/lib/python3.13/site-packages/referencing/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c": 8494977275215578998, - "venv/lib/python3.13/site-packages/passlib/win32.py": 5311393450489898748, - "venv/lib/python3.13/site-packages/urllib3/contrib/pyopenssl.py": 11839715589709210412, - "venv/lib/python3.13/site-packages/pygments/lexers/boa.py": 14409319610243925864, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_combine_concat.py": 3201068805128232483, - "venv/lib/python3.13/site-packages/pandas/plotting/__init__.py": 13230487326686617492, - "backend/src/services/clean_release/stages/base.py": 344723354852893815, - "venv/lib/python3.13/site-packages/authlib/oauth2/auth.py": 8455258275234626534, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_collections.py": 14307204206312829238, - "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.pyi": 9854069702366900663, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/WHEEL": 18203500019759199992, - "venv/lib/python3.13/site-packages/pygments/lexers/gsql.py": 15294109558028161389, - "venv/lib/python3.13/site-packages/pygments/lexers/rita.py": 8105458520706587972, - "venv/lib/python3.13/site-packages/pygments/lexers/_ada_builtins.py": 16331776886501464264, - "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.pyi": 12275242654430570028, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine_first.py": 3100691245280812910, - "venv/lib/python3.13/site-packages/fastapi/middleware/cors.py": 7452860773712601508, - "venv/lib/python3.13/site-packages/ecdsa/test_ecdsa.py": 17595025859105321562, - "venv/lib/python3.13/site-packages/ecdsa/eddsa.py": 15966858338456571506, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/datasource.pyi": 80441145804744162, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isetitem.py": 14895552405828068177, - "frontend/build/favicon.svg": 6451919037497541980, - "backend/tests/core/test_defensive_guards.py": 1048600814279591148, - "backend/tests/test_translate_scheduler_guard.py": 13396608843530344156, - "venv/lib/python3.13/site-packages/idna/package_data.py": 6583909243002417298, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/url.py": 1558176735588971829, - "venv/lib/python3.13/site-packages/cffi/commontypes.py": 11198107299826138465, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_droplevel.py": 2071197388394658690, - "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pygments/lexers/mime.py": 7768464764849718825, - "backend/tests/test_smoke_app.py": 7819901244710945164, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation": 13992741783834278677, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/wrappers.py": 315409799569602977, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator": 6870991911243684132, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/api.py": 9829629144629841277, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/compiler.py": 11662494978292401568, - "venv/lib/python3.13/site-packages/pandas/tests/apply/conftest.py": 13798335354961261346, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/yaml.py": 17801117405950663611, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/discovery.py": 12479996594187326798, - "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.pyi": 15848834171197104301, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/resource_protector.py": 3563910821279222695, - "venv/lib/python3.13/site-packages/PIL/ExifTags.py": 6869879826623916830, - "venv/lib/python3.13/site-packages/idna-3.11.dist-info/WHEEL": 8600534672961461758, - "backend/src/models/translate.py": 17253774670319669066, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_scalar.py": 2434773821902319678, - "backend/src/plugins/translate/__tests__/test_dictionary_crud.py": 17953628511626558088, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_timeseries_window.py": 1973365560758236222, - "venv/lib/python3.13/site-packages/jaraco/functools/__init__.py": 15334412919279565528, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/errors.py": 6538052228921426956, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE": 4274653168153720331, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/__init__.py": 15130871412783076140, - "frontend/src/lib/components/reports/__tests__/reports_page.integration.test.js": 16463062768004950066, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_round.py": 8336918400205461173, - "venv/lib/python3.13/site-packages/numpy/_utils/__init__.pyi": 13530522898409268883, - "venv/lib/python3.13/site-packages/passlib/tests/__main__.py": 16477180140297957650, - "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py": 63497920264089252, - "venv/lib/python3.13/site-packages/jeepney/io/tests/utils.py": 10346859893683522113, - "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/__init__.py": 4390908730288159455, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_ipython_compat.py": 12632271159842988561, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/provision.py": 13156893203444936309, - "venv/lib/python3.13/site-packages/pycparser/ply/ygen.py": 5520340773074632724, - "venv/lib/python3.13/site-packages/uvicorn/config.py": 17317823506849880916, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_cut.py": 7800833253841657380, - "venv/lib/python3.13/site-packages/dateutil/parser/_parser.py": 9443336890192151397, - "backend/git_repos/remote/test-repo.git/refs/heads/dev": 8596267258668462395, - "frontend/src/components/llm/__tests__/provider_config.integration.test.js": 12605115626277870995, - "venv/lib/python3.13/site-packages/keyring/compat/__init__.py": 7578020229796085753, - "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/integration.py": 3085827906490477329, - "venv/lib/python3.13/site-packages/pip/_internal/utils/temp_dir.py": 8657533190026387896, - "venv/lib/python3.13/site-packages/numpy/typing/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/sync.py": 6189260178302531376, - "backend/src/plugins/translate/_token_budget.py": 1545056585783198863, - "venv/lib/python3.13/site-packages/pygments/lexers/hexdump.py": 10665271113239513484, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_arithmetic.py": 13320788210970132239, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/__init__.py": 9884041726796476720, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90": 14350239197565389508, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/version.py": 5000350193835202949, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_misc.py": 8706265665356094801, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_cpp.cpython-313-x86_64-linux-gnu.so": 7490281502544276964, - "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pillow.libs/libwebpdemux-747f2b49.so.2.0.17": 7615380692384566654, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_join.py": 11910166566689889389, - "venv/lib/python3.13/site-packages/httpx/_api.py": 6697370469329778523, - "venv/lib/python3.13/site-packages/git/index/typ.py": 11661540784850363024, - "frontend/src/lib/stores/assistantChat.js": 13807808925025688939, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/styles/fruity.py": 7925019839136894457, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufuncs.pyi": 14995898537484305307, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_setops.py": 14246225281428284850, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/__init__.py": 2345997696115514124, - "frontend/src/components/PasswordPrompt.svelte": 13739802421315835398, - "frontend/src/components/git/GitManager.svelte": 2759220622954168718, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/json.py": 15373167408891671190, - "venv/lib/python3.13/site-packages/psycopg2/__init__.py": 15798412693009721199, - "venv/lib/python3.13/site-packages/git/cmd.py": 8854786163152637148, - "venv/lib/python3.13/site-packages/pyasn1/compat/__init__.py": 5902203086150636670, - "venv/bin/activate.csh": 14513616043256836238, - "venv/lib/python3.13/site-packages/pandas/_libs/missing.cpython-313-x86_64-linux-gnu.so": 1990755879067132155, - "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/auto.py": 12818217385551437286, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/METADATA": 9041650844081036822, - "venv/lib/python3.13/site-packages/jose/backends/native.py": 50023158618000658, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_index.py": 4908727359687606870, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv": 1665171675551692225, - "backend/src/services/clean_release/__tests__/test_compliance_orchestrator.py": 4990536554328205752, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.obj": 11967637259540485652, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timestamp.py": 10308799534491190078, - "backend/src/models/__init__.py": 13280325675752905975, - "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/functions.py": 14107377669163193871, - "backend/src/plugins/storage/plugin.py": 17070362975404691950, - "venv/lib/python3.13/site-packages/pandas/_config/config.py": 1494288055210911451, - "venv/lib/python3.13/site-packages/authlib/jose/jwk.py": 13560749074922587626, - "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/__init__.py": 11283047029180207588, - "venv/lib/python3.13/site-packages/pandas/core/reshape/tile.py": 17137524194129840833, - "venv/lib/python3.13/site-packages/pandas/tests/window/moments/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/dtype_api.h": 17040779421165903019, - "venv/lib/python3.13/site-packages/httpx/_models.py": 6516278895118988231, - "venv/lib/python3.13/site-packages/jose/backends/__init__.py": 16581763658239070112, - "venv/lib/python3.13/site-packages/jaraco/classes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/ecdsa/rfc6979.py": 11564966030899162026, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_calendar.py": 12313641252472031631, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connection.py": 8190661510572400096, - "venv/lib/python3.13/site-packages/git/objects/util.py": 691018806932355307, - "venv/lib/python3.13/site-packages/pygments/formatters/svg.py": 11686316844190214147, - "frontend/src/routes/admin/roles/+page.svelte": 1343040884276845574, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_twodim_base.py": 17623133613018058380, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/generic.py": 17755579497690180620, - "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA": 18410956221497090898, - "venv/lib/python3.13/site-packages/authlib/oidc/discovery/well_known.py": 8259335680633926377, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_gcs.py": 7733247456252965901, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_datetimelike.py": 5317270578347271174, - "venv/lib/python3.13/site-packages/pandas/io/sas/sasreader.py": 12766780210114366112, - "venv/lib/python3.13/site-packages/cffi/_imp_emulation.py": 17246725564704952212, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/RECORD": 3617343778671172258, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/provision.py": 17812733620485633975, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_function.py": 7048185308307653546, - "venv/lib/python3.13/site-packages/pycparser/ply/yacc.py": 4218889705926129841, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/INSTALLER": 17282701611721059870, - "frontend/src/routes/admin/users/+page.svelte": 4464001185352807842, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/licenses/LICENSE": 17020744174398828059, - "backend/src/core/auth/config.py": 2496494846548336902, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sample.py": 16877779557071324115, - "backend/src/plugins/translate/orchestrator.py": 2899451611486868631, - "venv/lib/python3.13/site-packages/multipart/__init__.py": 6496114190873890851, - "backend/src/api/routes/dashboards/_listing_routes.py": 1750634467656242702, - "venv/lib/python3.13/site-packages/uvicorn/middleware/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/cffi/ffiplatform.py": 6782148110863549472, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/npyio.pyi": 14147712281086095231, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/__init__.py": 7526309124863950484, - "venv/lib/python3.13/site-packages/PIL/PpmImagePlugin.py": 7107324729714470853, - "venv/lib/python3.13/site-packages/pygments/lexers/devicetree.py": 9820277168995231927, - "venv/lib/python3.13/site-packages/pygments/lexers/prolog.py": 599539463980699865, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/dotenv.py": 5872848911499749500, - "backend/src/core/mapping_service.py": 17981290763325170519, - "backend/src/api/routes/__tests__/test_profile_api.py": 1724401885939803766, - "venv/lib/python3.13/site-packages/numpy/lib/__init__.pyi": 1537495515469182226, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_sorting.py": 8944017570338511677, - "venv/lib/python3.13/site-packages/numpy/lib/mixins.pyi": 15597536290223628777, - "backend/git_repos/remote/test-repo.git/refs/heads/feature/e2e-update": 9577764946931187657, - "venv/lib/python3.13/site-packages/pip/_internal/operations/check.py": 16650663913976953800, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py": 7019253290755243568, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90": 10939657740734987454, - "venv/lib/python3.13/site-packages/numpy/_core/_asarray.py": 3468915833437229425, - "venv/lib/python3.13/site-packages/rsa/randnum.py": 13958355153634534526, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py": 11425629729736599320, - "backend/src/core/migration_engine.py": 3310429374293524108, - "backend/src/services/git_service.py": 1930048176535450912, - "venv/lib/python3.13/site-packages/pygments/styles/xcode.py": 14124729477757765388, - "venv/lib/python3.13/site-packages/pygments/lexers/_postgres_builtins.py": 2383906454995727700, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/vector.py": 9941185556118343263, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5support-d0bcff84.so.0.1": 16819924515291719993, - "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__init__.py": 2833016678144975576, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/request.py": 10492090878715126550, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayobject.h": 4345432890284821918, - "venv/lib/python3.13/site-packages/numpy/strings/__init__.pyi": 6213864891045042045, - "venv/lib/python3.13/site-packages/passlib/tests/test_totp.py": 9150389741890748343, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.pyi": 1830368009811266890, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/base.py": 3250660921154829815, - "venv/lib/python3.13/site-packages/PIL/FliImagePlugin.py": 13364963053197422923, - "venv/lib/python3.13/site-packages/anyio/_core/_sockets.py": 10525237827959090532, - "venv/lib/python3.13/site-packages/pandas/core/arrays/numeric.py": 17834058423729918687, - "frontend/src/lib/stores/__tests__/mocks/state.js": 3616783395254238777, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_concatenate_chunks.py": 9693420220003544490, - "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.py": 4037074830103951000, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/testing.pyi": 16263777835572515739, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/mod.pyi": 10591120373577657317, - "venv/lib/python3.13/site-packages/numpy/random/_generator.cpython-313-x86_64-linux-gnu.so": 15625019745021657670, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/transforms.py": 3773159138960141434, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_arrayobject.py": 9578555381494297966, - "venv/lib/python3.13/site-packages/numpy/conftest.py": 8971879716683736515, - "venv/lib/python3.13/site-packages/pandas/core/groupby/ops.py": 2036968385544457016, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_libfrequencies.py": 16302676625743291594, - "venv/lib/python3.13/site-packages/fastapi/exception_handlers.py": 9907950997607808699, - "venv/lib/python3.13/site-packages/jose/constants.py": 10880650415673457194, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/gevent.py": 4811840397266785551, - "venv/lib/python3.13/site-packages/numpy/_core/getlimits.pyi": 15746478550640231553, - "venv/lib/python3.13/site-packages/passlib/apps.py": 4633269405597895766, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/base.py": 7855217087916771270, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/METADATA": 2053484635654179443, - "venv/lib/python3.13/site-packages/pygments/lexers/ada.py": 17032408976634308999, - "venv/lib/python3.13/site-packages/pandas/tests/io/generate_legacy_storage_files.py": 11015954144633661960, - "venv/lib/python3.13/site-packages/attrs/validators.py": 10346563361083429998, - "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.py": 15854257948148516490, - "venv/lib/python3.13/site-packages/_pytest/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi": 1065808244870331598, - "venv/lib/python3.13/site-packages/fastapi/middleware/wsgi.py": 3706578020491442104, - "venv/lib/python3.13/site-packages/pip/_vendor/pkg_resources/__init__.py": 1677532855362260338, - "venv/lib/python3.13/site-packages/passlib/handlers/sun_md5_crypt.py": 1949993216707182407, - "venv/lib/python3.13/site-packages/pandas/core/groupby/grouper.py": 18110568057754450953, - "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_ewm.py": 12153690217678546798, - "venv/lib/python3.13/site-packages/passlib/__init__.py": 6987142392711441525, - "venv/lib/python3.13/site-packages/pydantic/error_wrappers.py": 11273827025986230629, - "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.py": 12355826783958402233, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/horizontal_shard.py": 17615732108308858890, - "venv/lib/python3.13/site-packages/jeepney/io/tests/test_blocking.py": 6312017389529916004, - "venv/lib/python3.13/site-packages/pandas/conftest.py": 747626550806435763, - "venv/lib/python3.13/site-packages/pandas/core/generic.py": 10174952306641057447, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_records.py": 18167578114159312327, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_subclass.py": 11096337912872573314, - "venv/lib/python3.13/site-packages/PIL/AvifImagePlugin.py": 1872412416505003364, - "venv/lib/python3.13/site-packages/PIL/ImagePalette.py": 9227837918026991107, - "venv/lib/python3.13/site-packages/httpcore/_backends/anyio.py": 6167729964577005634, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE": 17675192170670564526, - "venv/lib/python3.13/site-packages/anyio/abc/_streams.py": 8089057973257658396, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_gcc.h": 3561524604274567339, - "venv/lib/python3.13/site-packages/rpds/rpds.cpython-313-x86_64-linux-gnu.so": 561326734302492859, - "venv/lib/python3.13/site-packages/_pytest/threadexception.py": 10464996327276961035, - "venv/lib/python3.13/site-packages/git/index/fun.py": 18338379518768926372, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.pyi": 2700568594438441246, - "venv/lib/python3.13/site-packages/passlib/handlers/sha1_crypt.py": 5752556581809938954, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/blocking.py": 3483388533957772681, - "venv/lib/python3.13/site-packages/pygments/lexers/_css_builtins.py": 17478340487186531268, - "frontend/src/routes/storage/+page.svelte": 5003283673039328108, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/wait.py": 6196757964348666082, - "frontend/src/lib/components/dataset-review/__tests__/validation_findings_panel.ux.test.js": 8994492423600483794, - "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/LICENSE": 16343563559291870811, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/checks.pyx": 13187505236986855177, - "venv/lib/python3.13/site-packages/tzlocal/utils.py": 7893867974548929154, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_fillna.py": 16297834601116528166, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/exclusions.py": 15852672500377116297, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/requests.py": 6703055041957748929, - "venv/lib/python3.13/site-packages/websockets/sync/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/filters/__init__.py": 2992007913496948339, - "venv/lib/python3.13/site-packages/numpy/typing/tests/test_isfile.py": 14544060093268573418, - "venv/lib/python3.13/site-packages/pygments/lexers/functional.py": 15896849233007178031, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90": 6123192245816905092, - "venv/lib/python3.13/site-packages/pygments/formatters/terminal256.py": 11473927781167132440, - "venv/bin/normalizer": 10972303485259566838, - "venv/lib/python3.13/site-packages/click/testing.py": 15973659312284678327, - "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.py": 7658234162211356265, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_toml_compat.py": 10196543528439925412, - "frontend/src/routes/settings/LlmSettings.svelte": 11336336338708911991, - "frontend/src/components/TaskList.svelte": 3024343043730631288, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py": 6152202474302791232, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numeric.py": 5627177940393829333, - "frontend/build/_app/immutable/nodes/0.BaFrsBeG.js": 13601843076067331330, - "frontend/build/_app/immutable/chunks/BLWhLUWr.js": 10944150245569987395, - "backend/src/scripts/clean_release_tui.py": 11100359353752859553, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_spinners.py": 15873416546130487469, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.BSD": 16833702494864671773, - "backend/src/schemas/dataset_review.py": 15720223123457526104, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/RECORD": 10264342250058307301, - "venv/lib/python3.13/site-packages/gitdb/typ.py": 16374739906244805047, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling.py": 18221459425751198218, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/RECORD": 7914594107698271488, - "backend/src/api/routes/__tests__/test_assistant_api.py": 4079781811717182404, - "backend/tests/test_deprecation_audit_fixes.py": 17902995210831708431, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_comparison.py": 4611207880323503098, - "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_salsa.py": 1756536674254931838, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_searchsorted.py": 12074107109575676897, - "backend/src/core/plugin_base.py": 11649432288706102843, - "venv/lib/python3.13/site-packages/pandas/core/series.py": 11618272682977710696, - "venv/lib/python3.13/site-packages/numpy/core/records.py": 12604652690721760437, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_read.py": 8825002468745406134, - "venv/lib/python3.13/site-packages/yaml/resolver.py": 6669674521776449098, - "venv/lib/python3.13/site-packages/numpy/ma/LICENSE": 6723325434476453127, - "backend/src/api/routes/assistant/_schemas.py": 4855661257485426649, - "backend/src/api/routes/dashboards/__init__.py": 15214026957520044598, - "venv/lib/python3.13/site-packages/pandas/plotting/_core.py": 6766059152026241747, - "backend/src/schemas/translate.py": 15939985987703420591, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation": 4826455560768665215, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/implicit.py": 7379110378465568776, - "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/provider.py": 16463243654123731993, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_groupby.py": 15721254196883995634, - "backend/src/models/mapping.py": 3582903535753840317, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/errors.py": 4817746830102488448, - "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/METADATA": 6502714564886871819, - "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.pyi": 13945478633722616250, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_shape_base.py": 8837845103338426570, - "frontend/src/services/toolsService.js": 1568142461283466080, - "backend/tests/test_translate_scheduler.py": 14274816721941617887, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx": 15936470837420356071, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/registry.py": 13306388361671753373, - "venv/lib/python3.13/site-packages/numpy/f2py/__version__.py": 8588600299261398598, - "venv/lib/python3.13/site-packages/ecdsa/test_rw_lock.py": 1572802971060634697, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_construction.py": 6564829381134214401, - "venv/lib/python3.13/site-packages/keyring/cli.py": 10996746519742056101, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_subclass.py": 5540948578269213810, - "venv/lib/python3.13/site-packages/yaml/dumper.py": 11376022992370902766, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/licenses/LICENSE": 6808958893921859106, - "venv/lib/python3.13/site-packages/pillow.libs/libwebp-d8b9687f.so.7.2.0": 116215608212382352, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_index_equal.py": 10617870815989304510, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_util.py": 16908393806993809474, - "venv/lib/python3.13/site-packages/fastapi/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/packaging/_manylinux.py": 8268418900652790584, - "venv/lib/python3.13/site-packages/click/core.py": 16793133181718891193, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_macosx.h": 3653129798702716366, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_indexing.py": 4063662953863959087, - "backend/src/core/task_manager/event_bus.py": 15798578020529126889, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/decl_class.py": 6328411894571735935, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/util.py": 2866856507760047219, - "venv/lib/python3.13/site-packages/pip/_internal/utils/entrypoints.py": 11268059714209889385, - "backend/src/api/routes/translate/_metrics_routes.py": 13468336445030118059, - "venv/lib/python3.13/site-packages/websockets/legacy/server.py": 5390090919193784186, - "venv/lib/python3.13/site-packages/anyio/_core/_exceptions.py": 11969894261631227715, - "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_xport.py": 14080914637071212225, - "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/fallback.py": 4260636031748548345, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_ewm.py": 13789842684407148830, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/version.py": 14723293207188512766, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/twodim_base.pyi": 3773329770170248877, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_constructors.pyi": 4993066609272697419, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_astype.py": 4178231007649608531, - "venv/lib/python3.13/site-packages/urllib3/util/timeout.py": 17922362393077965047, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/emoji.py": 9166774203918731896, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_quantile.py": 17110581927381599978, - "venv/lib/python3.13/site-packages/attrs/__init__.py": 9502968706258875910, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numba.py": 18148155441554555618, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/compiler.py": 13924519162400330589, - "venv/include/site/python3.13/greenlet/greenlet.h": 16216120538647882082, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/__init__.py": 5863110456909134678, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dtype.py": 5336980126536664360, - "frontend/src/lib/ui/Button.svelte": 921807193049478213, - "backend/src/core/auth/repository.py": 7314530014494164270, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/fixed_string.f90": 8654788371538544793, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90": 3492659529812762861, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/dtype.pyi": 12178008080078679769, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/conftest.py": 13388202260795998613, - "venv/lib/python3.13/site-packages/pandas/arrays/__init__.py": 10005095663840461954, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90": 8680230823849248800, - "venv/lib/python3.13/site-packages/numpy/core/overrides.py": 11228841530565061867, - "backend/src/services/__init__.py": 15123879863527585264, - "backend/src/plugins/mapper.py": 1970475023222782681, - "venv/lib/python3.13/site-packages/pygments/lexers/wowtoc.py": 17527844575999013592, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py": 13763154154862871596, - "venv/lib/python3.13/site-packages/jeepney/io/__init__.py": 2568357146184259175, - "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/RECORD": 12575893084587070195, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_assignability.pyi": 1718610984396277997, - "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.py": 17055498803745289016, - "venv/lib/python3.13/site-packages/pandas/_libs/pandas_datetime.cpython-313-x86_64-linux-gnu.so": 15874094681262240628, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/_writer.py": 15053365792216907149, - "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.abi3.so": 8691731321358529264, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_cat_accessor.py": 4304062895283374927, - "venv/lib/python3.13/site-packages/PIL/ImageTk.py": 17063969714816564357, - "venv/lib/python3.13/site-packages/PIL/PcxImagePlugin.py": 1691405132377495336, - "frontend/build/_app/immutable/chunks/DahbS9be.js": 1297770004698741582, - "venv/lib/python3.13/site-packages/ecdsa/test_ecdh.py": 3338834550392548171, - "venv/lib/python3.13/site-packages/authlib/jose/__init__.py": 317573635113539563, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_keys.py": 10813898277355150779, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_functions.py": 2255133375699086300, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/interfaces.py": 5371646629319169153, - "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp.py": 16797760903996739079, - "venv/lib/python3.13/site-packages/httpx/_exceptions.py": 18399489130669465891, - "venv/lib/python3.13/site-packages/passlib/tests/test_registry.py": 15377817946543064293, - "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_builtin_md4.py": 16840174243259839994, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_label_or_level_utils.py": 3423644585913150841, - "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_stat_reductions.py": 11569525436540769152, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_readers.py": 2136472634307645842, - "venv/lib/python3.13/site-packages/fastapi/openapi/docs.py": 16735218221639179927, - "frontend/src/components/tasks/LogFilterBar.svelte": 5318774167984892372, - "backend/src/plugins/translate/_batch_sizer.py": 13074277127276828485, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/AUTHORS": 10073225185964928425, - "venv/lib/python3.13/site-packages/_pytest/capture.py": 17850967053989495422, - "frontend/build/_app/immutable/nodes/32.DGVYF_cJ.js": 2057646517212489979, - "venv/lib/python3.13/site-packages/websockets/sync/messages.py": 15699091325918681038, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_routines.py": 4860173574365060471, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_formats.py": 10263085276270778330, - "venv/lib/python3.13/site-packages/pygments/lexers/blueprint.py": 6370363226580199085, - "frontend/src/lib/components/translate/TranslationPreview.svelte": 3234775946311369733, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/_cryptography_key.py": 388489172928969873, - "backend/src/api/routes/__tests__/test_clean_release_v2_api.py": 13464989331176891726, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_period.py": 12593777226419608212, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/__init__.py": 12290228927283601067, - "backend/alembic/versions/9f8e7d6c5b4a_add_is_multimodal_to_llm_providers.py": 11090205342799426943, - "backend/src/plugins/translate/preview_resolve_provider.py": 7349483761713339246, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_info.py": 10615285239043745712, - "venv/lib/python3.13/site-packages/pandas/_testing/asserters.py": 272063856832951430, - "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.py": 7029935879540617057, - "venv/lib/python3.13/site-packages/click/exceptions.py": 9734955259447933725, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_macos.py": 7028037591427052891, - "venv/lib/python3.13/site-packages/pandas/core/arrays/string_arrow.py": 16997970607998635570, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_constructors.py": 12118296571694122743, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_datetimelike.py": 10294379314868108649, - "venv/lib/python3.13/site-packages/httpx/_main.py": 1812303705973265093, - "venv/lib/python3.13/site-packages/httpcore/_ssl.py": 6665087294869504820, - "venv/lib/python3.13/site-packages/greenlet/TMainGreenlet.cpp": 9489520001674089404, - "backend/src/services/git/_remote_providers.py": 11131218419284688941, - "backend/src/plugins/translate/preview.py": 1878554949419203980, - "venv/lib/python3.13/site-packages/numpy/_core/_methods.py": 16805668769357938792, - "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/RECORD": 8201759541483070364, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/__init__.py": 1948986914452928735, - "venv/lib/python3.13/site-packages/numpy/random/_common.cpython-313-x86_64-linux-gnu.so": 12834724130890991478, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_frame.py": 4303613319747945709, - "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/util.py": 18279366777506483176, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/color_triplet.py": 17264298271771184, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_array.f90": 9711940829820746513, - "venv/lib/python3.13/site-packages/pandas/_libs/join.pyi": 369262334342439364, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_value_counts.py": 13270420637302622174, - "venv/lib/python3.13/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz": 17626265752554406355, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_values.py": 8372572954663628844, - "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.py": 2953876934840155920, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_openid.py": 8708980645667847439, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/__init__.py": 15340047930888693984, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/token.py": 4161760290367932793, - "venv/lib/python3.13/site-packages/git/repo/base.py": 13975465345838683533, - "venv/lib/python3.13/site-packages/sqlalchemy/util/_has_cy.py": 11979732417254560424, - "venv/lib/python3.13/site-packages/pygments/lexers/modeling.py": 15714077241620129689, - "venv/lib/python3.13/site-packages/pygments/lexers/minecraft.py": 10133579583270214110, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/bar.py": 12859947592168238832, - "venv/lib/python3.13/site-packages/pandas/api/types/__init__.py": 3995030354191071797, - "venv/lib/python3.13/site-packages/pip/_internal/cli/index_command.py": 15798187258841839292, - "frontend/src/routes/settings/FeaturesSettings.svelte": 14068252633661039168, - "venv/lib/python3.13/site-packages/PIL/ImageFilter.py": 10974179993355630141, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi": 1626154870044880426, - "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/RECORD": 17594742868855466393, - "venv/lib/python3.13/site-packages/passlib/ext/__init__.py": 15240312484046875203, - "venv/lib/python3.13/site-packages/cryptography/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_bcrypt.py": 11146468670439284889, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_downcast.py": 10399746645741452200, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/coercions.py": 5112358449376598662, - "frontend/src/lib/components/translate/CorrectionCell.svelte": 14340498120654577399, - "backend/git_repos/remote/test-repo.git/description": 15262637409357137373, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py": 8539232219382152238, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_holiday.py": 8541197358003711845, - "venv/lib/python3.13/site-packages/referencing/_core.py": 14744795336121513230, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_reduction.py": 2671872764983553906, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_normalize.py": 7378656958631172603, - "venv/lib/python3.13/site-packages/httpcore/_sync/http2.py": 11167798787131917524, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf": 14717748358749934995, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/cymysql.py": 5570881524647789741, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_datetimelike.py": 17304541521108700317, - "frontend/src/routes/datasets/+page.svelte": 1253723176637759895, - "venv/lib/python3.13/site-packages/uvicorn/supervisors/multiprocess.py": 10047012560534876149, - "backend/src/api/routes/git/_config_routes.py": 6093940098740660772, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_one_public_routine.f90": 7957683453180939605, - "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.pyi": 9935587108964614958, - "venv/lib/python3.13/site-packages/pygments/lexers/urbi.py": 1611762607688882372, - "venv/lib/python3.13/site-packages/pygments/lexers/bare.py": 18266858932333619451, - "venv/lib/python3.13/site-packages/packaging/tags.py": 1999137344425005827, - "backend/src/plugins/llm_analysis/__init__.py": 9254812131558249924, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_array_to_datetime.py": 3467480435568672840, - "venv/lib/python3.13/site-packages/pandas/tests/frame/conftest.py": 15090201792072045503, - "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/future/engine.py": 4639404437703898767, - "venv/lib/python3.13/site-packages/pygments/styles/tango.py": 12389250878249075539, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nditer.pyi": 33523064068376750, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta.py": 7742506012012398830, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.pyi": 11967691665766452312, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_size.py": 16658280641516916790, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_construction.py": 10619501873883861745, - "venv/lib/python3.13/site-packages/pandas/io/json/_normalize.py": 15938855324762935595, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_groupby.py": 12709199432838648700, - "venv/lib/python3.13/site-packages/PIL/ImageMorph.py": 13861961228125789866, - "venv/lib/python3.13/site-packages/fastapi/middleware/__init__.py": 5289703478893407762, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh18335.f90": 1126438609189294255, - "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/array.py": 13040461386712513615, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nested_sequence.pyi": 11245460325970663922, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_interval.py": 14749388246573356959, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/RECORD": 9803861100978586236, - "venv/lib/python3.13/site-packages/pydantic/_internal/_import_utils.py": 4029157986210295967, - "venv/lib/python3.13/site-packages/fastapi/dependencies/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/core/function_base.py": 12696640832638144604, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_struct_accessor.py": 6567451952835390075, - "venv/lib/python3.13/site-packages/pip/_internal/utils/egg_link.py": 18211947508793805393, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/__init__.py": 15130871412783076140, - "frontend/src/lib/components/reports/__tests__/report_detail.ux.test.js": 11878832350632571462, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_mangle_dupes.py": 15613858733226279352, - "venv/lib/python3.13/site-packages/cryptography/fernet.py": 10137792148038140630, - "venv/lib/python3.13/site-packages/tzlocal/windows_tz.py": 11696765495002954868, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/offsets.pyi": 13173581775000480811, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/claims.py": 14794441479740527265, - "venv/lib/python3.13/site-packages/pip/_internal/cache.py": 210214424535803946, - "venv/lib/python3.13/site-packages/keyring/backends/SecretService.py": 17482492072907438453, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.c": 9134176670140958459, - "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.py": 4984721349618127021, - "venv/lib/python3.13/site-packages/pydantic/v1/networks.py": 13262073155118055511, - "venv/lib/python3.13/site-packages/jeepney/tests/test_wrappers.py": 4813328996575597980, - "venv/lib/python3.13/site-packages/passlib/crypto/__init__.py": 16409196868630049365, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_intervalindex.py": 5053113227747333759, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/meson.build.template": 9935732744553086652, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/casting.py": 12226803454582253097, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_symbolic.py": 8093576026032854125, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_dataframe.py": 14945138617962156057, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_reduction.py": 1049551473665255648, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraysetops.pyi": 1782641795267171928, - "venv/lib/python3.13/site-packages/pygments/lexers/installers.py": 5083244110640899732, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategy_options.py": 16342048970907383117, - "venv/lib/python3.13/site-packages/pygments/lexers/tablegen.py": 2917626373516779857, - "venv/bin/websockets": 12099863324306500376, - "frontend/e2e/tests/git.e2e.js": 5892730242199126550, - "frontend/src/lib/components/translate/TranslationRunGlobalIndicator.svelte": 16210598715819306972, - "frontend/build/_app/immutable/nodes/35.COBBmrv2.js": 8747723511655561757, - "venv/lib/python3.13/site-packages/numpy/doc/ufuncs.py": 11706048944901534664, - "backend/src/plugins/translate/superset_executor.py": 5480256123348033488, - "backend/src/plugins/translate/executor.py": 15866803979457728942, - "venv/lib/python3.13/site-packages/pandas/_libs/hashtable.pyi": 15034917167424979097, - "venv/lib/python3.13/site-packages/pillow.libs/libjpeg-32d42e18.so.62.4.0": 11717944412021329207, - "venv/lib/python3.13/site-packages/websockets/utils.py": 17624459810483092475, - "venv/lib/python3.13/site-packages/PIL/Jpeg2KImagePlugin.py": 16905402423248975204, - "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/METADATA": 3643456577199395707, - "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/WHEEL": 7454950858448014158, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_frame.py": 9378623452601244234, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_ndarray.py": 6863874753941288585, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/WHEEL": 16097436423493754389, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/utils.py": 3710235316419562274, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_quarter.py": 6795026338946382805, - "venv/lib/python3.13/site-packages/pandas/core/reshape/pivot.py": 4736553530021653868, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_setitem.py": 14920902525192671548, - "venv/lib/python3.13/site-packages/pandas/io/parsers/__init__.py": 11752833703934347122, - "venv/lib/python3.13/site-packages/jeepney/bindgen.py": 7094585345946943534, - "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.pyi": 14558091964387571257, - "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/METADATA": 317417773265681256, - "frontend/src/lib/components/translate/TargetSchemaHint.svelte": 4679159885307545370, - "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/METADATA": 14070889071949105584, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/index.py": 2763962019423787504, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/revocation.py": 5718403706971163960, - "venv/lib/python3.13/site-packages/pip/_internal/utils/compatibility_tags.py": 15862649917149158291, - "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/licenses/COPYING": 14459782230785388765, - "venv/lib/python3.13/site-packages/numpy/testing/tests/test_utils.py": 5291132432383518704, - "venv/lib/python3.13/site-packages/passlib/handlers/md5_crypt.py": 7669328623914474137, - "venv/lib/python3.13/site-packages/numpy/ma/testutils.py": 9355402483340137461, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_indexing.py": 6039808271042864401, - "venv/lib/python3.13/site-packages/numpy/exceptions.pyi": 13942486291715303235, - "venv/lib/python3.13/site-packages/idna/idnadata.py": 200840860629525970, - "venv/lib/python3.13/site-packages/pandas/core/internals/blocks.py": 6448406236246476333, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_to_offset.py": 3929599794655343911, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_dtype.py": 1647214604678171565, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ranges.py": 14549386056660231279, - "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/licenses/LICENSE": 12684353321716745791, - "venv/lib/python3.13/site-packages/pygments/lexers/typoscript.py": 6706632522710582762, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_cumulative.py": 8178093067175155877, - "backend/src/api/routes/__tests__/test_dataset_review_api.py": 8023021851133925740, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_transform.py": 6759417099641034692, - "backend/src/api/routes/assistant/_routes.py": 438564212453429233, - "venv/lib/python3.13/site-packages/anyio/to_thread.py": 12767326212338028587, - "backend/src/api/routes/git_schemas.py": 9243114525622127446, - "venv/lib/python3.13/site-packages/more_itertools/recipes.py": 5254043689078173976, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_loc.py": 2127584756555503873, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_iter.py": 9232021002336641851, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_string.py": 10141066226714805009, - "venv/lib/python3.13/site-packages/referencing/retrieval.py": 11921179805977833120, - "venv/lib/python3.13/site-packages/smmap/test/lib.py": 2924931247676024085, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/_mapping.py": 11752660241391232497, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_conversion.py": 9159276697339089788, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_floats.py": 3064615530495290792, - "venv/lib/python3.13/site-packages/pyasn1/codec/streaming.py": 13202773554072937140, - "venv/lib/python3.13/site-packages/charset_normalizer/py.typed": 15130871412783076140, - "frontend/build/_app/immutable/chunks/BCU-MFdY.js": 8106991191056329764, - "backend/src/services/git/_branch.py": 4560456889410483402, - "venv/lib/python3.13/site-packages/idna-3.11.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_timestamp_method.py": 11393911418463808195, - "venv/lib/python3.13/site-packages/authlib/jose/drafts/__init__.py": 4770885427721822507, - "venv/lib/python3.13/site-packages/starlette/_utils.py": 8384087194580626069, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/mongodb.py": 5310116401542377882, - "venv/lib/python3.13/site-packages/websockets/legacy/client.py": 4032878587330592478, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.pyx": 17138729833735744777, - "frontend/src/routes/settings/+page.svelte": 8601836419948434099, - "backend/src/api/routes/git/_repo_lifecycle_routes.py": 6605622512801609889, - "venv/lib/python3.13/site-packages/pygments/styles/staroffice.py": 11694998942433220413, - "venv/lib/python3.13/site-packages/pygments/lexers/rnc.py": 9747352274729854620, - "backend/src/plugins/llm_analysis/plugin.py": 9573839268541284705, - "venv/lib/python3.13/site-packages/PIL/_imagingmath.pyi": 18222325750818585549, - "backend/src/services/reports/normalizer.py": 11408466232944555336, - "backend/src/plugins/storage/__init__.py": 5046554941488079204, - "venv/lib/python3.13/site-packages/sqlalchemy/schema.py": 16029542421991709659, - "backend/src/scripts/init_auth_db.py": 1846761799125222512, - "venv/lib/python3.13/site-packages/pip/_internal/req/__init__.py": 12266077985828139928, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/missing.py": 11241703105777668183, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop_duplicates.py": 2397396876872403048, - "venv/lib/python3.13/site-packages/pandas/core/arrays/_utils.py": 11574890848475750509, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/__init__.py": 9997757256282720103, - "venv/lib/python3.13/site-packages/pandas/core/base.py": 10262717073058743378, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_constructors.py": 17219764538851313252, - "venv/lib/python3.13/site-packages/PIL/_imagingft.cpython-313-x86_64-linux-gnu.so": 11054435406031360190, - "venv/lib/python3.13/site-packages/passlib/handlers/cisco.py": 15004707325761459775, - "venv/lib/python3.13/site-packages/jeepney/tests/test_bus_messages.py": 4323093138307306385, - "venv/lib/python3.13/site-packages/greenlet/tests/test_throw.py": 4119265751381210399, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_update.py": 9098258267671647783, - "venv/lib/python3.13/site-packages/pygments/lexers/_sourcemod_builtins.py": 11809503654078535014, - "frontend/build/_app/immutable/chunks/BjmYur9w.js": 508374990425589695, - "venv/lib/python3.13/site-packages/pip/_internal/locations/_distutils.py": 13559457590971821771, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/random.py": 12722750410117529986, - "frontend/src/routes/settings/git/+page.svelte": 9547035239167234477, - "venv/lib/python3.13/site-packages/click/decorators.py": 2920877667855377423, - "venv/lib/python3.13/site-packages/pydantic/v1/version.py": 2758971830527526972, - "venv/lib/python3.13/site-packages/jeepney/io/common.py": 15160647397460834508, - "venv/lib/python3.13/site-packages/httpx/__init__.py": 6383055693166097719, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_implementation.py": 12245524932757110911, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/modes.py": 6832635056228445650, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_ops.py": 14420421526781215500, - "venv/lib/python3.13/site-packages/PIL/WalImageFile.py": 12442826195371137238, - "backend/git_repos/remote/test-repo.git/objects/3e/05ec6ef6504483c4bc7d00f0d0272c38ec661f": 11182016264585388842, - "venv/lib/python3.13/site-packages/_pytest/debugging.py": 16135285365306979060, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/base.py": 5924592154431932923, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py": 7852235015155694076, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/comparisons.pyi": 4158883009780474220, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937_regressions.py": 8981142329261965538, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/licenses/LICENSE.rst": 5960743202700406649, - "venv/lib/python3.13/site-packages/pandas/_libs/properties.cpython-313-x86_64-linux-gnu.so": 7092136701092358552, - "backend/src/api/routes/__tests__/test_assistant_authz.py": 13343271902390197049, - "backend/git_repos/remote/test-repo.git/refs/heads/master": 12485529318667335076, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_highlight.py": 7573043358244876807, - "venv/lib/python3.13/site-packages/jeepney/io/threading.py": 525625939662612746, - "venv/lib/python3.13/site-packages/numpy/random/_pickle.py": 7774620933480975313, - "venv/lib/python3.13/site-packages/pip/_internal/commands/uninstall.py": 11003472265011262515, - "venv/lib/python3.13/site-packages/pygments/styles/abap.py": 11543320440974964547, - "venv/lib/python3.13/site-packages/PIL/ImageTransform.py": 7825940907094338808, - "venv/lib/python3.13/site-packages/jeepney/__init__.py": 1063800617763464773, - "venv/lib/python3.13/site-packages/uvicorn/server.py": 15714008348292243019, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content": 16257335642847993866, - "venv/lib/python3.13/site-packages/pydantic/json.py": 4109352930301629308, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate.py": 11205714006000849926, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_openpyxl.py": 9542840527483618681, - "venv/lib/python3.13/site-packages/pygments/styles/manni.py": 11853576691280294949, - "backend/src/core/utils/matching.py": 12567367681677699487, - "venv/lib/python3.13/site-packages/_pytest/outcomes.py": 12782895027812738142, - "venv/lib/python3.13/site-packages/pydantic/deprecated/copy_internals.py": 1245428320513062166, - "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/assertion_session.py": 18109848200936213195, - "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_reductions.py": 11624188672428941494, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/parameters.py": 5104015814292812973, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_period.py": 6255181868181182780, - "venv/lib/python3.13/site-packages/_pytest/freeze_support.py": 494952714451267295, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_getlimits.py": 118041882543413669, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply_relabeling.py": 3930092097678339743, - "dist/docker/frontend.1.2.0.tar.xz": 2118312929856113798, - "venv/lib/python3.13/site-packages/pip/_internal/configuration.py": 2563100675379605810, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/__init__.py": 5027355874704300832, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape.pyi": 2188930129299348535, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_from_dummies.py": 5670811108950300761, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot.py": 334735766122314163, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_at.py": 1029744344133153888, - "venv/lib/python3.13/site-packages/python_multipart/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict.py": 808180749933361743, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_check_indexer.py": 2929031395357057009, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py": 15644105878811738516, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_reductions.py": 17810094294132819208, - "venv/lib/python3.13/site-packages/PIL/IcnsImagePlugin.py": 1870235606309784691, - "backend/src/api/routes/dashboards/_helpers.py": 16683849709430404975, - "backend/git_repos/remote/test-repo.git/hooks/pre-commit.sample": 102291230237676317, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/zip-safe": 15240312484046875203, - "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.c": 9318655518998644962, - "venv/lib/python3.13/site-packages/numpy/random/_philox.pyi": 7503018432880404291, - "venv/lib/python3.13/site-packages/numpy/_core/_methods.pyi": 9155045948490225716, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_constructors.pyi": 164538008396001632, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/enumerated.py": 16623643153933348755, - "backend/src/models/assistant.py": 15004657265198809796, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/api.py": 12339139862411341381, - "venv/lib/python3.13/site-packages/pandas/core/indexes/accessors.py": 14394872772838047912, - "venv/lib/python3.13/site-packages/httpcore/_sync/connection_pool.py": 8159971229245441880, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_quantile.py": 4225791949463893856, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename.py": 4890779493250245903, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_app.py": 14788764260762890368, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90": 7589258200398878529, - "venv/lib/python3.13/site-packages/anyio/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/cffi/model.py": 13544803366359102016, - "venv/lib/python3.13/site-packages/numpy/_core/lib/pkgconfig/numpy.pc": 14713682399742251335, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/__init__.py": 8924316361489544973, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_dst.py": 12243642467695371088, - "venv/lib/python3.13/site-packages/pygments/lexers/web.py": 11104721221615804497, - "venv/lib/python3.13/site-packages/starlette/middleware/authentication.py": 15211131264936212938, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_pick.py": 15760492005471315814, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_day.py": 2200008998040663785, - "venv/lib/python3.13/site-packages/pip/_internal/utils/wheel.py": 450504439085405418, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/numpy/matlib.pyi": 8017902013455539981, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/sum_.py": 7062070517544958546, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv": 9287774220881887502, - "venv/lib/python3.13/site-packages/git/refs/tag.py": 9979537867501757110, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90": 8821492401453445757, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/min_max_.py": 13457611930368041821, - "venv/lib/python3.13/site-packages/pandas/core/_numba/executor.py": 2205130934861422769, - "venv/lib/python3.13/site-packages/numpy/random/_pickle.pyi": 16081120364372391381, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/python.py": 17886036670342116501, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_fillna.py": 7349777469648334282, - "venv/lib/python3.13/site-packages/h11/_headers.py": 7592730288271984585, - "backend/src/models/task.py": 10701108436197477339, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/ccalendar.pyi": 15789956857032062129, - "docker/nginx.conf": 14595959129793115016, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_indexing.py": 13703573544185051910, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_equivalence.py": 17843623343419137458, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi": 3254633032236269842, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_setitem.py": 10389770446834773837, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.cpython-313-x86_64-linux-gnu.so": 14468234464367691795, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/METADATA": 3044554568188160018, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape.pyi": 17197248408326188931, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_numeric.py": 9383693732009547935, - "frontend/src/lib/stores/__tests__/test_datasetReviewSession.js": 12620073136419991103, - "venv/lib/python3.13/site-packages/numpy/random/lib/libnpyrandom.a": 1802449692091040396, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.pyx": 7085380878820747579, - "venv/lib/python3.13/site-packages/requests/api.py": 12339139862411341381, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/controller.py": 5450931608244830335, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90": 15768643271492041853, - "venv/lib/python3.13/site-packages/numpy/_core/multiarray.py": 4484782354376574355, - "venv/lib/python3.13/site-packages/pandas/tests/api/test_api.py": 13385690673368400635, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_find_common_type.py": 9581516171321396333, - "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/METADATA": 4975169119201255384, - "frontend/build/_app/immutable/nodes/23.D9VK1d8G.js": 10743642281977700356, - "backend/src/services/reports/__tests__/test_type_profiles.py": 17262223295445285285, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_initialstub_already_started.py": 5562030563802006923, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_fields.py": 16222559851336781264, - "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/METADATA": 7214286447912789067, - "venv/lib/python3.13/site-packages/urllib3/util/ssltransport.py": 1175688460659745788, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_function_base.pyi": 2792940598392356268, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_cisco.py": 1786475632318043669, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/__init__.py": 260774374497653876, - "venv/lib/python3.13/site-packages/jeepney/io/tests/conftest.py": 13381752264278264218, - "venv/lib/python3.13/site-packages/annotated_doc/__init__.py": 6834198874252778425, - "venv/lib/python3.13/site-packages/starlette/websockets.py": 13834731343216764204, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_size.py": 8527839563560550806, - "frontend/build/_app/immutable/nodes/9.CXHsHyJQ.js": 13718585776867539206, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_api_info.py": 16491629653122827368, - "backend/src/core/utils/superset_context_extractor/_pii.py": 16897386128094460655, - "backend/src/models/connection.py": 7467905739729526898, - "venv/lib/python3.13/site-packages/pandas/core/window/numba_.py": 1444123360986509769, - "venv/lib/python3.13/site-packages/sqlalchemy/util/compat.py": 16148553252010089561, - "venv/lib/python3.13/site-packages/yaml/parser.py": 18021832376874455801, - "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/poly1305.py": 10854598965202354516, - "venv/lib/python3.13/site-packages/greenlet/TGreenletGlobals.cpp": 17400526028982558937, - "backend/src/api/routes/health.py": 4494840518139445701, - "venv/lib/python3.13/site-packages/cryptography/__about__.py": 10471312538528457144, - "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/METADATA": 11759004913807981650, - "venv/lib/python3.13/site-packages/PIL/PsdImagePlugin.py": 4347581352716313298, - "venv/lib/python3.13/site-packages/pycparser/__init__.py": 16499940957411260458, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pyasn1/type/tagmap.py": 14075859042659927673, - "venv/lib/python3.13/site-packages/pandas/core/computation/align.py": 13027916530558901817, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/METADATA": 3390257212824996989, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_setitem.py": 2059440410065814114, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_values.py": 12064896795288302730, - "venv/lib/python3.13/site-packages/charset_normalizer/__init__.py": 12412600648990392633, - "venv/lib/python3.13/site-packages/_pytest/unittest.py": 10848803633530338204, - "venv/lib/python3.13/site-packages/pygments/lexers/graph.py": 10445044822847205061, - "venv/lib/python3.13/site-packages/urllib3/util/proxy.py": 17667887856427739069, - "venv/lib/python3.13/site-packages/fastapi/params.py": 14263655860695381481, - "venv/lib/python3.13/site-packages/PIL/ImageStat.py": 18442709639217312689, - "backend/src/core/middleware/trace.py": 13093835356377196397, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/__init__.py": 8434616194114282088, - "venv/lib/python3.13/site-packages/pydantic/v1/__init__.py": 1642038155370734658, - "backend/src/core/ws_log_handler.py": 17175572704051278951, - "backend/src/services/notifications/__tests__/test_notification_service.py": 5767450314963603475, - "venv/lib/python3.13/site-packages/httpcore/_backends/mock.py": 6849131425727092784, - "venv/lib/python3.13/site-packages/_pytest/recwarn.py": 15312759837838083596, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_crackfortran.py": 10278720705326601943, - "frontend/src/routes/translate/[id]/+page.svelte": 1911443262444004956, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/nonce.py": 18219168479887197733, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/theme.py": 14225878259183479398, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period.py": 9715843209581883915, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo.f": 5690596225005490325, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_half.py": 3121836756584726126, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_describe.py": 14493300276133670380, - "venv/lib/python3.13/site-packages/passlib/tests/_test_bad_register.py": 5446848310854472376, - "venv/lib/python3.13/site-packages/PIL/ImageMath.py": 7395449734007598797, - "backend/src/plugins/translate/dictionary_crud.py": 17858252266960667195, - "backend/src/services/clean_release/manifest_service.py": 10873340336255220063, - "venv/lib/python3.13/site-packages/websockets/sync/router.py": 10335595955948355382, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_array.py": 16867692337986161626, - "backend/src/services/__tests__/test_health_service.py": 17832814613637967046, - "venv/lib/python3.13/site-packages/pandas/core/arrays/interval.py": 16281221279220043867, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_join.py": 13115782559805895662, - "venv/lib/python3.13/site-packages/pydantic/v1/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_cell_widths.py": 5724379364993806351, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/markers.py": 8297667990263004097, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_timegrouper.py": 276805119790266454, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/clsregistry.py": 1589692649837935355, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py": 9430762168079129025, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_replace.py": 4953527309376861139, - "venv/lib/python3.13/site-packages/greenlet/tests/test_tracing.py": 10227316489696807112, - "venv/lib/python3.13/site-packages/pandas/_libs/__init__.py": 17117112389651696580, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/setitem.py": 9552868454186447925, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets_properties.py": 2340780879864207500, - "venv/lib/python3.13/site-packages/anyio/from_thread.py": 7973678341601453474, - "venv/lib/python3.13/site-packages/anyio/_core/_synchronization.py": 7050001375718876608, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/modules.pyi": 131293606732000587, - "venv/lib/python3.13/site-packages/numpy/ma/__init__.pyi": 1855615156913010107, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/__init__.py": 8093984834068317399, - "venv/lib/python3.13/site-packages/cryptography/x509/ocsp.py": 17973800752927680404, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_compat.py": 11481259393140789881, - "venv/lib/python3.13/site-packages/pyasn1/codec/cer/decoder.py": 17559787396729804535, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_searchsorted.py": 11161416745923343741, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_formats.py": 1265319125235346745, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/__init__.py": 16123561007855424016, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/oracledb.py": 7158791242292470472, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/schema.py": 5391655516870611151, - "venv/lib/python3.13/site-packages/PIL/MspImagePlugin.py": 3034490726971829439, - "venv/lib/python3.13/site-packages/pandas/tests/test_errors.py": 10116716310156374885, - "venv/lib/python3.13/site-packages/pygments/lexers/maxima.py": 11824576541091274641, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_nep50_promotions.py": 6318578947214302182, - "venv/lib/python3.13/site-packages/PIL/DdsImagePlugin.py": 10646832373516499548, - "frontend/build/_app/immutable/chunks/BQZKMTAB.js": 16299439739655813122, - "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/licenses/LICENSE": 10253862887434903467, - "backend/src/core/migration/archive_parser.py": 7392694914943455006, - "backend/src/api/routes/git/_deps.py": 8233286973979159721, - "backend/src/services/clean_release/dto.py": 11031410734734770552, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/RECORD": 6187512110158566509, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_datetime.py": 11417836378782978454, - "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/RECORD": 9974324769263969827, - "venv/lib/python3.13/site-packages/keyring/backends/kwallet.py": 3071915635647280308, - "venv/lib/python3.13/site-packages/pandas/core/roperator.py": 2587829042468916489, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_partial_indexing.py": 4132091154215910029, - "venv/lib/python3.13/site-packages/uvicorn/importer.py": 5449629250971153435, - "venv/lib/python3.13/site-packages/pandas/_libs/sparse.pyi": 12526865400413362140, - "frontend/src/lib/components/health/HealthMatrix.svelte": 13165441444996153191, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/response.py": 353446217435156470, - "venv/lib/python3.13/site-packages/_pytest/helpconfig.py": 3033477806668470951, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_xs.py": 11073752361562791165, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/reflection.py": 5951113078754792806, - "venv/lib/python3.13/site-packages/pandas/core/indexes/timedeltas.py": 13653393430363556843, - "backend/src/api/routes/assistant/_llm_planner_intent.py": 16189718762013093878, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_converter.py": 7709581879446228856, - "venv/lib/python3.13/site-packages/anyio/__init__.py": 12752386096259972231, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py": 3177255974394221645, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/selectable.py": 14646717349365560549, - "backend/test_auth.db": 18214842050920965999, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_replace.py": 15992095120302643273, - "backend/src/api/routes/dataset_review.py": 3689614039699023362, - "venv/lib/python3.13/site-packages/httpx/_multipart.py": 2181282475656908730, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi": 18143251582901996072, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/framework_integration.py": 3935346152156572025, - "venv/lib/python3.13/site-packages/pip/__init__.py": 9449893869469432503, - "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.pyi": 13068936038543812082, - "venv/lib/python3.13/site-packages/passlib/utils/__init__.py": 11704122205941631503, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/processors.py": 4817637175145012571, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.pyx": 649821942746469002, - "venv/lib/python3.13/site-packages/click/_textwrap.py": 14586282603215052310, - "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/WHEEL": 8600534672961461758, - "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.cpython-313-x86_64-linux-gnu.so": 16604252871044637047, - "venv/lib/python3.13/site-packages/referencing/tests/test_referencing_suite.py": 8875120876162738440, - "venv/lib/python3.13/site-packages/numpy/linalg/__init__.pyi": 18409133021422984774, - "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/utils.py": 617314300548081590, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isin.py": 8136794647591341784, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_empty.py": 6845813091876023610, - "venv/lib/python3.13/site-packages/PIL/_tkinter_finder.py": 14045496501810535432, - "venv/lib/python3.13/site-packages/PIL/PcfFontFile.py": 8867692961463798279, - "venv/lib/python3.13/site-packages/fastapi/datastructures.py": 727178955746650271, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi": 16048852379621461316, - "venv/lib/python3.13/site-packages/pydantic/_internal/_validate_call.py": 4078236486720616395, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.pyi": 9003794318682878317, - "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77fixedform.f95": 10898637805043867370, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/ccalendar.cpython-313-x86_64-linux-gnu.so": 11019871270094058038, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_replace.py": 8784361132920473760, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_strptime.py": 14328510310436552635, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_swaplevel.py": 3584770792383216626, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args_and_kwargs.py": 3381939712123764154, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rank.py": 14115215895836854973, - "venv/lib/python3.13/site-packages/yaml/reader.py": 9873075843010693205, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_constructors.py": 6440526981746306640, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/__init__.py": 8807410829260170597, - "venv/lib/python3.13/site-packages/rsa/pkcs1_v2.py": 3533398238491175229, - "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/WHEEL": 15858869568085970864, - "venv/bin/pytest": 2593802493707545818, - "frontend/build/_app/immutable/nodes/22.BJHvtv0h.js": 5549431036175803158, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/conftest.py": 3691712173202219606, - "venv/lib/python3.13/site-packages/PIL/ImImagePlugin.py": 15452956038794399492, - "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/PIL/report.py": 9428754440615681790, - "venv/lib/python3.13/site-packages/PIL/FontFile.py": 112053841436523305, - "backend/src/plugins/translate/__tests__/test_orchestrator.py": 5663680156343544051, - "venv/lib/python3.13/site-packages/apscheduler/executors/__init__.py": 15130871412783076140, - "backend/ss_tools_backend.egg-info/PKG-INFO": 15134841326777953914, - "venv/lib/python3.13/site-packages/pandas/io/formats/format.py": 3364941338174434661, - "venv/lib/python3.13/site-packages/pygments/lexers/j.py": 9766594937623918053, - "venv/lib/python3.13/site-packages/pydantic/_internal/_serializers.py": 12077180322353709930, - "venv/lib/python3.13/site-packages/authlib/common/errors.py": 16082974228565515177, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/charset_normalizer/constant.py": 3070316197495651997, - "backend/src/plugins/translate/__tests__/test_token_budget.py": 9612693566837223655, - "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.pyi": 2186875333484796630, - "frontend/e2e/tests/translation.e2e.js": 6244274143080191568, - "venv/lib/python3.13/site-packages/pandas/tests/test_optional_dependency.py": 7930709646653025355, - "venv/lib/python3.13/site-packages/anyio/_core/_streams.py": 6436461519284884601, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_constructors.py": 5627819885594450614, - "backend/src/services/resource_service.py": 1414472862621734532, - "backend/src/services/clean_release/__tests__/test_policy_engine.py": 15331910119765064311, - "backend/tests/test_translate_jobs.py": 16585154497956900995, - "venv/lib/python3.13/site-packages/pandas/core/arrays/numpy_.py": 16641729409992576358, - "venv/lib/python3.13/site-packages/pandas/core/indexes/interval.py": 17965911911189276907, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arithmetic.py": 14858832264660410908, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_invalid_arg.py": 610891871484326055, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.py": 183817263146423033, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filters/__init__.py": 835924536855006596, - "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.pyi": 5786150108623563787, - "venv/lib/python3.13/site-packages/greenlet/slp_platformselect.h": 10428201768098464386, - "frontend/src/lib/api/__tests__/reports_api.test.js": 11820587361929895100, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/METADATA": 15876173086384975957, - "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas.py": 9446226619493404132, - "venv/lib/python3.13/site-packages/pandas/tests/strings/__init__.py": 5060190599837877599, - "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/METADATA": 3786116428839780263, - "frontend/e2e/run-e2e.sh": 8106714116467101372, - "venv/lib/python3.13/site-packages/referencing/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/npyio.py": 6782361985454523908, - "venv/lib/python3.13/site-packages/h11/_events.py": 13800479928851716538, - "venv/lib/python3.13/site-packages/pandas/util/_print_versions.py": 15326663505771588740, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/client.py": 18443944554871937480, - "venv/lib/python3.13/site-packages/ecdsa/test_curves.py": 6577762025900435885, - "venv/lib/python3.13/site-packages/pandas/_testing/_warnings.py": 5640964566228306285, - "venv/lib/python3.13/site-packages/pydantic/annotated_handlers.py": 10186120300163345360, - "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/LICENSE": 16510279186416777136, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_regression.py": 16266600037241221681, - "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/licenses/LICENSE": 3868190977070717994, - "venv/lib/python3.13/site-packages/websockets/cli.py": 14049106025886056110, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/utils.h": 3920393832993063886, - "venv/lib/python3.13/site-packages/pandas/tseries/offsets.py": 13750652921710295115, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/__init__.py": 2246704695838251846, - "venv/lib/python3.13/site-packages/pandas/core/arrays/integer.py": 7775055011080964709, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_loc.py": 17839380711970027363, - "venv/lib/python3.13/site-packages/secretstorage/util.py": 1004887530903069622, - "venv/lib/python3.13/site-packages/numpy/lib/user_array.pyi": 1968484998382771986, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_overlap.py": 4202716587079637350, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_repeat.py": 16971624301893342868, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_iteration.py": 15247340610412364508, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/base.py": 10514193453447954780, - "venv/lib/python3.13/site-packages/authlib/integrations/django_client/integration.py": 13610682193839598457, - "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/METADATA": 1684451390569121499, - "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/__init__.py": 18019562641348687547, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_copy.py": 11335108864615756235, - "venv/lib/python3.13/site-packages/dateutil/tz/__init__.py": 9617254832690762236, - "docker/all-in-one.Dockerfile": 10896793266219904099, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv": 1443087417808027268, - "venv/lib/python3.13/site-packages/urllib3/py.typed": 12220177918227495093, - "venv/lib/python3.13/site-packages/PIL/PixarImagePlugin.py": 12061717157676819554, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/live.py": 8586058300967410643, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/dtype.py": 9342837412280377086, - "venv/lib/python3.13/site-packages/pygments/styles/friendly_grayscale.py": 16840106759769837649, - "venv/lib/python3.13/site-packages/attrs/__init__.pyi": 14353885498883901855, - "venv/lib/python3.13/site-packages/httpx/_utils.py": 4836536051177895209, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_nat.py": 18428782698385974380, - "venv/lib/python3.13/site-packages/pygments/lexers/pony.py": 2720635393743617141, - "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.py": 12796890117561096360, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_typst.py": 14619529283550788275, - "backend/src/services/clean_release/stages/manifest_consistency.py": 14323717074129560178, - "backend/tests/test_core_scheduler.py": 6589618269087393661, - "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py": 12693210357718751894, - "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.h": 5980733638838895780, - "venv/lib/python3.13/site-packages/pandas/core/reshape/reshape.py": 5387892304726762127, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_map.py": 32086858815359344, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/interfaces.py": 4890958419958257958, - "docker/backend.entrypoint.sh": 1034669340368151691, - "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.cpython-313-x86_64-linux-gnu.so": 11074560904305737689, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/events.py": 15099787454570172797, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_array_from_pyobj.py": 9596224861290975079, - "venv/lib/python3.13/site-packages/pandas/core/shared_docs.py": 2173578869755325502, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_join.py": 2585969863606902743, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/orm.py": 7554417559838785150, - "venv/lib/python3.13/site-packages/pygments/lexers/rust.py": 8605690716125176329, - "venv/lib/python3.13/site-packages/uvicorn/middleware/wsgi.py": 9179913252056394958, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_palettes.py": 13495896173068490516, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_conversion.py": 7507083194555424923, - "backend/src/models/dataset_review_pkg/_session_models.py": 227824164148429934, - "venv/lib/python3.13/site-packages/numpy/random/_generator.pyi": 17167649524261942483, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/datetimelike_accumulations.py": 14719894187829729175, - "frontend/build/_app/immutable/chunks/Sz88Zx7X.js": 14482204499901240843, - "backend/src/core/logger.py": 13412438111456825541, - "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/licenses/COPYING": 14459782230785388765, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libselinux-0922c95c.so.1": 16516617710645376769, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_to_timestamp.py": 17572983799929378095, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_libsparse.py": 1859997684694949029, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/const_vs_enum.py": 12873459583943748931, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli/__init__.py": 12906995259233516197, - "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth1_session.py": 1911069558956893789, - "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/RECORD": 173225030102092319, - "venv/lib/python3.13/site-packages/h11/_state.py": 11398755254809751139, - "venv/lib/python3.13/site-packages/pandas/core/groupby/groupby.py": 5536922766239875007, - "venv/lib/python3.13/site-packages/pip/__main__.py": 574438877257676911, - "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.pyi": 9911899303567570646, - "venv/lib/python3.13/site-packages/rsa/__init__.py": 14623742580410014505, - "frontend/src/components/Footer.svelte": 17748559656923032, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi": 10548370574281981402, - "venv/lib/python3.13/site-packages/anyio/_backends/__init__.py": 15130871412783076140, - "backend/src/scripts/__init__.py": 5400372851656282343, - "backend/src/api/routes/translate/_run_routes.py": 6617818713940695689, - "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension_cpp.cpp": 4590574206187223887, - "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py": 16610770935842519289, - "venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py": 1246582552828542841, - "backend/src/models/clean_release.py": 6080208142954589647, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.py": 5735043585893007971, - "backend/src/__init__.py": 11250920420388310655, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix_py.py": 6653895521961110080, - "venv/lib/python3.13/site-packages/pandas/_libs/interval.cpython-313-x86_64-linux-gnu.so": 8964760352224019544, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE": 17284252174641192866, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/adapters.py": 2224938661429637508, - "venv/lib/python3.13/site-packages/PIL/_imagingmorph.pyi": 18222325750818585549, - "venv/lib/python3.13/site-packages/secretstorage/exceptions.py": 16701299261122689924, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/__init__.py": 9482393721453335937, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/console.py": 10217327186846649646, - "venv/lib/python3.13/site-packages/rsa/prime.py": 10820898885044917095, - "venv/lib/python3.13/site-packages/certifi/__init__.py": 9045580998764948967, - "venv/lib/python3.13/site-packages/cryptography/x509/verification.py": 1079694784860492682, - "venv/lib/python3.13/site-packages/pydantic/plugin/_loader.py": 792663962985957671, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unstack.py": 11834917665446437163, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_indexing.py": 16264430536704066847, - "venv/lib/python3.13/site-packages/pandas/io/excel/_xlrd.py": 14430937200583666658, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_old_ma.py": 18116460138221458026, - "venv/lib/python3.13/site-packages/requests/hooks.py": 9888227370911151341, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/astype_copy.pkl": 4470155972891419163, - "venv/lib/python3.13/site-packages/pandas/io/excel/_util.py": 6664989864423807444, - "venv/lib/python3.13/site-packages/pandas/io/excel/__init__.py": 6662687963241471393, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/RECORD": 8104089156015954779, - "venv/lib/python3.13/site-packages/git/objects/commit.py": 12317865358846331802, - "venv/lib/python3.13/site-packages/pandas/core/arrays/__init__.py": 10460719978124302175, - "venv/lib/python3.13/site-packages/httpcore/_sync/http11.py": 5947339024588907032, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/six.py": 1161259802604920635, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/__init__.py": 13584649922093198724, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress_bar.py": 15595912766961891283, - "venv/lib/python3.13/site-packages/git/util.py": 7424113599506269603, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_constructors.py": 12628643543371952431, - "venv/bin/pip3": 13861749540792881808, - "venv/lib/python3.13/site-packages/pandas/_config/dates.py": 3863381688916127265, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_pickle.py": 6232650893735715362, - "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/RECORD": 13494296690334916257, - "venv/lib/python3.13/site-packages/git/objects/base.py": 11498407361286170399, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_asymmetric.py": 6903778603779934572, - "venv/lib/python3.13/site-packages/pydantic/class_validators.py": 4643597082531287188, - "backend/src/api/routes/git/_repo_routes.py": 7367823490321383813, - "venv/lib/python3.13/site-packages/pandas/core/arrays/string_.py": 14865733321317939478, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_mixed.py": 3476101699679108025, - "backend/src/api/routes/dashboards/_action_routes.py": 11814954258886577640, - "backend/src/plugins/llm_analysis/__tests__/test_screenshot_service.py": 17792688368296989200, - "backend/src/plugins/translate/__tests__/test_dictionary.py": 4341966549214032934, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/instrumentation.py": 13198832283145198959, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_memmap.py": 8709963808115492688, - "venv/lib/python3.13/site-packages/pygments/lexers/_lilypond_builtins.py": 1766946089314631488, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_set.py": 14375107704596905983, - "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.pyi": 4587511199710546030, - "frontend/src/lib/components/dataset-review/SemanticLayerReview.svelte": 10805621354490209991, - "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/WHEEL": 18203500019759199992, - "backend/tests/services/clean_release/test_compliance_task_integration.py": 682622548217611215, - "venv/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py": 7733356903092860495, - "venv/lib/python3.13/site-packages/ecdsa/util.py": 10543788809724099209, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-2.csv": 5423145402839576695, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/WHEEL": 16784970174376303810, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_strings.py": 7168544888340296373, - "backend/src/services/__tests__/test_llm_prompt_templates.py": 17912427710321938757, - "venv/lib/python3.13/site-packages/cffi/error.py": 8147505969912539538, - "frontend/postcss.config.js": 5714274776976071678, - "venv/lib/python3.13/site-packages/pluggy/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.py": 1948707545068786, - "venv/lib/python3.13/site-packages/pygments/lexers/textfmts.py": 17438453283146671997, - "backend/git_repos/remote/test-repo.git/hooks/pre-receive.sample": 6118492409684431911, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE.PSF": 13208428090829817329, - "backend/src/plugins/translate/__tests__/test_target_schema.py": 3945452632405275208, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/crud.py": 805684028038896506, - "venv/lib/python3.13/site-packages/httpx/_config.py": 8800538050293498928, - "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/WHEEL": 17410883677306885019, - "venv/lib/python3.13/site-packages/pydantic_settings/version.py": 17263591404988984480, - "venv/lib/python3.13/site-packages/pandas/core/reshape/concat.py": 2218848863149192467, - "venv/lib/python3.13/site-packages/pandas/_version.py": 3480474785419232091, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_constructors.py": 979131987837682435, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_recfunctions.py": 16014503284544747867, - "venv/lib/python3.13/site-packages/requests/help.py": 1885413874621672882, - "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.pyi": 1521384724035973688, - "venv/lib/python3.13/site-packages/python_multipart/decoders.py": 14252672585219598429, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/base.cpython-313-x86_64-linux-gnu.so": 8335798324308957127, - "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/RECORD": 11788532857617688351, - "venv/lib/python3.13/site-packages/pygments/lexers/css.py": 517586374264113606, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/WHEEL": 691462085217888236, - "venv/lib/python3.13/site-packages/passlib/handlers/oracle.py": 12959175637015399815, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex_like.py": 13803156447991282315, - "frontend/src/lib/api/translate/__tests__/test-target-schema.test.js": 2329724860725977662, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/__init__.py": 1437580234680265326, - "venv/lib/python3.13/site-packages/sqlalchemy/util/concurrency.py": 1325673503812009695, - "venv/lib/python3.13/site-packages/ecdsa/_sha3.py": 10353612776869489378, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_user_array.py": 8711697474193296376, - "backend/src/core/encryption_key.py": 5870186928729062534, - "venv/lib/python3.13/site-packages/rapidfuzz/utils_cpp.cpython-313-x86_64-linux-gnu.so": 16145829319198889672, - "frontend/src/routes/settings/MigrationSettings.svelte": 3323392929444734663, - "venv/lib/python3.13/site-packages/gitdb/db/pack.py": 13460574575424209609, - "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE": 16499431172938528491, - "frontend/src/lib/i18n/index.ts": 2428391315568750665, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_function_base.py": 16624804022675533740, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/apps.py": 4219758952914498116, - "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.pyi": 15745512451486888537, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f": 12558972205518833024, - "venv/lib/python3.13/site-packages/pydantic/root_model.py": 20625057828723317, - "venv/lib/python3.13/site-packages/_pytest/_io/pprint.py": 11202117031437223527, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_isin.py": 11330491145602008796, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_frame_equal.py": 12459816298158655274, - "backend/src/core/auth/__init__.py": 16435384828055133073, - "venv/lib/python3.13/site-packages/pandas/core/groupby/__init__.py": 3015263524218708013, - "backend/src/plugins/translate/service.py": 11825307511971639412, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/endpoints.py": 18334891787808122725, - "backend/src/services/notifications/service.py": 7032100258837946310, - "backend/src/plugins/translate/dictionary_correction.py": 18051915404774774954, - "frontend/e2e/tests/login.e2e.js": 16303843677272482041, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/toml.py": 2225382735669153136, - "venv/lib/python3.13/site-packages/jsonschema/__main__.py": 18136546137047911521, - "backend/tests/services/clean_release/test_report_audit_immutability.py": 4097909280121147581, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_interval.py": 2613503970235591726, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexers.py": 6773751569163287047, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__init__.py": 5895297076117159245, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_equals.py": 9405821443172167066, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_windows.py": 9171347078900057357, - "venv/lib/python3.13/site-packages/psycopg2/sql.py": 18041240927130590808, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv": 221209423454319618, - "backend/src/plugins/translate/dictionary_filter.py": 18047895364995512274, - "backend/git_repos/remote/test-repo.git/objects/79/b070ad8af7bbc12169f7660d2a7a72ec7a889a": 8153595714065675791, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/mercurial.py": 335201628064585213, - "venv/lib/python3.13/site-packages/pandas/core/computation/common.py": 5369352684655954608, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/asymmetric_key.py": 14948661854506285135, - "venv/lib/python3.13/site-packages/smmap/test/test_mman.py": 8977119225749253844, - "venv/lib/python3.13/site-packages/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so": 2888939866336522308, - "venv/lib/python3.13/site-packages/pygments/lexers/_openedge_builtins.py": 4979988747924637739, - "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.py": 652332294655046106, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/json.py": 14755215397454910426, - "venv/lib/python3.13/site-packages/_pytest/_py/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/tests/test_apache.py": 12515001998770565375, - "venv/lib/python3.13/site-packages/numpy/_core/memmap.pyi": 14124415711399771715, - "venv/lib/python3.13/site-packages/uvicorn/protocols/http/h11_impl.py": 1419719055394402145, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine.py": 16193618152415684421, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/bitwise_ops.py": 14350609278188982939, - "venv/lib/python3.13/site-packages/pydantic/v1/errors.py": 11245135449608452720, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/panel.py": 17832701246248000383, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv": 5882025767947638305, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/replace.py": 1708865864686705833, - "venv/lib/python3.13/site-packages/packaging/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/tests/sample1.cfg": 9597283806285213340, - "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/array.py": 12658302948819867972, - "venv/lib/python3.13/site-packages/requests/utils.py": 17045260098091371478, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/test_indexing.py": 2274965639578580723, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_ujson.py": 12184194085993665945, - "venv/lib/python3.13/site-packages/attr/setters.py": 12467854389745942025, - "backend/src/scripts/clean_release_cli.py": 5126837099976660772, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_setops.py": 9991233160569430204, - "backend/src/api/routes/git/_environment_routes.py": 1034235394475003092, - "backend/git_repos/remote/test-repo.git/objects/93/9cc583a18267406014c57617ccb557569f6aaf": 5474754694741999746, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_filter.py": 2388681477981649268, - "venv/lib/python3.13/site-packages/starlette/types.py": 6372850128669191435, - "venv/lib/python3.13/site-packages/passlib/handlers/sha2_crypt.py": 8171587560325812664, - "venv/lib/python3.13/site-packages/passlib/crypto/_md4.py": 379335134151814809, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_take.py": 14969455660160053080, - "venv/lib/python3.13/site-packages/numpy/core/_internal.py": 14816989375912210674, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_api.py": 6439927798101672423, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_insert.py": 15536994417338770457, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply_relabeling.py": 5600949862632014700, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content": 12465123883296161860, - "venv/lib/python3.13/site-packages/fastapi/openapi/constants.py": 1111838716953068285, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/roles.py": 5448455900674232810, - "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_transform.py": 18159263102656491974, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_ndarray_backed.py": 10097812802469682233, - "venv/lib/python3.13/site-packages/pygments/lexers/ride.py": 14096748896451437594, - "venv/lib/python3.13/site-packages/rsa/pkcs1.py": 2576732594642491910, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_unique.py": 3148372351781648868, - "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.py": 2234931733687557433, - "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.pyi": 16372699564794732463, - "venv/lib/python3.13/site-packages/numpy/_core/strings.py": 3623885046208831106, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_equals.py": 11041884432990762650, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_npy_units.py": 8966226962799105383, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_datetime.py": 7456744745424297814, - "backend/src/services/dataset_review/clarification_engine.py": 13640221555439415988, - "venv/lib/python3.13/site-packages/pandas/core/reshape/encoding.py": 12702053687535473061, - "venv/lib/python3.13/site-packages/pydantic/v1/mypy.py": 17076910404409672245, - "venv/lib/python3.13/site-packages/fastapi/openapi/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_is_full.py": 9577318758326279694, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_converters.py": 8869440774594127419, - "venv/lib/python3.13/site-packages/gitdb/utils/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/jaraco/classes/meta.py": 15930255620248873425, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parsing.py": 2228959015420278458, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pytest_asyncio/plugin.py": 13414541723622354359, - "venv/lib/python3.13/site-packages/h11/_util.py": 9362339074207904329, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-2.csv": 14641856424618845798, - "venv/lib/python3.13/site-packages/pip/_internal/utils/unpacking.py": 106471890743211548, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/diagnose.py": 17275977405061138181, - "venv/lib/python3.13/site-packages/pydantic/v1/parse.py": 5875950480538559709, - "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.py": 16854377502491291093, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90": 12296500845667555672, - "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/METADATA": 14543822270526146783, - "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.py": 1644743742545329282, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_join.py": 1697622393195784944, - "venv/lib/python3.13/site-packages/numpy/_core/_struct_ufunc_tests.cpython-313-x86_64-linux-gnu.so": 13269324887178340397, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_common.py": 12064185052519470358, - "venv/lib/python3.13/site-packages/dateutil/tz/win.py": 8427821225251397364, - "venv/lib/python3.13/site-packages/pygments/lexers/kusto.py": 16285533608924436308, - "venv/lib/python3.13/site-packages/pygments/lexers/d.py": 18120801227801223376, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iloc.py": 7586049606891014270, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/util.py": 6088868370298560146, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_linux.h": 4071314837793906998, - "venv/lib/python3.13/site-packages/pygments/styles/vim.py": 2621036947954523349, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pymssql.py": 6650008663791598065, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_network.py": 13159427333040109523, - "venv/lib/python3.13/site-packages/pygments/lexers/ruby.py": 6898093948224302592, - "frontend/public/vite.svg": 13568221685541582385, - "frontend/src/components/storage/FileUpload.svelte": 14805293086068620697, - "frontend/build/_app/immutable/chunks/ikwS1dR6.js": 3267599179274813039, - "backend/src/plugins/translate/__tests__/test_dictionary_filter.py": 2426844436521732941, - "venv/lib/python3.13/site-packages/sqlalchemy/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_html.py": 7947998260347730581, - "venv/lib/python3.13/site-packages/uvicorn/loops/auto.py": 13086005977087619545, - "venv/lib/python3.13/site-packages/greenlet/greenlet_thread_support.hpp": 7773996382104849037, - "venv/lib/python3.13/site-packages/anyio/_core/_tasks.py": 14104828341875599130, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_types.py": 7175518113263603341, - "venv/lib/python3.13/site-packages/numpy/core/einsumfunc.py": 3484247123731380377, - "venv/lib/python3.13/site-packages/pydantic/v1/datetime_parse.py": 10467114625921924095, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_ints.py": 5616705208267050659, - "venv/lib/python3.13/site-packages/_pytest/setupplan.py": 7496801885995567141, - "venv/lib/python3.13/site-packages/pygments/lexers/yara.py": 17510792615476493957, - "venv/lib/python3.13/site-packages/smmap/buf.py": 18231775424238352734, - "frontend/src/components/git/GitInitPanel.svelte": 3002620133377315800, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_insert.py": 9195027887301180927, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/__init__.py": 1398617034174236358, - "venv/lib/python3.13/site-packages/pydantic/fields.py": 4142211199816898047, - "venv/lib/python3.13/site-packages/numpy/core/__init__.pyi": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending.py": 16515485226251040454, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/foo.f": 6349567809926050379, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_old_base.py": 191359377446257900, - "venv/lib/python3.13/site-packages/pandas/_libs/index.cpython-313-x86_64-linux-gnu.so": 18409579812171549318, - "venv/lib/python3.13/site-packages/pandas/api/__init__.py": 1145864207387918302, - "venv/lib/python3.13/site-packages/gitdb/__init__.py": 15381521749253695923, - "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.py": 1731362089136926666, - "venv/lib/python3.13/site-packages/pandas/core/interchange/column.py": 9498044216416177656, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_printing.py": 8859757563354666575, - "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pyi": 14150710436003340771, - "venv/lib/python3.13/site-packages/numpy/_utils/__init__.py": 7731065084036767848, - "venv/lib/python3.13/site-packages/pandas/io/excel/_xlsxwriter.py": 16873939324418752965, - "frontend/src/lib/components/dataset-review/__tests__/us3_execution_batch.ux.test.js": 13416996904332574966, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiarray.py": 5928288171180750841, - "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/WHEEL": 5160964596297665692, - "venv/lib/python3.13/site-packages/dotenv/py.typed": 9796674040111366709, - "venv/lib/python3.13/site-packages/sqlalchemy/types.py": 15819795572817819102, - "venv/lib/python3.13/site-packages/pip/_internal/locations/_sysconfig.py": 4773855595767526182, - "backend/src/plugins/translate/_llm_parse.py": 3278211416813203155, - "frontend/src/routes/dashboards/[id]/components/DashboardHeader.svelte": 5572977872383619871, - "venv/lib/python3.13/site-packages/numpy/fft/_helper.pyi": 9546918341939102632, - "venv/lib/python3.13/site-packages/pip/_internal/utils/filetypes.py": 4415340223268174913, - "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.APACHE": 11041304845352917971, - "venv/lib/python3.13/site-packages/apscheduler/executors/debug.py": 14072221218785494847, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/METADATA": 2810323639884879396, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90": 14624074967635860696, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust.abi3.so": 2537152913308578487, - "venv/lib/python3.13/site-packages/attr/_version_info.pyi": 7141309436445210354, - "venv/lib/python3.13/site-packages/numpy/_core/cversions.py": 9724467539503410469, - "backend/tests/core/test_mapping_service.py": 6888870177029085220, - "backend/git_repos/remote/test-repo.git/objects/cf/d2dcbd55735b8cedf21e04e64ac627c6f9a458": 10982669277486885525, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_values.py": 430620320423334461, - "backend/git_repos/remote/test-repo.git/objects/22/c0ea49cea7e5138fb91b25b1bc0e101ae6e017": 17630871400599334193, - "frontend/src/routes/+error.svelte": 9437886843842311915, - "venv/lib/python3.13/site-packages/annotated_doc/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi": 3533739482029983817, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/ops.py": 13451323660386712332, - "venv/lib/python3.13/site-packages/pip/_internal/utils/filesystem.py": 7716285033598020316, - "frontend/src/lib/api/reports.js": 2328857814720054000, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/base.py": 16052592982063844259, - "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.py": 6142062990691556076, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/licenses/LICENSE": 8364608327598414179, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_timezones.py": 15157687716502574038, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_join.py": 17508073052750406350, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_index.py": 12015738970771703312, - "venv/lib/python3.13/site-packages/pandas/core/strings/__init__.py": 13025387151657797130, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_missing.py": 1963705411068820866, - "venv/lib/python3.13/site-packages/passlib/utils/decor.py": 21351391767102899, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/path_registry.py": 8410829659513707067, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/__init__.py": 1856412417337875350, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/bootstrap.py": 3865947239497500815, - "venv/lib/python3.13/site-packages/multipart/exceptions.py": 8580522204565816132, - "venv/lib/python3.13/site-packages/pygments/lexers/python.py": 8995519134978505744, - "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/jws_eddsa.py": 833927568269372333, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_cumulative.py": 6346947559103505068, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/text.py": 6096215585499446070, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/__init__.py": 3247870839323520754, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pyx": 11739218099400096619, - "backend/src/services/clean_release/repositories/manifest_repository.py": 12395698948312301073, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/METADATA": 4954909612926293404, - "venv/lib/python3.13/site-packages/pydantic/_internal/_generics.py": 16438159042939059717, - "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/RECORD": 8971487317739420905, - "frontend/build/_app/immutable/chunks/DtOwWuT9.js": 10977610495234790965, - "venv/lib/python3.13/site-packages/authlib/integrations/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__main__.py": 8412594868333244844, - "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/__init__.py": 9083396324667433335, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_julian_date.py": 6868080396693831272, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval.py": 8549680643865283913, - "venv/lib/python3.13/site-packages/numpy/f2py/rules.pyi": 1342380029484127983, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_freq_attr.py": 7685756734926749093, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_fiscal.py": 14652343698825214870, - "venv/lib/python3.13/site-packages/pydantic/warnings.py": 5142352784799639092, - "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_cpp_avx2.cpython-313-x86_64-linux-gnu.so": 12574929384355254457, - "venv/lib/python3.13/site-packages/yaml/loader.py": 18284689412149643959, - "venv/lib/python3.13/site-packages/greenlet/tests/test_leaks.py": 1219835696230215605, - "venv/lib/python3.13/site-packages/numpy/ma/extras.py": 7559838309481824664, - "venv/lib/python3.13/site-packages/pygments/lexers/rego.py": 16022844238903541738, - "venv/lib/python3.13/site-packages/pip/_internal/utils/setuptools_build.py": 13594639612360346306, - "venv/lib/python3.13/site-packages/pygments/lexers/unicon.py": 1155454077052833821, - "venv/lib/python3.13/site-packages/pygments/lexers/csound.py": 2175454840368374515, - "venv/pyvenv.cfg": 2513607356761047446, - "venv/lib/python3.13/site-packages/uvicorn/protocols/http/auto.py": 15947958974558543657, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/nested_schemas.py": 4114645644496880787, - "venv/lib/python3.13/site-packages/typing_inspection/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.py": 13012775703413938576, - "venv/lib/python3.13/site-packages/numpy/char/__init__.pyi": 12214207343146244743, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategies.py": 15673926142454922581, - "venv/lib/python3.13/site-packages/numpy/_core/_asarray.pyi": 3940937389249665490, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_localize.py": 4937713043686953098, - "venv/lib/python3.13/site-packages/rapidfuzz/utils.pyi": 7400725037332728015, - "venv/lib/python3.13/site-packages/keyring/backends/Windows.py": 4103830951042463184, - "venv/lib/python3.13/site-packages/sqlalchemy/util/__init__.py": 15821192733097665649, - "backend/src/plugins/translate/_llm_call.py": 13441764941895838344, - "venv/lib/python3.13/site-packages/numpy/lib/npyio.pyi": 3212440968296555560, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_clip.py": 11111183698178681331, - "frontend/build/_app/immutable/chunks/0sBtm-8-.js": 8006549633347394169, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_dialect.py": 6294522482440261756, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/char/__init__.py": 4428218097234308768, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string.py": 3834067244989779682, - "venv/lib/python3.13/site-packages/PIL/ImageCms.py": 5610897002957128546, - "venv/lib/python3.13/site-packages/numpy/testing/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/styles/vs.py": 4188729978573652106, - "venv/lib/python3.13/site-packages/click/__init__.py": 9261629899056870564, - "venv/lib/python3.13/site-packages/iniconfig/_version.py": 8497474654470220170, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npz": 9481735723557962988, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_zips.py": 5184894018177148648, - "venv/lib/python3.13/site-packages/greenlet/CObjects.cpp": 3454797518210223926, - "venv/lib/python3.13/site-packages/pluggy/_hooks.py": 6941854999025808196, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_api.py": 16743710460729009914, - "venv/lib/python3.13/site-packages/pygments/styles/_mapping.py": 11752660241391232497, - "venv/lib/python3.13/site-packages/passlib/registry.py": 5050675058011850564, - "frontend/e2e/tests/migration.e2e.js": 12564023806718668322, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_interval_array_equal.py": 15654625365223535344, - "frontend/src/routes/tools/storage/+page.svelte": 2651964385884112547, - "backend/src/app.py": 6639394142091523642, - "backend/src/api/routes/settings.py": 12171289292260529147, - "backend/git_repos/remote/test-repo.git/refs/heads/preprod": 2288780285329550368, - "venv/lib/python3.13/site-packages/py.py": 16248211404003181569, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_cpp_avx2.cpython-313-x86_64-linux-gnu.so": 2991745295485163924, - "venv/lib/python3.13/site-packages/numpy/rec/__init__.pyi": 1782063765067823837, - "venv/lib/python3.13/site-packages/more_itertools/recipes.pyi": 16788810745659802820, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_wrap.py": 17083394123203662880, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/mod_derived_types.f90": 2556756676983488922, - "venv/lib/python3.13/site-packages/pydantic/experimental/pipeline.py": 9493054841465227788, - "venv/lib/python3.13/site-packages/pycparser/ply/cpp.py": 1665654017894222868, - "backend/git_repos/remote/test-repo.git/config": 14478893374498894766, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlrd.py": 9982457234958102003, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f": 3980077223827767077, - "venv/lib/python3.13/site-packages/pandas/tests/test_nanops.py": 8709105600366913011, - "frontend/src/lib/stores/__tests__/taskDrawer.test.js": 12307450726550947042, - "venv/lib/python3.13/site-packages/pygments/styles/algol_nu.py": 6229131016121450375, - "venv/lib/python3.13/site-packages/pandas/core/interchange/from_dataframe.py": 8278998381856028462, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timezones.py": 8042029178538467146, - "venv/lib/python3.13/site-packages/numpy/_core/lib/libnpymath.a": 17555816778997028283, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/authorization_server.py": 6858244712625056421, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_compression.py": 8577756801858495168, - "backend/src/plugins/translate/orchestrator_planner.py": 1630348739588568408, - "venv/lib/python3.13/site-packages/pydantic/v1/error_wrappers.py": 5701679786078971939, - "venv/lib/python3.13/site-packages/authlib/oidc/discovery/models.py": 6924198551176217533, - "venv/lib/python3.13/site-packages/numpy/random/__init__.pyi": 13833571330152615376, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi": 9294219058621261971, - "venv/lib/python3.13/site-packages/PIL/_webp.cpython-313-x86_64-linux-gnu.so": 11070012119632935103, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA_py.py": 2494967094400350388, - "venv/lib/python3.13/site-packages/pygments/lexers/tact.py": 1164971357219795420, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polyutils.pyi": 3841660741524427413, - "venv/lib/python3.13/site-packages/pygments/lexers/asc.py": 10744437946030875496, - "venv/lib/python3.13/site-packages/tzlocal/win32.py": 1949985224569608978, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/asyncio.py": 11442130378027628520, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/retry.py": 17371295199208325375, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo77.f": 12000068001851270396, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timezones.pyi": 17528421279543420867, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_case_justify.py": 8204537837649550062, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadb.py": 3109042476851791996, - "venv/lib/python3.13/site-packages/pandas/core/indexes/range.py": 3838277376774246164, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/RECORD": 2963644632913976754, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayprint.py": 13335063050941743734, - "venv/lib/python3.13/site-packages/pycparser/ast_transforms.py": 9032453625977464506, - "venv/lib/python3.13/site-packages/_yaml/__init__.py": 3395829783751571350, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/ma/extras.pyi": 15292036493781556342, - "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.pyi": 17825266810219495672, - "venv/lib/python3.13/site-packages/numpy/core/arrayprint.py": 9652368112174245943, - "venv/lib/python3.13/site-packages/pandas/_libs/arrays.cpython-313-x86_64-linux-gnu.so": 8634234308863090562, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_indexing.py": 81180636019259296, - "venv/lib/python3.13/site-packages/pygments/styles/stata_dark.py": 324072437809944751, - "frontend/src/lib/stores/environmentContext.js": 1762535408632658714, - "frontend/src/services/gitService.js": 7044825476968825357, - "backend/src/api/routes/assistant/_dataset_review.py": 14508672919199309579, - "venv/lib/python3.13/site-packages/keyring/backends/macOS/api.py": 4502902558534812719, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.py": 17817123894903120316, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_freq_attr.py": 1720704043778272895, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/licenses/LICENSE": 9235234428907927646, - "venv/lib/python3.13/site-packages/requests/status_codes.py": 17005213506461710202, - "venv/lib/python3.13/site-packages/pandas/tests/test_take.py": 17628004130770326677, - "venv/lib/python3.13/site-packages/starlette/middleware/wsgi.py": 12506262030845301606, - "venv/lib/python3.13/site-packages/jeepney/io/trio.py": 11859775321483330469, - "venv/lib/python3.13/site-packages/pandas/tests/test_multilevel.py": 10500316376521962061, - "venv/lib/python3.13/site-packages/pandas/io/excel/_odswriter.py": 17220892094904423676, - "venv/lib/python3.13/site-packages/pygments/lexers/teraterm.py": 16132676290138105984, - "backend/src/api/routes/reports.py": 5647380957044157360, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/models.py": 5656065513234782067, - "venv/lib/python3.13/site-packages/dateutil/tz/_common.py": 9009072600471223066, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_chaining_and_caching.py": 11784574265874608859, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_masked_matrix.py": 1444179242134203344, - "venv/lib/python3.13/site-packages/PIL/features.py": 3481835375516797487, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_stack_unstack.py": 3737891757817696405, - "backend/src/services/clean_release/compliance_execution_service.py": 3379474749353250488, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/__init__.py": 2436195108273216959, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlsxwriter.py": 8445547874832015203, - "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/meson.build": 9642189398934130247, - "venv/lib/python3.13/site-packages/pandas/core/window/doc.py": 4204367435727844696, - "venv/lib/python3.13/site-packages/keyring/backend_complete.zsh": 14339032329370660432, - "venv/lib/python3.13/site-packages/_pytest/pytester_assertions.py": 1899505062406979663, - "venv/lib/python3.13/site-packages/pyasn1/codec/der/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_index.py": 10971093361190283675, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_cross.py": 17742712348672218852, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv": 8620268345075425735, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_quoting.py": 1147992698412929658, - "venv/lib/python3.13/site-packages/anyio/_core/_signals.py": 1204322949639513552, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_version.py": 10384171076976071398, - "venv/lib/python3.13/site-packages/pandas/core/config_init.py": 16537122488227845090, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_indexing.py": 9862204223281834360, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_reductions.py": 1713831062142840146, - "venv/lib/python3.13/site-packages/keyring/testing/util.py": 11195868112805409554, - "venv/lib/python3.13/site-packages/pandas/_testing/compat.py": 10172779814048259850, - "venv/lib/python3.13/site-packages/keyring/testing/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/_testing/_io.py": 14264259716673715185, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/strategies.py": 14007486769065345085, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg.py": 8023549900603235601, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_pyf_src.py": 12351476647369971852, - "venv/lib/python3.13/site-packages/pygments/lexers/objective.py": 10966124906622044512, - "frontend/src/lib/stores/__tests__/setupTests.js": 13316015450930652502, - "frontend/src/lib/api/translate/runs.js": 1220731879179347641, - "frontend/src/components/Navbar.svelte": 10594730954703520477, - "venv/lib/python3.13/site-packages/pydantic/_internal/_forward_ref.py": 10623110912945011703, - "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/RECORD": 12733654377842895588, - "venv/lib/python3.13/site-packages/dotenv/ipython.py": 15904966766060247908, - "venv/lib/python3.13/site-packages/greenlet/TExceptionState.cpp": 17617354576371846109, - "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_core.py": 12712110303898046818, - "venv/lib/python3.13/site-packages/fastapi/openapi/utils.py": 9058442333718187759, - "venv/lib/python3.13/site-packages/keyring/__init__.py": 991260689223167957, - "venv/lib/python3.13/site-packages/jaraco/functools/__init__.pyi": 2872039192528394677, - "venv/lib/python3.13/site-packages/passlib/ext/django/utils.py": 8118896525895185626, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/_spdx.py": 17182188548503720124, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dtypes.py": 4985057130807802395, - "venv/lib/python3.13/site-packages/pygments/styles/bw.py": 869630132791421268, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/RECORD": 10052481303799123207, - "venv/lib/python3.13/site-packages/pygments/lexers/jsonnet.py": 1314044008440065525, - "venv/lib/python3.13/site-packages/pandas/compat/pickle_compat.py": 11073483984394766474, - "venv/lib/python3.13/site-packages/packaging/markers.py": 11602308203217831543, - "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.py": 9654828595008925976, - "frontend/build/_app/immutable/chunks/x6uj_Szm.js": 18390522503436031837, - "backend/src/core/migration/dry_run_orchestrator.py": 6268210017505159964, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_shape_base.py": 4117141349022217163, - "venv/lib/python3.13/site-packages/PIL/__init__.py": 10393984345353752724, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/idnadata.py": 1169745920682458213, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_decimal.py": 3515468590005709183, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_week.py": 5756727157937218128, - "backend/tests/conftest.py": 6261639680613686031, - "venv/lib/python3.13/site-packages/websockets/uri.py": 264376168984862773, - "venv/lib/python3.13/site-packages/rapidfuzz/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/compat/_optional.py": 12714208019736797073, - "venv/lib/python3.13/site-packages/pygments/unistring.py": 18037463865539157041, - "backend/_convert_defs.py": 208535643309836247, - "backend/git_repos/remote/test-repo.git/hooks/pre-applypatch.sample": 15598058327720909861, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/LICENSE": 12688029424398428498, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/_internal_utils.py": 4091305333167213279, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/jwt.py": 9642615960197748105, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/totp.py": 11888568940387752607, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/random.pyi": 9425735458050148191, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/bitwise_ops.pyi": 15598239133239520456, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo90.f90": 58572216018544419, - "venv/lib/python3.13/site-packages/rapidfuzz/process.pyi": 6959881293311340830, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/string.f": 17328443345813567449, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90": 13833561828029901615, - "venv/lib/python3.13/site-packages/pandas/_libs/testing.cpython-313-x86_64-linux-gnu.so": 16758333404587340103, - "venv/lib/python3.13/site-packages/pandas/tests/apply/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_doc.py": 7865575374100528149, - "venv/lib/python3.13/site-packages/ecdsa/test_ellipticcurve.py": 11125783981574901613, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_complex.py": 12963449957363121481, - "venv/lib/python3.13/site-packages/pandas/tests/frame/common.py": 7426635866622531875, - "venv/lib/python3.13/site-packages/pandas/tests/extension/list/__init__.py": 10072943986583771248, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_antijoin.py": 14435396877404907826, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/event/__init__.py": 16182540084654095394, - "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/METADATA": 3188324716322823755, - "venv/lib/python3.13/site-packages/pandas/tests/config/test_localization.py": 9524481848419616725, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_reductions.py": 3575617237516305456, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_observance.py": 18178414966262524534, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/extensions.py": 217122171232375592, - "venv/lib/python3.13/site-packages/git/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpx/__version__.py": 9473642134297828811, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_diff.py": 7420674239386436885, - "venv/lib/python3.13/site-packages/pygments/styles/stata_light.py": 16319330015324455277, - "venv/lib/python3.13/site-packages/pygments/lexers/dns.py": 17149871769553794654, - "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.test.js": 7689381541193660594, - "frontend/build/_app/immutable/chunks/BEwn28XL.js": 7210511466488204704, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_log_render.py": 18076931145915444473, - "venv/lib/python3.13/site-packages/pandas/io/formats/csvs.py": 17223598248259691292, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90": 13315882216322269383, - "venv/lib/python3.13/site-packages/numpy.libs/libgfortran-040039e1-0352e75f.so.5.0.0": 13946067868274850557, - "backend/src/plugins/translate/orchestrator_retry.py": 7628306124703690760, - "venv/lib/python3.13/site-packages/pandas/io/_util.py": 13608922148814398500, - "venv/lib/python3.13/site-packages/jsonschema/validators.py": 3832874295500213309, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf": 10179237442840865225, - "venv/lib/python3.13/site-packages/pandas/core/util/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_matplotlib.py": 12775850858284584296, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_map.py": 1115471561925426082, - "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/RECORD": 6488682447051657004, - "venv/lib/python3.13/site-packages/pygments/lexers/_php_builtins.py": 2344562378679281201, - "venv/lib/python3.13/site-packages/fastapi/templating.py": 10760135144345238340, - "venv/lib/python3.13/site-packages/httpx/_urls.py": 4219389176352582046, - "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/WHEEL": 9788895026336324100, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_multi.py": 4612816468258071810, - "backend/src/services/clean_release/repository.py": 11403333156347178483, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/padding.py": 11244071766694094554, - "venv/lib/python3.13/site-packages/PIL/PdfParser.py": 13710342183037972042, - "venv/lib/python3.13/site-packages/passlib/tests/sample1c.cfg": 13088198405762342506, - "venv/lib/python3.13/site-packages/pydantic/_migration.py": 17982816821930887921, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/specifiers.py": 12284901056355482991, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_backend.py": 17793139799410518847, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_crosstab.py": 6631711416347033281, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.cpython-313-x86_64-linux-gnu.so": 6157288238855118017, - "venv/lib/python3.13/site-packages/numpy/_core/function_base.py": 5676611841071163854, - "venv/lib/python3.13/site-packages/git/objects/submodule/util.py": 8621897576747443758, - "venv/lib/python3.13/site-packages/pyasn1/codec/ber/eoo.py": 5126566925877730303, - "venv/lib/python3.13/site-packages/pydantic/experimental/missing_sentinel.py": 1637241331832367709, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_accumulations.py": 11428556645065711062, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_.py": 644667973700652263, - "venv/lib/python3.13/site-packages/pydantic/v1/types.py": 10761779263335288559, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/use_modules.f90": 3913612933340746297, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_duplicate_labels.py": 10663105616336167414, - "backend/test_app.db": 2486636812009447051, - "venv/lib/python3.13/site-packages/passlib/apache.py": 2357244937629445006, - "venv/lib/python3.13/site-packages/cffi/vengine_gen.py": 6582900613549620556, - "frontend/src/lib/components/layout/sidebarNavigation.js": 1277379523298972456, - "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/test-failed-1.png": 5297796663331551625, - "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.pyi": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reindex.py": 12459492712890114705, - "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.pyi": 6576645822227068922, - "venv/lib/python3.13/site-packages/passlib/tests/tox_support.py": 9200774792427691602, - "venv/lib/python3.13/site-packages/pandas/core/_numba/extensions.py": 4132402557064663751, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/markup.py": 5413800947725916538, - "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/METADATA": 7727489762869155085, - "venv/lib/python3.13/site-packages/numpy/lib/scimath.pyi": 18165025261847276375, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_fileno.py": 15541504502174047167, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/gcp.py": 12328409672947966867, - "venv/lib/python3.13/site-packages/numpy/rec/__init__.py": 7467092880535460658, - "venv/lib/python3.13/site-packages/pygments/lexers/esoteric.py": 16839499623020685146, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunclike.pyi": 14623308681600207918, - "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.py": 5583478355093966990, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f": 13126319439858352711, - "venv/lib/python3.13/site-packages/pillow.libs/liblcms2-cc10e42f.so.2.0.17": 4221600618602131476, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/__init__.py": 3673322722277252961, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_index_tricks.py": 4676293127859087991, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/licenses/LICENSE": 13322127602069971876, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_assumed_shape.py": 18361009188431483164, - "frontend/src/lib/components/assistant/__tests__/assistant_clarification.integration.test.js": 12258270009984504212, - "venv/lib/python3.13/site-packages/numpy/ma/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_conversion.py": 6205112277291935767, - "venv/lib/python3.13/site-packages/pip/_internal/models/search_scope.py": 9282393652860589543, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py": 256154392957334831, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/RECORD": 9461427699726982537, - "venv/lib/python3.13/site-packages/pydantic/_internal/_git.py": 8760779092674434712, - "venv/lib/python3.13/site-packages/pygments/lexers/rdf.py": 14488319292387226505, - "venv/lib/python3.13/site-packages/pydantic/_internal/_known_annotated_metadata.py": 9308620143218174987, - "frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js": 3674649277514557450, - "venv/lib/python3.13/site-packages/greenlet/tests/test_contextvars.py": 6077482318964702132, - "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.pyi": 11535882608355652318, - "backend/src/scripts/seed_superset_load_test.py": 8023054867629574975, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_float.py": 10455718110956856820, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_arithmetic.py": 13304014482504911016, - "venv/lib/python3.13/site-packages/pandas/core/ops/mask_ops.py": 16152832446926420035, - "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.py": 12771179468704314203, - "venv/lib/python3.13/site-packages/pandas/tests/libs/test_join.py": 5982692266872978444, - "frontend/tailwind.config.js": 13139381085024634801, - "venv/lib/python3.13/site-packages/httpcore/_trace.py": 9576253018891841832, - "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.py": 16856718240972376883, - "venv/lib/python3.13/site-packages/starlette/exceptions.py": 15978811612997200737, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.pyi": 5973671421648618563, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_comment.py": 5603075924832933306, - "venv/lib/python3.13/site-packages/dateutil/__init__.py": 17666544837260663800, - "venv/lib/python3.13/site-packages/passlib/ext/django/models.py": 12386223748379294996, - "backend/git_repos/remote/test-repo.git/hooks/pre-push.sample": 8029776382195911768, - "venv/lib/python3.13/site-packages/pluggy/_result.py": 16790448391766505769, - "venv/bin/pyrsa-keygen": 8222542582170363672, - "venv/lib/python3.13/site-packages/pandas/tests/apply/common.py": 1113935558495455492, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_index_as_string.py": 292438690259156869, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_parameter.py": 15173522343126004527, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__main__.py": 6480933938145689964, - "venv/lib/python3.13/site-packages/jose/utils.py": 1926138853970725083, - "backend/src/services/clean_release/stages/internal_sources_only.py": 15680055221844544848, - "venv/lib/python3.13/site-packages/numpy/random/_sfc64.pyi": 3536657185495782642, - "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/np_datetime.pyi": 2884703536776830012, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py": 6509914623926583629, - "frontend/build/index.html": 7987635536612282874, - "venv/lib/python3.13/site-packages/starlette/middleware/sessions.py": 11719848399661632707, - "venv/lib/python3.13/site-packages/pyasn1/codec/der/encoder.py": 4790267438222037867, - "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.pyi": 84606125837677197, - "backend/src/models/dataset_review_pkg/__init__.py": 17789694606496652579, - "venv/lib/python3.13/site-packages/pandas/core/ops/invalid.py": 10186546927135277579, - "venv/lib/python3.13/site-packages/greenlet/_greenlet.cpython-313-x86_64-linux-gnu.so": 6036818030377883416, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/names.py": 705261158040926128, - "backend/src/models/git.py": 9387561498910534118, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/errors.py": 17581857895562494222, - "frontend/src/routes/dashboards/[id]/+page.svelte": 12833231703682809118, - "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/accessors.py": 12743680296510533030, - "frontend/static/favicon.png": 16740551781088792605, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_describe.py": 362374422228593281, - "venv/lib/python3.13/site-packages/pandas/tests/extension/json/test_json.py": 12422315190455428620, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/inout.f90": 1521999519583206538, - "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/RECORD": 1164466882742493155, - "venv/lib/python3.13/site-packages/pygments/lexers/snobol.py": 414946539602526513, - "backend/src/core/__tests__/test_native_filters.py": 823253235973274872, - "venv/lib/python3.13/site-packages/pygments/lexers/_stata_builtins.py": 18053452765493556047, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/util.py": 10640907133050862176, - "venv/lib/python3.13/site-packages/pandas/tests/libs/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/client_auth.py": 3301527187487914220, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90": 11945588837236968550, - "venv/lib/python3.13/site-packages/PIL/ImageSequence.py": 16459886231802763032, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv": 16333455295913164408, - "frontend/src/routes/profile/__tests__/fixtures/profile.fixtures.js": 2726190101012864209, - "backend/src/services/reports/type_profiles.py": 8365014439236739390, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/WHEEL": 1598805043198466373, - "venv/lib/python3.13/site-packages/click/_winconsole.py": 8133229457213704188, - "venv/lib/python3.13/site-packages/greenlet/TStackState.cpp": 16720079760074325527, - "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.py": 2215312866861772848, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_formats.py": 17821648708413143557, - "venv/lib/python3.13/site-packages/pandas/io/formats/string.py": 14718123345899686696, - "venv/lib/python3.13/site-packages/attr/__init__.py": 14436902698244718082, - "venv/lib/python3.13/site-packages/sqlalchemy/util/tool_support.py": 4926732415520779988, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/operators.py": 5584982192355398255, - "venv/lib/python3.13/site-packages/attr/exceptions.pyi": 12323493441583681402, - "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.pyi": 1826323011169529229, - "venv/lib/python3.13/site-packages/pandas/testing.py": 18352975429944961593, - "venv/lib/python3.13/site-packages/numpy/_core/_simd.cpython-313-x86_64-linux-gnu.so": 12609666221355091416, - "venv/lib/python3.13/site-packages/pandas/core/resample.py": 13814298871925341617, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/getitem.py": 556339939822508169, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/common.py": 11384497819737275399, - "venv/lib/python3.13/site-packages/smmap/test/test_util.py": 5634593621291240094, - "venv/lib/python3.13/site-packages/idna/uts46data.py": 5698404064763638591, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite_e.py": 8912795372542950449, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_datetime64.py": 16272266806084058743, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pct_change.py": 10313980265441433173, - "venv/lib/python3.13/site-packages/pygments/lexers/hare.py": 8693002231020751711, - "frontend/src/routes/datasets/review/review-workspace-helpers.js": 8577563379877694502, - "venv/lib/python3.13/site-packages/pygments/lexers/markup.py": 10311057264960923433, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_arithmetics.py": 16527169124402715210, - "backend/src/api/routes/llm.py": 7404985960617844546, - "backend/src/api/routes/translate/_job_routes.py": 15469484615259714480, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/resource_protector.py": 9147671710440653567, - "venv/lib/python3.13/site-packages/pip/_vendor/distro/distro.py": 12494639376332486204, - "backend/src/services/mapping_service.py": 9713400496587758211, - "frontend/src/lib/components/reports/__tests__/reports_list.ux.test.js": 16252194679528846126, - "venv/lib/python3.13/site-packages/pygments/lexers/openscad.py": 13045825115225232396, - "backend/src/plugins/llm_analysis/scheduler.py": 14673660738877638091, - "venv/lib/python3.13/site-packages/pygments/lexers/clean.py": 17772169928835025327, - "venv/lib/python3.13/site-packages/jaraco/classes/ancestry.py": 11742194518360056470, - "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_builtin.py": 74545289993348593, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_qcut.py": 8972418112914954758, - "venv/lib/python3.13/site-packages/pandas/tests/test_flags.py": 411845322592830527, - "venv/lib/python3.13/site-packages/numpy/fft/_helper.py": 15906444100774706395, - "venv/lib/python3.13/site-packages/fastapi/logger.py": 11590581556317053213, - "venv/lib/python3.13/site-packages/pyasn1/codec/cer/encoder.py": 3261739474564948330, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/token.py": 6987328478153445584, - "venv/lib/python3.13/site-packages/apscheduler/triggers/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/plotting/_misc.py": 10202078355301731720, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_npfuncs.py": 8238385897366878558, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_unary.py": 2573825678342936734, - "venv/lib/python3.13/site-packages/pandas/core/strings/object_array.py": 17631047188839635539, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/hstore.py": 9700253004947691961, - "venv/lib/python3.13/site-packages/pygments/lexers/parasail.py": 7758704230750989282, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_concat.py": 3788461606817482165, - "frontend/src/lib/utils/debounce.js": 16884470786640632815, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_latex.py": 15077617224435782028, - "venv/lib/python3.13/site-packages/numpy/_core/memmap.py": 4093510602708416858, - "frontend/build/_app/immutable/chunks/BdM_DyAU.js": 4733561840148651548, - "frontend/build/_app/immutable/chunks/Cvm7P5dV.js": 4585441182838434632, - "backend/src/api/routes/assistant/_dispatch.py": 3122025109125421448, - "venv/lib/python3.13/site-packages/ecdsa/numbertheory.py": 13538480862642502330, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_info.py": 15151894356374015812, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/packages.py": 11689856177725665974, - "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/test_common.py": 8987965560487646705, - "venv/lib/python3.13/site-packages/pygments/lexers/text.py": 10572727755736597715, - "frontend/build/_app/immutable/chunks/CRVzg5g_.js": 16221258449455332676, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_periodindex.py": 13430003945574795792, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/plugin.py": 16042078006552521613, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS": 17022185907188244883, - "venv/lib/python3.13/site-packages/pandas/tests/window/moments/conftest.py": 6137462119729731945, - "venv/lib/python3.13/site-packages/PIL/TiffImagePlugin.py": 6845043550424565106, - "venv/lib/python3.13/site-packages/authlib/consts.py": 14226604841596736870, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending_distributions.py": 209769687436320665, - "venv/lib/python3.13/site-packages/dateutil/_common.py": 12492546559232079071, - "venv/lib/python3.13/site-packages/keyring/compat/py312.py": 17581691618899404491, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_clearing_run_switches.py": 3020294789560975101, - "venv/lib/python3.13/site-packages/websockets/asyncio/messages.py": 6848925149930551457, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_iterrows.py": 3791886201566670087, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_setops.py": 15365064654930699428, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_indexing.py": 6539365174681852769, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/referencing/_attrs.pyi": 10030665705880994025, - "venv/lib/python3.13/site-packages/urllib3/response.py": 1987354357306756790, - "backend/src/scripts/delete_running_tasks.py": 7776896567014157554, - "backend/src/api/routes/plugins.py": 4567336078922104278, - "venv/lib/python3.13/site-packages/numpy/_typing/__init__.py": 18242238390157333247, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_base_indexer.py": 3129123098288498633, - "venv/lib/python3.13/site-packages/PIL/CurImagePlugin.py": 17697303205012181529, - "backend/git_repos/remote/test-repo.git/hooks/update.sample": 8204581436750313444, - "backend/git_repos/remote/test-repo.git/hooks/applypatch-msg.sample": 12627299623252391515, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.h": 4516275133897904047, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/attributes.py": 5068814626384132900, - "venv/lib/python3.13/site-packages/git/objects/tag.py": 7954808535585493300, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/RECORD": 16740224557818847141, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_errstate.py": 10788459171326750780, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libssl-81ffa89e.so.3": 13913673119166658781, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_defchararray.py": 15135904718007443306, - "venv/lib/python3.13/site-packages/pygments/lexers/factor.py": 15788613154609197002, - "venv/lib/python3.13/site-packages/numpy/_core/strings.pyi": 1981676808027146409, - "venv/lib/python3.13/site-packages/pydantic/experimental/__init__.py": 492399139963056461, - "venv/lib/python3.13/site-packages/pygments/lexers/_cocoa_builtins.py": 15468347167912293394, - "backend/src/core/scheduler.py": 2472649939852521889, - "venv/lib/python3.13/site-packages/_pytest/assertion/rewrite.py": 2425990712758915831, - "venv/lib/python3.13/site-packages/itsdangerous/signer.py": 3694661094753475840, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_integer.py": 16102640589300356639, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x32_unix.h": 9165722966153119887, - "venv/lib/python3.13/site-packages/requests/sessions.py": 6936640856092320928, - "venv/lib/python3.13/site-packages/anyio/abc/_sockets.py": 15042495744291042062, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_random.py": 4179188367630060654, - "venv/lib/python3.13/site-packages/dateutil/easter.py": 14631233890122048084, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timedeltas.pyi": 3783371827926657291, - "frontend/src/components/llm/ProviderConfig.svelte": 1968349576688210309, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_longdouble.py": 9337218715436213122, - "venv/lib/python3.13/site-packages/pandas/core/computation/pytables.py": 16326122536715961388, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dropna.py": 3168969662216766293, - "venv/lib/python3.13/site-packages/cffi/api.py": 5325821560978502135, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_unary.py": 7128845965976836334, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/subversion.py": 7423946096970870727, - "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/WHEEL": 5076688779572520166, - "backend/src/plugins/translate/_run_source.py": 11569137727611732019, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_select.py": 17823338162428379468, - "backend/tests/test_security_audit_fixes.py": 10329229098676202553, - "venv/lib/python3.13/site-packages/pydantic/v1/main.py": 213087273729911492, - "backend/src/core/task_manager/__tests__/test_context.py": 4211690952139950648, - "backend/src/services/auth_service.py": 17642785219801916280, - "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/nimrod.py": 8457135214131458774, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/heuristics.py": 1422768761337195135, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_timedelta.py": 17052461094717926538, - "venv/lib/python3.13/site-packages/pygments/lexers/ptx.py": 4855144232064607995, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5-fcafa220.so.3.3": 5620628698712971642, - "venv/lib/python3.13/site-packages/fastapi/dependencies/models.py": 8626894872248212015, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/__init__.py": 8558541715982163200, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/live_render.py": 14619617939683800204, - "venv/lib/python3.13/site-packages/pandas/core/interchange/__init__.py": 15130871412783076140, - "frontend/build/_app/immutable/chunks/Bhogwjd0.js": 5613453459417995897, - "backend/src/plugins/backup.py": 9775992510122456201, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py": 14946223589457772924, - "venv/lib/python3.13/site-packages/apscheduler/executors/pool.py": 10344126569001032241, - "backend/git_repos/remote/test-repo.git/refs/heads/feature/test": 7714224145564125988, - "venv/lib/python3.13/site-packages/PIL/PngImagePlugin.py": 5076219228736706283, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_join.py": 1131792466825856990, - "venv/lib/python3.13/site-packages/uvicorn/logging.py": 12858188863836778374, - "venv/lib/python3.13/site-packages/pydantic/networks.py": 15767095796055034509, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_function_base.pyi": 10972502518588022706, - "venv/lib/python3.13/site-packages/h11/_readers.py": 832030916375670301, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraypad.py": 4907193085512342162, - "dist/docker/frontend.1.2.1.tar.xz": 5384558848012153878, - "venv/lib/python3.13/site-packages/numpy/_distributor_init.py": 1101690714183863290, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timestamps.pyi": 51728851886466199, - "backend/src/services/dataset_review/repositories/__tests__/test_session_repository.py": 13584543719626464409, - "venv/lib/python3.13/site-packages/PIL/BufrStubImagePlugin.py": 5520941821175895889, - "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/cryptography/x509/__init__.py": 4066756344049307453, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows.py": 13341168721223961872, - "venv/lib/python3.13/site-packages/PIL/ImtImagePlugin.py": 17599267755504817169, - "frontend/src/routes/settings/MigrationMappingsTable.svelte": 4467573699012255407, - "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.pyi": 8879196542984811747, - "frontend/build/_app/immutable/nodes/24.DxGnW5qM.js": 14090440194482960673, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dtypes.py": 7550022036887594386, - "venv/lib/python3.13/site-packages/anyio/_core/_asyncio_selector_thread.py": 1760597191437520000, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/abstract.py": 14216912708889351810, - "venv/lib/python3.13/site-packages/websockets/sync/client.py": 10892557975919033983, - "venv/lib/python3.13/site-packages/gitdb/test/test_stream.py": 18159319442241857857, - "venv/lib/python3.13/site-packages/pydantic/_internal/_validators.py": 2939255306814626438, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv": 12896264205153363031, - "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_stringdtype.py": 8381476847196129074, - "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h": 8933016749764021181, - "venv/lib/python3.13/site-packages/jeepney/io/tests/test_asyncio.py": 2820168745710754136, - "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/test_array_with_attr.py": 6568496539994758985, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/accumulate.py": 5780225603819849877, - "venv/lib/python3.13/site-packages/ecdsa/keys.py": 10281170640484982154, - "venv/lib/python3.13/site-packages/pandas/core/ops/dispatch.py": 7041711677358147534, - "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.pyi": 14543653817631274394, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_categorical_equal.py": 7942323667866280872, - "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.py": 11621577915097515056, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_arrow_interface.py": 9757086292358759236, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_html.py": 7732330576029516854, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/asyncio.py": 2517623574187179319, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/sqltypes.py": 2952996080192295188, - "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.pyi": 7171810177801103765, - "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/licenses/LICENSE": 5757922580822401219, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/_psycopg_common.py": 4111797647365870137, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pyodbc.py": 8175468565413744516, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_inference.py": 5741637509343419942, - "venv/lib/python3.13/site-packages/PIL/_imaging.cpython-313-x86_64-linux-gnu.so": 1425926264271197601, - "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_multi_thread.py": 5660352470978621226, - "venv/lib/python3.13/site-packages/pycparser/plyparser.py": 5251740466238035035, - "venv/lib/python3.13/site-packages/pygments/lexers/freefem.py": 9851243865301700231, - "venv/lib/python3.13/site-packages/pygments/lexers/apdlexer.py": 14222752852221009085, - "venv/lib/python3.13/site-packages/pygments/lexers/whiley.py": 218468511185731869, - "venv/bin/pyrsa-priv2pub": 16766314338551408621, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/quoted_character/foo.f": 15318083678609435813, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/authorization_server.py": 724388765673082720, - "venv/lib/python3.13/site-packages/pygments/styles/zenburn.py": 1031869867933871309, - "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/INSTALLER": 17282701611721059870, "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/video.webm": 3868075359950286684, - "backend/src/core/__tests__/test_superset_profile_lookup.py": 2078836378584435447, - "backend/src/services/clean_release/demo_data_service.py": 1822246829322620623, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2cmap.py": 5863341586534531594, - "venv/lib/python3.13/site-packages/numpy/_globals.pyi": 12839879732484756979, - "venv/lib/python3.13/site-packages/PIL/_deprecate.py": 15076725072094847812, - "venv/lib/python3.13/site-packages/pip/_internal/models/index.py": 2839270935469791607, - "frontend/build/_app/immutable/nodes/26.OrmfF8FW.js": 16537908264177321471, - "venv/lib/python3.13/site-packages/ecdsa/test_keys.py": 17117188373419689467, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_generic.py": 1098361087956787007, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/conftest.py": 16571782049241458769, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_eng_formatting.py": 14768815444701392013, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/pytestplugin.py": 1591034895268415944, - "venv/lib/python3.13/site-packages/PIL/ImageFont.py": 15621336334706847865, - "venv/lib/python3.13/site-packages/pygments/console.py": 3540660073442483692, - "frontend/build/_app/immutable/assets/AssistantChatPanel.D4L5jlt0.css": 10724144138366384732, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/style.py": 10665998898253460114, - "venv/lib/python3.13/site-packages/numpy/typing/__init__.py": 3608665862759745048, - "backend/src/core/__tests__/test_config_manager_compat.py": 656412918792001580, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/flatiter.pyi": 6885824496927786205, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_partial.py": 3151286293440416036, - "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/meson.build": 17468163147765825687, - "venv/lib/python3.13/site-packages/pygments/lexers/soong.py": 10273453675034306814, - "frontend/e2e/fixtures/auth.fixture.js": 12330457928638392604, - "frontend/src/components/TaskRunner.svelte": 18014857434320509117, - "backend/src/plugins/translate/orchestrator_runner.py": 1192466559618297192, - "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pillow.libs/libfreetype-ee1c40c4.so.6.20.4": 12301510769231120312, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_subclassing.py": 17318983445227658412, - "venv/lib/python3.13/site-packages/httpx/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/handlers/postgres.py": 14162382430051693313, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_aix.h": 8706347224105630468, - "venv/bin/uvicorn": 3776670267111625708, - "backend/tests/test_task_persistence.py": 1764267414712263025, - "venv/lib/python3.13/site-packages/jsonschema/tests/fuzz_validate.py": 2328585939822059352, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiprocessing.py": 5522490547285108448, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_value_counts.py": 12340872812120847127, - "venv/lib/python3.13/site-packages/apscheduler/executors/base.py": 1980520974511822101, - "venv/lib/python3.13/site-packages/h11/_abnf.py": 10456996134895429201, - "venv/lib/python3.13/site-packages/apscheduler/executors/twisted.py": 2695602672085615762, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/licenses/LICENSE": 11199044866758471950, - "venv/lib/python3.13/site-packages/_pytest/scope.py": 7603155109542903644, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90": 15981076495193915107, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_astype.py": 15768655715952923925, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/missing.py": 14589973874359353799, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_easter.py": 3397863170068576196, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex.tpl": 8820045022551446255, - "venv/lib/python3.13/site-packages/pygments/lexers/jsx.py": 13855228003748707341, - "venv/lib/python3.13/site-packages/pygments/lexers/typst.py": 8883289726601667104, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_cython.py": 2933400021016349431, - "venv/lib/python3.13/site-packages/pip/_internal/models/scheme.py": 4101322315594430874, - "venv/lib/python3.13/site-packages/PIL/_imagingcms.pyi": 12476347428820346383, - "backend/src/core/superset_client/_dashboards_filters.py": 8706676245520282810, - "backend/git_repos/remote/test-repo.git/hooks/commit-msg.sample": 13435789416588783681, - "venv/lib/python3.13/site-packages/pygments/lexers/elm.py": 14683437310498104916, - "venv/lib/python3.13/site-packages/jose/jwk.py": 2781217726458801910, - "backend/src/plugins/translate/__tests__/test_dictionary_import.py": 828852818135096215, - "venv/lib/python3.13/site-packages/keyring/backends/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/_pytest/doctest.py": 6126919596776592278, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_dispatcher.py": 2063037275809439611, - "venv/bin/Activate.ps1": 1196103427939049710, - "venv/lib/python3.13/site-packages/starlette/middleware/trustedhost.py": 8302185291610019926, - "frontend/src/routes/datasets/review/ReviewWorkspaceLeftSidebar.svelte": 9009994851177005358, - "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/asn1.py": 8801155055979135092, - "venv/lib/python3.13/site-packages/numpy/_globals.py": 8736093011628027941, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2cffi.py": 5997687240967250164, - "backend/src/plugins/translate/_batch_proc.py": 5830558923416766212, - "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/METADATA": 15987199384245264478, - "venv/lib/python3.13/site-packages/pyasn1/debug.py": 6305633719847955310, - "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.py": 14446508217220482719, - "venv/lib/python3.13/site-packages/pandas/_libs/_cyutility.cpython-313-x86_64-linux-gnu.so": 3372660143512868174, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/sql.py": 13315906751371033170, - "venv/lib/python3.13/site-packages/numpy.libs/libscipy_openblas64_-096271d3.so": 14338208504131470036, - "venv/lib/python3.13/site-packages/sqlalchemy/pool/events.py": 13473858896579666058, - "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/licenses/LICENSE": 3868190977070717994, - "venv/lib/python3.13/site-packages/sqlalchemy/__init__.py": 9751988289698484530, - "venv/lib/python3.13/site-packages/pygments/lexers/stata.py": 7249891970174867363, - "venv/lib/python3.13/site-packages/pygments/lexers/oberon.py": 15220143799603451830, - "backend/src/models/dataset_review.py": 5814500849969423218, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_masked.py": 5380551301916549925, - "backend/src/services/clean_release/repositories/publication_repository.py": 11208425895213508165, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/zookeeper.py": 4318643109309626098, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/random.pyi": 1808392097712315455, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/kind/foo.f90": 1367964042730902899, - "venv/lib/python3.13/site-packages/_pytest/_version.py": 4890545974654141536, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_interface.py": 13648006002292914247, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resample_api.py": 3278209206670699265, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/dtypes.cpython-313-x86_64-linux-gnu.so": 657138415665704488, - "venv/lib/python3.13/site-packages/itsdangerous/timed.py": 12571102606719555007, - "venv/lib/python3.13/site-packages/pandas/core/indexers/utils.py": 5861072573716897447, - "frontend/src/lib/ui/Icon.svelte": 2201964532717139995, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_api.py": 10514120091521589282, - "venv/lib/python3.13/site-packages/jose/backends/ecdsa_backend.py": 2684176977865283060, - "venv/lib/python3.13/site-packages/pygments/lexers/c_cpp.py": 1211842877043321095, - "venv/lib/python3.13/site-packages/pygments/lexers/apl.py": 16767474673619335683, - "venv/lib/python3.13/site-packages/pygments/lexers/fift.py": 7537570342576781911, - "venv/lib/python3.13/site-packages/jeepney/tests/test_bus.py": 4260827599660763641, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_misc.py": 16393451200513733144, - "frontend/src/lib/api/translate/datasources.js": 17202165717960970061, - "backend/src/services/clean_release/enums.py": 7365670144442292671, - "venv/lib/python3.13/site-packages/fastapi/background.py": 16533963020573865222, - "venv/lib/python3.13/site-packages/gitdb/base.py": 7927279446353696534, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py": 17873236864291624476, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/__init__.py": 16211693040174992594, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_quoted_character.py": 2316632434571797367, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_math.h": 16701045088211015518, - "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/_arrow_utils.py": 17808805047762566525, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_take.py": 9847808489301498487, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_comparison.py": 11333735187162513512, - "venv/lib/python3.13/site-packages/PIL/SgiImagePlugin.py": 6916200065790425497, - "venv/lib/python3.13/site-packages/pip/_internal/commands/configuration.py": 1608697090566485893, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django.py": 3210697476292094384, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py": 1331438198531942242, - "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/licenses/LICENSE": 6965457853328313914, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90": 8308927438994838783, - "venv/lib/python3.13/site-packages/pygments/lexers/gcodelexer.py": 13712494327007684318, - "frontend/src/lib/api/translate/jobs.js": 9613844538417291513, - "backend/src/api/routes/translate/_schedule_routes.py": 18180097500694105300, - "venv/lib/python3.13/site-packages/starlette/formparsers.py": 9019779181100355515, - "venv/lib/python3.13/site-packages/numpy/core/numeric.py": 17025007229779320230, - "venv/lib/python3.13/site-packages/pandas/core/computation/expr.py": 13085709365673019494, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/putmask.py": 10934101690788549526, - "backend/src/services/clean_release/__tests__/test_audit_service.py": 1679130450221264383, - "venv/lib/python3.13/site-packages/starlette/middleware/httpsredirect.py": 16837082808103815044, - "venv/lib/python3.13/site-packages/pip/_internal/commands/search.py": 8292218231992728142, - "dist/docker/ss-tools.1.1.0.tar.xz": 14627825683119220800, - "venv/lib/python3.13/site-packages/fastapi/security/utils.py": 2616633862993539558, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/layout.py": 11554376181083053156, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/scalars.pyi": 17683675356659300769, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_getitem.py": 11882213323878588707, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_direct.py": 12680113511641199070, - "venv/lib/python3.13/site-packages/PIL/GribStubImagePlugin.py": 14954946414134984896, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi": 9405122752084210696, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_conversion.pyi": 11580106670226366710, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv": 13441294827017400897, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_index_as_string.py": 13421551616136437100, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_tzconversion.py": 7205566353454584259, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_upcast.py": 6496794053681247105, - "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/RECORD": 18314788057673509075, - "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.ux.test.js": 5439236328736424365, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/RECORD": 3205266407680661753, - "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.pyi": 10360538024015064036, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.cpython-313-x86_64-linux-gnu.so": 2311012065007769341, - "backend/git_repos/remote/test-repo.git/objects/71/47ad0836409b35c1650dddf5fa6329ba61a824": 16601919569600972016, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/shape.py": 13410030168622484801, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_convert.py": 17957207974799052653, - "venv/lib/python3.13/site-packages/pandas/_libs/sparse.cpython-313-x86_64-linux-gnu.so": 2051484129454294720, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_as_unit.py": 4283520188709399244, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.f": 9330535808093475892, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/requirements.py": 2362917888844255805, - "venv/lib/python3.13/site-packages/pygments/lexers/x10.py": 6167378515780115912, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_generic.py": 1297407268239966429, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/measure.py": 18327922742808984428, - "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_chained_assignment_deprecation.py": 7694137945143129474, - "frontend/build/_app/immutable/chunks/BbkjCG-u.js": 8279216661890316784, - "venv/lib/python3.13/site-packages/sqlalchemy/connectors/asyncio.py": 4200928269459447593, - "venv/lib/python3.13/site-packages/pandas/core/ops/missing.py": 9493665944764255854, - "venv/lib/python3.13/site-packages/pip/_internal/self_outdated_check.py": 991029278889407558, - "venv/lib/python3.13/site-packages/pydantic/aliases.py": 14481980467204711659, - "venv/lib/python3.13/site-packages/sqlalchemy/events.py": 9329355486544822483, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_structures.py": 16375837477294135345, - "venv/lib/python3.13/site-packages/pandas/compat/pyarrow.py": 13693379998785127538, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/control.py": 2034518223411945438, - "venv/lib/python3.13/site-packages/pillow.libs/libzstd-761a17b6.so.1.5.7": 17875236748140157032, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/numpyconfig.h": 13339221870252345205, - "venv/lib/python3.13/site-packages/pandas/core/ops/array_ops.py": 10061020479033421596, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_head_tail.py": 13047338070883375426, - "backend/src/core/task_manager/models.py": 7035565766825575890, - "venv/lib/python3.13/site-packages/pygments/formatters/other.py": 13124903290103898118, - "frontend/src/lib/api/translate.js": 18140498250896378509, - "venv/lib/python3.13/site-packages/pip/_internal/vcs/versioncontrol.py": 13742159245132241245, - "venv/lib/python3.13/site-packages/_pytest/logging.py": 10972553724755511468, - "venv/lib/python3.13/site-packages/pydantic/_internal/_mock_val_ser.py": 12265320534388472158, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.pyi": 6616985736007157309, - "venv/lib/python3.13/site-packages/keyring/backends/fail.py": 5792496235026678021, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_reductions.py": 633644255158859565, - "venv/lib/python3.13/site-packages/pygments/lexers/futhark.py": 10102535873433759899, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/traceback.py": 2535227583726271746, - "venv/lib/python3.13/site-packages/yaml/emitter.py": 6036657460416912844, - "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/WHEEL": 9100692507274722091, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/__init__.py": 4014740126161973332, - "venv/lib/python3.13/site-packages/numpy/_core/_dtype.py": 7796703383405149774, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_set_name.py": 9094608008538024609, - "venv/lib/python3.13/site-packages/fastapi/exceptions.py": 12665775976182239091, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_join.py": 1364886077926604427, - "frontend/src/lib/components/layout/TaskDrawer.svelte": 11803999908168836613, - "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/pointless.py": 17552020039609007881, - "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24662.f90": 4241310200087270990, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_astype.py": 563689238486630866, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_frozen.py": 3484963987053884566, - "venv/lib/python3.13/site-packages/pydantic/v1/env_settings.py": 6194387033830177219, - "backend/src/core/superset_client/__init__.py": 14560361361214953450, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.pyi": 16976386782787920450, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/bitgen.h": 12421210767114721499, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/keywrap.py": 10424037418528425800, - "venv/lib/python3.13/site-packages/pygments/lexers/usd.py": 934820244673741695, - "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_digest.py": 7988469818593853943, - "venv/lib/python3.13/site-packages/fastapi/applications.py": 4975013401500183420, - "venv/lib/python3.13/site-packages/pyasn1/type/useful.py": 10313387611927801339, - "venv/lib/python3.13/site-packages/uvicorn/lifespan/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/fastapi/security/oauth2.py": 1925394177931547776, - "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/LICENSE": 11167201188673981085, - "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/RECORD": 5169907629260560698, - "backend/tests/services/clean_release/test_compliance_execution_service.py": 5924200441771414883, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_asof.py": 15792528637923603240, - "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/licenses/LICENSE": 11986475601091748012, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_mips_unix.h": 17373389962405490482, - "venv/lib/python3.13/site-packages/numpy/_core/umath.pyi": 11775804030935134661, - "backend/tests/services/clean_release/test_demo_mode_isolation.py": 1970652424726919519, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/conftest.py": 17897502508251413988, - "backend/src/plugins/llm_analysis/service.py": 6306529701818786359, - "frontend/src/routes/translate/+page.svelte": 15284819686967093613, - "venv/lib/python3.13/site-packages/websockets/legacy/http.py": 16266924390281399720, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_format.py": 1947585389944838076, - "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_openssl.py": 10446441599800965961, - "venv/lib/python3.13/site-packages/dotenv/version.py": 13508433229287636267, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_reductions.py": 3227705565578016389, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libgssapi_krb5-497db0c6.so.2.2": 6199424505696679197, - "venv/lib/python3.13/site-packages/pandas/tests/base/common.py": 13335865314907577354, - "venv/lib/python3.13/site-packages/pygments/lexers/numbair.py": 17382646010399794697, - "venv/lib/python3.13/site-packages/pandas/tests/libs/test_lib.py": 6721066015604956469, - "frontend/src/lib/utils.js": 5436516952434475239, - "venv/lib/python3.13/site-packages/gitdb/db/__init__.py": 2615504918450276693, - "backend/src/services/clean_release/facade.py": 11231787492455424065, - "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/ext.py": 15699809032725838985, - "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.pyi": 12566839271245057531, - "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.pyi": 18395688193449688360, - "venv/lib/python3.13/site-packages/sqlalchemy/connectors/__init__.py": 17194870661869873083, - "venv/lib/python3.13/site-packages/pip/_internal/commands/list.py": 13035925292530461722, - "venv/lib/python3.13/site-packages/pip/_internal/cli/__init__.py": 11914508471759255927, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_take.py": 1216902953519121176, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_interpolate.py": 6154072863387383113, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE": 2345070715845618109, - "venv/bin/pyrsa-encrypt": 5858278204727417482, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py": 16045758521544316139, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_common.h": 14732581790650403546, - "frontend/build/_app/immutable/nodes/18.Cz1yA8fe.js": 11415817195501354077, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.py": 3762934316884129514, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_index.py": 13517883160584591966, - "venv/lib/python3.13/site-packages/starlette/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/click/_utils.py": 16491408631876616271, - "venv/lib/python3.13/site-packages/gitdb/test/lib.py": 13294941660283059872, - "frontend/src/components/llm/ValidationReport.svelte": 11810571826279890996, - "venv/lib/python3.13/site-packages/packaging/specifiers.py": 2800449842990194437, - "venv/lib/python3.13/site-packages/pyasn1/error.py": 11036037300994516747, - "venv/lib/python3.13/site-packages/pip/_internal/build_env.py": 3614358934066127900, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi": 3893434234020223151, - "venv/lib/python3.13/site-packages/pydantic/_internal/_generate_schema.py": 7343380095251236503, - "venv/lib/python3.13/site-packages/greenlet/platform/setup_switch_x64_masm.cmd": 8473866644286785815, - "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/WHEEL": 6514509858522675228, - "venv/lib/python3.13/site-packages/keyring/__main__.py": 14602212239605295451, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_assign.py": 2647902466315482406, - "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/urllib3/util/wait.py": 14629837381061032546, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite.py": 3628609433179387988, - "venv/lib/python3.13/site-packages/authlib/oauth1/client.py": 7314311571224771, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapper.py": 16715864918034312591, - "venv/lib/python3.13/site-packages/uvicorn/_compat.py": 2593000889619875759, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_time_series.py": 5205199092955498507, - "venv/lib/python3.13/site-packages/numpy/f2py/__init__.pyi": 3566887042414273892, - "venv/lib/python3.13/site-packages/pygments/lexers/bibtex.py": 14652372822443154388, - "frontend/src/components/git/useGitManager.js": 5317184945628692154, - "venv/lib/python3.13/site-packages/pygments/lexers/int_fiction.py": 8806961041808606055, - "frontend/build/_app/immutable/nodes/5.C4eoj6jI.js": 12855092635622474830, - "venv/lib/python3.13/site-packages/websockets/datastructures.py": 5180442040351387281, - "frontend/build/_app/immutable/chunks/Bzxh7XzU.js": 3796955463932545147, - "frontend/build/_app/immutable/chunks/D0x3O7MA.js": 5796228701724686318, - "venv/lib/python3.13/site-packages/numpy/_configtool.py": 2946953194004101078, - "venv/lib/python3.13/site-packages/numpy/core/__init__.py": 10397294636564169377, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authenticate_client.py": 16886645731942472285, - "venv/lib/python3.13/site-packages/greenlet/greenlet_allocator.hpp": 11041111583319491309, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_bool.py": 433342705586552936, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_dtypes.py": 2313400030798822026, - "venv/lib/python3.13/site-packages/pandas/tests/test_aggregation.py": 16863055892192070549, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/mypy.py": 823265492261272631, - "frontend/src/routes/settings/__tests__/settings_page.ux.test.js": 8756428349518151160, - "venv/lib/python3.13/site-packages/pydantic/validators.py": 8292819706488319845, - "frontend/src/components/git/CommitHistory.svelte": 61942790722897211, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_m68k_gcc.h": 6580173800099450404, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/base.py": 13269563625127294513, - "frontend/src/lib/api/assistant.js": 15470667170083225911, - "frontend/build/_app/immutable/chunks/2dOUpm6k.js": 11811637653151731489, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.pyi": 17469792319379909312, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/pickleable.py": 7712040860601343075, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/console.py": 3540660073442483692, - "venv/lib/python3.13/site-packages/pygments/styles/colorful.py": 15708848112363953394, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/common.py": 9354442374897565498, - "venv/lib/python3.13/site-packages/pandas/_typing.py": 17795648994662434211, - "backend/src/api/routes/__tests__/conftest.py": 8465980330386544642, - "venv/lib/python3.13/site-packages/cffi/_cffi_errors.h": 1479575326813300292, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data": 9599129816090399315, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_format.py": 9331389900588353667, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/uvicorn/loops/asyncio.py": 16496916527760969173, - "venv/lib/python3.13/site-packages/_pytest/deprecated.py": 5452408732344157294, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_update.py": 12293424926920594944, - "backend/src/plugins/translate/events.py": 8282921049842647968, - "venv/lib/python3.13/site-packages/_pytest/junitxml.py": 5871715626272366062, - "venv/lib/python3.13/site-packages/pandas/_libs/missing.pyi": 13543139288840944411, - "venv/lib/python3.13/site-packages/pydantic/datetime_parse.py": 196119761382305574, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/hist.py": 10928173425078493095, - "venv/lib/python3.13/site-packages/pip/_internal/cli/status_codes.py": 9143625681947330756, - "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.py": 13446184230476677032, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_hist_method.py": 2109257663592928, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_arithmetic.py": 976970179757115407, - "venv/lib/python3.13/site-packages/pygments/styles/algol.py": 3040373291664740876, - "venv/lib/python3.13/site-packages/iniconfig/_parse.py": 11418441008427032090, - "backend/src/models/profile.py": 6081037345174498278, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel.py": 7728646523045538484, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_scalar_compat.py": 10068989979144965125, - "venv/lib/python3.13/site-packages/git/refs/reference.py": 2038789918710608481, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.py": 17112989332785349705, - "venv/lib/python3.13/site-packages/smmap/mman.py": 9091562788592406032, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_index_new.py": 796607958391882182, - "venv/lib/python3.13/site-packages/sqlalchemy/log.py": 10101221585967121334, - "venv/lib/python3.13/site-packages/PIL/BlpImagePlugin.py": 7209218638257731375, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_repeat.py": 18394463352314692642, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_between_time.py": 14266333058913745751, - "venv/lib/python3.13/site-packages/pandas/_libs/lib.cpython-313-x86_64-linux-gnu.so": 6452315003728497116, - "venv/lib/python3.13/site-packages/pygments/lexers/diff.py": 5930189593946259160, - "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.pyi": 7410507092040239447, - "venv/lib/python3.13/site-packages/pydantic/_internal/_signature.py": 17075003201648027250, - "venv/lib/python3.13/site-packages/apscheduler/schedulers/qt.py": 12828696264909048448, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge.py": 11366935134260232329, - "venv/lib/python3.13/site-packages/pandas/tests/extension/test_string.py": 13234624995755549329, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/manifest.py": 16998683210177680416, - "venv/lib/python3.13/site-packages/pygments/lexers/smalltalk.py": 6113431347120223592, - "backend/src/core/superset_client/_dashboards_list.py": 10999374002470143873, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/file_proxy.py": 17695135735211897444, - "venv/lib/python3.13/site-packages/jeepney/io/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_markdown.py": 9964642152916165317, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_is_unique.py": 3989602816674881215, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/adapter.py": 5908944827805063108, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/authorization_server.py": 2491654903543600678, - "venv/lib/python3.13/site-packages/numpy/__init__.pyi": 15820654525292895396, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_astype.py": 6578539240745332772, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_equals.py": 9903250467264848187, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/models.py": 9513172366009392193, - "frontend/src/lib/components/translate/TermCorrectionPopup.svelte": 5276611147503580165, - "backend/git_repos/remote/test-repo.git/objects/59/3a37acec7d2bddce10df90ab17bc9ede52e523": 1117161574576783985, - "venv/lib/python3.13/site-packages/h11/_receivebuffer.py": 4631433251046338381, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_unique.py": 16285418015531891530, - "backend/git_repos/remote/test-repo.git/hooks/post-update.sample": 4288868784459664203, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqldb.py": 2138006249556140141, - "venv/lib/python3.13/site-packages/pandas/tests/io/sas/__init__.py": 15130871412783076140, - "frontend/build/_app/immutable/nodes/20.DpAY-jEt.js": 10650560774924620070, - "backend/tests/test_auth.py": 6167020718035755646, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.pyx": 5760108632332714287, - "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.pyi": 8708830448398500675, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/libdivide.h": 5314232500579481313, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/visitors.py": 5190923415390076080, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_asof.py": 8656532774394927388, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_categorical.py": 12897027063618569795, - "venv/lib/python3.13/site-packages/pandas/io/excel/_pyxlsb.py": 10035587889954731645, - "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py": 2375452080667815941, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/timeseries.py": 17641722582848932332, - "venv/bin/pyrsa-decrypt": 10929163076272054227, - "backend/tests/test_models.py": 3998442321184404421, - "backend/src/models/dataset_review_pkg/_semantic_models.py": 3910791744304398663, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/schema.py": 8358664670620586363, - "venv/lib/python3.13/site-packages/greenlet/greenlet_compiler_compat.hpp": 465436185632243991, - "venv/lib/python3.13/site-packages/fastapi/temp_pydantic_v1_params.py": 9436036880518047720, - "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.pyi": 18253950285509265097, - "venv/lib/python3.13/site-packages/ecdsa/__init__.py": 6237633580090653788, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/instrumentation.py": 14882045449667214075, - "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.pyi": 18290764713161282980, - "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/METADATA": 15970460108484113417, - "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_analytics.py": 8155550493311083506, - "venv/lib/python3.13/site-packages/packaging/_tokenizer.py": 7442392076059866359, - "venv/bin/dotenv": 953953349803507198, - "backend/git_repos/remote/test-repo.git/objects/6f/85e20ce3ef98cf07a2f102498b71b9462552c5": 3012017807908986452, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py": 7624316342162916928, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_regression.py": 12593643817685777170, - "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_writers.py": 103545128256076790, - "venv/lib/python3.13/site-packages/httpcore/_sync/socks_proxy.py": 4418971149260853240, - "venv/lib/python3.13/site-packages/git/__init__.py": 15867730798565725003, - "venv/lib/python3.13/site-packages/numpy/fft/__init__.py": 9343449448737026658, - "backend/src/plugins/translate/preview_constants.py": 12447768695944862994, - "venv/lib/python3.13/site-packages/multipart/decoders.py": 11346752866822986212, - "venv/lib/python3.13/site-packages/dateutil/zoneinfo/__init__.py": 10261654903106416888, - "venv/lib/python3.13/site-packages/numpy/__config__.pyi": 1422114139050700402, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_kind.py": 18178830861475480607, - "venv/lib/python3.13/site-packages/pycparser/c_generator.py": 14922277346364091122, - "venv/lib/python3.13/site-packages/numpy/typing/mypy_plugin.py": 1306129775649200113, - "backend/src/services/clean_release/__tests__/test_manifest_builder.py": 9320699981861675127, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/shared.py": 1162754506656505196, - "backend/src/services/dataset_review/orchestrator_pkg/_commands.py": 15474996500928063708, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/converter.py": 9041278869295701566, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_concat.py": 4472503149811617440, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_interpolate.py": 7354685880215444946, - "venv/lib/python3.13/site-packages/pip/_internal/commands/hash.py": 11824898770873127699, - "backend/git_repos/remote/test-repo.git/objects/17/66251d8cb2693136e09ea3def3e776559cb722": 1137762010493457272, - "venv/lib/python3.13/site-packages/numpy/fft/tests/test_helper.py": 5362180645056413158, - "backend/src/models/storage.py": 5952240576082791619, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_deprecations.py": 16367195310156359251, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/signals.py": 10390443713463805090, - "venv/lib/python3.13/site-packages/passlib/utils/compat/_ordered_dict.py": 14248790502300368024, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/uts46data.py": 1867240043777383728, - "venv/lib/python3.13/site-packages/pygments/lexers/testing.py": 17148598391210353576, - "venv/lib/python3.13/site-packages/PIL/ImageOps.py": 3884310863548175682, - "venv/lib/python3.13/site-packages/pyasn1/type/univ.py": 7163437624197683039, - "venv/lib/python3.13/site-packages/starlette/middleware/cors.py": 11384893784314197864, - "backend/git_repos/remote/test-repo.git/objects/38/0395343915d386a8d58774cc6c6677205065e8": 5481382229802988191, - "venv/lib/python3.13/site-packages/referencing/_attrs.py": 14434891919747863272, - "venv/lib/python3.13/site-packages/authlib/integrations/django_client/apps.py": 14151733532064278336, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/cmac.py": 12011944740750051829, - "venv/lib/python3.13/site-packages/authlib/oidc/core/claims.py": 2035724920423374302, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/linalg.pyi": 7217817172953767893, - "venv/lib/python3.13/site-packages/pygments/lexers/ampl.py": 4594260378653369985, - "venv/lib/python3.13/site-packages/urllib3/util/url.py": 15992369651965016538, - "venv/lib/python3.13/site-packages/attrs/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpx/_client.py": 1063593889704982038, - "venv/lib/python3.13/site-packages/pip/_internal/network/download.py": 5256731341219268693, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayprint.pyi": 2424868797160722318, - "venv/lib/python3.13/site-packages/pandas/core/indexes/extension.py": 7193879749426425951, - "venv/lib/python3.13/site-packages/psycopg2/pool.py": 8855184580138330938, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_cat.py": 15988884721768567895, - "venv/lib/python3.13/site-packages/urllib3/util/connection.py": 15511685694589961094, - "venv/lib/python3.13/site-packages/requests/compat.py": 5836590172733661320, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_rank.py": 5398520257852104723, - "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pip/_internal/operations/freeze.py": 3469845570614985559, - "venv/lib/python3.13/site-packages/numpy/ma/core.pyi": 4829891173366130328, - "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/WHEEL": 12146818530001975731, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_symbol.py": 10792387279408528886, - "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/__init__.py": 5896924546560667519, - "venv/lib/python3.13/site-packages/pip/_internal/utils/retry.py": 15244280495983216204, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/METADATA": 15658158392301945427, - "venv/lib/python3.13/site-packages/keyring/backends/macOS/__init__.py": 1010937986753403630, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_iterator.py": 13869355993837330406, - "frontend/build/_app/immutable/chunks/CA7O3zHN.js": 783829162929040261, - "backend/src/plugins/translate/orchestrator_aggregator.py": 2072358957289443762, - "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_gather.py": 3634138701088855517, - "venv/lib/python3.13/site-packages/greenlet/greenlet.cpp": 3281107194043468270, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_formats.py": 9738552308554950419, - "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.pyi": 1424133074692438241, - "venv/lib/python3.13/site-packages/PIL/IcoImagePlugin.py": 14483964191652228364, - "frontend/src/routes/reports/llm/[taskId]/+page.svelte": 14394593511269407852, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/passlib/handlers/__init__.py": 3424087230285514388, - "venv/lib/python3.13/site-packages/PIL/_avif.cpython-313-x86_64-linux-gnu.so": 5243449968857258659, - "backend/src/api/routes/assistant/_admin_routes.py": 3380446401429936332, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_feather.py": 13613400750755530364, - "venv/lib/python3.13/site-packages/rsa/cli.py": 1753949198467694190, - "backend/src/plugins/translate/orchestrator_sql.py": 15420456250044832567, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_coercion.py": 3339075591248270762, - "backend/src/core/utils/superset_context_extractor/_filters.py": 281666313889333545, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_constructors.py": 11065058462752831997, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/context.py": 1041624619197012753, - "venv/lib/python3.13/site-packages/pygments/lexers/_stan_builtins.py": 1961875544235948177, - "frontend/src/lib/components/dataset-review/__tests__/source_intake_panel.ux.test.js": 13445861056598482363, - "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_app.py": 4329794049222609894, - "venv/lib/python3.13/site-packages/pandas/util/_decorators.py": 14780166101442507665, - "venv/lib/python3.13/site-packages/keyring/backend.py": 14185808762437650951, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.pyi": 4432290176776357346, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-1.csv": 16349400027062875699, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_finalize.py": 12539815426478689538, - "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/WHEEL": 13232065379159720345, - "venv/lib/python3.13/site-packages/keyring/completion.py": 1027436016070040568, - "venv/lib/python3.13/site-packages/uvicorn/_subprocess.py": 13965754246493254447, - "venv/lib/python3.13/site-packages/_pytest/pathlib.py": 9719734558816066453, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_polynomial.pyi": 4266795948450921502, - "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.py": 12886275429547303345, - "venv/lib/python3.13/site-packages/passlib/pwd.py": 14727089240749133060, - "venv/lib/python3.13/site-packages/jsonschema/tests/test_validators.py": 14178329676643700151, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/ssh.py": 16262079536832961001, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_subclass.py": 16342917051908786497, - "venv/lib/python3.13/site-packages/fastapi/security/__init__.py": 1345944646061334046, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_first_valid_index.py": 15763400665851423183, - "venv/lib/python3.13/site-packages/pandas/_testing/_hypothesis.py": 12298650110193262367, - "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/PIL/FitsImagePlugin.py": 618556384932056120, - "backend/src/api/routes/translate/_helpers.py": 13265933139767815312, - "backend/src/plugins/translate/dictionary_validation.py": 16674754716565921261, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexing.py": 5910217172351020811, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/size/foo.f90": 18067977329435720684, - "venv/lib/python3.13/site-packages/git/index/__init__.py": 7874728461616959441, - "venv/lib/python3.13/site-packages/pydantic/v1/_hypothesis_plugin.py": 6383299780629629080, - "venv/lib/python3.13/site-packages/psycopg2/_ipaddress.py": 12332672835751787869, - "venv/lib/python3.13/site-packages/httpx/_status_codes.py": 1758440600462491839, - "venv/lib/python3.13/site-packages/pyasn1/codec/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/passlib/tests/test_hosts.py": 8284535274820610802, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/base.py": 16891437410462671317, - "frontend/build/_app/immutable/chunks/CNLYuUB9.js": 17587259240659633356, - "venv/lib/python3.13/site-packages/pip/_vendor/distro/py.typed": 15130871412783076140, - "frontend/build/_app/immutable/chunks/BlSS2OGX.js": 1837769579623381097, - "backend/src/services/__tests__/test_llm_provider.py": 13082073379648782691, - "docker/frontend.entrypoint.sh": 11397342350356400663, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_argsort.py": 7320661835159648143, - "venv/bin/numpy-config": 17104619511899110252, - "venv/lib/python3.13/site-packages/numpy/lib/tests/data/win64python2.npy": 11005857803794805939, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/compat.py": 5871636909854554063, - "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/WHEEL": 7795541085444298627, - "venv/lib/python3.13/site-packages/pip/_internal/operations/install/__init__.py": 10456333337205488584, - "venv/lib/python3.13/site-packages/numpy/_typing/_nbit.py": 15498810174380798405, - "venv/lib/python3.13/site-packages/pandas/_libs/reshape.cpython-313-x86_64-linux-gnu.so": 10639750501333255943, - "venv/lib/python3.13/site-packages/numpy/lib/format.py": 14971167445246135440, - "backend/src/core/task_manager/task_logger.py": 12820629458199400734, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libk5crypto-b1f99d5c.so.3.1": 10669523137596317954, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f90continuation.f90": 17056591497459381871, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_indexing.py": 1926721846569184112, - "backend/src/scripts/test_dataset_dashboard_relations.py": 11883199369340933897, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_spss.py": 4865360315909532603, - "venv/lib/python3.13/site-packages/urllib3/_collections.py": 3440910792774742262, - "frontend/build/_app/immutable/chunks/Da1Lh9io.js": 10821565507585267104, - "venv/lib/python3.13/site-packages/pandas/tests/io/xml/conftest.py": 17514079438846557943, - "backend/src/plugins/translate/orchestrator_validation.py": 17464651621865127561, - "backend/src/api/routes/dashboards/_schemas.py": 10686942001147126057, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_getitem.py": 18202683049446557047, - "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/WHEEL": 14550174241288068152, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90": 14491312943942432024, - "backend/src/services/clean_release/policy_engine.py": 3180817867716931725, - "backend/alembic/versions/2a7b8c9d0e1f_add_target_languages_to_translation_jobs.py": 7201017059554918882, - "venv/lib/python3.13/site-packages/greenlet/platform/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/anyio/_core/_testing.py": 14024940365851109155, - "venv/lib/python3.13/site-packages/pandas/core/col.py": 4221271461723119525, - "backend/tests/services/clean_release/test_candidate_manifest_services.py": 16861589402854148894, - "venv/lib/python3.13/site-packages/_pytest/hookspec.py": 387790426108810884, - "backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py": 2367759303622417201, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/requests.py": 1102963893193914979, - "frontend/src/components/DashboardGrid.svelte": 17669234585849525689, - "scripts/scan_secrets.sh": 599173385111063848, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_indexing.py": 1947969642791009285, - "backend/src/services/git/_status.py": 11400014053359523156, - "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_spec_conformance.py": 16448324304809345527, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24008.f": 3872245077994936272, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/poolmanager.py": 5071697837617938064, - "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.pyi": 3111521453255595221, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/models.py": 17870758731501836303, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_julian_date.py": 850085757774959003, - "venv/lib/python3.13/site-packages/pandas/core/tools/datetimes.py": 13313374952742129866, - "venv/lib/python3.13/site-packages/pygments/__main__.py": 13200500591994479045, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nested_sequence.pyi": 10985533017688918283, - "venv/lib/python3.13/site-packages/pyasn1/codec/native/decoder.py": 15336592439379775543, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi": 14119032813912827271, - "venv/lib/python3.13/site-packages/pandas/_libs/parsers.cpython-313-x86_64-linux-gnu.so": 14134106903573638108, - "venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py": 10408538054406276433, - "venv/lib/python3.13/site-packages/pandas/_config/__init__.py": 3577026529387563519, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/resource_protector.py": 4823504113176750140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/writeonly.py": 14213960431308620600, - "venv/lib/python3.13/site-packages/pip/_internal/operations/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/attr/filters.pyi": 13942974755090135724, - "venv/lib/python3.13/site-packages/pandas/tests/io/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/__init__.py": 15130871412783076140, - "frontend/build/_app/immutable/nodes/25.CdjtCq6f.js": 14137987200289316226, - "venv/lib/python3.13/site-packages/pip/_vendor/requests/structures.py": 2668010839316715865, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-1.csv": 16078879475693341404, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_arithmetic.py": 11620920548943067949, - "venv/lib/python3.13/site-packages/PIL/PSDraw.py": 1927169421822446045, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_extras.py": 16160090335191788104, - "venv/lib/python3.13/site-packages/pandas/io/parquet.py": 14415622950469421518, - "venv/lib/python3.13/site-packages/sqlalchemy/pool/__init__.py": 4337679908168515343, - "venv/bin/pyrsa-sign": 15564653706771700451, - "frontend/src/lib/stores/__tests__/mocks/env_public.js": 2540122820969872185, - "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/RECORD": 15194367076254806710, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/boxplot.py": 7090586111222952862, - "venv/lib/python3.13/site-packages/fastapi/_compat/__init__.py": 12380131786677943349, - "venv/lib/python3.13/site-packages/pygments/lexers/q.py": 15426466074881683794, - "venv/lib/python3.13/site-packages/pydantic_settings/main.py": 17272314000918984790, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarprint.py": 9482100952562512933, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reflection.py": 1799734694597531652, - "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/RECORD": 3649834117451110628, - "venv/lib/python3.13/site-packages/httpx/_transports/wsgi.py": 11981127094916412794, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_series.pyi": 7112486730197067087, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90": 1409455010615482779, - "venv/lib/python3.13/site-packages/pygments/lexers/ezhil.py": 10294520768762308887, - "venv/lib/python3.13/site-packages/attrs/filters.py": 6844006230924162452, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/__init__.py": 71159121705871510, - "venv/lib/python3.13/site-packages/pygments/lexers/mosel.py": 1877592344012288438, - "venv/lib/python3.13/site-packages/rsa/pem.py": 3118524021576082054, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_python_parser_only.py": 12231449578582108346, - "backend/src/core/__tests__/test_superset_preview_pipeline.py": 5793244881571660499, - "frontend/src/components/Toast.svelte": 4155277822937119359, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/socks.py": 17581293673028078134, - "backend/src/schemas/__tests__/test_settings_and_health_schemas.py": 10518526918751273612, - "venv/lib/python3.13/site-packages/PIL/_util.py": 17116054813914373606, - "frontend/build/_app/immutable/chunks/C3s8enYH.js": 9141759639804281041, - "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.cpython-313-x86_64-linux-gnu.so": 9014806524727977333, - "venv/lib/python3.13/site-packages/greenlet/__init__.py": 3447613556981242475, - "venv/lib/python3.13/site-packages/itsdangerous/encoding.py": 205863946173486958, - "venv/lib/python3.13/site-packages/apscheduler/triggers/date.py": 9545774812177853725, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numerictypes.py": 8836108334624807647, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_delete.py": 3485374671877063217, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot_multilevel.py": 9830258607305392103, - "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_internal/cli/progress_bars.py": 7584699216537478969, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_align.py": 6050248183327934780, - "backend/src/api/routes/__tests__/test_clean_release_api.py": 11565478953155085157, - "backend/src/api/routes/__tests__/test_reports_detail_api.py": 7284151749869192310, - "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.py": 13115032674230220791, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/testing.pyi": 9317922890783549326, - "backend/src/api/routes/__tests__/test_git_api.py": 222548597993158802, - "backend/src/services/clean_release/candidate_service.py": 8516915994721977806, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_callback.py": 1689177048527329209, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_timedelta.py": 12822713918114715561, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_compat.h": 6512969159139431485, - "venv/lib/python3.13/site-packages/numpy/ma/mrecords.py": 687170905107114309, - "venv/lib/python3.13/site-packages/greenlet/tests/test_gc.py": 6383305344377882524, - "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_policy.py": 13856626567322091253, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_numpy_compat.py": 9112925138440787555, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_map.py": 6556132946198785761, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_missing.py": 3991199131191840903, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/row.py": 9763935103055608874, - "venv/lib/python3.13/site-packages/pydantic/_internal/_discriminated_union.py": 1818179910730401509, - "venv/lib/python3.13/site-packages/fastapi/security/api_key.py": 6965937678104291169, - "venv/lib/python3.13/site-packages/pip/_internal/commands/check.py": 6937252393012787214, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mutable.py": 9323088483998280629, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h": 10634781863364525895, - "venv/lib/python3.13/site-packages/pygments/cmdline.py": 15628499088643246809, - "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.cpython-313-x86_64-linux-gnu.so": 17652852308919396403, - "venv/lib/python3.13/site-packages/pygments/styles/gruvbox.py": 9489017112545247388, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg8000.py": 6580512354643849828, - "frontend/src/lib/stores/translationRun.js": 10005138082029605368, - "frontend/src/routes/+page.ts": 11160596731849880920, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_almost_equal.py": 9333355453468475330, - "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas7bdat.py": 8963983384208121526, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_legend.py": 13094583566764796297, - "backend/src/services/clean_release/repositories/approval_repository.py": 15069637305272665109, - "backend/src/plugins/translate/orchestrator_run_completion.py": 5945172469962331273, - "frontend/build/_app/immutable/chunks/gnz6SBPl.js": 11312702971088716611, - "venv/lib/python3.13/site-packages/pandas/tests/extension/json/array.py": 7437107031079833232, - "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/INSTALLER": 17282701611721059870, - "dist/docker/ss-tools.current.tar.xz": 12481237908945663094, - "venv/lib/python3.13/site-packages/pip/_internal/network/__init__.py": 1586148254475575526, - "backend/src/services/clean_release/exceptions.py": 14631509303697939633, - "venv/lib/python3.13/site-packages/ecdsa/test_numbertheory.py": 2117130219401053225, - "venv/lib/python3.13/site-packages/pydantic/functional_validators.py": 5835339743072048940, - "backend/src/core/config_models.py": 4264626520931642357, - "backend/src/models/llm.py": 6672505429570175379, - "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/backend.py": 9072112660082423691, - "venv/lib/python3.13/site-packages/pandas/__init__.py": 793698514004377486, - "venv/lib/python3.13/site-packages/yaml/serializer.py": 1783761365703703558, - "backend/src/services/__tests__/test_rbac_permission_catalog.py": 5190751380981933250, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath.py": 13010939919217862164, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py": 14995426099932276090, - "venv/lib/python3.13/site-packages/PIL/GimpGradientFile.py": 9777026720028891154, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf": 10893958728966010450, - "venv/lib/python3.13/site-packages/pandas/io/excel/_base.py": 1251545894005373734, - "venv/lib/python3.13/site-packages/pip/_vendor/idna/intranges.py": 12536174834761591006, - "venv/lib/python3.13/site-packages/pip/_internal/commands/cache.py": 1892313355296776523, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_block_docstring.py": 18146459246837890489, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcrypto-2e26a48f.so.3": 3658133521245392852, - "backend/src/models/dataset_review_pkg/_profile_models.py": 9621392840420324583, - "venv/lib/python3.13/site-packages/websockets/legacy/auth.py": 16685128086396181286, - "venv/lib/python3.13/site-packages/cffi/parse_c_type.h": 9889309594462820068, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.h": 16138871162713175599, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arrow_interface.py": 5231449831607036031, - "venv/lib/python3.13/site-packages/pygments/lexers/math.py": 1647133236144311250, - "venv/lib/python3.13/site-packages/pandas/core/tools/numeric.py": 8510988912136285022, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_store.py": 1500300322083708794, - "venv/lib/python3.13/site-packages/attr/converters.py": 5179615793507170642, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test__datasource.py": 1747755531265478106, - "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict_of_blocks.py": 11646835537993064324, - "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth1_client.py": 3129955464287331242, - "venv/lib/python3.13/site-packages/_pytest/_code/__init__.py": 6211607282116942091, - "venv/lib/python3.13/site-packages/pygments/styles/perldoc.py": 4857683935715743356, - "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.pyi": 6796322258258182775, - "backend/src/services/dataset_review/semantic_resolver.py": 8447496149691924829, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_parser.py": 8145921552236189367, - "backend/src/services/clean_release/repositories/artifact_repository.py": 9040122866024534865, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py": 14571251344510763303, - "venv/lib/python3.13/site-packages/numpy/_core/numeric.pyi": 17785360553418386488, - "venv/lib/python3.13/site-packages/rsa/key.py": 4783269051050521475, - "venv/lib/python3.13/site-packages/numpy/ma/tests/test_deprecations.py": 8310244516175542839, - "backend/tests/test_translate_scheduler_execution.py": 16687335504320865378, - "venv/lib/python3.13/site-packages/dateutil/parser/__init__.py": 11377431154251655738, - "venv/lib/python3.13/site-packages/rapidfuzz/process_py.py": 17563673072076876125, - "venv/lib/python3.13/site-packages/apscheduler/executors/tornado.py": 6635576580306890718, - "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/METADATA": 10220680536734745103, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_regression.py": 6742646011852052645, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_round.py": 14996007456708990295, - "venv/lib/python3.13/site-packages/pandas/_libs/ops.pyi": 1192312467209548763, - "venv/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so": 829323374625147265, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/unistring.py": 18037463865539157041, - "venv/lib/python3.13/site-packages/pydantic/color.py": 1007422551673129827, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/dml.py": 5340326603935367534, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/table.py": 16856253349556498073, - "venv/lib/python3.13/site-packages/idna/codec.py": 4260241549062101779, - "venv/lib/python3.13/site-packages/pandas/tests/interchange/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reserved_words.py": 8022121780993497971, - "venv/lib/python3.13/site-packages/pygments/lexers/dotnet.py": 17970884907837213099, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__init__.py": 8811477458865810434, - "venv/lib/python3.13/site-packages/pydantic/v1/utils.py": 902648247561165429, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/distributions.h": 17162252287980242413, - "venv/lib/python3.13/site-packages/pandas/io/__init__.py": 9767690163638898709, - "venv/lib/python3.13/site-packages/pygments/lexers/prql.py": 1159462562014166646, - "venv/lib/python3.13/site-packages/pygments/lexers/__init__.py": 4627540245914849670, - "backend/alembic/versions/8dd0a93af539_drop_deprecated_source_language_column_.py": 3574830605384611294, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/__init__.py": 13841777369501476946, - "venv/lib/python3.13/site-packages/pandas/_libs/pandas_parser.cpython-313-x86_64-linux-gnu.so": 18056339336364727359, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/provision.py": 9472538482404392519, - "venv/lib/python3.13/site-packages/_pytest/mark/expression.py": 1821437025841201912, - "venv/lib/python3.13/site-packages/pandas/api/typing/__init__.py": 6438268275857060114, - "backend/src/api/routes/environments.py": 1329328901500854319, - "venv/lib/python3.13/site-packages/numpy/tests/test_matlib.py": 14395481530627870882, - "venv/lib/python3.13/site-packages/gitdb/db/mem.py": 15823812455996199993, - "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_version.py": 849232015288488204, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/errors.py": 2147619440137604907, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_s3.py": 17425535047477778484, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/wrapper.py": 4633931060151989960, - "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/py.typed": 9796674040111366709, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2py2e.py": 8571347023940385644, - "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/METADATA": 8128818962678047497, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.py": 4672871351134074735, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nth.py": 17151595277666975085, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_tooltip.py": 853808724844451770, - "venv/lib/python3.13/site-packages/passlib/ifc.py": 14479133654556657428, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html.tpl": 12550218314797699304, - "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_impl.py": 15673691977157706075, - "venv/lib/python3.13/site-packages/numpy/core/_dtype.pyi": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/igor.py": 6506221273085723501, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_resolution.py": 18198858926948468112, - "venv/lib/python3.13/site-packages/numpy/tests/test_reloading.py": 17532116685329953400, - "venv/lib/python3.13/site-packages/pygments/lexers/erlang.py": 11757064262773184741, - "venv/lib/python3.13/site-packages/pip/_internal/utils/_log.py": 13011536737418204268, - "venv/lib/python3.13/site-packages/pygments/lexers/basic.py": 12723021007042054402, - "venv/lib/python3.13/site-packages/pygments/lexers/arrow.py": 6699009974224818979, - "venv/lib/python3.13/site-packages/packaging/_parser.py": 13394093358675095309, - "frontend/src/routes/settings/DatabaseConnectionsTab.svelte": 834010895835527896, - "frontend/src/components/EnvSelector.svelte": 3937920133889630193, - "venv/lib/python3.13/site-packages/PIL/TarIO.py": 13651401276968618561, - "backend/git_repos/remote/test-repo.git/objects/f7/6ee984d9d47c3cd0b362fdf60a47162bbc202d": 5351983130474596028, - "dist/docker/ss-tools.20260517.tar.xz": 10542870312371880474, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py": 14190849361275154667, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/requests.py": 14847842002253212098, - "venv/lib/python3.13/site-packages/greenlet/greenlet_refs.hpp": 8525862687669040510, - "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators.py": 9928398334052202841, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_stride_tricks.py": 1064774375151677743, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_timezones.py": 4771674179164304731, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/dml.py": 6519732236745017861, - "venv/lib/python3.13/site-packages/pillow.libs/libopenjp2-94e588ba.so.2.5.4": 2483101806045986252, - "venv/lib/python3.13/site-packages/jeepney/bus.py": 5163075760432139100, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_size.py": 14032390806503440750, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_arithmetic.py": 15071337112968886738, - "venv/lib/python3.13/site-packages/pygments/lexers/mips.py": 2078929831513352031, - "backend/git_repos/remote/test-repo.git/objects/4f/4e0958b3a42eff67a2b8cfd084d05c43e54716": 6040513978194442637, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/__init__.py": 348469143777130970, - "venv/lib/python3.13/site-packages/anyio/_core/_resources.py": 8463932838064724564, - "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/android.py": 8607703347015852195, - "venv/lib/python3.13/site-packages/dateutil/relativedelta.py": 5903095963079475484, - "venv/lib/python3.13/site-packages/pygments/lexers/scdoc.py": 8481749542463754279, - "venv/lib/python3.13/site-packages/pygments/lexers/ul4.py": 9580182474451220952, - "frontend/build/_app/immutable/nodes/19.DACqZYZD.js": 11864421393155320979, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90": 2174121054736811903, - "venv/lib/python3.13/site-packages/_pytest/__init__.py": 3769333500910148571, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string_arrow.py": 10008395772220468318, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arithmetic.pyi": 467927803068643024, - "venv/lib/python3.13/site-packages/numpy/lib/array_utils.py": 18135114588643176359, - "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64_np126.pkl.gz": 1630203486813146863, - "frontend/src/lib/components/layout/__tests__/test_taskDrawer.svelte.js": 15288009749873977442, - "frontend/src/routes/migration/+page.svelte": 7821836225621176583, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_manylinux.py": 12272275001961360101, - "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/licenses/LICENSE": 1424673738228762254, - "venv/lib/python3.13/site-packages/passlib/tests/test_utils_md4.py": 15270721044910698449, - "venv/lib/python3.13/site-packages/pip/_internal/cli/req_command.py": 2887890799766730546, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/resolver.py": 9931394693284776391, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/apps.py": 10758062668702044519, - "venv/lib/python3.13/site-packages/_pytest/timing.py": 14080119171718125986, - "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.pyi": 17639497083041129225, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_astype.py": 11995587502880659624, - "venv/lib/python3.13/site-packages/pandas/tests/api/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpcore/_async/interfaces.py": 18250473733460571816, - "frontend/build/_app/immutable/chunks/CFh-aOc_.js": 16795336353623031933, - "venv/lib/python3.13/site-packages/pandas/io/formats/templates/string.tpl": 15796203549130590784, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/errors.py": 14634768861119075506, - "venv/lib/python3.13/site-packages/pytest/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.py": 16539612003028676816, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_halfyear.py": 587199217232946404, - "frontend/src/routes/settings/git/__tests__/git_settings_page.ux.test.js": 5334904955024018051, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/METADATA": 9586902338916246692, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_fillna.py": 8802093795040069423, - "venv/lib/python3.13/site-packages/pyasn1/type/namedval.py": 8273171503516887681, - "venv/lib/python3.13/site-packages/authlib/oidc/core/__init__.py": 16029653645350087968, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/trafficscript.py": 776604244051744646, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_elements_constructors.py": 9279447066034364952, - "venv/lib/python3.13/site-packages/sqlalchemy/inspection.py": 8563914460959280101, - "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.pyi": 9282436354926617898, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/token_endpoint.py": 6118770923176099889, - "venv/lib/python3.13/site-packages/httpx/_urlparse.py": 8270294590945652412, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/scope.py": 4096190764836489091, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/stride_tricks.pyi": 8257977532799807847, - "venv/lib/python3.13/site-packages/numpy/_core/defchararray.pyi": 2277933368373498515, - "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.py": 7352635707860427145, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_describe.py": 11923715539897559626, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval_new.py": 3893421355544517336, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_selectable_constructors.py": 84919308502240880, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_arrow_compat.py": 17818294260710640443, - "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.cpython-313-x86_64-linux-gnu.so": 9380059465932560412, - "venv/lib/python3.13/site-packages/PIL/ImageShow.py": 11437096951764124817, - "frontend/src/lib/stores/__tests__/test_sidebar.js": 113566022614194798, - "venv/lib/python3.13/site-packages/numpy/lib/_version.pyi": 10804755840730584157, - "venv/lib/python3.13/site-packages/pip/_internal/req/req_install.py": 7181005402818830655, - "venv/lib/python3.13/site-packages/urllib3/util/response.py": 6106698559175827207, - "backend/src/plugins/translate/_llm_http.py": 15686826696693103176, - "frontend/src/routes/dashboards/[id]/components/DashboardGitManager.svelte": 14665567599893731601, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexing.py": 9988098331562906950, - "frontend/build/_app/immutable/nodes/34.BIHJG9go.js": 5518402256855988094, - "venv/lib/python3.13/site-packages/starlette/concurrency.py": 9835859079437525910, - "venv/lib/python3.13/site-packages/rsa/util.py": 13423880475585138638, - "venv/lib/python3.13/site-packages/numpy/_core/__init__.py": 14951958843029076911, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/scanner.py": 5640381644804445932, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/oct_key.py": 11504245602045724, - "venv/lib/python3.13/site-packages/pandas/api/extensions/__init__.py": 882327406374020760, - "venv/lib/python3.13/site-packages/pandas/tests/libs/test_libalgos.py": 13934861984871432400, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_ccalendar.py": 8819357623337533489, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/RECORD": 10552906886624188222, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py": 8079219938116542284, - "venv/lib/python3.13/site-packages/pydantic/experimental/arguments_schema.py": 8644805798814234457, - "venv/lib/python3.13/site-packages/pandas/io/clipboard/__init__.py": 3656451154829206939, - "venv/lib/python3.13/site-packages/pip/_internal/utils/datetime.py": 6816292030061301011, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/ansi.py": 948249091929588017, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/zip-safe": 15240312484046875203, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_character.py": 850554362222586199, - "venv/lib/python3.13/site-packages/pydantic/_internal/_core_utils.py": 13248004771466837645, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_validate.py": 12789481642730855139, - "venv/lib/python3.13/site-packages/fastapi/__main__.py": 10755252341326986079, - "venv/lib/python3.13/site-packages/pandas/tests/resample/test_time_grouper.py": 3203729024111501071, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_show_versions.py": 10577134135855180356, - "venv/lib/python3.13/site-packages/dotenv/variables.py": 5438726379749803751, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filter.py": 16846063190466267618, - "venv/lib/python3.13/site-packages/pydantic/plugin/_schema_validator.py": 857640644840976862, - "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.pyi": 6723628093359375823, - "venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py": 7301817934902711510, - "venv/lib/python3.13/site-packages/pygments/lexers/wren.py": 6259586056260713984, - "venv/lib/python3.13/site-packages/pygments/lexers/_csound_builtins.py": 14530739818491398298, - "venv/bin/f2py": 11006035631504708368, - "backend/src/api/routes/admin.py": 235004514833998579, - "venv/lib/python3.13/site-packages/certifi/core.py": 7472627735517449185, - "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py": 3960540415600165213, - "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/iniconfig/exceptions.py": 16501270224069836264, - "venv/lib/python3.13/site-packages/ecdsa/errors.py": 11755424742691057760, - "venv/lib/python3.13/site-packages/jose/jwe.py": 3325660353225624025, - "venv/lib/python3.13/site-packages/fastapi/middleware/httpsredirect.py": 5775982317459922443, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/json_schema.py": 15678278224696353978, - "venv/lib/python3.13/site-packages/numpy/testing/__init__.py": 2831275254313750978, - "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_chebyshev.py": 8054411443686791426, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq_py.py": 16054175754674285311, - "venv/lib/python3.13/site-packages/websockets/sync/server.py": 7966978001578584901, - "venv/lib/python3.13/site-packages/pip/_internal/__init__.py": 7060345458485901709, - "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.py": 3646474165295296669, - "venv/lib/python3.13/site-packages/numpy/linalg/__init__.py": 15647756307608142577, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multithreading.py": 12547048606098186681, - "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/extension_types.py": 1856757457657310231, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asfreq.py": 2701081989348180239, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/create.py": 16693261531832306870, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_modules.py": 16835987029123241300, - "venv/lib/python3.13/site-packages/yaml/composer.py": 13619070314468518566, - "venv/lib/python3.13/site-packages/urllib3/http2/__init__.py": 62108352209996836, - "venv/lib/python3.13/site-packages/pygments/styles/native.py": 4559566444883341527, - "venv/lib/python3.13/site-packages/PIL/TgaImagePlugin.py": 9208942494595222259, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/warnings_and_errors.pyi": 9019577563960071498, - "frontend/src/lib/components/translate/BulkCorrectionSidebar.svelte": 10114621552038076221, - "venv/lib/python3.13/site-packages/authlib/oauth2/client.py": 7237359250450222680, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hmac.py": 18132740541139891824, - "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/WHEEL": 2357997949040430835, - "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth2_client.py": 6742098857947604729, - "venv/lib/python3.13/site-packages/_pytest/_code/code.py": 5248836309618416369, - "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.py": 13574106461973044500, - "venv/lib/python3.13/site-packages/python_multipart/__init__.py": 10290895261363712562, - "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.py": 6348811074249398741, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90": 11326797716215117266, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_sql.py": 3901697517087276687, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/bulk_persistence.py": 2307818727114646866, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/requirements.py": 11478648568700804705, - "venv/lib/python3.13/site-packages/pygments/lexers/r.py": 14263133575134645005, - "frontend/src/routes/datasets/review/useReviewSession.js": 2378011913105385059, - "backend/src/services/profile_preference_service.py": 58722622434127499, - "backend/test_pat_api.py": 4206656943734821967, - "venv/lib/python3.13/site-packages/pygments/lexers/_lasso_builtins.py": 4006621424665751347, - "backend/tests/core/test_git_service_gitea_pr.py": 6098719224379185148, - "venv/lib/python3.13/site-packages/packaging/metadata.py": 9168255069163141470, - "frontend/src/lib/components/assistant/AssistantClarificationCard.svelte": 6722890639215637790, - "venv/lib/python3.13/site-packages/pygments/lexers/idl.py": 11454152060351801696, - "venv/lib/python3.13/site-packages/pip/_internal/pyproject.py": 6155748929233245415, - "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/zip-safe": 15240312484046875203, - "backend/src/scripts/create_admin.py": 7540310914822649547, - "venv/lib/python3.13/site-packages/pygments/modeline.py": 6194365452131561478, - "venv/lib/python3.13/site-packages/httpcore/_async/http_proxy.py": 13364803556177997526, - "backend/tests/test_constants_audit_fixes.py": 18298690956132739779, - "venv/lib/python3.13/site-packages/fastapi/cli.py": 13972351579061154035, - "venv/lib/python3.13/site-packages/pip/_internal/cli/main.py": 9304034369762028739, - "venv/lib/python3.13/site-packages/charset_normalizer/cli/__init__.py": 9702005609966176016, - "backend/src/core/database.py": 1922063344803331432, - "backend/tests/services/clean_release/test_approval_service.py": 8359796700245201345, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_engines.py": 2790877023773269276, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/exceptions.py": 7518613450390473990, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapped_collection.py": 11377280960650304531, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_records.py": 6252761812228230408, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_tokenizer.py": 7994281991455916540, - "backend/src/api/routes/dashboards/_projection.py": 1559143255780155174, - "venv/lib/python3.13/site-packages/pandas/io/formats/__init__.py": 18140261896107421679, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_categorical.py": 18254320571347851153, - "venv/lib/python3.13/site-packages/sqlalchemy/util/preloaded.py": 3719702436309355562, - "venv/lib/python3.13/site-packages/pandas/tests/window/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_features.py": 955759654189150497, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_editable.py": 14352954849821931255, - "venv/lib/python3.13/site-packages/yaml/error.py": 5626374410579058436, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_date_range.py": 16128552513324017349, - "venv/lib/python3.13/site-packages/pandas/tests/base/test_misc.py": 9190561773853901527, - "frontend/src/components/__tests__/task_log_viewer.test.js": 6512653335179659416, - "backend/src/core/superset_client/_user_projection.py": 16484323195475306883, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_extending.py": 10202091354750153497, - "venv/lib/python3.13/site-packages/certifi/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/METADATA": 14158024963562115116, - "venv/lib/python3.13/site-packages/fastapi/utils.py": 15402403831700548944, - "venv/lib/python3.13/site-packages/pydantic/plugin/__init__.py": 16803973597469216174, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_explode.py": 16195468192763502449, - "venv/lib/python3.13/site-packages/pygments/styles/onedark.py": 17580335614588531275, - "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimes.py": 14331984919364185787, - "venv/lib/python3.13/site-packages/numpy/core/getlimits.py": 14257687540182552408, - "venv/lib/python3.13/site-packages/pandas/tests/strings/test_split_partition.py": 2715491071550545667, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/WHEEL": 9788895026336324100, - "venv/lib/python3.13/site-packages/pandas/_libs/internals.pyi": 11662356720550765508, - "venv/lib/python3.13/site-packages/anyio/to_interpreter.py": 8369454842687342401, - "venv/lib/python3.13/site-packages/pandas/io/stata.py": 14370692318835340323, - "venv/lib/python3.13/site-packages/PIL/GimpPaletteFile.py": 2040459799887417392, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/util.py": 4890614159013873000, - "venv/lib/python3.13/site-packages/urllib3/connection.py": 12761371748350595804, - "backend/src/services/__tests__/test_resource_service.py": 13275183651826747527, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_loop.py": 6502725909989655118, - "venv/lib/python3.13/site-packages/authlib/oidc/core/userinfo.py": 17201158389976619872, - "frontend/build/_app/immutable/chunks/B90ABsQ9.js": 13613302137140904970, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows_renderer.py": 1076842273781909680, - "backend/git_repos/remote/test-repo.git/objects/5d/9eb555c4cac2d3ffdba84c07682b154fe4180d": 10756202165146702691, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/liblber-1c9097e2.so.2.0.200": 2651879839738900594, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/core/groupby/numba_.py": 15997665748332235683, - "venv/lib/python3.13/site-packages/pyasn1/compat/integer.py": 7365270971777550573, - "frontend/src/components/StartupEnvironmentWizard.svelte": 13169478544862386336, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_musllinux.py": 2423350951094915747, - "frontend/src/routes/dashboards/+page.svelte": 12050524336689510248, - "venv/lib/python3.13/site-packages/sqlalchemy/pool/impl.py": 4687705587963980337, - "venv/lib/python3.13/site-packages/urllib3/util/__init__.py": 2848870790459558599, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_overrides.py": 92685611709898742, - "venv/lib/python3.13/site-packages/PIL/__main__.py": 827665918723937817, - "frontend/build/_app/immutable/nodes/12.BUPMnNpz.js": 6618250635091063727, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/_dml_constructors.py": 4497038002189188311, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_names.py": 10037208029090713121, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/default_comparator.py": 47118577003622736, - "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.pyi": 8232620851756907417, - "venv/lib/python3.13/site-packages/pandas/core/array_algos/take.py": 3170415198452493008, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_online.py": 11850497659869773510, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/npyio.pyi": 15811156298637131744, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_contains.py": 17630310725250553247, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/scoping.py": 17216492046645992674, - "venv/lib/python3.13/site-packages/pygments/lexers/chapel.py": 7619603166448145621, - "venv/lib/python3.13/site-packages/pygments/lexers/ml.py": 7510453371068494792, - "venv/lib/python3.13/site-packages/pygments/lexers/webmisc.py": 9530962803076253849, - "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/__init__.py": 3521833849634327520, - "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_scrypt.py": 17378030264314664250, - "frontend/build/_app/immutable/nodes/17.Uj-PnH-w.js": 10590848701558584268, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/exc.py": 3242780937124999391, - "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/resolution.py": 5132658725516243311, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/literal.py": 5641382379370828704, - "venv/lib/python3.13/site-packages/psycopg2/errorcodes.py": 6711830404954314463, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/__init__.py": 14481526616887213120, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/logging.py": 2426447364230673649, - "venv/lib/python3.13/site-packages/cryptography/x509/oid.py": 13909847799728532602, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_delete.py": 5958440386632506587, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_win32_console.py": 18092547253031555768, - "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_latex.py": 2628895559914914693, - "venv/lib/python3.13/site-packages/urllib3/contrib/socks.py": 645086578806871685, - "venv/lib/python3.13/site-packages/pip/_internal/locations/__init__.py": 8147012724727395488, - "venv/lib/python3.13/site-packages/idna-3.11.dist-info/METADATA": 14036738037171597049, - "venv/lib/python3.13/site-packages/pygments/lexers/graphviz.py": 15677908982985025500, - "frontend/src/lib/components/reports/__tests__/reports_filter_performance.test.js": 10583581505638859039, - "backend/src/services/clean_release/repositories/__init__.py": 9926779835387630811, - "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunclike.py": 12077553320554633586, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_str_accessor.py": 4066094997616994612, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__main__.py": 111505188798650285, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/__init__.py": 13331622784664204066, - "venv/lib/python3.13/site-packages/pip/_internal/models/selection_prefs.py": 14700113736620314923, - "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_django.py": 8455054295577203929, - "venv/lib/python3.13/site-packages/numpy/tests/test_scripts.py": 5790352482583964348, - "venv/lib/python3.13/site-packages/PIL/ImageDraw.py": 12919304671639673744, - "venv/bin/httpx": 6651007446865716794, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/char.pyi": 13143560686049627445, - "venv/lib/python3.13/site-packages/numpy/testing/__init__.pyi": 8126257788928282891, - "backend/src/services/profile_service.py": 7430451608615934464, - "venv/lib/python3.13/site-packages/cffi/lock.py": 13507686939203117974, - "venv/lib/python3.13/site-packages/rapidfuzz/__init__.pyi": 13131938031654453415, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/resource_protector.py": 11539718751174980004, - "venv/lib/python3.13/site-packages/apscheduler/jobstores/sqlalchemy.py": 811968833735951956, - "frontend/src/routes/login/+page.svelte": 18430869485200259448, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/scripts.py": 8759605303886441976, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py": 8395157526634674143, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/index_tricks.pyi": 6035507586990711471, - "venv/lib/python3.13/site-packages/pandas/core/interchange/utils.py": 11401792151107207834, - "frontend/src/lib/stores/__tests__/mocks/stores.js": 14098417748659067309, - "frontend/src/routes/tools/debug/+page.svelte": 8699044541980877686, - "backend/src/plugins/llm_analysis/__tests__/test_service.py": 9850768293526486431, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/util.py": 387985965709546512, - "backend/src/plugins/translate/orchestrator_exec.py": 16278134717094910089, - "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/test_rapidfuzz_packaging.py": 5189055608193366093, - "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/REQUESTED": 15130871412783076140, - "backend/src/models/dataset_review_pkg/_finding_models.py": 7257895729340231285, - "venv/lib/python3.13/site-packages/_pytest/unraisableexception.py": 4597178803320514675, - "venv/lib/python3.13/site-packages/more_itertools/more.py": 1631135582441184133, - "venv/lib/python3.13/site-packages/gitdb/db/loose.py": 17467413653016810702, - "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_insert.py": 11635164392966270621, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_type_check.py": 3935091606923106753, - "frontend/src/lib/components/layout/Breadcrumbs.svelte": 10874106485242690185, - "backend/src/services/clean_release/artifact_catalog_loader.py": 7672031618376179570, - "frontend/src/lib/ui/Card.svelte": 3442526978752993023, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.f90": 1249061697041863692, - "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.pyi": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/lexers/business.py": 10410439210806697214, - "venv/lib/python3.13/site-packages/git/repo/__init__.py": 6173604284490891047, - "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe_protocol.py": 12857147443873820285, - "frontend/build/_app/immutable/nodes/16.BxR3hKD0.js": 16372567637608282, - "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_conversion.py": 12184280074522274780, - "frontend/build/_app/immutable/chunks/voZEUQBO.js": 14236307922338214156, - "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/LICENSE": 8177430849046795595, - "venv/lib/python3.13/site-packages/pip/_internal/utils/logging.py": 9639351759822608724, - "backend/src/services/clean_release/approval_service.py": 15944489428318420008, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/ecdsa/ellipticcurve.py": 15624510849346629163, - "venv/lib/python3.13/site-packages/pip/_internal/utils/urls.py": 8698341051522816167, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/endpoint.py": 18260428408051728802, - "backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py": 11718998093543631478, - "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_sort.py": 11941630642630249576, - "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/jsonschema_specifications/__init__.py": 5732822354953774657, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/signature.py": 3614545297259098566, - "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.pyi": 2628035888703031029, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_3kcompat.h": 5377305123299457337, - "venv/lib/python3.13/site-packages/PIL/_imagingcms.cpython-313-x86_64-linux-gnu.so": 15198265718775753589, - "backend/src/api/routes/storage.py": 17448492494022569347, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/result.py": 12262298207886620908, - "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.pyi": 8195943561787777127, - "venv/lib/python3.13/site-packages/urllib3/_request_methods.py": 13671055114247516883, - "venv/lib/python3.13/site-packages/pandas/tests/series/test_subclass.py": 13490541871827928531, - "frontend/build/_app/immutable/chunks/BPGBzR36.js": 17958176020731804885, - "frontend/src/routes/datasets/review/ReviewWorkspaceRightRail.svelte": 13437011381072252917, - "venv/lib/python3.13/site-packages/smmap/test/test_buf.py": 6910367739329016619, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_c_parser_only.py": 3038797485572319804, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_polynomial.py": 3049262771098624825, - "venv/lib/python3.13/site-packages/greenlet/tests/fail_slp_switch.py": 16490710972475154509, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_tree.py": 15789443159423302291, - "venv/lib/python3.13/site-packages/jeepney/io/asyncio.py": 13239992245695516007, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/resource_protector.py": 17080006010679257864, - "venv/lib/python3.13/site-packages/fastapi/param_functions.py": 14585101566697773072, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/WHEEL": 11630459739183915695, - "venv/lib/python3.13/site-packages/authlib/oidc/core/errors.py": 18154419146257747681, - "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/mean_.py": 3641008929910474457, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pop.py": 5700439923973346681, - "venv/lib/python3.13/site-packages/pyasn1/codec/cer/__init__.py": 15728752901274520502, - "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.pyi": 15130871412783076140, - "venv/lib/python3.13/site-packages/git/refs/__init__.py": 16246686106073400519, - "venv/lib/python3.13/site-packages/pygments/lexers/nix.py": 15050086330545600356, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/METADATA": 5045041742469375466, - "venv/lib/python3.13/site-packages/greenlet/greenlet_slp_switch.hpp": 1694714764745718414, - "venv/lib/python3.13/site-packages/rsa/core.py": 13203947234024924497, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/unused_registry.py": 10153622516112471812, - "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_timedelta64.py": 16821719402662529276, - "frontend/src/lib/stores/__tests__/test_activity.js": 15599963775430388097, - "venv/lib/python3.13/site-packages/starlette/middleware/__init__.py": 9524277524025372856, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/color.py": 15062855556511243610, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/block.f": 10727418304254548946, - "venv/lib/python3.13/site-packages/pygments/lexers/elpi.py": 5736689911777977822, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf": 15094859289098837494, - "frontend/src/lib/api.js": 1856641899861379694, - "backend/src/core/superset_client/_base.py": 10958088163566963237, - "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/style.py": 15214295655795348821, - "venv/lib/python3.13/site-packages/pygments/lexers/jslt.py": 11805394130669644345, - "venv/lib/python3.13/site-packages/pandas/tests/util/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/json.py": 4660603129768960095, - "venv/lib/python3.13/site-packages/pandas/tests/window/test_pairwise.py": 2673370322448160842, - "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.asm": 15349921092257597740, - "frontend/src/lib/ui/Input.svelte": 8632025378593263475, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_utils.py": 4612923732868929770, - "venv/lib/python3.13/site-packages/dateutil/_version.py": 8279235793001245767, - "backend/src/plugins/translate/preview_token_estimator.py": 254295902082954386, - "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_numeric.py": 17391095502314929042, - "venv/lib/python3.13/site-packages/attr/validators.py": 4453080662115911998, - "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/__init__.py": 913610541217778747, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein_py.py": 1933257612725836484, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_version.pyi": 3636944488233043883, - "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.py": 10803011906582324302, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.obj": 2884737706935637437, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/entities.py": 8001287806688585081, - "venv/lib/python3.13/site-packages/dateutil/parser/isoparser.py": 18015430204844361067, - "venv/lib/python3.13/site-packages/numpy/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/util.py": 3591114320020964752, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libsasl2-883649fd.so.3.0.0": 13306917506408577991, - "venv/lib/python3.13/site-packages/passlib/context.py": 10362592407593745107, - "frontend/src/app.css": 3020720639702954139, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90": 5949265961908386974, - "backend/src/services/clean_release/repositories/report_repository.py": 17952038790457725175, - "venv/lib/python3.13/site-packages/numpy/linalg/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/_internal/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_internal/metadata/_json.py": 6718137926109998531, - "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/RECORD": 9502524172853437600, - "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.py": 1262543237476191714, - "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/METADATA": 14608873187265321271, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/warnings_and_errors.pyi": 3151453262733619734, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/modules.pyi": 14176187662591164602, - "venv/lib/python3.13/site-packages/pandas/core/arraylike.py": 11439602957100017713, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_fillna.py": 13675584998644907265, - "venv/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd": 1476688171642957054, - "venv/lib/python3.13/site-packages/gitdb/const.py": 14122142034887286559, - "venv/lib/python3.13/site-packages/pydantic/_internal/_typing_extra.py": 14843908493613991959, - "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.py": 738588649412338185, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_common_basic.py": 1945891789924713537, - "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/RECORD": 7810411361439269754, - "venv/lib/python3.13/site-packages/passlib/crypto/des.py": 14699826058580193499, - "venv/lib/python3.13/site-packages/pytest/__init__.py": 6137272437722350673, - "venv/lib/python3.13/site-packages/pygments/filter.py": 16846063190466267618, - "frontend/src/routes/tools/mapper/+page.svelte": 11954517841045690204, - "frontend/build/_app/immutable/chunks/DVED-6ks.js": 11096828156569191966, - "backend/git_repos/remote/test-repo.git/objects/48/c3fde4d5fff5bf98e9bcaa5f328b199aa18292": 6121250272621110311, - "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_freq_code.py": 13758353172962109140, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_case_when.py": 4133174129660834805, - "backend/src/models/dataset_review_pkg/_filter_models.py": 13932350898582638473, - "venv/lib/python3.13/site-packages/idna/intranges.py": 12536174834761591006, - "frontend/build/_app/immutable/nodes/30.CZpfvQF1.js": 16339196812939889509, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_api_info.pyi": 7887489694871300469, - "backend/git_repos/remote/test-repo.git/objects/5a/82ef700fef88b69cd480e4025283809496ee20": 7003383965314354150, - "venv/lib/python3.13/site-packages/numpy/lib/_iotools.pyi": 12873243737872788349, - "venv/lib/python3.13/site-packages/pandas/core/window/rolling.py": 6316477981414191778, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/__init__.py": 15130871412783076140, - "frontend/src/lib/stores/__tests__/mocks/navigation.js": 10782992736745205981, - "frontend/src/components/git/__tests__/git_manager.unfinished_merge.integration.test.js": 4508809242640248036, - "venv/lib/python3.13/site-packages/pydantic/utils.py": 1533455264689378477, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77comments.f": 4801926170672147659, - "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_pandas.py": 10894229569442891394, - "venv/lib/python3.13/site-packages/sqlalchemy/ext/serializer.py": 8708767945343850816, - "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_list_accessor.py": 8613662386779664039, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix_py.py": 17041764258638228993, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_concat.py": 16549010224568175202, - "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pyasn1/__init__.py": 8089201217593738032, - "venv/lib/python3.13/site-packages/numpy/tests/test_warnings.py": 3154249157134620649, - "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/licenses/LICENSE": 3996324383113221529, - "venv/lib/python3.13/site-packages/pygments/lexers/cplint.py": 13990118342267278047, - "backend/git_repos/remote/test-repo.git/objects/ee/59553241ef084b83d3351ba4c33caf2ed9a840": 11587106407031972706, - "venv/lib/python3.13/site-packages/numpy/ma/mrecords.pyi": 8945514863366384484, - "venv/lib/python3.13/site-packages/numpy/random/c_distributions.pxd": 16574161095720077595, - "venv/lib/python3.13/site-packages/pandas/core/util/hashing.py": 13106575357604888913, - "frontend/src/lib/stores/health.js": 1061942219531952418, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/subcomponents.py": 10365594934527289233, - "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/RECORD": 11904769847385571600, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_array_utils.py": 14682148205379122638, - "venv/lib/python3.13/site-packages/rapidfuzz/process.py": 3870006735299537016, - "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.hpp": 6366432579621298231, - "venv/lib/python3.13/site-packages/bcrypt/__about__.py": 11196369962175692786, - "venv/lib/python3.13/site-packages/numpy/random/_philox.cpython-313-x86_64-linux-gnu.so": 9916143171057774705, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_kwargs.py": 10173906126211473463, - "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.pyi": 16372699564794732463, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_append.py": 9644955836191900614, - "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.APACHE": 8359973023624924624, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/tree.py": 4991806303236874829, - "venv/lib/python3.13/site-packages/itsdangerous/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pydantic/v1/config.py": 12050640083719340958, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_equals.py": 18261810467289276844, - "venv/lib/python3.13/site-packages/pydantic/v1/tools.py": 1995883197897112278, - "venv/lib/python3.13/site-packages/numpy/testing/overrides.py": 11819432487830192978, - "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/highlighter.py": 10615901258492570740, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_api.py": 13739775047493489785, - "venv/lib/python3.13/site-packages/cffi/recompiler.py": 17809252277700094304, - "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/METADATA": 11439969143853665311, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_contains.py": 5273759677032634868, - "frontend/build/_app/immutable/nodes/36.bKL3SVnO.js": 4914020072748784679, - "venv/lib/python3.13/site-packages/PIL/PalmImagePlugin.py": 13008868719182630239, - "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/WHEEL": 18203500019759199992, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_cpu.h": 13799366908726531089, - "dist/docker/backend.1.2.1.tar.xz": 10352037330818810014, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/format": 12697928260201325593, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_complex.py": 4290059580478881700, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_unix.h": 9608771997528633681, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/__init__.py": 11709551233929312136, - "venv/lib/python3.13/site-packages/pandas/core/methods/describe.py": 17006836623161521092, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_ufunc.py": 5025605639221470838, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reshaping.py": 18085648077811502689, - "venv/lib/python3.13/site-packages/pip/_internal/operations/install/editable_legacy.py": 8145740626773638218, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_read_errors.py": 4559483361564472117, - "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.cpython-313-x86_64-linux-gnu.so": 12776951671822017500, - "venv/lib/python3.13/site-packages/pygments/lexers/html.py": 17288963642862550116, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_setops.py": 5208912445718807372, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_codes.py": 13901854719435716195, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/histograms.pyi": 9255620158831643201, - "venv/lib/python3.13/site-packages/pandas/tests/io/test_parquet.py": 11050150015772440923, - "venv/lib/python3.13/site-packages/pip/_internal/req/req_uninstall.py": 3515239440812977025, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_protocols.py": 5019018645804313814, - "frontend/src/lib/stores.js": 8062876368729352764, - "venv/lib/python3.13/site-packages/charset_normalizer/md__mypyc.cpython-313-x86_64-linux-gnu.so": 12629680116730190225, - "venv/lib/python3.13/site-packages/pandas/core/sparse/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/_pytest/monkeypatch.py": 2635774457434545573, - "venv/lib/python3.13/site-packages/secretstorage/item.py": 15486045386471912693, - "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/models.py": 15928924478695638423, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertions.py": 5556667947376168765, - "venv/lib/python3.13/site-packages/sqlalchemy/sql/cache_key.py": 11118819065204404106, - "venv/lib/python3.13/site-packages/pandas/io/clipboards.py": 5183212433608887727, - "venv/lib/python3.13/site-packages/keyring/http.py": 1408024724330078009, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dropna.py": 17272771246760486947, - "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/__init__.py": 10470644151952252331, - "venv/lib/python3.13/site-packages/pygments/lexers/sas.py": 6128008194712914874, - "frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js": 15198772446275187033, - "venv/lib/python3.13/site-packages/pandas/_libs/parsers.pyi": 18402185996588014111, - "backend/src/core/auth/jwt.py": 15575717945774687118, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv": 4581185622290535488, - "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimes.py": 10585034798097337148, - "venv/lib/python3.13/site-packages/numpy/matlib.py": 112839038090033740, - "backend/src/plugins/translate/service_target_schema.py": 15018144148162493344, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/numpy/lib/tests/test_ufunclike.py": 13752381070039804384, - "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/METADATA": 13695483537390128881, - "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/RECORD": 1051307407005554409, - "venv/lib/python3.13/site-packages/_pytest/mark/structures.py": 12237146603608917650, - "frontend/src/components/git/GitReleasePanel.svelte": 14875953299937841077, - "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_sansio_impl.py": 17221368219485351394, - "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/METADATA": 16498441272591167134, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/pandas/tests/frame/test_cumulative.py": 15644124412739892167, - "venv/lib/python3.13/site-packages/httpcore/_async/http2.py": 16350817785499681224, - "frontend/src/routes/+page.svelte": 16267809857510759396, - "venv/lib/python3.13/site-packages/annotated_types/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/test_decimal.py": 17811784255174057561, - "venv/lib/python3.13/site-packages/gitdb/fun.py": 55226330810782184, - "backend/git_repos/remote/test-repo.git/hooks/pre-merge-commit.sample": 10013699873067956556, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/style.py": 12654125988995362593, - "venv/lib/python3.13/site-packages/pip/_vendor/distlib/metadata.py": 1362166613223529108, - "backend/src/core/utils/superset_context_extractor/_base.py": 2165790563924045511, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo77.f": 16156304612888138777, - "venv/lib/python3.13/site-packages/authlib/oauth1/__init__.py": 3692257288065292607, - "venv/lib/python3.13/site-packages/greenlet/PyGreenletUnswitchable.cpp": 3160733517193315684, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/__init__.py": 635200170992032966, - "venv/lib/python3.13/site-packages/pip/_internal/models/wheel.py": 10473287225032326206, - "venv/lib/python3.13/site-packages/pillow.libs/libbrotlicommon-c55a5f7a.so.1.2.0": 2635192149914499986, - "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.py": 17192211156810267818, - "backend/alembic/script.py.mako": 7041141123739810216, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py": 5946672289916692272, - "venv/lib/python3.13/site-packages/pip/_internal/commands/install.py": 17631777189475433503, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_shape_manipulation.py": 12598431412396627042, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/comparisons.pyi": 9338084426044982038, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nested_sequence.pyi": 11245460325970663922, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/base.py": 10200916670889920659, "venv/lib/python3.13/site-packages/urllib3/util/retry.py": 17988032431204662756, - "frontend/src/lib/components/translate/BulkReplaceModal.svelte": 9447617465987205060, - "venv/lib/python3.13/site-packages/cffi/cparser.py": 5246372077864988755, - "venv/lib/python3.13/site-packages/jsonschema/benchmarks/issue232.py": 6498198296113395367, - "venv/lib/python3.13/site-packages/websockets/asyncio/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pygments/styles/lovelace.py": 15082819162722685616, - "venv/lib/python3.13/site-packages/pygments/lexers/dsls.py": 11696359794961833087, - "backend/src/api/routes/assistant/_dataset_review_dispatch.py": 10108558091463171824, - "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.py": 3001896031623204147, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/WHEEL": 2823347510103459191, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_docs.py": 17898499890274685198, - "venv/lib/python3.13/site-packages/pandas/tseries/__init__.py": 2648641118117738895, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/util.py": 1520899420719605380, - "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/errors.py": 16711622442922413520, - "venv/lib/python3.13/site-packages/numpy/random/mtrand.pyi": 17144590106028661128, - "venv/lib/python3.13/site-packages/pygments/formatters/rtf.py": 5850574956253747036, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/REQUESTED": 15130871412783076140, - "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/RECORD": 3283324710045856319, - "frontend/build/_app/immutable/nodes/21.B5RjTw3i.js": 18170938944340806145, - "venv/lib/python3.13/site-packages/tzlocal/unix.py": 995019116408448073, - "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkeyutils-dfe70bd6.so.1.5": 9414227432578104677, - "venv/lib/python3.13/site-packages/numpy/lib/format.pyi": 11752225430594536662, - "backend/src/api/routes/translate/_preview_routes.py": 16234500901707822839, - "backend/src/services/clean_release/manifest_builder.py": 10633987497931832162, - "venv/lib/python3.13/site-packages/greenlet/tests/leakcheck.py": 10179165748538820557, - "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/array.py": 1919242530821725197, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_diff.py": 2216748778018882333, - "venv/lib/python3.13/site-packages/pygments/lexers/capnproto.py": 15713281507099411738, - "backend/src/plugins/translate/orchestrator_cancel.py": 673611364664367049, - "venv/lib/python3.13/site-packages/uvicorn/lifespan/on.py": 2866195356090164296, - "venv/lib/python3.13/site-packages/cffi/cffi_opcode.py": 8411344362428947268, - "venv/lib/python3.13/site-packages/greenlet/tests/__init__.py": 1181423074160870921, - "venv/lib/python3.13/site-packages/packaging/utils.py": 3469957615920103670, - "frontend/src/app.html": 10207534912546549080, - "backend/src/plugins/translate/scheduler.py": 13413202759986193820, - "frontend/build/_app/immutable/nodes/33.D9TTg-YL.js": 9646041660282399993, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_set_value.py": 4166411740676564820, - "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.c": 11535375410441493281, - "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.pyi": 11310761736182213265, - "venv/lib/python3.13/site-packages/pydantic/generics.py": 15019381413806459410, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_data_list.py": 1131520422778420758, - "venv/lib/python3.13/site-packages/pygments/lexers/tcl.py": 10343667975436015855, - "venv/lib/python3.13/site-packages/pandas/core/internals/construction.py": 893951849732478990, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_indexing.py": 16291207621268530224, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/assignOnlyModule.f90": 15967199601254912096, - "venv/lib/python3.13/site-packages/numpy/lib/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py": 16829312896275893002, - "venv/lib/python3.13/site-packages/pandas/tests/util/test_shares_memory.py": 2911029123657970431, - "venv/lib/python3.13/site-packages/pygments/lexers/crystal.py": 3579547906957125755, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_isocalendar.py": 5704842983090753914, - "venv/lib/python3.13/site-packages/pydantic/v1/generics.py": 1150594223414883339, - "venv/lib/python3.13/site-packages/pip/_vendor/packaging/tags.py": 254599446317461188, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi": 17458894097215345719, - "venv/lib/python3.13/site-packages/passlib/hash.py": 5238710192614935875, - "frontend/src/lib/components/assistant/AssistantChatPanel.svelte": 4130047433623185888, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_parse_dates.py": 7597935994945336408, - "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_common.py": 2223069451949206319, - "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/METADATA": 6557531107125553027, - "backend/src/services/clean_release/policy_resolution_service.py": 5075709738950902327, - "venv/lib/python3.13/site-packages/pip/_internal/models/__init__.py": 13482731985065116750, - "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py": 9627328185578406121, - "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.pyi": 15509415708991012734, - "venv/lib/python3.13/site-packages/sqlalchemy/future/__init__.py": 17688444679736059779, - "venv/lib/python3.13/site-packages/python_multipart/exceptions.py": 5971058243218049183, - "backend/src/plugins/translate/preview_session_serializer.py": 8901687711861433007, - "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_round_trip.py": 14684057343786032776, - "venv/lib/python3.13/site-packages/requests/__init__.py": 2604491098990438229, - "run.sh": 4808871544409245302, - "venv/lib/python3.13/site-packages/pip/_vendor/rich/json.py": 6429651405841289922, - "venv/lib/python3.13/site-packages/pandas/tests/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/fastapi/_compat/may_v1.py": 9880083742927480960, - "venv/lib/python3.13/site-packages/itsdangerous/_json.py": 4872267972688724005, - "venv/lib/python3.13/site-packages/passlib/utils/handlers.py": 10182859005870689026, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/errors.py": 10750605030539582738, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/common.py": 10996276696597806957, - "venv/lib/python3.13/site-packages/pip/_internal/network/xmlrpc.py": 5064964778750366059, - "venv/lib/python3.13/site-packages/pygments/lexers/automation.py": 8021926838024836904, - "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/endpoint.py": 8519226897299461194, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/filepost.py": 16698380375728063923, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadbconnector.py": 14865906347579451546, - "venv/lib/python3.13/site-packages/pydantic_settings/sources/utils.py": 8633356372647820801, - "venv/lib/python3.13/site-packages/numpy/_core/overrides.py": 252940520997718714, - "venv/lib/python3.13/site-packages/cryptography/x509/general_name.py": 4481582226129488535, - "venv/lib/python3.13/site-packages/_pytest/subtests.py": 14573790885130724739, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py": 18325640697829098192, - "frontend/src/lib/components/layout/TopNavbar.svelte": 16593656019460608311, - "backend/src/core/config_manager.py": 18161236261317111528, - "venv/lib/python3.13/site-packages/git/index/util.py": 5022401275553420722, - "venv/lib/python3.13/site-packages/pydantic/_internal/_config.py": 12760390602912369447, - "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi": 7385072545198817771, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reset_index.py": 5946666595195952693, - "backend/src/services/dataset_review/orchestrator.py": 8780497744077644822, - "scripts/gen_semantics.py": 11397714264377363083, - "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension_cpp.cpython-313-x86_64-linux-gnu.so": 7659849621107414188, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_duplicates.py": 9830936017197354309, - "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/core/dtypes/dtypes.py": 9839461501970023861, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pct_change.py": 18056235438452125034, - "venv/lib/python3.13/site-packages/pyasn1/codec/ber/decoder.py": 12653470212935324322, - "venv/lib/python3.13/site-packages/pandas/tests/computation/test_eval.py": 2921337784087808487, - "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/__init__.py": 293004106962245584, - "venv/lib/python3.13/site-packages/psycopg2/_range.py": 7184417109068014771, - "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/licenses/LICENSE": 14230156892574098522, - "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.pyi": 6286629088867436848, - "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/WHEEL": 9131187629260560775, - "venv/lib/python3.13/site-packages/pygments/lexers/lean.py": 14518351619544450286, - "venv/lib/python3.13/site-packages/starlette/schemas.py": 697416731579555195, - "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_editable.py": 12494407279914732338, - "venv/lib/python3.13/site-packages/pip/_internal/commands/wheel.py": 16397273591245583356, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/licenses/LICENSE": 5563356551734678258, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_einsum.py": 17286384318722237180, - "venv/lib/python3.13/site-packages/pandas/tests/generic/test_to_xarray.py": 15341013524814290960, - "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/cache.py": 3177663126928467950, - "venv/lib/python3.13/site-packages/pydantic/py.typed": 15130871412783076140, - "venv/lib/python3.13/site-packages/sqlalchemy/orm/__init__.py": 5118993772178969104, - "venv/bin/pygmentize": 2166491742035772877, - "venv/lib/python3.13/site-packages/pip/_internal/cli/spinners.py": 7664056305019151182, - "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/RECORD": 1689342214025776630, - "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core": 6622984507059115517, - "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/__init__.py": 2791238481813240414, - "venv/lib/python3.13/site-packages/sqlalchemy/engine/characteristics.py": 2916810597149066609, - "venv/bin/pip3.13": 13861749540792881808, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_argparse.py": 11111699418217357084, - "venv/lib/python3.13/site-packages/dateutil/tzwin.py": 5149446703746204349, - "frontend/src/lib/stores/__tests__/mocks/environment.js": 16653269108049932073, - "backend/src/core/migration/__init__.py": 13075189211840127611, - "backend/src/core/superset_client/_datasets_preview_filters.py": 14154361389981199486, - "venv/lib/python3.13/site-packages/pygments/styles/murphy.py": 8177992406082781615, - "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_common.py": 9097104320321411408, - "venv/lib/python3.13/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp": 10880681943327843928, - "venv/lib/python3.13/site-packages/starlette/endpoints.py": 3379755567024530053, - "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_slice.py": 9936085512921529417, - "venv/lib/python3.13/site-packages/uvicorn/protocols/utils.py": 6147480543268737542, - "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py": 17106903014205241774, - "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimelike.py": 4356700619632833878, - "venv/lib/python3.13/site-packages/attr/filters.py": 14156141488477438777, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_shape_base.py": 8837845103338426570, + "backend/src/core/auth/logger.py": 9289916075840905359, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90": 15768643271492041853, "venv/lib/python3.13/site-packages/requests/exceptions.py": 6474239743209354989, - "backend/src/api/routes/dataset_review_pkg/_dependencies.py": 15939232213193276681, - "venv/lib/python3.13/site-packages/pandas/compat/__init__.py": 6077099417711209303, - "venv/lib/python3.13/site-packages/python_multipart/multipart.py": 5677735019292537174, - "venv/lib/python3.13/site-packages/PIL/ImageDraw2.py": 13610162107593278891, - "venv/lib/python3.13/site-packages/gitdb/pack.py": 7828244200815444166, - "venv/lib/python3.13/site-packages/websockets/legacy/protocol.py": 762692033188392424, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_msvc.h": 14580207065003376324, - "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/licenses/LICENSE": 3868190977070717994, - "venv/lib/python3.13/site-packages/pip/_internal/utils/_jaraco_text.py": 9046755357011730699, - "venv/lib/python3.13/site-packages/pandas/tests/config/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_bin_groupby.py": 14831211659124136806, - "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.pyi": 16799580742094025110, - "venv/lib/python3.13/site-packages/pydantic/functional_serializers.py": 15285359935059345032, - "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pop.py": 14885271225856187795, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_function.py": 644452398244782315, - "venv/lib/python3.13/site-packages/PIL/XpmImagePlugin.py": 6644626557482464312, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_explode.py": 18263694040596159591, - "venv/lib/python3.13/site-packages/httpcore/_backends/sync.py": 576247220834179928, - "venv/lib/python3.13/site-packages/httpcore/_models.py": 2501866419898326733, - "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/_mapping.py": 13335227913146542481, - "venv/lib/python3.13/site-packages/h11/_connection.py": 6971907312737339559, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/__init__.py": 12793458753561114666, - "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate_regression.py": 17425202198134409689, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_formats.py": 3525283725314253763, - "venv/lib/python3.13/site-packages/pandas/core/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pycparser/_build_tables.py": 569728086093219621, - "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/INSTALLER": 17282701611721059870, - "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/information_schema.py": 8551227132710897346, - "venv/lib/python3.13/site-packages/websockets/headers.py": 13587146967490088657, - "venv/lib/python3.13/site-packages/pydantic/version.py": 3699343596421001359, - "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/resource_protector.py": 14354891358060085360, - "venv/lib/python3.13/site-packages/PIL/WebPImagePlugin.py": 5378349556563611996, - "venv/lib/python3.13/site-packages/pandas/_libs/join.cpython-313-x86_64-linux-gnu.so": 2947947484481830203, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_subclass.py": 12453252499544981915, - "venv/lib/python3.13/site-packages/pygments/lexers/iolang.py": 10997512999728724130, - "venv/lib/python3.13/site-packages/certifi/cacert.pem": 14727832973577663826, - "venv/lib/python3.13/site-packages/anyio/_core/_tempfile.py": 230288423480899091, - "venv/lib/python3.13/site-packages/websockets/protocol.py": 6401227903827084901, - "venv/lib/python3.13/site-packages/greenlet/platform/switch_aarch64_gcc.h": 8140470539757491899, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_indexing.py": 546024765756472196, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_chunksize.py": 7107619871245389835, - "venv/lib/python3.13/site-packages/_pytest/_io/__init__.py": 1510478951261938348, - "venv/lib/python3.13/site-packages/numpy/core/_multiarray_umath.py": 10973016138581934035, - "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/__init__.py": 15130871412783076140, - "venv/lib/python3.13/site-packages/pip/_internal/cli/main_parser.py": 7942770969280622910, - "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_reindex.py": 15680924058960901067, - "venv/lib/python3.13/site-packages/git/objects/__init__.py": 2110615482320355676, - "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_py.py": 6518425342376455821, - "venv/lib/python3.13/site-packages/pygments/formatters/html.py": 1918541918263449443, - "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numeric.pyi": 17005748821769179511, - "venv/lib/python3.13/site-packages/pyasn1/codec/der/decoder.py": 11876648884087997745, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_fillna.py": 4610666845291315333, - "venv/lib/python3.13/site-packages/pygments/lexers/jmespath.py": 7426464251945393925, - "venv/lib/python3.13/site-packages/pygments/lexers/templates.py": 16267123844830647955, - "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/INSTALLER": 17282701611721059870, - "frontend/src/components/tools/ConnectionForm.svelte": 4060811448046342875, - "frontend/build/_app/immutable/chunks/CnYH3mIf.js": 6533250047888326055, - "frontend/vitest.config.js": 142965001777137074, - "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_ctors.py": 631744056514965940, - "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.pyi": 10487441680587530350, + "venv/lib/python3.13/site-packages/anyio/streams/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/AvifImagePlugin.py": 1872412416505003364, + "venv/lib/python3.13/site-packages/pygments/lexers/typoscript.py": 6706632522710582762, + "frontend/src/lib/stores/datasetReviewSession.js": 3915919349382526215, + "backend/src/services/reports/__init__.py": 11818812865847046400, + "venv/lib/python3.13/site-packages/pygments/regexopt.py": 16073437303824961930, + "venv/lib/python3.13/site-packages/pandas/core/generic.py": 10174952306641057447, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/indexable.py": 4131796922597075758, + "venv/lib/python3.13/site-packages/fastapi/middleware/httpsredirect.py": 5775982317459922443, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.py": 4672871351134074735, + "venv/lib/python3.13/site-packages/greenlet/platform/__init__.py": 15130871412783076140, + "frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js": 3674649277514557450, + "venv/lib/python3.13/site-packages/numpy/testing/overrides.py": 11819432487830192978, + "venv/lib/python3.13/site-packages/keyring/compat/py312.py": 17581691618899404491, + "venv/bin/pygmentize": 2166491742035772877, + "backend/src/services/__tests__/test_llm_prompt_templates.py": 17912427710321938757, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_sparse.py": 14343335524508450058, + "venv/lib/python3.13/site-packages/starlette/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jose/backends/rsa_backend.py": 13507186353881931758, + "frontend/src/routes/dashboards/[id]/components/DashboardGitManager.svelte": 14665567599893731601, + "venv/lib/python3.13/site-packages/authlib/common/urls.py": 13627272625165922482, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/util.py": 1520899420719605380, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_index_as_string.py": 292438690259156869, + "backend/src/schemas/settings.py": 7182606947764184429, + "venv/lib/python3.13/site-packages/greenlet/greenlet.h": 16216120538647882082, + "venv/lib/python3.13/site-packages/numpy/_typing/_array_like.py": 2161873439361281488, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunclike.pyi": 12215374902556647369, + "venv/lib/python3.13/site-packages/pandas/core/indexes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/multipart/multipart.py": 26386459953377432, + "frontend/build/_app/immutable/chunks/CqpGinL9.js": 3758913754304389665, + "venv/lib/python3.13/site-packages/yaml/cyaml.py": 9157893742065554693, + "venv/lib/python3.13/site-packages/numpy/core/defchararray.py": 11371045148957547088, + "venv/lib/python3.13/site-packages/numpy/f2py/__version__.pyi": 9759534743796867731, + "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.py": 13115032674230220791, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit.py": 15498810174380798405, + "backend/src/schemas/__tests__/test_settings_and_health_schemas.py": 10518526918751273612, + "backend/src/api/routes/git/_config_routes.py": 6093940098740660772, + "frontend/src/routes/dashboards/health/__tests__/health_page.integration.test.js": 11653729504599199718, + "venv/lib/python3.13/site-packages/PIL/MpoImagePlugin.py": 644327650732339301, + "venv/lib/python3.13/site-packages/pandas/_config/display.py": 433650013567734821, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/connection.py": 15405047955974108860, + "backend/src/plugins/translate/_utils.py": 10016440264788256359, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_constructors.py": 16197656939536784142, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_cpp_avx2.cpython-313-x86_64-linux-gnu.so": 12574929384355254457, + "venv/lib/python3.13/site-packages/pip/_internal/models/search_scope.py": 9282393652860589543, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust.abi3.so": 2537152913308578487, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numerictypes.py": 5719374287454872555, + "venv/lib/python3.13/site-packages/gitdb/db/git.py": 13552203494737962026, + "venv/lib/python3.13/site-packages/websockets/frames.py": 4901850477414613953, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_deprecations.py": 16124509063246256847, + "venv/lib/python3.13/site-packages/yaml/loader.py": 18284689412149643959, + "venv/lib/python3.13/site-packages/pydantic/_internal/_mock_val_ser.py": 12265320534388472158, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.c": 9134176670140958459, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_pickle.py": 4216445955812104014, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_array_to_datetime.py": 3467480435568672840, + "backend/src/models/mapping.py": 3582903535753840317, + "venv/lib/python3.13/site-packages/numpy/testing/__init__.py": 2831275254313750978, + "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.py": 548928042543500365, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/blocking.py": 3483388533957772681, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_argon2.py": 11345706437113628133, + "venv/lib/python3.13/site-packages/passlib/ext/django/models.py": 12386223748379294996, + "venv/lib/python3.13/site-packages/fastapi/requests.py": 14587947416691824903, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_impl.py": 12056958946481531279, + "venv/lib/python3.13/site-packages/anyio/streams/tls.py": 4191898645554875562, "backend/src/api/routes/clean_release_v2.py": 12814311709297749713, + "venv/lib/python3.13/site-packages/authlib/common/security.py": 2291133227104016684, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/challenge.py": 6388445104761482746, + "venv/lib/python3.13/site-packages/yaml/constructor.py": 8731384179016992045, + "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.pyi": 9629457630163613604, + "venv/lib/python3.13/site-packages/pandas/util/__init__.py": 4070574585004336241, + "backend/src/api/routes/__tests__/test_reports_api.py": 8830242634438523357, + "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.pyi": 8708830448398500675, + "venv/lib/python3.13/site-packages/httpx/_api.py": 6697370469329778523, + "venv/lib/python3.13/site-packages/pip/_internal/__init__.py": 7060345458485901709, + "backend/src/services/clean_release/repositories/audit_repository.py": 9617813121624417458, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_setops.py": 13440916133402971190, + "backend/src/services/profile_service.py": 7430451608615934464, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/idnadata.py": 1169745920682458213, + "backend/test_app.db": 2486636812009447051, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending_distributions.pyx": 15302775787158991386, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_any_index.py": 10800968419286329268, + "venv/lib/python3.13/site-packages/urllib3/contrib/socks.py": 645086578806871685, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_partial_indexing.py": 4132091154215910029, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/emoji.py": 9166774203918731896, + "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.pyi": 2628035888703031029, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/util.py": 5252158959761945519, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.py": 13853220736499979380, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/conftest.py": 25473177671450048, + "venv/lib/python3.13/site-packages/dateutil/tzwin.py": 5149446703746204349, + "venv/lib/python3.13/site-packages/pygments/lexers/factor.py": 15788613154609197002, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/resource_protector.py": 3563910821279222695, + "frontend/src/lib/components/dataset-review/__tests__/us3_execution_batch.ux.test.js": 13416996904332574966, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.pyf": 14358606965464506398, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/adapter.py": 5908944827805063108, + "venv/bin/pyrsa-keygen": 8222542582170363672, + "backend/alembic/script.py.mako": 7041141123739810216, + "venv/lib/python3.13/site-packages/jeepney/tests/test_auth.py": 15125055415702968414, + "venv/lib/python3.13/site-packages/apscheduler/util.py": 11440701924954413440, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi": 14119032813912827271, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/hashtable.pyi": 15034917167424979097, + "venv/lib/python3.13/site-packages/pandas/core/window/__init__.py": 15180240812077877933, + "venv/lib/python3.13/site-packages/uvicorn/middleware/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_delitem.py": 16538190861492829338, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_regression.py": 16293647824734937323, + "venv/lib/python3.13/site-packages/numpy/lib/npyio.pyi": 3212440968296555560, + "frontend/src/routes/datasets/review/[id]/__tests__/dataset_review_workspace.ux.test.js": 4105775024258653726, + "frontend/build/_app/env.js": 8815854342083926790, + "venv/lib/python3.13/site-packages/pandas/core/arraylike.py": 11439602957100017713, + "backend/git_repos/remote/test-repo.git/objects/22/c0ea49cea7e5138fb91b25b1bc0e101ae6e017": 17630871400599334193, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nested_sequence.pyi": 10985533017688918283, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/passlib/handlers/ldap_digests.py": 8658529184965699766, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isetitem.py": 14895552405828068177, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_libalgos.py": 13934861984871432400, + "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.pyi": 15767546107856827543, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/licenses/LICENSE": 14230156892574098522, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/fetch.py": 13937019222549208796, + "venv/lib/python3.13/site-packages/pygments/lexers/testing.py": 17148598391210353576, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayprint.py": 5912583751693302370, + "venv/lib/python3.13/site-packages/pandas/_libs/ops_dispatch.cpython-313-x86_64-linux-gnu.so": 5284769758475394095, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/response.py": 15004896908941411698, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/well_known.py": 7183795183137931709, + "venv/lib/python3.13/site-packages/numpy/core/_multiarray_umath.py": 10973016138581934035, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_array_from_pyobj.py": 9596224861290975079, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/horizontal_shard.py": 17615732108308858890, + "venv/lib/python3.13/site-packages/greenlet/CObjects.cpp": 3454797518210223926, + "venv/lib/python3.13/site-packages/pandas/core/reshape/melt.py": 14109947554124551986, + "venv/lib/python3.13/site-packages/pandas/util/_tester.py": 1033951890304257539, + "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.pyi": 17903213294220335051, + "venv/lib/python3.13/site-packages/pip/_internal/commands/install.py": 17631777189475433503, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi": 7385072545198817771, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_pbkdf2.py": 17016810698578473773, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.pyi": 10947021928755741366, + "venv/lib/python3.13/site-packages/numpy/random/mtrand.cpython-313-x86_64-linux-gnu.so": 16146459667121787202, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/index_tricks.pyi": 11463747060334597941, + "venv/lib/python3.13/site-packages/httpcore/_exceptions.py": 6716590711697088732, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bus_messages.py": 4323093138307306385, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_eng_formatting.py": 14768815444701392013, + "backend/src/services/__init__.py": 15123879863527585264, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pymssql.py": 6650008663791598065, + "frontend/src/lib/components/translate/TranslationMetricsDashboard.svelte": 8577281635452165836, + "venv/lib/python3.13/site-packages/fastapi/_compat/v1.py": 9776181748061371513, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90": 6208802899442270399, + "venv/lib/python3.13/site-packages/pandas/io/formats/format.py": 3364941338174434661, + "venv/lib/python3.13/site-packages/pip/_internal/commands/wheel.py": 16397273591245583356, + "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.py": 9409852116555866847, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_astype.py": 4854809596041987380, + "venv/lib/python3.13/site-packages/cffi/_embedding.h": 9441285871823018603, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatter.py": 16499277113779414101, + "venv/lib/python3.13/site-packages/_pytest/stepwise.py": 3527630676691417317, + "venv/lib/python3.13/site-packages/uvicorn/middleware/message_logger.py": 14825516604555033580, + "venv/lib/python3.13/site-packages/pandas/core/methods/describe.py": 17006836623161521092, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/RECORD": 1689342214025776630, + "venv/lib/python3.13/site-packages/h11/_readers.py": 832030916375670301, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/licenses/LICENSE.rst": 5960743202700406649, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ctypeslib.pyi": 8623725566434725526, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/dtypes.cpython-313-x86_64-linux-gnu.so": 657138415665704488, + "venv/lib/python3.13/site-packages/urllib3/contrib/pyopenssl.py": 11839715589709210412, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_interval_array_equal.py": 15654625365223535344, + "venv/lib/python3.13/site-packages/uvicorn/_compat.py": 2593000889619875759, + "venv/lib/python3.13/site-packages/pygments/formatters/bbcode.py": 8614391937525677922, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/etcd.py": 4078354986605069279, + "venv/lib/python3.13/site-packages/pygments/lexers/teraterm.py": 16132676290138105984, + "frontend/src/routes/settings/FeaturesSettings.svelte": 14068252633661039168, + "frontend/build/_app/immutable/chunks/DsnmJJEf.js": 17416107759626312632, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.pyi": 3573629536236108391, + "dist/docker/ss-tools.20260517.tar.xz": 10542870312371880474, + "backend/src/plugins/llm_analysis/service.py": 8900828214099151536, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_iteration.py": 15247340610412364508, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/reporter.py": 6510864297510700136, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/api.py": 12339139862411341381, + "venv/lib/python3.13/site-packages/rpds/__init__.py": 5862197328247012275, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_promote.py": 16601872688404846307, + "venv/lib/python3.13/site-packages/ecdsa/_sha3.py": 10353612776869489378, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_pickle.py": 388513670243918273, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_file_handling.py": 732772718210067599, + "venv/lib/python3.13/site-packages/uvicorn/main.py": 5843333502356171120, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_api.py": 13739775047493489785, + "venv/lib/python3.13/site-packages/uvicorn/importer.py": 5449629250971153435, + "venv/lib/python3.13/site-packages/pygments/lexers/hare.py": 8693002231020751711, + "frontend/e2e/helpers/api.helper.js": 12740720187461301874, + "frontend/src/routes/settings/LoggingSettings.svelte": 1737218883899664063, + "frontend/build/_app/immutable/chunks/DStEdtqg.js": 10774751570130754344, + "venv/lib/python3.13/site-packages/packaging/_parser.py": 13394093358675095309, + "backend/src/services/reports/__tests__/test_report_service.py": 7145268223824508607, + "venv/lib/python3.13/site-packages/iniconfig/exceptions.py": 16501270224069836264, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/__init__.py": 63497920264089252, + "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/keyring/backends/SecretService.py": 17482492072907438453, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/decoder.py": 11876648884087997745, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/well_known.py": 8259335680633926377, + "venv/lib/python3.13/site-packages/passlib/tests/test_apps.py": 10454136535890937237, + "venv/lib/python3.13/site-packages/pandas/_libs/index.pyi": 17679349633640606985, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_period_index.py": 6634414375581820058, + "venv/lib/python3.13/site-packages/pandas/_testing/asserters.py": 272063856832951430, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py": 2285778903282667561, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_astype.py": 8633811117672837999, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_readlines.py": 15928258358116399067, + "venv/lib/python3.13/site-packages/numpy/core/overrides.pyi": 1968648615494204783, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_arithmetic.py": 15071337112968886738, + "venv/lib/python3.13/site-packages/pandas/_libs/writers.cpython-313-x86_64-linux-gnu.so": 6878855127769203372, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/datetimelike_accumulations.py": 14719894187829729175, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_indexing.py": 13703573544185051910, + "venv/lib/python3.13/site-packages/sqlalchemy/event/base.py": 18238453132776154057, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_datetimeindex.py": 14816894350435545024, + "frontend/src/routes/datasets/__tests__/ColumnsTable.test.js": 15883951776898228284, + "frontend/build/_app/immutable/chunks/CjuuSE8_.js": 9588276202929766355, + "venv/lib/python3.13/site-packages/passlib/handlers/md5_crypt.py": 7669328623914474137, + "venv/lib/python3.13/site-packages/numpy/typing/mypy_plugin.py": 1306129775649200113, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args_and_kwargs.py": 3381939712123764154, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_ndarray.py": 6863874753941288585, + "venv/lib/python3.13/site-packages/pandas/core/indexes/timedeltas.py": 13653393430363556843, + "backend/src/core/superset_client/_base.py": 10958088163566963237, + "backend/src/api/routes/translate/_preview_routes.py": 16234500901707822839, + "backend/src/plugins/translate/dictionary_crud.py": 17858252266960667195, + "backend/tests/test_logging_audit_fixes.py": 14806902244422319839, + "backend/src/core/task_manager/__tests__/test_task_logger.py": 1651218524520477084, + "venv/lib/python3.13/site-packages/pygments/lexers/kusto.py": 16285533608924436308, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_arrow_interface.py": 9757086292358759236, + "venv/lib/python3.13/site-packages/greenlet/tests/test_generator_nested.py": 12822240347707346718, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/gcp.py": 12328409672947966867, + "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.pyi": 8232620851756907417, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_normalize.py": 7378656958631172603, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_date_range.py": 16128552513324017349, + "backend/src/api/routes/dashboards/__init__.py": 15214026957520044598, + "venv/lib/python3.13/site-packages/pygments/formatters/latex.py": 7514533384468139434, + "venv/lib/python3.13/site-packages/requests/compat.py": 5836590172733661320, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/azure.py": 13529763490186254462, + "venv/lib/python3.13/site-packages/pandas/_libs/indexing.pyi": 90995502095752726, + "frontend/src/components/tools/MapperTool.svelte": 452311121889230749, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/__init__.py": 11734104142988812647, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_setops.py": 10550603120090683350, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/scoping.py": 18223258186431020473, + "venv/lib/python3.13/site-packages/pandas/util/_validators.py": 10201915528715968165, + "backend/src/api/routes/__tests__/test_clean_release_v2_api.py": 13464989331176891726, + "venv/lib/python3.13/site-packages/pandas/api/interchange/__init__.py": 181911269762882069, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/box.py": 14303526978791498662, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.py": 2401931196871484449, + "venv/lib/python3.13/site-packages/passlib/handlers/phpass.py": 16489430001449160264, + "venv/lib/python3.13/site-packages/pandas/util/version/__init__.py": 3844072588696074141, + "backend/src/api/routes/translate/_schedule_routes.py": 18180097500694105300, + "backend/src/api/routes/dataset_review_pkg/_dependencies.py": 15939232213193276681, + "venv/lib/python3.13/site-packages/passlib/handlers/postgres.py": 14162382430051693313, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/__init__.py": 15971002342788501945, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/LICENSE": 11167201188673981085, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_function_base.py": 16624804022675533740, + "backend/src/plugins/translate/_run_service.py": 1705461175389858266, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data": 11957232619107868023, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_musllinux.py": 2423350951094915747, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/util.py": 2866856507760047219, + "venv/lib/python3.13/site-packages/greenlet/tests/test_weakref.py": 6780204527427742510, + "venv/lib/python3.13/site-packages/passlib/tests/sample1.cfg": 9597283806285213340, + "venv/lib/python3.13/site-packages/numpy/tests/test_public_api.py": 11741922758622705449, + "venv/lib/python3.13/site-packages/websockets/server.py": 16599051743322571790, + "venv/lib/python3.13/site-packages/attr/_version_info.pyi": 7141309436445210354, + "venv/lib/python3.13/site-packages/gitdb/util.py": 645937410168583692, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_pickle.py": 8705060420848529055, + "venv/lib/python3.13/site-packages/pandas/tseries/offsets.py": 13750652921710295115, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_csky_gcc.h": 12929785267195988209, + "frontend/src/routes/admin/roles/+page.svelte": 1343040884276845574, + "backend/tests/test_security_audit_fixes.py": 10329229098676202553, + "venv/lib/python3.13/site-packages/authlib/common/encoding.py": 52296066492753953, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_version.pyi": 18093228021414910594, + "venv/lib/python3.13/site-packages/ecdsa/test_keys.py": 17117188373419689467, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/__init__.py": 11157967642611612522, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/help.py": 3124654001287175629, + "venv/lib/python3.13/site-packages/rsa/util.py": 13423880475585138638, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_msvc.h": 14580207065003376324, + "venv/lib/python3.13/site-packages/attr/_typing_compat.pyi": 2823472697859409877, + "venv/lib/python3.13/site-packages/numpy/_core/_asarray.pyi": 3940937389249665490, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/bulk_persistence.py": 2307818727114646866, + "frontend/src/routes/profile/+page.svelte": 17979719303737794427, + "frontend/build/_app/immutable/chunks/tRYuMz19.js": 10125858668706792743, + "backend/ss_tools_backend.egg-info/PKG-INFO": 15134841326777953914, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/__init__.py": 15487893533770969571, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/meson.build": 8784756284679859367, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_setitem.py": 15731267129055947469, + "venv/lib/python3.13/site-packages/PIL/_imagingft.cpython-313-x86_64-linux-gnu.so": 11054435406031360190, + "venv/lib/python3.13/site-packages/pygments/formatters/other.py": 13124903290103898118, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/dml.py": 6567627855667533645, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_fillna.py": 13675584998644907265, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_macos.py": 7028037591427052891, + "venv/lib/python3.13/site-packages/attr/exceptions.py": 11532465891810816417, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/traversals.py": 1188980668212022868, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/mongodb.py": 5310116401542377882, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/types.py": 1343652083039949282, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/METADATA": 10220680536734745103, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_iter.py": 9232021002336641851, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arrow_interface.py": 5231449831607036031, + "venv/lib/python3.13/site-packages/numpy/_core/shape_base.py": 3996519099530770308, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_index.py": 12015738970771703312, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_cat_accessor.py": 4304062895283374927, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/aioodbc.py": 12704729841432715246, + "venv/lib/python3.13/site-packages/pygments/lexers/forth.py": 17623561228839319663, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/cli.py": 6382193953727339271, + "frontend/src/components/storage/FileUpload.svelte": 14805293086068620697, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/rsa_key.py": 7092106298733667895, + "venv/lib/python3.13/site-packages/pandas/core/config_init.py": 16537122488227845090, + "venv/lib/python3.13/site-packages/pydantic/v1/version.py": 2758971830527526972, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py": 7421910137064160936, + "venv/lib/python3.13/site-packages/git/__init__.py": 15867730798565725003, + "venv/lib/python3.13/site-packages/cffi/cffi_opcode.py": 8411344362428947268, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24662.f90": 4241310200087270990, + "venv/lib/python3.13/site-packages/referencing/_attrs.py": 14434891919747863272, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/__init__.py": 11283047029180207588, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_transform.py": 5674175311567817854, + "venv/lib/python3.13/site-packages/attr/_make.py": 2348458829123990579, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/base.py": 16052592982063844259, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_core.py": 12712110303898046818, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_take.py": 3281943380342853080, + "venv/lib/python3.13/site-packages/yaml/events.py": 745772917931702910, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_period.py": 6047041810867211174, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_base_indexer.py": 3129123098288498633, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_table.tpl": 8706980975714184465, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_holiday.py": 8541197358003711845, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reserved_words.py": 8022121780993497971, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/METADATA": 10241403930811743893, + "backend/src/plugins/translate/orchestrator_aggregator.py": 2072358957289443762, + "backend/tests/test_translate_scheduler_guard.py": 13396608843530344156, + "venv/lib/python3.13/site-packages/anyio/to_thread.py": 12767326212338028587, + "venv/lib/python3.13/site-packages/cryptography/x509/certificate_transparency.py": 11337143186866439208, + "venv/lib/python3.13/site-packages/pandas/core/internals/concat.py": 12151675567885981464, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_size.py": 8527839563560550806, + "venv/lib/python3.13/site-packages/PIL/PcfFontFile.py": 8867692961463798279, + "venv/lib/python3.13/site-packages/charset_normalizer/md.py": 2029760700380476138, + "venv/lib/python3.13/site-packages/urllib3/connection.py": 12761371748350595804, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numerictypes.py": 8836108334624807647, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_extension.py": 17245018204352082978, + "venv/lib/python3.13/site-packages/pygments/styles/vs.py": 4188729978573652106, + "venv/lib/python3.13/site-packages/pygments/lexers/spice.py": 1376126320935115350, + "frontend/build/_app/immutable/chunks/0Yt6AaS4.js": 10069770374807615911, + "backend/src/schemas/auth.py": 12332369795585412464, + "venv/lib/python3.13/site-packages/itsdangerous/serializer.py": 14271229091461164933, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf": 14717748358749934995, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/__init__.py": 635200170992032966, + "venv/lib/python3.13/site-packages/attr/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/WHEEL": 16784970174376303810, + "venv/lib/python3.13/site-packages/_pytest/terminal.py": 885450969703476729, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/style.py": 10665998898253460114, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_deprecations.py": 16367195310156359251, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/RECORD": 12555714734722889695, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_nanfunctions.py": 2356468092336024365, + "venv/lib/python3.13/site-packages/annotated_types/test_cases.py": 5123395674810472016, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated": 11193150813314469394, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/kind/foo.f90": 1367964042730902899, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_numpy.py": 4073641912755651877, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/candidates.py": 5951912505933673835, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pxd": 13413785818999584986, + "venv/lib/python3.13/site-packages/pygments/styles/trac.py": 13968346768164381833, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/WHEEL": 7145482834744213753, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/METADATA": 1684451390569121499, + "venv/lib/python3.13/site-packages/pandas/_libs/sas.cpython-313-x86_64-linux-gnu.so": 16309838137741124637, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_scalar_compat.py": 10534925655070162459, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_arithmetic.py": 4858019700859362660, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.pyi": 17825266810219495672, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/pygments/lexers/webidl.py": 8097260111959278117, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/RECORD": 1051307407005554409, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py": 17873236864291624476, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/base.py": 3628510830969664111, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/licenses/COPYING": 14459782230785388765, + "venv/lib/python3.13/site-packages/numpy/_core/function_base.py": 5676611841071163854, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/index.py": 15694995431926521471, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/functions.py": 14107377669163193871, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/types.py": 16795741817129898714, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/RECORD": 8104089156015954779, + "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.py": 1262543237476191714, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_construction.py": 13953424340346625390, + "venv/lib/python3.13/site-packages/pygments/lexers/go.py": 11118104397271513417, + "venv/lib/python3.13/site-packages/pygments/lexers/d.py": 18120801227801223376, + "frontend/src/lib/components/translate/CorrectionCell.svelte": 14340498120654577399, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_classes.py": 1440926036579216168, + "frontend/build/_app/immutable/chunks/Cn2fCIej.js": 14831712472782315002, + "frontend/build/favicon.png": 16740551781088792605, + "venv/lib/python3.13/site-packages/pandas/util/_print_versions.py": 15326663505771588740, + "backend/src/api/routes/translate/_helpers.py": 13265933139767815312, + "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.py": 14696841109142419143, + "venv/lib/python3.13/site-packages/pandas/core/computation/common.py": 5369352684655954608, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_pickle.py": 6232650893735715362, + "venv/lib/python3.13/site-packages/urllib3/util/ssltransport.py": 1175688460659745788, + "frontend/src/routes/validation/history/+page.svelte": 3920288174017004134, + "backend/src/schemas/dataset_review.py": 15720223123457526104, + "venv/lib/python3.13/site-packages/numpy/dtypes.pyi": 6713822658171717369, + "venv/lib/python3.13/site-packages/pip/_internal/build_env.py": 3614358934066127900, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_sparc_sun_gcc.h": 2915128971664712180, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reshape.py": 10576230966727810832, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/core.py": 2300277198409164253, + "venv/lib/python3.13/site-packages/anyio/_core/_fileio.py": 4507100568401692983, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/palette.py": 17383863392192572184, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_isin.py": 11330491145602008796, + "venv/lib/python3.13/site-packages/PIL/PSDraw.py": 1927169421822446045, + "frontend/src/lib/stores/__tests__/setupTests.js": 13316015450930652502, + "frontend/build/_app/immutable/chunks/DA9vsgRx.js": 17494370639184435895, + "venv/lib/python3.13/site-packages/secretstorage/py.typed": 15130871412783076140, + "backend/src/api/routes/__tests__/test_dataset_review_api.py": 8023021851133925740, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/themes.py": 6451091097727599550, + "venv/lib/python3.13/site-packages/_pytest/raises.py": 8188402179490363767, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/const_vs_enum.py": 12873459583943748931, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_duplicated.py": 14676058112867601208, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayterator.py": 3076316311545674897, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_timezones.py": 4771674179164304731, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/json.py": 4660603129768960095, + "venv/lib/python3.13/site-packages/cffi/backend_ctypes.py": 2042566833861899211, + "venv/bin/uvicorn": 3776670267111625708, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas_constants.py": 14492427939536692313, + "frontend/src/routes/datasets/review/ReviewWorkspaceHeader.svelte": 15302107925819930527, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_constructors.py": 3440572832185940666, + "venv/lib/python3.13/site-packages/authlib/__init__.py": 8957417237987377675, + "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.py": 15031197044862908440, + "venv/lib/python3.13/site-packages/passlib/utils/__init__.py": 11704122205941631503, + "venv/lib/python3.13/site-packages/fastapi/dependencies/models.py": 8626894872248212015, + "venv/lib/python3.13/site-packages/h11/_abnf.py": 10456996134895429201, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/LICENSE": 4672913476475760762, + "backend/alembic/versions/2a7b8c9d0e1f_add_target_languages_to_translation_jobs.py": 7201017059554918882, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/greenlet_exceptions.hpp": 8819301638282185623, + "venv/lib/python3.13/site-packages/sqlalchemy/util/queue.py": 1289234691048379395, + "venv/lib/python3.13/site-packages/numpy/random/_pcg64.cpython-313-x86_64-linux-gnu.so": 5759445712745875888, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/__init__.py": 15130871412783076140, + "backend/src/services/clean_release/enums.py": 7365670144442292671, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/astype.py": 9925183787411796679, + "venv/lib/python3.13/site-packages/pydantic/decorator.py": 6984214881365537811, + "venv/lib/python3.13/site-packages/websockets/legacy/exceptions.py": 16025779645869134942, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py": 8530403239168529668, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_where.py": 16584772339591698754, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype.py": 7796703383405149774, + "venv/lib/python3.13/site-packages/git/objects/submodule/util.py": 8621897576747443758, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/utils.py": 9959199071030996679, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pct_change.py": 10313980265441433173, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/util.py": 2176177435997659667, + "venv/lib/python3.13/site-packages/pip/_internal/operations/check.py": 16650663913976953800, + "venv/lib/python3.13/site-packages/pygments/lexers/capnproto.py": 15713281507099411738, + "frontend/src/routes/datasets/__tests__/bulk_actions.test.js": 8445672988319354987, + "backend/src/api/auth.py": 6636844886257776670, + "venv/lib/python3.13/site-packages/pygments/lexers/pointless.py": 17552020039609007881, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/request.py": 17642741955458391050, + "venv/lib/python3.13/site-packages/pip/_internal/index/collector.py": 7454652626329467900, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_construction.py": 10619501873883861745, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi": 1065808244870331598, + "venv/lib/python3.13/site-packages/anyio/abc/_resources.py": 8330687082933028623, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_case_justify.py": 8204537837649550062, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/base.py": 16951268065271931235, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/WHEEL": 3749476255729626245, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.pyi": 16372699564794732463, + "venv/lib/python3.13/site-packages/starlette/middleware/authentication.py": 15211131264936212938, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/RECORD": 9461427699726982537, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py": 10057637461647348368, + "venv/lib/python3.13/site-packages/_pytest/subtests.py": 14573790885130724739, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_inclusive.py": 1389676378885557519, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/missing.py": 14589973874359353799, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_constructors.py": 6440526981746306640, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_sql.py": 3901697517087276687, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_dml_constructors.py": 4497038002189188311, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_parser.py": 8145921552236189367, + "venv/lib/python3.13/site-packages/git/py.typed": 15130871412783076140, + "backend/src/services/clean_release/stages/base.py": 344723354852893815, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/__init__.py": 12849371269359608058, + "frontend/src/lib/components/layout/__tests__/test_topNavbar.svelte.js": 11053755879172333925, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunc_config.pyi": 11754104063443791746, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/_mapping.py": 17519715342700184302, + "venv/lib/python3.13/site-packages/pydantic/v1/tools.py": 1995883197897112278, + "venv/lib/python3.13/site-packages/cffi/ffiplatform.py": 6782148110863549472, + "venv/lib/python3.13/site-packages/sqlalchemy/inspection.py": 8563914460959280101, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/util.py": 4890614159013873000, + "venv/lib/python3.13/site-packages/pandas/_libs/join.cpython-313-x86_64-linux-gnu.so": 2947947484481830203, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_abc.py": 10164280045317807365, + "backend/src/core/__tests__/test_native_filters.py": 823253235973274872, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/test_array_with_attr.py": 6568496539994758985, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_normalize.py": 11373923576259976755, + "backend/src/api/routes/migration.py": 6030566471113208264, + "venv/lib/python3.13/site-packages/anyio/abc/_subprocesses.py": 4297459042599291531, + "venv/lib/python3.13/site-packages/numpy/core/__init__.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_invalid_arg.py": 610891871484326055, + "venv/lib/python3.13/site-packages/idna/__init__.py": 6489437464172324468, + "venv/lib/python3.13/site-packages/keyring/testing/backend.py": 14295829193445781542, + "venv/lib/python3.13/site-packages/urllib3/util/connection.py": 15511685694589961094, + "backend/src/plugins/llm_analysis/plugin.py": 17113713561460406867, + "venv/lib/python3.13/site-packages/jeepney/io/tests/conftest.py": 13381752264278264218, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_multiarray.py": 3592197154340095431, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_ops.py": 14420421526781215500, + "venv/lib/python3.13/site-packages/urllib3/py.typed": 12220177918227495093, + "venv/lib/python3.13/site-packages/charset_normalizer/md.cpython-313-x86_64-linux-gnu.so": 1835299664481804968, + "backend/alembic/versions/a7b1c2d3e4f5_add_provider_id_to_validation_policies.py": 7446022200459040057, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/nested_secrets.py": 15691917061715429369, + "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.pyi": 8195943561787777127, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/__init__.py": 11526998905763262175, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_aggregate.py": 15038915958422670700, + "venv/lib/python3.13/site-packages/authlib/oauth2/auth.py": 8455258275234626534, + "venv/lib/python3.13/site-packages/PIL/JpegImagePlugin.py": 10621639599916796689, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/base_key.py": 10402800587070352851, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/util.py": 9373891872370603585, + "venv/lib/python3.13/site-packages/fastapi/dependencies/utils.py": 7687214523082385505, + "venv/lib/python3.13/site-packages/numpy/_globals.py": 8736093011628027941, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/fastapi/middleware/cors.py": 7452860773712601508, + "backend/src/core/utils/network.py": 8313622593956890768, + "backend/src/services/reports/__tests__/test_type_profiles.py": 17262223295445285285, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine_first.py": 3100691245280812910, + "backend/src/schemas/dataset_review_pkg/_composites.py": 1898056130177244572, + "venv/lib/python3.13/site-packages/pip/_internal/utils/subprocess.py": 3095012838116670328, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nbit_base_example.pyi": 8571452382806614924, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/getitem.py": 556339939822508169, + "backend/src/plugins/translate/_batch_insert.py": 12482635271028646257, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/authorization_server.py": 4427151727224472650, + "venv/lib/python3.13/site-packages/fastapi/encoders.py": 1914192268055730299, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_impl.py": 15673691977157706075, + "venv/lib/python3.13/site-packages/pygments/lexers/carbon.py": 6753624244809529841, + "venv/lib/python3.13/site-packages/sqlalchemy/future/__init__.py": 17688444679736059779, + "venv/lib/python3.13/site-packages/fastapi/types.py": 3867821246650502267, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_concat.py": 1351478313334379336, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/METADATA": 6960169108624303030, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/licenses/LICENSE": 3868190977070717994, + "venv/lib/python3.13/site-packages/pip/_internal/exceptions.py": 2252826732781519645, + "venv/lib/python3.13/site-packages/_pytest/legacypath.py": 7512065138259788426, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/__init__.py": 15991623390785635773, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/util/_exceptions.py": 14426860079366867683, + "venv/lib/python3.13/site-packages/numpy/_core/records.pyi": 14194354215405544730, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/memmap.pyi": 15629663272474054909, + "venv/lib/python3.13/site-packages/pandas/tests/test_expressions.py": 16378925536309828288, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_categorical.py": 9615571808720893016, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/base.py": 7110726987481713080, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype.pyi": 17662618580381221543, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f": 13562390882286135024, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_delete.py": 3485374671877063217, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_inference.py": 16402427186697071465, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_string_array.py": 8260883866404398980, + "frontend/src/lib/stores/__tests__/mocks/navigation.js": 10782992736745205981, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py": 18229054440703471493, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_insert.py": 11635164392966270621, + "frontend/build/_app/immutable/chunks/wt4XWbu0.js": 4990845376538135578, + "venv/lib/python3.13/site-packages/PIL/PsdImagePlugin.py": 4347581352716313298, + "backend/src/api/routes/__tests__/test_reports_detail_api.py": 7284151749869192310, + "backend/test_pat_api.py": 4206656943734821967, + "venv/lib/python3.13/site-packages/sqlalchemy/util/deprecations.py": 7020540470348910770, + "frontend/build/_app/immutable/chunks/BJiYbwAa.js": 8907192462661233986, + "frontend/build/_app/immutable/chunks/CGljkz0L.js": 11134357768940312112, + "backend/src/api/routes/__tests__/test_git_status_route.py": 6682904773087475636, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_unique.py": 16285418015531891530, + "venv/lib/python3.13/site-packages/numpy/__config__.pyi": 1422114139050700402, + "venv/lib/python3.13/site-packages/starlette/schemas.py": 697416731579555195, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_html.py": 12040484325988635032, + "backend/src/plugins/translate/orchestrator_query.py": 4760681990145471312, + "venv/lib/python3.13/site-packages/h11/_connection.py": 6971907312737339559, + "docker/all-in-one.Dockerfile": 10896793266219904099, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_pbkdf2.py": 4977067068389993374, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_cov_corr.py": 13652339565475304679, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_concat.py": 4472503149811617440, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/rebuild.py": 1813298167468704155, + "venv/lib/python3.13/site-packages/greenlet/TUserGreenlet.cpp": 16258622236210473101, + "venv/lib/python3.13/site-packages/sqlalchemy/types.py": 15819795572817819102, + "venv/lib/python3.13/site-packages/pandas/core/reshape/api.py": 16364136812252343076, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_indexing.py": 11572911419313573163, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/METADATA": 15658158392301945427, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers.py": 4940305787631493030, + "venv/lib/python3.13/site-packages/jsonschema/__init__.py": 6925762200139836824, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_interp_fillna.py": 5530041283991655415, + "venv/lib/python3.13/site-packages/charset_normalizer/version.py": 9948878594498587774, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py": 6152202474302791232, + "venv/lib/python3.13/site-packages/pygments/styles/bw.py": 869630132791421268, + "venv/lib/python3.13/site-packages/pygments/lexers/javascript.py": 16869490851285457857, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/color_triplet.py": 17264298271771184, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_numba.py": 1548992314517942530, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/__init__.py": 371829636800613137, + "venv/lib/python3.13/site-packages/fastapi/openapi/constants.py": 1111838716953068285, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_inference.py": 5741637509343419942, + "venv/lib/python3.13/site-packages/starlette/types.py": 6372850128669191435, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/implicit.py": 5400555157488808948, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_time_series.py": 5205199092955498507, + "venv/lib/python3.13/site-packages/pydantic/v1/json.py": 16596969681914729251, + "backend/src/core/task_manager/persistence.py": 17734987286155732710, + "venv/lib/python3.13/site-packages/pydantic/v1/_hypothesis_plugin.py": 6383299780629629080, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.py": 1094797446508902066, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_formats.py": 1265319125235346745, + "frontend/src/lib/stores/__tests__/sidebar.test.js": 5168138864675110669, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c": 8494977275215578998, + "frontend/build/_app/immutable/nodes/35.WwS3x7o7.js": 12473284951496245672, + "backend/src/plugins/translate/preview.py": 1878554949419203980, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/flow_control.py": 4822804840057360506, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.py": 1472021608501071055, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_array.py": 12514884344165043136, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_converter.py": 7709581879446228856, + "frontend/src/components/PasswordPrompt.svelte": 13739802421315835398, + "frontend/build/_app/immutable/chunks/7VHeY8vo.js": 6746038362986324688, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/encoder.py": 3261739474564948330, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/claims.py": 11853156183819186599, + "frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js": 15198772446275187033, + "venv/lib/python3.13/site-packages/_pytest/tracemalloc.py": 5530234062530858720, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/WHEEL": 9788895026336324100, + "venv/lib/python3.13/site-packages/tzlocal/win32.py": 1949985224569608978, + "venv/lib/python3.13/site-packages/pandas/_libs/interval.cpython-313-x86_64-linux-gnu.so": 8964760352224019544, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/pickleable.py": 7712040860601343075, + "venv/lib/python3.13/site-packages/numpy/fft/_helper.py": 15906444100774706395, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numeric_only.py": 13610631681447961840, + "venv/lib/python3.13/site-packages/pandas/tests/util/conftest.py": 11143177766735481660, + "venv/lib/python3.13/site-packages/PIL/ImageGrab.py": 11114379915762058868, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asfreq.py": 2701081989348180239, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/format": 12697928260201325593, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64_np126.pkl.gz": 1630203486813146863, + "venv/lib/python3.13/site-packages/pygments/lexers/python.py": 8995519134978505744, + "venv/lib/python3.13/site-packages/pygments/lexers/tal.py": 447505725492547461, + "frontend/src/lib/components/translate/TranslationRunGlobalIndicator.svelte": 16210598715819306972, + "frontend/src/routes/migration/__tests__/migration_dashboard.ux.test.js": 17118608261683412409, + "backend/tests/test_auth.py": 6167020718035755646, + "backend/git_repos/remote/test-repo.git/refs/heads/feature/e2e-update": 9577764946931187657, + "backend/git_repos/remote/test-repo.git/hooks/sendemail-validate.sample": 8058833260784074657, + "venv/lib/python3.13/site-packages/passlib/tests/__init__.py": 16543763165305017760, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_fileno.py": 15541504502174047167, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_get_numeric_data.py": 11747933921770969706, + "venv/lib/python3.13/site-packages/pyasn1/type/opentype.py": 340146737126677655, + "venv/lib/python3.13/site-packages/git/cmd.py": 8854786163152637148, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/endpoint.py": 13389763148720370546, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arrayterator.py": 1646530870049791291, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_is_monotonic.py": 12769599198035357753, + "frontend/src/components/git/GitOperationsPanel.svelte": 5140779139910068800, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_overlaps.py": 2328652590379935311, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_records.py": 18167578114159312327, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_sort_values.py": 15072305514178699398, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/einsumfunc.pyi": 200771351328522379, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_join.py": 4213933887062089605, + "venv/lib/python3.13/site-packages/greenlet/tests/test_contextvars.py": 6077482318964702132, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_fillna.py": 9297637486401098611, + "venv/lib/python3.13/site-packages/pandas/io/excel/_xlsxwriter.py": 16873939324418752965, + "venv/lib/python3.13/site-packages/pygments/lexers/business.py": 10410439210806697214, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi": 1626154870044880426, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_shares_memory.py": 2911029123657970431, + "venv/lib/python3.13/site-packages/httpx/_models.py": 6516278895118988231, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_check_indexer.py": 2929031395357057009, + "frontend/src/components/git/CommitHistory.svelte": 61942790722897211, + "backend/src/core/utils/async_network.py": 840981454868177222, + "venv/lib/python3.13/site-packages/numpy/random/lib/libnpyrandom.a": 1802449692091040396, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils.py": 10362977406431569031, + "backend/src/services/llm_provider.py": 18361253887642486050, + "venv/include/site/python3.13/greenlet/greenlet.h": 16216120538647882082, + "frontend/src/lib/components/reports/ReportDetailPanel.svelte": 16014663571033060148, + "backend/src/models/dataset_review.py": 5814500849969423218, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/WHEEL": 14929202952940710322, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_timer.py": 8196003526646080498, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/resource_protector.py": 4823504113176750140, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/serialize.py": 11139432164346742421, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/package_data.py": 3078502124870585867, + "venv/lib/python3.13/site-packages/apscheduler/__init__.py": 8652514118183227412, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py": 2609365889369107154, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/einsumfunc.py": 9944042006439149561, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh18335.f90": 1126438609189294255, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90": 4990763135487995517, + "venv/lib/python3.13/site-packages/pygments/lexers/email.py": 4355246279485460399, + "frontend/src/lib/components/translate/TargetSchemaHint.svelte": 4679159885307545370, + "backend/src/api/routes/assistant/_dispatch.py": 3122025109125421448, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/modules.py": 9023244176010175562, + "venv/lib/python3.13/site-packages/pygments/lexers/c_like.py": 13004061780700827047, + "venv/lib/python3.13/site-packages/pygments/lexers/monte.py": 15158829991357994573, + "frontend/src/routes/tools/mapper/+page.svelte": 11954517841045690204, + "venv/lib/python3.13/site-packages/httpcore/_async/interfaces.py": 18250473733460571816, + "backend/src/plugins/translate/__tests__/test_text_cleaner.py": 8349602354072854086, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/conftest.py": 3691712173202219606, + "backend/src/plugins/translate/__tests__/test_sql_generator.py": 4676288356986389564, + "venv/lib/python3.13/site-packages/anyio/_core/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_timedelta.py": 364160935264757405, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/aioodbc.py": 2018840826888846321, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/structs.py": 4479429145468072604, + "venv/bin/activate": 14735074000123383125, + "frontend/src/lib/api/translate.js": 18140498250896378509, + "backend/src/plugins/translate/preview_prompt_helpers.py": 14303328860208074708, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension_cpp.cpp": 4590574206187223887, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/scalars.py": 3468820466230647963, + "venv/lib/python3.13/site-packages/annotated_doc/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/introspect.pyi": 12239924839764265507, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/oct_key.py": 11504245602045724, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90": 12508663906609241323, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop.py": 17940792593116540139, + "venv/lib/python3.13/site-packages/pandas/tests/internals/test_internals.py": 2049484047553296860, + "venv/lib/python3.13/site-packages/git/index/__init__.py": 7874728461616959441, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_is_unique.py": 3989602816674881215, + "venv/lib/python3.13/site-packages/anyio/_core/_contextmanagers.py": 1258491775823080427, + "venv/lib/python3.13/site-packages/rsa/prime.py": 10820898885044917095, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.cpython-313-x86_64-linux-gnu.so": 16604252871044637047, + "venv/lib/python3.13/site-packages/pandas/core/computation/parsing.py": 3084943521520476999, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/json_schema_test_suite.py": 6152158310190822762, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/requirements.py": 2362917888844255805, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/reflection.py": 5951113078754792806, + "venv/lib/python3.13/site-packages/pip/_internal/models/target_python.py": 422323125651848065, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_cpp_avx2.cpython-313-x86_64-linux-gnu.so": 2991745295485163924, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_alpha_unix.h": 2759424570606117942, + "backend/src/api/routes/git/_repo_routes.py": 7367823490321383813, + "backend/tests/test_smoke_app.py": 7819901244710945164, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_quantile.py": 11966156706220948315, + "frontend/src/routes/settings/+page.ts": 3719008513710037840, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/RECORD": 7810411361439269754, + "venv/lib/python3.13/site-packages/referencing/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_toml_compat.py": 10196543528439925412, + "venv/lib/python3.13/site-packages/passlib/handlers/des_crypt.py": 15304795681178011265, + "venv/lib/python3.13/site-packages/numpy/_core/records.py": 11414828908088050950, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi": 9405122752084210696, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_regression.py": 12593643817685777170, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/misc.py": 6571241778569465264, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/test_astype.py": 10171766562093740708, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.pyi": 3145980717589050713, + "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.pyi": 3814281717779245045, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_utils.pyi": 3708905060001289515, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_algs.py": 2479791018067637690, + "frontend/static/favicon.svg": 6451919037497541980, + "frontend/build/_app/immutable/nodes/2.mx71xuky.js": 6999670584988180754, + "venv/lib/python3.13/site-packages/numpy/tests/test_ctypeslib.py": 9592016432737074765, + "venv/lib/python3.13/site-packages/pandas/errors/__init__.py": 13444371880185740908, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_arithmetic.py": 976970179757115407, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_copy.py": 12902342280706372953, + "venv/lib/python3.13/site-packages/starlette/middleware/gzip.py": 4321371046149637632, + "frontend/src/lib/api/validation.js": 10650815174196870103, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/AB.inc": 10441778083831997423, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_subclass.py": 5540948578269213810, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_ufunc.py": 669019702416198889, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpq-9b38f5e3.so.5.17": 9680474575710585826, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/METADATA": 3044554568188160018, + "backend/src/api/routes/git/__init__.py": 14824479456728364642, + "venv/lib/python3.13/site-packages/click/_termui_impl.py": 3296085065310341855, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_transform.py": 18159263102656491974, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/requests/packages.py": 7733041271118298220, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/licenses/LICENSE": 5757922580822401219, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_csv.py": 6678500392137188521, + "venv/lib/python3.13/site-packages/pyasn1/type/error.py": 1479878696626082697, + "venv/lib/python3.13/site-packages/pygments/lexers/modeling.py": 15714077241620129689, + "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending.py": 16515485226251040454, + "venv/lib/python3.13/site-packages/jsonschema/tests/typing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_direct.py": 12680113511641199070, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_reductions.py": 3575617237516305456, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/factory.py": 3042005457138956499, + "venv/lib/python3.13/site-packages/typing_inspection/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/commands/freeze.py": 8644678595442275485, + "backend/src/core/cot_logger.py": 12977179701814261121, + "venv/lib/python3.13/site-packages/pandas/core/arrays/categorical.py": 15993211255162930859, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_copy_deprecation.py": 16045426957636349035, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_stata.py": 3030675968330529905, + "venv/lib/python3.13/site-packages/ecdsa/test_ecdh.py": 3338834550392548171, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro_py.py": 11991492232381887787, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/AUTHORS": 10073225185964928425, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo77.f": 16250175448122328648, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_month.py": 1613806538807726074, + "venv/lib/python3.13/site-packages/passlib/__init__.py": 6987142392711441525, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/RECORD": 4487477737768669516, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_openid.py": 8708980645667847439, + "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.py": 6348811074249398741, + "venv/lib/python3.13/site-packages/pandas/core/indexes/category.py": 18192569199634406001, + "venv/lib/python3.13/site-packages/passlib/tests/sample1c.cfg": 13088198405762342506, + "frontend/build/_app/immutable/chunks/D8hfZjLA.js": 12615667196561753295, + "backend/src/core/auth/security.py": 8289703096420999159, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_unary.py": 8046543893978198672, + "backend/src/core/logger/__tests__/test_logger.py": 11665830455325390168, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_chained_assignment_deprecation.py": 7694137945143129474, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/authorization_server.py": 724388765673082720, + "venv/lib/python3.13/site-packages/pytest/__init__.py": 6137272437722350673, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reflection.py": 1799734694597531652, + "venv/lib/python3.13/site-packages/rapidfuzz/__init__.pyi": 13131938031654453415, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/literal.py": 5641382379370828704, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_exceptions.py": 12145393002202744314, + "frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js": 6561454515118560091, + "venv/lib/python3.13/site-packages/pydantic_settings/exceptions.py": 18300876747412267999, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_legacy.py": 9226692984248279094, + "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.pyi": 14558091964387571257, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/tags.py": 254599446317461188, + "venv/lib/python3.13/site-packages/pillow.libs/libsharpyuv-95d8a097.so.0.1.2": 5320647379976541240, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arithmetic.pyi": 467927803068643024, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate_regression.py": 17425202198134409689, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE": 14316979437290727897, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi": 11733449165276720901, + "venv/lib/python3.13/site-packages/pandas/core/groupby/grouper.py": 18110568057754450953, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_at_time.py": 15352346149584081864, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_arithmetic.py": 11620920548943067949, + "venv/lib/python3.13/site-packages/PIL/_version.py": 3025206805667405876, + "venv/lib/python3.13/site-packages/cffi/vengine_gen.py": 6582900613549620556, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_openssl.py": 10446441599800965961, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py": 8079219938116542284, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_utils.py": 11574890848475750509, + "venv/lib/python3.13/site-packages/pygments/lexers/q.py": 15426466074881683794, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/common.py": 16314033415206173235, + "venv/lib/python3.13/site-packages/keyring/backends/macOS/__init__.py": 1010937986753403630, + "venv/lib/python3.13/site-packages/pygments/lexers/slash.py": 8320676560518108343, + "backend/src/scripts/test_dataset_dashboard_relations.py": 11883199369340933897, + "backend/src/services/git/_branch.py": 4560456889410483402, + "frontend/src/lib/components/translate/__tests__/test_correction_cell.svelte.js": 2314051239468628554, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/base.py": 17992335652981439676, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/base.py": 11386927749822539057, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/parameters.py": 12219404446503940066, + "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.pyi": 2667658052734929089, + "frontend/src/routes/settings/StorageSettings.svelte": 1953157077500445570, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/abstract.py": 14216912708889351810, + "frontend/build/_app/immutable/chunks/B7C5taL7.js": 3263577474657580028, + "venv/lib/python3.13/site-packages/pygments/lexers/hdl.py": 6772823608124143123, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_factorize.py": 861897342553280506, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pandas/io/json/_table_schema.py": 3103776773020058805, + "venv/lib/python3.13/site-packages/pandas/io/__init__.py": 9767690163638898709, + "venv/lib/python3.13/site-packages/numpy/_core/__init__.pyi": 2783897020308040960, + "venv/lib/python3.13/site-packages/pandas/tests/internals/test_api.py": 11217428888457119601, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_is_homogeneous_dtype.py": 15378147393056707851, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/jws_eddsa.py": 833927568269372333, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_old_ma.py": 18116460138221458026, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_app.py": 4329794049222609894, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/nested_schemas.py": 4114645644496880787, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/query.py": 3867868366067025348, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/engine.py": 2652248727360250985, + "venv/lib/python3.13/site-packages/pyasn1/type/char.py": 16518487114777185541, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/__init__.py": 13584649922093198724, + "venv/lib/python3.13/site-packages/pygments/lexers/_usd_builtins.py": 8671446144574174964, + "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.pyi": 5879290708972838025, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_user_array.py": 8711697474193296376, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufuncs.py": 12732599294816239111, + "venv/lib/python3.13/site-packages/PIL/MpegImagePlugin.py": 7726254767528154514, + "venv/lib/python3.13/site-packages/_pytest/assertion/truncate.py": 14000392306994773741, + "venv/lib/python3.13/site-packages/numpy/f2py/__init__.pyi": 3566887042414273892, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh17797.f90": 17319074662077763768, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/styles/__init__.py": 18383248976818885498, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/chunks/uMCQOU-o.js": 9623204033582063323, + "venv/lib/python3.13/site-packages/secretstorage/__init__.py": 4535964275649588672, + "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pyi": 15790738442952696034, + "venv/lib/python3.13/site-packages/pillow.libs/libbrotlidec-b57ddf63.so.1.2.0": 10032590058372320813, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/resource_protector.py": 11539718751174980004, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.cpython-313-x86_64-linux-gnu.so": 9014806524727977333, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/warnings.py": 2552021607611112605, + "venv/lib/python3.13/site-packages/pandas/core/computation/scope.py": 16859504937881548797, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/eoo.py": 5126566925877730303, + "venv/lib/python3.13/site-packages/websockets/version.py": 5853118844880112885, + "venv/lib/python3.13/site-packages/pip/_internal/commands/debug.py": 13528633965821062950, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/util.py": 3591114320020964752, + "venv/lib/python3.13/site-packages/numpy/typing/__init__.py": 3608665862759745048, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/ImageSequence.py": 16459886231802763032, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/setup.py": 17086801293303202021, + "venv/lib/python3.13/site-packages/PIL/features.py": 3481835375516797487, + "venv/lib/python3.13/site-packages/httpcore/_models.py": 2501866419898326733, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadbconnector.py": 14865906347579451546, + "venv/lib/python3.13/site-packages/pygments/lexers/arrow.py": 6699009974224818979, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_str.py": 149688376805129532, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/wait.py": 6196757964348666082, + "venv/lib/python3.13/site-packages/dotenv/version.py": 13508433229287636267, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_numeric.py": 9383693732009547935, + "venv/lib/python3.13/site-packages/click/parser.py": 13988544851350599869, + "docker/backend.Dockerfile": 4384294014726084339, + "venv/lib/python3.13/site-packages/rsa/key.py": 4783269051050521475, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/simple.py": 11050636051019777317, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval_new.py": 3893421355544517336, + "venv/lib/python3.13/site-packages/PIL/QoiImagePlugin.py": 17663704273100331654, + "venv/lib/python3.13/site-packages/secretstorage/util.py": 1004887530903069622, + "venv/lib/python3.13/site-packages/pandas/tests/test_aggregation.py": 16863055892192070549, + "venv/lib/python3.13/site-packages/pandas/core/_numba/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/uvicorn/protocols/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/objects/util.py": 691018806932355307, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_expanding.py": 9047466276603454007, + "frontend/src/lib/stores/__tests__/test_taskDrawer.js": 13582869875796637016, + "backend/src/core/plugin_loader.py": 16320603855307510494, + "venv/lib/python3.13/site-packages/pandas/core/ops/common.py": 17314999825118928100, + "backend/src/plugins/mapper.py": 17959627965235532841, + "venv/lib/python3.13/site-packages/_pytest/unraisableexception.py": 4597178803320514675, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py": 8395157526634674143, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/sas.pyi": 873957906443703977, + "backend/src/core/utils/fileio.py": 8925306729946909050, + "venv/lib/python3.13/site-packages/numpy/ma/extras.py": 7559838309481824664, + "venv/lib/python3.13/site-packages/cffi/model.py": 13544803366359102016, + "venv/lib/python3.13/site-packages/passlib/tests/test_registry.py": 15377817946543064293, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/env.py": 1254612137164491329, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_byteswap.py": 5090287710338893350, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_reindex.py": 15680924058960901067, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/putmask.py": 10934101690788549526, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_delitem.py": 14336697139511118920, + "frontend/build/_app/immutable/chunks/DxOLV9lD.js": 7790909559343325514, + "backend/src/services/notifications/__init__.py": 13930898146447654299, + "frontend/src/routes/datasets/__tests__/DatasetList.test.js": 7832383286687203240, + "venv/lib/python3.13/site-packages/pyasn1/__init__.py": 8089201217593738032, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_drop.py": 11341278355685583133, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_chunksize.py": 7107619871245389835, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/__init__.py": 17454177076687312424, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/_pytest/capture.py": 17850967053989495422, + "venv/lib/python3.13/site-packages/pygments/lexers/functional.py": 15896849233007178031, + "backend/src/core/utils/matching.py": 12567367681677699487, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_collections.py": 14307204206312829238, + "backend/src/core/utils/superset_context_extractor/_filters.py": 281666313889333545, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.asm": 15349921092257597740, + "backend/src/services/profile_preference_service.py": 58722622434127499, + "venv/lib/python3.13/site-packages/numpy/rec/__init__.py": 7467092880535460658, + "frontend/src/lib/components/reports/__tests__/report_card.ux.test.js": 14899927226278257748, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi": 7801211423226951223, + "venv/lib/python3.13/site-packages/charset_normalizer/cd.py": 8687667152597941021, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_add_prefix_suffix.py": 4815518357936092237, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_codes.py": 13901854719435716195, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiarray.py": 5928288171180750841, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_empty.py": 6845813091876023610, + "backend/src/models/filter_state.py": 6470311179852241297, + "backend/src/schemas/health.py": 13764741380188041840, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/RECORD": 3283324710045856319, + "venv/lib/python3.13/site-packages/websockets/extensions/permessage_deflate.py": 12957105912018691390, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/RECORD": 10552906886624188222, + "venv/lib/python3.13/site-packages/keyring/backend_complete.bash": 16589214602970214174, + "venv/lib/python3.13/site-packages/numpy/_core/_struct_ufunc_tests.cpython-313-x86_64-linux-gnu.so": 13269324887178340397, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/fallback.py": 4260636031748548345, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_apply.py": 7511915990531229598, + "venv/lib/python3.13/site-packages/pip/_internal/locations/_distutils.py": 13559457590971821771, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_formats.py": 5259100336852479395, + "venv/lib/python3.13/site-packages/git/refs/remote.py": 4391983355222612205, + "venv/lib/python3.13/site-packages/fastapi/openapi/models.py": 1680354178147364813, + "venv/lib/python3.13/site-packages/smmap/test/lib.py": 2924931247676024085, + "venv/lib/python3.13/site-packages/pandas/core/sparse/api.py": 9094651265692218821, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/cacert.pem": 15624463015628939254, + "venv/lib/python3.13/site-packages/_pytest/scope.py": 7603155109542903644, + "venv/lib/python3.13/site-packages/yaml/_yaml.cpython-313-x86_64-linux-gnu.so": 16990140871649227895, + "venv/lib/python3.13/site-packages/PIL/DcxImagePlugin.py": 11767274218348117481, + "backend/src/plugins/translate/preview_review.py": 5584592578627646560, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/yaml.py": 17801117405950663611, + "venv/lib/python3.13/site-packages/pandas/tests/frame/conftest.py": 15090201792072045503, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_sh_gcc.h": 3574353221233465215, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/METADATA": 11419135077900073883, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/wrapper.py": 14599195010683170123, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_resolution.py": 9651416588266430520, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/dictionary.py": 9599439750713575741, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90": 10939657740734987454, + "venv/lib/python3.13/site-packages/pygments/styles/fruity.py": 7925019839136894457, + "venv/lib/python3.13/site-packages/pygments/lexers/markup.py": 10311057264960923433, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_interaction.py": 12216477658994324787, + "venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py": 4857114071347950833, + "venv/lib/python3.13/site-packages/cryptography/x509/ocsp.py": 17973800752927680404, + "venv/lib/python3.13/site-packages/pluggy/_tracing.py": 7276210024011809655, + "backend/src/core/task_manager/cleanup.py": 8316318318890394605, + "venv/lib/python3.13/site-packages/keyring/backends/kwallet.py": 3071915635647280308, + "venv/lib/python3.13/site-packages/authlib/oidc/core/__init__.py": 16029653645350087968, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/measure.py": 18327922742808984428, + "venv/lib/python3.13/site-packages/pydantic/schema.py": 83238111330132033, + "venv/lib/python3.13/site-packages/httpcore/_async/connection.py": 2155744160496556069, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/asyncio.py": 4200928269459447593, + "venv/lib/python3.13/site-packages/attrs/__init__.pyi": 14353885498883901855, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_typing.py": 10311989961588249147, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_print.py": 598821365691498702, + "backend/src/plugins/translate/__tests__/test_dictionary_correction.py": 17508858180216288123, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/context.py": 1041624619197012753, + "venv/lib/python3.13/site-packages/pygments/lexers/web.py": 11104721221615804497, + "backend/git_repos/remote/test-repo.git/objects/38/0395343915d386a8d58774cc6c6677205065e8": 5481382229802988191, + "venv/lib/python3.13/site-packages/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so": 2888939866336522308, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get_value.py": 389530025760539462, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_accumulations.py": 11428556645065711062, + "frontend/src/lib/auth/permissions.js": 12787489292887903923, + "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.cpython-313-x86_64-linux-gnu.so": 11074560904305737689, + "venv/lib/python3.13/site-packages/pandas/io/formats/style.py": 13235403689320479165, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/extensions.py": 217122171232375592, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/modules.pyi": 131293606732000587, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/scanner.py": 5640381644804445932, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_legacy.py": 12735901522735836481, + "venv/lib/python3.13/site-packages/anyio/lowlevel.py": 11919467357746648592, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/mod_derived_types.f90": 2556756676983488922, + "venv/bin/f2py": 11006035631504708368, + "frontend/src/lib/components/layout/__tests__/test_sidebar.svelte.js": 1424894894434906249, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/__init__.py": 8632038387100622009, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv": 13441294827017400897, + "venv/lib/python3.13/site-packages/pygments/lexers/ride.py": 14096748896451437594, + "venv/lib/python3.13/site-packages/_pytest/_code/code.py": 5248836309618416369, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_highlight.py": 7573043358244876807, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_table.tpl": 17198355067645888735, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/naming.py": 14503932124671438340, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_indexing.py": 81180636019259296, + "venv/lib/python3.13/site-packages/PIL/GbrImagePlugin.py": 7681313333602257802, + "venv/lib/python3.13/site-packages/anyio/abc/_tasks.py": 16839170934610571514, + "venv/lib/python3.13/site-packages/pandas/core/indexes/base.py": 496956059910401121, + "venv/lib/python3.13/site-packages/PIL/_webp.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/METADATA": 2053484635654179443, + "frontend/src/types/backup.ts": 1741234034896689348, + "venv/lib/python3.13/site-packages/numpy/_core/numeric.pyi": 17785360553418386488, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_concat.py": 10207975532842927134, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/__init__.py": 13749066369790839334, + "venv/lib/python3.13/site-packages/PIL/_util.py": 17116054813914373606, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/METADATA": 8128818962678047497, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayobject.h": 4345432890284821918, + "venv/lib/python3.13/site-packages/gitdb/pack.py": 7828244200815444166, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_timedelta64.py": 16821719402662529276, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_interval.py": 2911379732293827726, + "venv/lib/python3.13/site-packages/jsonschema/validators.py": 3832874295500213309, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/__init__.py": 4770885427721822507, + "venv/lib/python3.13/site-packages/pydantic_settings/version.py": 17263591404988984480, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/signals.py": 10390443713463805090, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_integrity.py": 12010564145080323987, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_function.py": 14142346897145169685, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_validators.py": 14178329676643700151, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_polynomial.pyi": 4266795948450921502, + "venv/lib/python3.13/site-packages/pandas/io/iceberg.py": 13137128885014736233, + "venv/lib/python3.13/site-packages/pycparser/_build_tables.py": 569728086093219621, + "venv/lib/python3.13/site-packages/pygments/styles/gh_dark.py": 7717523746712391809, + "venv/lib/python3.13/site-packages/httpx/_urlparse.py": 8270294590945652412, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/RECORD": 7320381591791379627, + "venv/lib/python3.13/site-packages/pygments/lexers/verification.py": 16645885125604874183, + "frontend/build/_app/immutable/nodes/15.5K1qnRVD.js": 12679623811228083751, + "venv/lib/python3.13/site-packages/more_itertools/__init__.pyi": 16479506520351014608, + "backend/src/__init__.py": 11250920420388310655, + "venv/lib/python3.13/site-packages/fastapi/__main__.py": 10755252341326986079, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_update.py": 12293424926920594944, + "venv/lib/python3.13/site-packages/git/diff.py": 6691274015605451565, + "venv/lib/python3.13/site-packages/pandas/io/formats/excel.py": 797619981868084011, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/reporters.py": 10760889726586439724, + "venv/lib/python3.13/site-packages/pyasn1/compat/__init__.py": 5902203086150636670, + "venv/lib/python3.13/site-packages/anyio/__init__.py": 12752386096259972231, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py": 17106903014205241774, + "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.pyi": 9911899303567570646, + "venv/lib/python3.13/site-packages/numpy/tests/test_configtool.py": 8208415015478205502, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_arithmetic.py": 13320788210970132239, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_api.py": 10514120091521589282, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_decimal.py": 3515468590005709183, + "venv/lib/python3.13/site-packages/yaml/representer.py": 10550136298978225013, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_function_base.pyi": 10972502518588022706, + "venv/lib/python3.13/site-packages/pip/_internal/self_outdated_check.py": 991029278889407558, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/__init__.py": 6327819603201859020, + "venv/lib/python3.13/site-packages/pygments/lexers/_qlik_builtins.py": 1728058904137960444, + "venv/lib/python3.13/site-packages/click/globals.py": 18353671282454331523, + "venv/lib/python3.13/site-packages/pycparser/__init__.py": 16499940957411260458, + "venv/lib/python3.13/site-packages/pandas/_libs/__init__.py": 17117112389651696580, + "venv/lib/python3.13/site-packages/rapidfuzz/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/__init__.py": 14493583771211110135, + "venv/lib/python3.13/site-packages/numpy/random/_pickle.py": 7774620933480975313, + "backend/tests/services/clean_release/test_publication_service.py": 17277940125978730159, + "venv/lib/python3.13/site-packages/PIL/_imagingmorph.cpython-313-x86_64-linux-gnu.so": 11171810899664471137, + "backend/git_repos/remote/test-repo.git/objects/aa/ea042a37c6f7bd010d91db93951328da7f01cc": 11936716919619613939, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_value_attrspec.py": 7741590618654448240, + "venv/lib/python3.13/site-packages/_pytest/deprecated.py": 5452408732344157294, + "venv/lib/python3.13/site-packages/numpy/random/_philox.pyi": 7503018432880404291, + "venv/lib/python3.13/site-packages/rapidfuzz/__init__.py": 12462153783886855740, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_getitem.py": 11882213323878588707, + "venv/lib/python3.13/site-packages/pydantic/v1/color.py": 14545509649623975912, + "backend/src/services/clean_release/__tests__/test_manifest_builder.py": 9320699981861675127, + "venv/lib/python3.13/site-packages/pip/_internal/network/session.py": 293771075394156394, + "venv/lib/python3.13/site-packages/numpy/_typing/_extended_precision.py": 4201820494689784136, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/implicit.py": 7379110378465568776, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_equivalence.py": 17843623343419137458, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py": 4383854709657749855, + "venv/lib/python3.13/site-packages/numpy/core/records.py": 12604652690721760437, + "venv/lib/python3.13/site-packages/pandas/errors/cow.py": 14381282473643980776, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_reductions.py": 11624188672428941494, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_function.py": 644452398244782315, + "frontend/build/_app/immutable/nodes/6.CYmSVZoE.js": 13913167887406589750, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/licenses/LICENSE": 12684353321716745791, + "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.pyi": 10077265709692546934, + "backend/src/services/clean_release/__tests__/test_compliance_orchestrator.py": 4990536554328205752, + "backend/git_repos/remote/test-repo.git/objects/6a/f2b28e314c04fb4e03476c12d6491213591512": 4526311953587849385, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_py_collections.py": 16825222625411635946, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_join.py": 17508073052750406350, + "frontend/src/lib/components/reports/__tests__/report_type_profiles.test.js": 498330292141991614, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_numba.py": 8250377774229977284, + "venv/lib/python3.13/site-packages/numpy/doc/ufuncs.py": 11706048944901534664, + "venv/lib/python3.13/site-packages/_pytest/skipping.py": 10561585274103209115, + "frontend/src/components/MissingMappingModal.svelte": 11264881226066623003, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/RECORD": 18314788057673509075, + "venv/lib/python3.13/site-packages/passlib/tests/test_pwd.py": 10089138951415591061, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_astype.py": 16700461036658228009, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_defmatrix.py": 2982572083770917411, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_other.py": 783701524491896337, + "venv/lib/python3.13/site-packages/smmap/test/test_buf.py": 6910367739329016619, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/bitwise_ops.py": 14350609278188982939, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2cmap.py": 5863341586534531594, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90": 6123192245816905092, + "venv/lib/python3.13/site-packages/pandas/_libs/ops_dispatch.pyi": 16176428602589420913, + "venv/lib/python3.13/site-packages/pandas/tests/window/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/segment.py": 2555584120510872966, + "venv/lib/python3.13/site-packages/yaml/emitter.py": 6036657460416912844, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_one_public_routine.f90": 7957683453180939605, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/test_list.py": 4538625980063375611, + "backend/src/plugins/translate/orchestrator_retry.py": 7628306124703690760, + "venv/lib/python3.13/site-packages/jeepney/tests/test_fds.py": 6257376331171761928, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/METADATA": 3448868793744358515, + "venv/lib/python3.13/site-packages/PIL/GribStubImagePlugin.py": 14954946414134984896, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_encoding.py": 6622474614967398246, + "frontend/src/routes/settings/settings-utils.js": 15047838139853696545, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/__init__.py": 293004106962245584, + "backend/alembic/versions/8dd0a93af539_drop_deprecated_source_language_column_.py": 3574830605384611294, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/properties.py": 5799883762127872919, + "venv/lib/python3.13/site-packages/pip/_internal/commands/__init__.py": 3795218871212151351, + "backend/git_repos/remote/test-repo.git/hooks/push-to-checkout.sample": 4825338927654285910, + "backend/src/core/task_manager/manager.py": 4491234835514372291, + "venv/lib/python3.13/site-packages/six.py": 948867418687428421, + "venv/lib/python3.13/site-packages/numpy/exceptions.py": 10981418339663118022, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/RECORD": 10052481303799123207, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/licenses/LICENSE": 8364608327598414179, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py": 63497920264089252, + "venv/lib/python3.13/site-packages/dotenv/__init__.py": 15464030923609356017, + "venv/lib/python3.13/site-packages/numpy/_core/function_base.pyi": 8343632640078378312, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/util.py": 6088868370298560146, + "venv/lib/python3.13/site-packages/pandas/core/internals/managers.py": 13547912653290063698, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_count.py": 16947194157984708529, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/encoder.py": 8912119133548489544, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/keywrap.py": 10424037418528425800, + "frontend/e2e/run-e2e.sh": 8106714116467101372, + "venv/lib/python3.13/site-packages/greenlet/greenlet_internal.hpp": 13173115501223013762, + "frontend/src/components/llm/ValidationReport.svelte": 11810571826279890996, + "backend/src/plugins/translate/preview_session_serializer.py": 8901687711861433007, + "backend/src/services/notifications/__tests__/test_notification_service.py": 5767450314963603475, + "backend/:memory:test_main": 15130871412783076140, + "backend/src/api/routes/assistant/__init__.py": 14959302162073618175, + "venv/lib/python3.13/site-packages/pillow.libs/libxcb-64009ff3.so.1.1.0": 7322566017497612912, + "venv/lib/python3.13/site-packages/jaraco/functools/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/scipy_sparse.py": 2091608752719976909, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_insert.py": 9195027887301180927, + "venv/lib/python3.13/site-packages/pydantic/_internal/_core_utils.py": 13248004771466837645, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_index_equal.py": 10617870815989304510, + "venv/lib/python3.13/site-packages/pandas/core/tools/numeric.py": 8510988912136285022, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parsing.py": 2228959015420278458, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dtype.py": 5336980126536664360, + "venv/lib/python3.13/site-packages/pytest_asyncio/plugin.py": 13414541723622354359, + "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet.py": 10727595500186011102, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/contains.py": 3098087827310439993, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_map.py": 10769974470610467636, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.py": 5564496700647900501, + "venv/lib/python3.13/site-packages/pip/__pip-runner__.py": 1138979712722199296, + "venv/lib/python3.13/site-packages/numpy/ma/testutils.pyi": 3899348061346041413, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_ujson.py": 12184194085993665945, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_where.py": 14167991754625133668, + "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.pyi": 9243829615414967057, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_nat.py": 7400568652984772972, + "venv/lib/python3.13/site-packages/pygments/plugin.py": 18006138132596504101, + "venv/lib/python3.13/site-packages/packaging/_musllinux.py": 2568338440457080365, + "venv/lib/python3.13/site-packages/pillow.libs/libtiff-295fd75c.so.6.2.0": 17866578820357536656, + "venv/lib/python3.13/site-packages/pandas/core/ops/array_ops.py": 10061020479033421596, + "frontend/src/components/Navbar.svelte": 6128753323363185057, + "venv/lib/python3.13/site-packages/authlib/oidc/core/errors.py": 18154419146257747681, + "venv/lib/python3.13/site-packages/attr/setters.pyi": 6670509359139243236, + "venv/lib/python3.13/site-packages/_pytest/threadexception.py": 10464996327276961035, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_common.py": 12064185052519470358, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategies.py": 15673926142454922581, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/passlib/handlers/windows.py": 8969739861295277439, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/path_registry.py": 8410829659513707067, + "venv/lib/python3.13/site-packages/_pytest/_io/terminalwriter.py": 16852767249156780980, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_series.py": 2980850649986213051, + "venv/lib/python3.13/site-packages/pygments/lexers/smv.py": 8253688483040957894, + "venv/lib/python3.13/site-packages/pygments/sphinxext.py": 2768161754523156130, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_pyf_src.py": 12351476647369971852, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.cpython-313-x86_64-linux-gnu.so": 16927263232848238698, + "venv/lib/python3.13/site-packages/pydantic/_internal/_repr.py": 1758478941817868344, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpcre-9513aab5.so.1.2.0": 12298861477332583668, + "venv/lib/python3.13/site-packages/click/_textwrap.py": 14586282603215052310, + "venv/lib/python3.13/site-packages/httpx/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/char.pyi": 1639810799219814643, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/sum_.py": 7062070517544958546, + "venv/lib/python3.13/site-packages/pygments/lexers/_asy_builtins.py": 1665617945818958781, + "backend/src/api/routes/environments.py": 1329328901500854319, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.py": 5260748170237305627, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_dtypes_basic.py": 10917162988625838981, + "venv/lib/python3.13/site-packages/PIL/_imagingmath.cpython-313-x86_64-linux-gnu.so": 77725273398858074, + "venv/lib/python3.13/site-packages/anyio/_core/_sockets.py": 10525237827959090532, + "venv/lib/python3.13/site-packages/passlib/utils/handlers.py": 10182859005870689026, + "venv/lib/python3.13/site-packages/pandas/plotting/__init__.py": 13230487326686617492, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/_gen_files.py": 6273314671315377131, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/quantile.py": 17341029201525362074, + "venv/lib/python3.13/site-packages/pygments/styles/solarized.py": 11231143047572616298, + "venv/lib/python3.13/site-packages/anyio/_core/_typedattr.py": 17584691045493791349, + "venv/lib/python3.13/site-packages/pygments/lexers/gsql.py": 15294109558028161389, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/RECORD": 10264342250058307301, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/RECORD": 8956798822782402202, + "venv/lib/python3.13/site-packages/PIL/ExifTags.py": 6869879826623916830, + "venv/lib/python3.13/site-packages/apscheduler/events.py": 10748346950729364899, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_reductions.py": 17810094294132819208, + "venv/lib/python3.13/site-packages/pygments/lexers/minecraft.py": 10133579583270214110, + "frontend/src/lib/api/translate/target-schema.js": 10665479411127476571, + "venv/lib/python3.13/site-packages/PIL/TiffTags.py": 8688883943071546469, + "venv/lib/python3.13/site-packages/pygments/lexers/igor.py": 6506221273085723501, + "frontend/src/routes/datasets/DatasetList.svelte": 3012753540033573252, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/liblber-1c9097e2.so.2.0.200": 2651879839738900594, + "backend/src/core/scheduler.py": 2472649939852521889, + "venv/lib/python3.13/site-packages/pip/_internal/pyproject.py": 6155748929233245415, + "venv/lib/python3.13/site-packages/dotenv/main.py": 7408889670575271484, + "venv/lib/python3.13/site-packages/apscheduler/executors/pool.py": 10344126569001032241, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/random.pyi": 9425735458050148191, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv": 12358602501260667480, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/json.py": 14755215397454910426, + "venv/lib/python3.13/site-packages/git/remote.py": 1694919255653049944, + "backend/src/models/__tests__/test_clean_release.py": 8187870494226758184, + "backend/src/plugins/translate/_batch_proc.py": 5830558923416766212, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_clearing_run_switches.py": 3020294789560975101, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_strings.py": 7379299916213794543, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_size.py": 16658280641516916790, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_autocorr.py": 1092316868398391792, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_threading.py": 6656552495241857519, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/__init__.py": 8434616194114282088, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_join.py": 5982692266872978444, + "venv/lib/python3.13/site-packages/PIL/GdImageFile.py": 16875784236394545058, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_character.py": 17168707712220699738, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_antijoin.py": 14435396877404907826, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_searchsorted.py": 11208047646304753715, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_datetime.py": 4179112383995346046, + "venv/lib/python3.13/site-packages/pygments/lexers/trafficscript.py": 776604244051744646, + "venv/lib/python3.13/site-packages/pygments/lexers/blueprint.py": 6370363226580199085, + "venv/lib/python3.13/site-packages/pygments/lexers/_mysql_builtins.py": 16087227298679432006, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_masked_matrix.py": 1444179242134203344, + "venv/lib/python3.13/site-packages/dateutil/easter.py": 14631233890122048084, + "venv/lib/python3.13/site-packages/pygments/lexers/__init__.py": 4627540245914849670, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/licenses/LICENSE": 3509878235770224233, + "backend/src/scripts/clean_release_cli.py": 5126837099976660772, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/chararray.pyi": 9683985931409244216, + "venv/lib/python3.13/site-packages/jeepney/io/blocking.py": 4699555965372200059, + "venv/lib/python3.13/site-packages/charset_normalizer/md__mypyc.cpython-313-x86_64-linux-gnu.so": 12629680116730190225, + "backend/src/scripts/seed_permissions.py": 17005340106913955508, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/WHEEL": 2357997949040430835, + "backend/src/core/migration/dry_run_orchestrator.py": 6268210017505159964, + "backend/src/api/routes/datasets.py": 5124620784591228136, + "backend/src/services/git/_remote_providers.py": 11131218419284688941, + "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector.py": 15458248567257759500, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_generic.py": 1098361087956787007, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_regression.py": 5652583095949741238, + "venv/lib/python3.13/site-packages/httpcore/_sync/socks_proxy.py": 4418971149260853240, + "backend/tests/core/test_git_service_gitea_pr.py": 6098719224379185148, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_cpu.h": 13799366908726531089, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/annotated_types/__init__.py": 7367790549779882749, + "venv/lib/python3.13/site-packages/numpy/ma/__init__.py": 214772578978182427, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/__init__.py": 9106887608906281686, + "frontend/build/_app/immutable/nodes/8.CRo3lzt1.js": 16824468691589595092, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/_orm_constructors.py": 4276726508722638048, + "venv/lib/python3.13/site-packages/pygments/styles/algol.py": 3040373291664740876, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/RECORD": 1556051687830913019, + "venv/lib/python3.13/site-packages/keyring/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/mypy.py": 10034028441785588819, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/gevent.py": 4811840397266785551, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/datasource.pyi": 80441145804744162, + "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.pyi": 2042169688753984918, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_character.py": 850554362222586199, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_pydatetime.py": 16228315407662560992, + "venv/lib/python3.13/site-packages/pandas/arrays/__init__.py": 10005095663840461954, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/common/pythoncapi-compat/COPYING": 3474104874623144155, + "frontend/src/routes/storage/+page.svelte": 5003283673039328108, + "venv/lib/python3.13/site-packages/sqlalchemy/util/preloaded.py": 3719702436309355562, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/strategies.py": 14007486769065345085, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/collections.py": 16114931075157411913, + "venv/lib/python3.13/site-packages/bcrypt/__init__.py": 11415155211917181362, + "venv/lib/python3.13/site-packages/pygments/lexers/mosel.py": 1877592344012288438, + "backend/src/plugins/translate/__tests__/test_dictionary_prompt_builder.py": 12854863376472707556, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_custom_dtypes.py": 12322100282959605055, + "backend/src/core/task_manager/task_logger.py": 12820629458199400734, + "venv/lib/python3.13/site-packages/pygments/lexers/apdlexer.py": 14222752852221009085, + "venv/lib/python3.13/site-packages/urllib3/filepost.py": 3814725067598042920, + "backend/conftest.py": 16521922883434363388, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_round.py": 1299086932398824299, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_indexing.py": 5063545640498065297, + "backend/src/services/dataset_review/orchestrator.py": 8780497744077644822, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.pyi": 4432290176776357346, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_period.py": 3419297908709788013, + "venv/lib/python3.13/site-packages/PIL/_imagingtk.cpython-313-x86_64-linux-gnu.so": 1708198947135304326, + "backend/tests/scripts/test_clean_release_cli.py": 13978106497618764226, + "venv/lib/python3.13/site-packages/numpy/random/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_latex.py": 2628895559914914693, + "venv/lib/python3.13/site-packages/pygments/lexers/_vbscript_builtins.py": 9882134558469491349, + "venv/lib/python3.13/site-packages/greenlet/PyModule.cpp": 3464405102256525511, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_insert.py": 17383986803728810587, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py": 9623344347519683527, + "venv/lib/python3.13/site-packages/pandas/tests/test_flags.py": 411845322592830527, + "backend/src/api/routes/__init__.py": 15832960904913829231, + "venv/lib/python3.13/site-packages/pygments/lexers/_julia_builtins.py": 8846111188795315103, + "venv/lib/python3.13/site-packages/httpcore/_sync/__init__.py": 7676937747094511752, + "venv/lib/python3.13/site-packages/numpy/_array_api_info.py": 9709101823494959741, + "venv/lib/python3.13/site-packages/pandas/io/excel/__init__.py": 6662687963241471393, + "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.pyi": 7171810177801103765, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator": 6616723520993329538, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_head_tail.py": 13047338070883375426, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/poolmanager.py": 5071697837617938064, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_observance.py": 18178414966262524534, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/index_tricks.pyi": 6035507586990711471, + "venv/lib/python3.13/site-packages/urllib3/util/response.py": 6106698559175827207, + "frontend/build/_app/immutable/chunks/Dsd-AOSr.js": 15996286082010225169, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_isocalendar.py": 5704842983090753914, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/jws.py": 7505219131537941130, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dot.py": 16876560325283070437, + "venv/lib/python3.13/site-packages/pygments/lexers/dax.py": 10868881057512002309, + "venv/lib/python3.13/site-packages/fastapi/_compat/__init__.py": 12380131786677943349, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-1.csv": 16078879475693341404, + "venv/lib/python3.13/site-packages/PIL/__init__.py": 10393984345353752724, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_dataframe.py": 14945138617962156057, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/filepost.py": 16698380375728063923, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/METADATA": 13428590545328703138, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd_module.py": 7122050193390298178, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/core/reshape/tile.py": 17137524194129840833, + "venv/lib/python3.13/site-packages/pandas/core/arrays/interval.py": 16281221279220043867, + "venv/lib/python3.13/site-packages/pygments/lexers/comal.py": 769727871242464458, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_astype.py": 4023134352880775277, + "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.py": 13574106461973044500, + "venv/lib/python3.13/site-packages/fastapi/temp_pydantic_v1_params.py": 9436036880518047720, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_dependency_group.py": 10505346210114745037, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_period.py": 10309599277099605395, + "backend/src/api/routes/dashboards/_detail_routes.py": 12522696473630508473, + "venv/lib/python3.13/site-packages/passlib/utils/decor.py": 21351391767102899, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/RECORD": 16740224557818847141, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/RECORD": 11541505360973709787, + "venv/lib/python3.13/site-packages/authlib/consts.py": 14226604841596736870, + "venv/lib/python3.13/site-packages/cffi/setuptools_ext.py": 30796527302561458, + "venv/lib/python3.13/site-packages/pip/_internal/locations/__init__.py": 8147012724727395488, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/RECORD": 2688648742701423549, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_astype.py": 7542068949396266883, + "venv/lib/python3.13/site-packages/pydantic/annotated_handlers.py": 10186120300163345360, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/providers.py": 7267821734584612032, + "venv/lib/python3.13/site-packages/_pytest/warning_types.py": 10695097290648045427, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv": 3026156288992132911, + "venv/lib/python3.13/site-packages/numpy/_core/_multiarray_tests.cpython-313-x86_64-linux-gnu.so": 442168371609469538, + "venv/lib/python3.13/site-packages/pandas/io/excel/_openpyxl.py": 6676451564208867775, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/terminal_theme.py": 13727399800263579809, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_openid.py": 5670082466989878756, + "venv/lib/python3.13/site-packages/pydantic/v1/annotated_types.py": 12925825196690299531, + "venv/lib/python3.13/site-packages/numpy/core/arrayprint.py": 9652368112174245943, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_federal.py": 16758212916399857971, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/compiler.py": 13924519162400330589, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pyodbc.py": 8175468565413744516, + "venv/lib/python3.13/site-packages/pygments/formatters/__init__.py": 8009871891954370829, + "frontend/src/routes/dashboards/[id]/components/DashboardHeader.svelte": 5572977872383619871, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timestamps.cpython-313-x86_64-linux-gnu.so": 13209491675968970365, + "venv/lib/python3.13/site-packages/fastapi/dependencies/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_builtin.py": 74545289993348593, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_indexing.py": 7181087459615188551, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/__init__.py": 3521833849634327520, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/__init__.py": 15130871412783076140, + "backend/src/services/clean_release/repositories/artifact_repository.py": 9040122866024534865, + "backend/src/services/security_badge_service.py": 6269749758059921511, + "venv/lib/python3.13/site-packages/packaging/metadata.py": 9168255069163141470, + "dist/docker/ss-tools.current.tar.xz": 12481237908945663094, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/umath/svml/LICENSE": 9584102918819171104, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py": 10843527833285941674, + "venv/lib/python3.13/site-packages/pydantic/v1/class_validators.py": 6471688474853407718, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/pwd.py": 14727089240749133060, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/conftest.py": 8406022190801970256, + "venv/lib/python3.13/site-packages/pygments/console.py": 3540660073442483692, + "venv/lib/python3.13/site-packages/packaging/requirements.py": 2896326326372719999, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/array.py": 12658302948819867972, + "venv/lib/python3.13/site-packages/pygments/lexers/boa.py": 14409319610243925864, + "frontend/src/lib/components/dataset-review/__tests__/source_intake_panel.ux.test.js": 13445861056598482363, + "backend/src/services/clean_release/approval_service.py": 15944489428318420008, + "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.pyi": 2186875333484796630, + "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/__init__.py": 1948986914452928735, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/operators.py": 5584982192355398255, + "venv/lib/python3.13/site-packages/pandas/_libs/algos.pyi": 22405377601029952, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/WHEEL": 16784970174376303810, + "backend/src/plugins/translate/orchestrator_run_completion.py": 5945172469962331273, + "venv/lib/python3.13/site-packages/pip/_internal/cli/req_command.py": 2887890799766730546, + "venv/lib/python3.13/site-packages/httpx/_transports/default.py": 8391302827983907910, + "venv/lib/python3.13/site-packages/pandas/tests/test_common.py": 8987965560487646705, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_year.py": 17441853503700184299, + "venv/lib/python3.13/site-packages/anyio/_core/_tasks.py": 14104828341875599130, + "venv/lib/python3.13/site-packages/pip/_internal/commands/cache.py": 1892313355296776523, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/subcomponents.py": 10365594934527289233, + "venv/lib/python3.13/site-packages/passlib/apache.py": 2357244937629445006, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_scalar.py": 2434773821902319678, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite_e.py": 8912795372542950449, + "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.py": 1644743742545329282, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_nditer.py": 8341339612899904236, + "venv/lib/python3.13/site-packages/pygments/lexers/berry.py": 4540479522141160472, + "frontend/src/lib/api/translate/jobs.js": 9613844538417291513, + "frontend/src/lib/components/dataset-review/__tests__/validation_findings_panel.ux.test.js": 8994492423600483794, + "backend/src/plugins/translate/__tests__/test_dictionary_import.py": 828852818135096215, + "venv/lib/python3.13/site-packages/pandas/api/typing/__init__.py": 6438268275857060114, + "backend/test.db": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/module_data_docstring.f90": 18245403117623015312, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex.py": 16348619731902304844, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/common.py": 9354442374897565498, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_append.py": 9644955836191900614, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8693/__init__.py": 11065844267208884531, + "venv/lib/python3.13/site-packages/numpy/random/_generator.cpython-313-x86_64-linux-gnu.so": 15625019745021657670, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_arithmetic.py": 13304014482504911016, + "venv/lib/python3.13/site-packages/pip/_internal/network/lazy_wheel.py": 12936988990566680659, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/result.py": 12262298207886620908, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.cpython-313-x86_64-linux-gnu.so": 6157288238855118017, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py": 6109201994963211857, + "venv/lib/python3.13/site-packages/PIL/__main__.py": 827665918723937817, + "venv/lib/python3.13/site-packages/charset_normalizer/cli/__main__.py": 2148876100501691980, + "venv/lib/python3.13/site-packages/pygments/styles/rainbow_dash.py": 12236746494379891602, + "venv/lib/python3.13/site-packages/PIL/ImageCms.py": 5610897002957128546, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_datetimelike.py": 17304541521108700317, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/METADATA": 10707390829735099042, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/errors.py": 14634768861119075506, + "backend/src/plugins/llm_analysis/__tests__/test_service.py": 9850768293526486431, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/LICENSE": 6774760218010069963, + "venv/lib/python3.13/site-packages/psycopg2/extras.py": 7510107741729866600, + "backend/git_repos/remote/test-repo.git/objects/f7/6ee984d9d47c3cd0b362fdf60a47162bbc202d": 5351983130474596028, + "venv/lib/python3.13/site-packages/numpy/random/bit_generator.cpython-313-x86_64-linux-gnu.so": 2574035311375507054, + "venv/lib/python3.13/site-packages/numpy/ma/mrecords.py": 687170905107114309, + "venv/lib/python3.13/site-packages/h11/py.typed": 12358286306858197118, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/provision.py": 13156893203444936309, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/cmac.py": 12011944740750051829, + "backend/git_repos/remote/test-repo.git/objects/17/66251d8cb2693136e09ea3def3e776559cb722": 1137762010493457272, + "venv/lib/python3.13/site-packages/numpy/_core/_simd.cpython-313-x86_64-linux-gnu.so": 12609666221355091416, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.pyi": 15420142722808118826, + "venv/lib/python3.13/site-packages/pip/_internal/utils/compat.py": 1841193561752758336, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/RECORD": 15865206372525596795, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_is_monotonic.py": 4626065848596214108, + "venv/lib/python3.13/site-packages/packaging/utils.py": 3469957615920103670, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_backend.py": 17793139799410518847, + "venv/lib/python3.13/site-packages/jsonschema/_format.py": 8987698648383779883, + "venv/lib/python3.13/site-packages/pandas/tests/test_sorting.py": 10751098438703044961, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/models.py": 17870758731501836303, + "venv/lib/python3.13/site-packages/packaging/tags.py": 1999137344425005827, + "frontend/src/lib/components/assistant/AssistantClarificationCard.svelte": 6722890639215637790, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/__init__.py": 16416360448593978041, + "venv/lib/python3.13/site-packages/pip/_internal/index/__init__.py": 14829074315307489628, + "venv/lib/python3.13/site-packages/greenlet/TGreenletGlobals.cpp": 17400526028982558937, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/conftest.py": 17897502508251413988, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/prompt.py": 9561640601516933380, + "venv/lib/python3.13/site-packages/numpy/tests/test__all__.py": 10689265249302359388, + "venv/lib/python3.13/site-packages/_pytest/cacheprovider.py": 5114545353355728201, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_exceptions.py": 15290185665769490169, + "venv/lib/python3.13/site-packages/pip/_internal/commands/check.py": 6937252393012787214, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/errors.py": 12935154705443176852, + "venv/lib/python3.13/site-packages/pydantic/experimental/missing_sentinel.py": 1637241331832367709, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo90.f90": 58572216018544419, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h": 5001035774408914877, + "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.py": 1809069379864985298, + "venv/lib/python3.13/site-packages/pandas/_libs/pandas_datetime.cpython-313-x86_64-linux-gnu.so": 15874094681262240628, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_indexing.py": 6039808271042864401, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_range.py": 3544406211185340973, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_libgroupby.py": 9985769511561272200, + "venv/lib/python3.13/site-packages/pandas/tests/util/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_time.py": 10463741033950978270, + "venv/lib/python3.13/site-packages/sqlalchemy/util/__init__.py": 15821192733097665649, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/string.tpl": 15796203549130590784, + "venv/lib/python3.13/site-packages/pycparser/_c_ast.cfg": 2649342580905806389, + "venv/lib/python3.13/site-packages/h11/_headers.py": 7592730288271984585, + "backend/src/plugins/translate/__tests__/__init__.py": 2490542523242946173, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_select.py": 7083040959665006634, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/RECORD": 18294169019244826301, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/errors.py": 4817746830102488448, + "venv/lib/python3.13/site-packages/numpy/_distributor_init.py": 1101690714183863290, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_join.py": 13115782559805895662, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_replace.py": 8165088653532047247, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ma.pyi": 8186102816080813799, + "venv/lib/python3.13/site-packages/pandas/core/arrays/string_arrow.py": 16997970607998635570, + "venv/lib/python3.13/site-packages/pydantic/env_settings.py": 18250976255197243083, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_between.py": 337429135216881486, + "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.h": 5980733638838895780, + "venv/lib/python3.13/site-packages/pydantic/dataclasses.py": 12384956801113860889, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/constants.pyi": 15633065380510755171, + "venv/lib/python3.13/site-packages/pandas/core/groupby/indexing.py": 18009437216172136227, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/bitwise_ops.pyi": 751490187478960891, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_insert.py": 6970975909565157982, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/mock.py": 14010776046610111182, + "venv/lib/python3.13/site-packages/git/refs/tag.py": 9979537867501757110, + "venv/lib/python3.13/site-packages/pygments/lexers/elm.py": 14683437310498104916, + "frontend/src/lib/components/reports/__tests__/report_detail.ux.test.js": 11878832350632571462, + "backend/alembic/versions/9f8e7d6c5b4a_add_is_multimodal_to_llm_providers.py": 11090205342799426943, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi": 13850254283540522444, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filter.py": 16846063190466267618, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/jwe.py": 10478268710546063196, + "backend/git_repos/remote/test-repo.git/hooks/pre-receive.sample": 6118492409684431911, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/numpyconfig.h": 13339221870252345205, + "venv/lib/python3.13/site-packages/pip/_internal/utils/urls.py": 8698341051522816167, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraypad.py": 4907193085512342162, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/core/algorithms.py": 487939626203097713, + "venv/lib/python3.13/site-packages/PIL/FitsImagePlugin.py": 618556384932056120, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/on.py": 2866195356090164296, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/aws.py": 1364297790170663941, + "venv/lib/python3.13/site-packages/ecdsa/test_numbertheory.py": 2117130219401053225, + "venv/lib/python3.13/site-packages/pillow.libs/libwebpmux-7f11e5ce.so.3.1.2": 13105940093474848953, + "frontend/build/_app/immutable/nodes/23.BFNPsk-Q.js": 10186472605920647275, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/array.py": 13040461386712513615, + "backend/src/models/assistant.py": 15004657265198809796, + "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.py": 151202984060101867, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_parse_dates.py": 7597935994945336408, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/RECORD": 17341460504914308184, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi": 16048852379621461316, + "backend/git_repos/remote/test-repo.git/objects/ee/59553241ef084b83d3351ba4c33caf2ed9a840": 11587106407031972706, + "venv/lib/python3.13/site-packages/pydantic/__init__.py": 11536052293866174672, + "venv/lib/python3.13/site-packages/pygments/formatters/pangomarkup.py": 17135620955205945255, + "venv/lib/python3.13/site-packages/PIL/ImageFilter.py": 10974179993355630141, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_first_valid_index.py": 15763400665851423183, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_matmul.py": 16169282225324014901, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/index.py": 2763962019423787504, + "venv/lib/python3.13/site-packages/anyio/_core/_synchronization.py": 7050001375718876608, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-1.csv": 2202360898679162333, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_tokenizer.py": 7994281991455916540, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npz": 12369168483236619421, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_multiindex.py": 13723677252432338937, + "venv/lib/python3.13/site-packages/pandas/io/clipboard/__init__.py": 3656451154829206939, + "venv/lib/python3.13/site-packages/pygments/lexers/func.py": 12257919753150082714, + "frontend/src/routes/profile/__tests__/fixtures/profile.fixtures.js": 2726190101012864209, + "venv/lib/python3.13/site-packages/gitdb/test/test_pack.py": 7518388297247535189, + "venv/lib/python3.13/site-packages/smmap/test/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_halfyear.py": 9376272342364384767, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/meson.build": 9642189398934130247, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_rank.py": 5398520257852104723, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_value_counts.py": 9352540710376306520, + "frontend/src/services/__tests__/gitService.test.js": 12845562082447336909, + "backend/src/models/dataset_review_pkg/_enums.py": 2243691494729792539, + "backend/src/plugins/translate/_token_budget.py": 1545056585783198863, + "backend/tests/test_smoke_plugins.py": 10704454611361370435, + "venv/lib/python3.13/site-packages/python_multipart/multipart.py": 5677735019292537174, + "venv/lib/python3.13/site-packages/pandas/_config/__init__.py": 3577026529387563519, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_errors.py": 3301889847545579393, + "venv/lib/python3.13/site-packages/pandas/io/json/_json.py": 1393095374713367445, + "venv/lib/python3.13/site-packages/pydantic/_internal/_validate_call.py": 4078236486720616395, + "venv/lib/python3.13/site-packages/pandas/core/nanops.py": 18291534943985310005, + "backend/alembic/versions/543d43d752b8_migrate_old_dictionary_entries_and_.py": 10988663686444687907, + "backend/git_repos/remote/test-repo.git/hooks/update.sample": 8204581436750313444, + "venv/lib/python3.13/site-packages/numpy/_array_api_info.pyi": 13283968924732680159, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/RECORD": 12575893084587070195, + "venv/lib/python3.13/site-packages/numpy/ma/LICENSE": 6723325434476453127, + "venv/lib/python3.13/site-packages/pip/_internal/network/utils.py": 13421242949994555055, + "venv/lib/python3.13/site-packages/numpy/_core/defchararray.pyi": 2277933368373498515, + "venv/lib/python3.13/site-packages/yaml/parser.py": 18021832376874455801, + "venv/lib/python3.13/site-packages/git/compat.py": 16843345645628515492, + "venv/lib/python3.13/site-packages/keyring/backends/macOS/api.py": 4502902558534812719, + "venv/lib/python3.13/site-packages/referencing/tests/test_jsonschema.py": 9815500901482570619, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_show_versions.py": 10577134135855180356, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.pyx": 5760108632332714287, + "frontend/static/favicon.png": 16740551781088792605, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nlargest_nsmallest.py": 11049656379959696695, + "frontend/src/lib/api/translate/datasources.js": 17202165717960970061, + "backend/src/services/clean_release/stages/internal_sources_only.py": 15680055221844544848, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_indexing.py": 3841182456456779012, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/conftest.py": 4124267277224879990, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_constructors.pyi": 164538008396001632, + "venv/lib/python3.13/site-packages/anyio/_core/_exceptions.py": 11969894261631227715, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/einsumfunc.pyi": 8902765738896588686, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timezones.cpython-313-x86_64-linux-gnu.so": 1137453907225619959, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_packbits.py": 7592956764084658562, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fft.pyi": 14454280827038327842, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_setops.py": 8622608042929141013, + "venv/lib/python3.13/site-packages/PIL/_imagingmath.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/websockets/protocol.py": 6401227903827084901, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_assign.py": 2647902466315482406, + "frontend/src/components/git/GitReleasePanel.svelte": 14875953299937841077, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dlpack.py": 7908102652282922952, + "venv/lib/python3.13/site-packages/pandas/io/json/__init__.py": 12333505155070172626, + "backend/tests/test_dashboards_api.py": 2278794209397518464, + "backend/alembic/README": 17625003422504608299, + "venv/lib/python3.13/site-packages/numpy/ma/extras.pyi": 15292036493781556342, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_structures.py": 16375837477294135345, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reduce.py": 14976712507854054776, + "frontend/src/components/TaskRunner.svelte": 18014857434320509117, + "venv/lib/python3.13/site-packages/pygments/lexers/vip.py": 11287963054551122004, + "frontend/src/routes/datasets/review/[id]/+page.svelte": 3248469759382215571, + "venv/lib/python3.13/site-packages/attrs/filters.py": 6844006230924162452, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/decoder.py": 17559787396729804535, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_formats.py": 2743326139283991615, + "frontend/src/types/dashboard.ts": 9718666955722367566, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_drop_duplicates.py": 12601598844977346213, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_infer_objects.py": 16868563755487479303, + "venv/lib/python3.13/site-packages/websockets/auth.py": 499195617702591757, + "venv/lib/python3.13/site-packages/_pytest/_py/error.py": 2257336434271433543, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv": 1443087417808027268, + "venv/lib/python3.13/site-packages/pandas/core/computation/eval.py": 3176226283265954028, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/size/foo.f90": 18067977329435720684, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_constructors.py": 2439700578107653984, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.pyi": 16372699564794732463, + "venv/lib/python3.13/site-packages/websockets/asyncio/async_timeout.py": 7267209982032642028, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_null_file.py": 6885565068723353414, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/strings.pyi": 15361498560917514616, + "venv/lib/python3.13/site-packages/pandas/_libs/window/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/RECORD": 17545477863793260029, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/plugin.py": 16042078006552521613, + "backend/tests/core/test_defensive_guards.py": 1048600814279591148, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_compression.py": 8577756801858495168, + "backend/src/models/__tests__/test_models.py": 1386812925656974657, + "backend/src/services/dataset_review/repositories/session_repository.py": 4058785536575367912, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_app.py": 14788764260762890368, + "venv/lib/python3.13/site-packages/numpy/lib/user_array.pyi": 1968484998382771986, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_constructors.py": 11065058462752831997, + "venv/lib/python3.13/site-packages/pygments/lexers/jvm.py": 897669925284011089, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/version.py": 14723293207188512766, + "venv/lib/python3.13/site-packages/pydantic/v1/validators.py": 1060954771151908883, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/METADATA": 3179724236887811680, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_read.py": 8825002468745406134, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/passlib/handlers/pbkdf2.py": 16686685453577026643, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/unix.py": 13808187640638677050, + "venv/lib/python3.13/site-packages/authlib/oauth2/base.py": 12948318231066662045, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_read_errors.py": 4559483361564472117, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/licenses/LICENSE": 1424673738228762254, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_copy.py": 3114918520437707410, + "venv/lib/python3.13/site-packages/_pytest/fixtures.py": 1442767529726551116, + "venv/lib/python3.13/site-packages/pandas/io/parsers/c_parser_wrapper.py": 5841064965672872661, + "venv/lib/python3.13/site-packages/pygments/lexers/dylan.py": 16246299896150112270, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_data.py": 2397937327057341, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_longtable.tpl": 12723621983797415444, + "frontend/src/lib/Counter.svelte": 4002153662176313030, + "frontend/src/lib/stores/__tests__/test_sidebar.js": 113566022614194798, + "venv/lib/python3.13/site-packages/pygments/lexers/c_cpp.py": 1211842877043321095, + "frontend/build/_app/immutable/nodes/5.8t8YAVGE.js": 8444804498487567107, + "frontend/build/_app/immutable/chunks/DHCQnn7S.js": 17943162662488133804, + "venv/lib/python3.13/site-packages/PIL/BlpImagePlugin.py": 7209218638257731375, + "backend/src/core/auth/__tests__/test_auth.py": 9487323693897023350, + "venv/lib/python3.13/site-packages/pygments/lexers/pascal.py": 5992422120590352714, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_repr.py": 16609300578827398344, + "backend/src/services/dataset_review/clarification_engine.py": 13640221555439415988, + "venv/lib/python3.13/site-packages/numpy/_core/strings.py": 3623885046208831106, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_logical.py": 6242457515917145500, + "venv/lib/python3.13/site-packages/requests/auth.py": 912521029864094489, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_frequencies.py": 14039315221824123200, + "venv/lib/python3.13/site-packages/attr/filters.pyi": 13942974755090135724, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ma.py": 15912582628112164509, + "venv/lib/python3.13/site-packages/attr/_version_info.py": 3850449653182103457, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.py": 893743087939984792, + "venv/lib/python3.13/site-packages/jose/backends/__init__.py": 16581763658239070112, + "venv/lib/python3.13/site-packages/pygments/lexers/fift.py": 7537570342576781911, + "frontend/build/_app/immutable/nodes/31.x6tK9wAf.js": 9694605018143438132, + "frontend/build/_app/immutable/nodes/29.Tmgk-PFy.js": 5159802046159303399, + "venv/lib/python3.13/site-packages/pygments/lexers/json5.py": 9736695186548899403, + "frontend/build/_app/immutable/nodes/4.Bx9tdohf.js": 11644400882065898247, + "frontend/build/_app/immutable/chunks/DTTkPSn7.js": 7541695882299051302, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/__init__.py": 16211693040174992594, + "venv/lib/python3.13/site-packages/numpy/f2py/__init__.py": 7470157159992827389, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/__init__.py": 6758781485387665020, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_compat.py": 11481259393140789881, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo.f": 5690596225005490325, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/strings.pyi": 402863478592154500, + "venv/lib/python3.13/site-packages/referencing/tests/test_retrieval.py": 10782087416909177703, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_hashtable.py": 2620207240930665390, + "venv/lib/python3.13/site-packages/pandas/core/strings/__init__.py": 13025387151657797130, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_case_when.py": 4133174129660834805, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.cpython-313-x86_64-linux-gnu.so": 13104135217735363438, + "venv/lib/python3.13/site-packages/dateutil/parser/__init__.py": 11377431154251655738, + "venv/lib/python3.13/site-packages/pygments/lexers/dalvik.py": 5549983892200382076, + "venv/lib/python3.13/site-packages/numpy/version.pyi": 5075382895829889457, + "venv/lib/python3.13/site-packages/websockets/__init__.py": 4916307256304054040, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_numeric.py": 9417128508433693658, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/replace.py": 1708865864686705833, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/__init__.py": 3673322722277252961, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_npfuncs.py": 8238385897366878558, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_multi.py": 4612816468258071810, + "backend/src/models/report.py": 9185954411073383239, + "venv/lib/python3.13/site-packages/ecdsa/errors.py": 11755424742691057760, + "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django_source.py": 15577951591316518967, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_file_buffer_url.py": 15377043158761455858, + "venv/lib/python3.13/site-packages/pydantic/_internal/_generate_schema.py": 7343380095251236503, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/decl_class.py": 6328411894571735935, + "backend/src/services/superset_lookup_service.py": 16520439978260397080, + "venv/lib/python3.13/site-packages/_yaml/__init__.py": 3395829783751571350, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi": 8666343427862784832, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/registration.py": 14639972512303032712, + "venv/lib/python3.13/site-packages/pandas/_libs/join.pyi": 369262334342439364, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/warnings_and_errors.pyi": 3151453262733619734, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/RECORD": 3288669175908898843, + "venv/lib/python3.13/site-packages/greenlet/tests/__init__.py": 1181423074160870921, + "venv/lib/python3.13/site-packages/websockets/__main__.py": 11948055520555854616, + "venv/lib/python3.13/site-packages/pandas/core/indexes/interval.py": 17965911911189276907, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_add_prefix_suffix.py": 8367793476246001244, + "venv/lib/python3.13/site-packages/pandas/tests/computation/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_constructors.py": 12118296571694122743, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_scalar_compat.py": 1306236983392218709, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_constructors.py": 11786151805350138436, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odswriter.py": 5134385709728943904, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/introspection.py": 14645217065508644154, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_rowcount.py": 6682800584070485197, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape_base.pyi": 10291383658131961346, + "backend/src/api/routes/git/_router.py": 8701683910668868827, + "backend/src/services/__tests__/test_health_service.py": 17832814613637967046, + "venv/lib/python3.13/site-packages/pycparser/ply/lex.py": 3393278208465358140, + "venv/lib/python3.13/site-packages/numpy/exceptions.pyi": 13942486291715303235, + "venv/lib/python3.13/site-packages/httpcore/_backends/anyio.py": 6167729964577005634, + "venv/lib/python3.13/site-packages/charset_normalizer/legacy.py": 1706599349563920562, + "backend/alembic/versions/e5f4d3c2b1a_add_policy_id_to_validation_results.py": 11168047633691803786, + "backend/git_repos/remote/test-repo.git/hooks/pre-rebase.sample": 15693225890270078290, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets2.py": 11100501798741918610, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_subplots.py": 4596089143375088346, + "venv/lib/python3.13/site-packages/httpx/_decoders.py": 14478643473006178492, + "venv/lib/python3.13/site-packages/pandas/core/arrays/masked.py": 13977195666947626206, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/serializer.py": 8708767945343850816, + "venv/lib/python3.13/site-packages/pygments/lexers/typst.py": 8883289726601667104, + "venv/lib/python3.13/site-packages/PIL/Jpeg2KImagePlugin.py": 16905402423248975204, + "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.py": 16856718240972376883, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/extension_types.py": 1856757457657310231, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/histograms.pyi": 2281259341486424755, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_string.py": 9224234539232195189, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_expanding.py": 12504275097476819918, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_compare.py": 3079569478684646491, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_coercion.py": 7261787308019145312, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_reflection.py": 10520778598547003532, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_mixins.py": 14293848457775268010, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/rec.pyi": 9140655366667421698, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_numpy.py": 9663734591667845940, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraysetops.py": 10588903945244480732, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling.py": 18221459425751198218, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_printing.py": 8859757563354666575, + "venv/lib/python3.13/site-packages/pip/_internal/operations/freeze.py": 3469845570614985559, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_cut.py": 7800833253841657380, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_pick.py": 15760492005471315814, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/instrumentation.py": 14882045449667214075, + "venv/lib/python3.13/site-packages/_pytest/main.py": 931018496411984909, + "venv/lib/python3.13/site-packages/pydantic/_internal/_forward_ref.py": 10623110912945011703, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_getitem.py": 18202683049446557047, + "venv/lib/python3.13/site-packages/git/repo/base.py": 13975465345838683533, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_diff.py": 2216748778018882333, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_categorical.py": 9923236395692943732, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_compat.py": 4677414058216516380, + "frontend/e2e/tests/settings.e2e.js": 14741334477359695649, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.pyi": 9854069702366900663, + "venv/lib/python3.13/site-packages/ecdsa/test_eddsa.py": 1785854649532849946, + "venv/lib/python3.13/site-packages/pip/_internal/cli/__init__.py": 11914508471759255927, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/jwk.py": 6458001384702613165, + "venv/lib/python3.13/site-packages/pandas/tests/libs/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/METADATA": 2624107638694809013, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_quarter.py": 6795026338946382805, + "venv/lib/python3.13/site-packages/anyio/abc/__init__.py": 11428476337116642278, + "venv/lib/python3.13/site-packages/cryptography/__init__.py": 641702726372647770, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayterator.pyi": 7439348655567232744, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/sphinxext.py": 2403717774564798878, + "venv/lib/python3.13/site-packages/pandas/core/interchange/column.py": 9498044216416177656, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/starlette/datastructures.py": 12097180838087229563, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/authorization_server.py": 6858244712625056421, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_linux.h": 4071314837793906998, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_csv.py": 571991535656576735, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_arithmetic.py": 17427754419626622853, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_mixed.py": 3476101699679108025, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/METADATA": 11439969143853665311, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_misc.py": 16393451200513733144, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/__init__.py": 1398617034174236358, + "venv/lib/python3.13/site-packages/gitdb/test/test_base.py": 16305779366785148795, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi": 16934250836612138541, + "venv/lib/python3.13/site-packages/_pytest/config/exceptions.py": 3199245296954654462, + "venv/lib/python3.13/site-packages/annotated_doc/__init__.py": 6834198874252778425, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/style.py": 15214295655795348821, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename_axis.py": 12432900682994622455, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_digest.py": 7988469818593853943, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/METADATA": 12295263493152296681, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine.py": 4446011286411407708, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/urllib3/_request_methods.py": 13671055114247516883, + "venv/lib/python3.13/site-packages/uvicorn/middleware/wsgi.py": 9179913252056394958, + "venv/lib/python3.13/site-packages/pygments/lexers/r.py": 14263133575134645005, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/signals.py": 13677199634497673845, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/background.py": 2105814165112049750, + "venv/lib/python3.13/site-packages/pandas/core/api.py": 3390809109543982410, + "venv/lib/python3.13/site-packages/authlib/oauth2/__init__.py": 13682931764896414722, + "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.pyi": 13945478633722616250, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/vectorized.cpython-313-x86_64-linux-gnu.so": 5441755022198996487, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/revocation.py": 16178499278312777474, + "run.sh": 4808871544409245302, + "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.py": 14034239842770171660, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayobject.py": 13337664596833150958, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/authorization_server.py": 2491654903543600678, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_export_format.py": 17862222951776199694, + "venv/lib/python3.13/site-packages/pandas/core/reshape/reshape.py": 5387892304726762127, + "venv/lib/python3.13/site-packages/numpy/ma/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_internals.py": 10472508540875131797, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_common.py": 9097104320321411408, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_period.py": 12593777226419608212, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_npy_units.py": 8966226962799105383, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numba.py": 18148155441554555618, + "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.py": 7658234162211356265, + "venv/lib/python3.13/site-packages/pandas/_libs/sparse.cpython-313-x86_64-linux-gnu.so": 2051484129454294720, + "venv/lib/python3.13/site-packages/pandas/_libs/json.cpython-313-x86_64-linux-gnu.so": 2436285663630821963, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_skew.py": 5276102682005383261, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/METADATA": 3814104793342833872, + "venv/lib/python3.13/site-packages/git/types.py": 13960696584646279283, + "venv/lib/python3.13/site-packages/pygments/styles/native.py": 4559566444883341527, + "venv/lib/python3.13/site-packages/pygments/lexers/fortran.py": 6859638690245583968, + "venv/lib/python3.13/site-packages/pygments/lexers/lilypond.py": 1088755646568511197, + "venv/lib/python3.13/site-packages/pandas/conftest.py": 747626550806435763, + "venv/lib/python3.13/site-packages/packaging/markers.py": 11602308203217831543, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/bazaar.py": 5630511062945201327, + "venv/lib/python3.13/site-packages/packaging/py.typed": 15130871412783076140, + "frontend/src/components/StartupEnvironmentWizard.svelte": 13169478544862386336, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv": 9287774220881887502, + "venv/lib/python3.13/site-packages/anyio/streams/text.py": 12507591237176920223, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_handlers.py": 556092537518149789, + "frontend/src/components/git/__tests__/git_manager.unfinished_merge.integration.test.js": 4508809242640248036, + "frontend/build/_app/immutable/chunks/DQJbqTlF.js": 8689087869754981677, + "venv/lib/python3.13/site-packages/httpcore/_async/http11.py": 7565741048880549265, + "frontend/build/_app/immutable/chunks/BhOprtEc.js": 5545318799712035703, + "backend/src/schemas/dataset_review_pkg/_dtos.py": 13301885458265748263, + "frontend/src/lib/components/dataset-review/ExecutionMappingReview.svelte": 6341989866442424314, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.pyi": 16164841755339571545, + "venv/lib/python3.13/site-packages/websockets/asyncio/server.py": 885415484558949506, + "venv/lib/python3.13/site-packages/httpcore/_async/socks_proxy.py": 9026788710898138090, + "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_config.py": 3636377988901907424, + "venv/lib/python3.13/site-packages/httpx/_auth.py": 1283189552342958900, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/errors.py": 12777931960088171310, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_from_dummies.py": 5670811108950300761, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_to_offset.py": 3929599794655343911, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/impl.py": 4687705587963980337, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/__init__.py": 8705044848308260480, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/base.py": 5294446834530589760, + "venv/lib/python3.13/site-packages/pandas/core/window/rolling.py": 6316477981414191778, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_indexing.py": 16264430536704066847, + "venv/lib/python3.13/site-packages/numpy/_core/multiarray.py": 4484782354376574355, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_cte.py": 9274103293201050794, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/__init__.py": 10456333337205488584, + "venv/lib/python3.13/site-packages/fastapi/security/open_id_connect_url.py": 3502444317759870079, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_serialization.py": 2011519400081029270, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.pyi": 13083543811193933305, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.pyi": 10360538024015064036, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/hooks.py": 9888227370911151341, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_info.py": 15151894356374015812, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/provision.py": 2676876852726658063, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_indexing.py": 14461606056665485421, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv": 8929553891827331780, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/string.f": 17328443345813567449, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_os.h": 7883047506449405400, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_indexing.py": 1947969642791009285, + "venv/lib/python3.13/site-packages/PIL/_deprecate.py": 15076725072094847812, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_replace.py": 18039668944453454689, + "venv/lib/python3.13/site-packages/PIL/ImageTransform.py": 7825940907094338808, + "venv/lib/python3.13/site-packages/smmap/util.py": 13276170835044840023, + "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.pyi": 15067467792538416274, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connectionpool.py": 10453724680327835821, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_parameter.py": 15173522343126004527, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_misc.py": 8706265665356094801, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/__init__.py": 12793458753561114666, + "venv/lib/python3.13/site-packages/websockets/speedups.c": 11800200877763464246, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/array.py": 3517673819082574078, + "venv/lib/python3.13/site-packages/PIL/WebPImagePlugin.py": 5378349556563611996, + "venv/lib/python3.13/site-packages/PIL/MicImagePlugin.py": 13540523615822507963, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/jwt.py": 9642615960197748105, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA": 7788873460115135563, + "venv/lib/python3.13/site-packages/_pytest/junitxml.py": 5871715626272366062, + "venv/lib/python3.13/site-packages/pygments/lexers/arturo.py": 4565524340706235725, + "venv/lib/python3.13/site-packages/pygments/lexers/floscript.py": 944042220740663491, + "venv/lib/python3.13/site-packages/packaging/specifiers.py": 2800449842990194437, + "frontend/src/routes/datasets/+page.svelte": 8425266984875514879, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90": 877982462186396830, + "venv/lib/python3.13/site-packages/pandas/io/parsers/python_parser.py": 7297059565749331767, + "backend/alembic.ini": 8897071018956157084, + "venv/lib/python3.13/site-packages/pip/_internal/utils/wheel.py": 450504439085405418, + "venv/lib/python3.13/site-packages/pip/_internal/cli/main_parser.py": 7942770969280622910, + "frontend/src/routes/+layout.ts": 8392799000856778740, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/ops.py": 13451323660386712332, + "backend/src/core/utils/__init__.py": 12454773556575864508, + "venv/lib/python3.13/site-packages/websockets/sync/router.py": 10335595955948355382, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_array.f90": 9711940829820746513, + "backend/src/models/git.py": 9387561498910534118, + "venv/lib/python3.13/site-packages/rsa/pkcs1_v2.py": 3533398238491175229, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_constructors.py": 6515602441449955627, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.py": 15511055314565873928, + "venv/lib/python3.13/site-packages/fastapi/openapi/utils.py": 9058442333718187759, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/_internal.pyi": 6840742333427164920, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/dtypes.py": 9839461501970023861, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.py": 4265012785873472600, + "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.cpython-313-x86_64-linux-gnu.so": 3478629877770507853, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.pyi": 13110894861187422750, + "venv/lib/python3.13/site-packages/certifi/__main__.py": 13417658012431779061, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/np_datetime.cpython-313-x86_64-linux-gnu.so": 7840846965295537844, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/errors.py": 6538052228921426956, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_regression.py": 9375525053479844400, + "venv/lib/python3.13/site-packages/pygments/lexers/sql.py": 15566262873151658034, + "venv/lib/python3.13/site-packages/pygments/lexers/parasail.py": 7758704230750989282, + "frontend/src/services/storageService.js": 14408290095426695791, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authenticate_client.py": 16886645731942472285, + "frontend/build/_app/immutable/nodes/38.CCZE7-Jg.js": 2655747731178665434, + "venv/lib/python3.13/site-packages/rsa/pem.py": 3118524021576082054, + "venv/lib/python3.13/site-packages/pandas/_libs/testing.pyi": 16691791330088523786, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/models.py": 5656065513234782067, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/RECORD": 16874983218652404911, + "frontend/src/routes/storage/backups/+page.svelte": 3437582895363203695, + "venv/lib/python3.13/site-packages/numpy/_core/__init__.py": 14951958843029076911, + "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/trace.zip": 14597002665264983691, + "backend/src/api/routes/assistant/_llm_planner.py": 444517242115816139, + "backend/src/plugins/translate/orchestrator_sql.py": 15420456250044832567, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_subclassing.py": 17318983445227658412, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77fixedform.f95": 10898637805043867370, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/__init__.py": 15130871412783076140, + "frontend/src/routes/tools/storage/+page.svelte": 2651964385884112547, + "venv/lib/python3.13/site-packages/dotenv/ipython.py": 15904966766060247908, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_astype.py": 11386658862732393123, + "backend/src/services/git/_status.py": 11400014053359523156, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resample_api.py": 3278209206670699265, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/result.py": 8306497889916212025, + "venv/lib/python3.13/site-packages/pydantic/utils.py": 1533455264689378477, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_fsspec.py": 6936167344144998172, + "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.pyi": 9291444594181042963, + "venv/lib/python3.13/site-packages/pip/_internal/req/__init__.py": 12266077985828139928, + "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.c": 2519219289444051739, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/random.pyi": 1808392097712315455, + "venv/lib/python3.13/site-packages/pydantic/deprecated/config.py": 12280996227531856230, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/ccalendar.pyi": 15789956857032062129, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/INSTALLER": 17282701611721059870, + "backend/src/schemas/translate.py": 15939985987703420591, + "backend/src/plugins/translate/sql_generator.py": 900251269659959067, + "venv/lib/python3.13/site-packages/numpy/linalg/__init__.pyi": 18409133021422984774, + "venv/lib/python3.13/site-packages/websockets/legacy/server.py": 5390090919193784186, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_block_docstring.py": 18146459246837890489, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.cpython-313-x86_64-linux-gnu.so": 12654188486128938170, + "venv/lib/python3.13/site-packages/git/util.py": 7424113599506269603, + "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/timeout.py": 1807228452024740476, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rank.py": 5817408252050193538, + "backend/src/core/task_manager/__tests__/test_context.py": 4211690952139950648, + "backend/src/api/routes/__tests__/test_clean_release_api.py": 11565478953155085157, + "venv/lib/python3.13/site-packages/pydantic/validate_call_decorator.py": 11130572937843915026, + "venv/lib/python3.13/site-packages/PIL/_typing.py": 17407980360703360848, + "venv/lib/python3.13/site-packages/rapidfuzz/utils.pyi": 7400725037332728015, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/multiarray.py": 3224049574922696945, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE.PSF": 13208428090829817329, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_aarch64_gcc.h": 8140470539757491899, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv": 6233924374281534211, + "venv/lib/python3.13/site-packages/pandas/tests/test_optional_dependency.py": 7930709646653025355, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_select_dtypes.py": 3530442956913622572, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_multi_thread.py": 5660352470978621226, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/provision.py": 9472538482404392519, + "venv/lib/python3.13/site-packages/authlib/oidc/registration/__init__.py": 9448552677419908109, + "frontend/playwright.config.js": 1601415616693761429, + "backend/src/core/utils/superset_context_extractor/_pii.py": 16897386128094460655, + "venv/lib/python3.13/site-packages/pydantic/_internal/_generics.py": 16438159042939059717, + "backend/src/api/routes/git/_helpers.py": 3960455954241740267, + "venv/lib/python3.13/site-packages/pip/_internal/utils/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/v1/parse.py": 5875950480538559709, + "venv/lib/python3.13/site-packages/iniconfig/_version.py": 8497474654470220170, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_update_delete.py": 1317337950621091021, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf": 10893958728966010450, + "backend/src/services/clean_release/__tests__/test_policy_engine.py": 15331910119765064311, + "backend/src/services/dataset_review/repositories/__tests__/test_session_repository.py": 13584543719626464409, + "backend/src/plugins/translate/_llm_call.py": 13441764941895838344, + "backend/tests/test_models.py": 3998442321184404421, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/WHEEL": 18203500019759199992, + "venv/lib/python3.13/site-packages/pandas/core/internals/__init__.py": 1377108808392195313, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_asyncio.py": 2820168745710754136, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/requirements.py": 13215932786801020434, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/cookies.py": 4997226307650350876, + "venv/lib/python3.13/site-packages/numpy/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_periodindex.py": 13430003945574795792, + "venv/lib/python3.13/site-packages/pip/_internal/commands/configuration.py": 1608697090566485893, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_to_xarray.py": 15341013524814290960, + "venv/lib/python3.13/site-packages/pygments/lexers/_csound_builtins.py": 14530739818491398298, + "frontend/src/lib/api/translate/schedules.js": 8616345664085016472, + "venv/lib/python3.13/site-packages/httpx/__init__.py": 6383055693166097719, + "venv/lib/python3.13/site-packages/numpy/rec/__init__.pyi": 1782063765067823837, + "venv/lib/python3.13/site-packages/httpx/_urls.py": 4219389176352582046, + "venv/lib/python3.13/site-packages/numpy/lib/scimath.py": 7616377937400918724, + "venv/lib/python3.13/site-packages/pygments/lexers/cplint.py": 13990118342267278047, + "backend/src/services/notifications/providers.py": 12897444612423813747, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_repeat.py": 18394463352314692642, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/poly1305.py": 10854598965202354516, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/tests/test_context_deprecated.py": 7876919198015151018, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np126.pkl.gz": 9677994062701347206, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/intranges.py": 12536174834761591006, + "venv/lib/python3.13/site-packages/attr/converters.py": 5179615793507170642, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_abstract_interface.py": 17625870734108222276, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/abc.py": 6227782083136374888, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_xs.py": 1897144171324167738, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/markup.py": 5413800947725916538, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arraymethod.py": 14421188237635557797, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py": 4301355720042319835, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/printing.py": 8681519649669408795, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_ops.py": 3875181889032080505, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_inf.py": 8659210689723088321, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata.py": 2021612995853910808, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/resolver.py": 2492962412506082234, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_ctors.py": 631744056514965940, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_sort.py": 11941630642630249576, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/base.py": 14734745827490220667, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_head_tail.py": 1906121476322841736, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_unix.h": 9608771997528633681, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/METADATA": 9458019064618635438, + "frontend/src/lib/api.js": 12258083425384759093, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/WHEEL": 5160964596297665692, + "venv/lib/python3.13/site-packages/jose/backends/native.py": 50023158618000658, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_elffile.py": 5728213398707817049, + "venv/lib/python3.13/site-packages/referencing/__init__.py": 10093824711214801917, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress.py": 5951745251426856398, + "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.py": 12355826783958402233, + "venv/lib/python3.13/site-packages/anyio/_core/_resources.py": 8463932838064724564, + "venv/lib/python3.13/site-packages/rsa/__init__.py": 14623742580410014505, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/numpy/_typing/_shape.py": 12667553664122376205, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_unittests.py": 18157503533859249155, + "venv/lib/python3.13/site-packages/pandas/_libs/ops.pyi": 1192312467209548763, + "venv/lib/python3.13/site-packages/apscheduler/executors/asyncio.py": 2230610508870117058, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/concat.py": 14737724508458849795, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/generic.py": 17755579497690180620, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_formats.py": 17821648708413143557, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_compat.py": 6032546839876195115, + "venv/lib/python3.13/site-packages/PIL/ImageShow.py": 11437096951764124817, + "venv/lib/python3.13/site-packages/pygments/styles/lilypond.py": 12486578704132023691, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core": 10616484054735611337, + "venv/lib/python3.13/site-packages/authlib/oauth2/client.py": 7237359250450222680, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/api/types/__init__.py": 3995030354191071797, + "venv/lib/python3.13/site-packages/gitdb/db/loose.py": 17467413653016810702, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/auth.py": 13542332344403032059, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi": 18143251582901996072, + "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.pyi": 6723628093359375823, + "venv/lib/python3.13/site-packages/pandas/core/tools/datetimes.py": 13313374952742129866, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/requests.py": 14847842002253212098, + "venv/lib/python3.13/site-packages/numpy/core/_utils.py": 14108063453670701289, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_hashing.py": 11119284926039008503, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/RECORD": 9964194961227523130, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_subclass.py": 11096337912872573314, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_select.py": 17823338162428379468, + "venv/lib/python3.13/site-packages/pandas/core/indexers/__init__.py": 1756397319068017890, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/identity.py": 326059526167697655, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/greenlet_slp_switch.hpp": 1694714764745718414, + "venv/lib/python3.13/site-packages/_pytest/_argcomplete.py": 3586514420674089892, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_julian_date.py": 850085757774959003, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE": 17675192170670564526, + "venv/lib/python3.13/site-packages/pygments/formatters/rtf.py": 5850574956253747036, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_string.py": 13234624995755549329, + "venv/lib/python3.13/site-packages/pygments/formatters/irc.py": 2133711525226123259, + "venv/lib/python3.13/site-packages/pygments/lexers/supercollider.py": 15306357945850389082, + "frontend/src/components/tools/DebugTool.svelte": 17267560034225794881, + "frontend/build/_app/immutable/nodes/37.-c22J1JB.js": 4811240094247488916, + "backend/src/scripts/seed_superset_load_test.py": 8023054867629574975, + "venv/lib/python3.13/site-packages/pygments/lexers/ruby.py": 6898093948224302592, + "venv/lib/python3.13/site-packages/anyio/streams/file.py": 15232345967545920863, + "venv/lib/python3.13/site-packages/starlette/middleware/cors.py": 11384893784314197864, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi": 10784666243744187693, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/base.py": 6348888156686452825, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/python3.npy": 4957143805477405905, + "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.py": 4037074830103951000, + "venv/lib/python3.13/site-packages/pandas/io/parsers/arrow_parser_wrapper.py": 11745253171984606573, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.pyi": 7410507092040239447, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_period.py": 15671388508498441412, + "venv/lib/python3.13/site-packages/pygments/styles/paraiso_dark.py": 3976779833379189837, + "venv/lib/python3.13/site-packages/pygments/lexers/ooc.py": 14540210212631538007, + "venv/lib/python3.13/site-packages/pygments/lexers/_sql_builtins.py": 5906655440517434734, + "frontend/src/lib/components/layout/Sidebar.svelte": 8588237337148619706, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_size.py": 12449835577388069407, + "frontend/src/lib/components/translate/TranslationRunProgress.svelte": 18041933754930100165, + "venv/lib/python3.13/site-packages/numpy/random/__init__.py": 11732100564412485633, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pxd": 9126772093305708921, + "venv/lib/python3.13/site-packages/itsdangerous/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/auth.py": 912521029864094489, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_common.py": 2223069451949206319, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_cpp.cpython-313-x86_64-linux-gnu.so": 14187094676876471848, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hiworld.f90": 6321872653169140461, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_ufunc.py": 3326502989311831856, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_contains.py": 5273759677032634868, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/ddl.py": 5006132143435653867, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/METADATA": 2604612822968175379, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_groupby_shift_diff.py": 1210657479716368827, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_groupby.py": 12709199432838648700, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/theorem.py": 15666523910367201285, + "venv/lib/python3.13/site-packages/cffi/recompiler.py": 17809252277700094304, + "frontend/src/lib/components/translate/ScheduleConfig.svelte": 14007615494976044075, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/unused_registry.py": 10153622516112471812, + "frontend/src/app.css": 3020720639702954139, + "venv/lib/python3.13/site-packages/certifi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connection.py": 8190661510572400096, + "venv/lib/python3.13/site-packages/numpy/f2py/rules.pyi": 1342380029484127983, + "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.py": 16854377502491291093, + "frontend/vite.config.js": 982595057268821071, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_deprecations.py": 6015734648984591027, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/npyio.pyi": 15811156298637131744, + "venv/lib/python3.13/site-packages/numpy/core/_dtype.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_converters.py": 8869440774594127419, + "venv/lib/python3.13/site-packages/fastapi/applications.py": 4975013401500183420, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_astype.py": 15384141282611151560, + "venv/lib/python3.13/site-packages/packaging/pylock.py": 15346942039643310253, + "backend/src/models/dataset_review_pkg/_finding_models.py": 7257895729340231285, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/status.py": 2214590120238144582, + "venv/lib/python3.13/site-packages/pygments/lexers/pawn.py": 18127303119414402594, + "venv/lib/python3.13/site-packages/greenlet/tests/test_generator.py": 14156412320760444199, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_localize.py": 4937713043686953098, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/__init__.py": 10920760520224795596, + "venv/lib/python3.13/site-packages/cryptography/x509/base.py": 9124948989225782039, + "backend/src/models/dashboard.py": 8479838979214366697, + "backend/src/core/superset_client/_databases.py": 7987972129012382620, + "venv/lib/python3.13/site-packages/referencing/typing.py": 8296636464219681747, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90": 5765181406654284736, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/anyio/to_process.py": 16627578499791368365, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/metadata.py": 1362166613223529108, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein_py.py": 1933257612725836484, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isin.py": 14387850595546682314, + "venv/lib/python3.13/site-packages/pandas/tests/apply/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/fromnumeric.py": 3792079757208879362, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_util.py": 16908393806993809474, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_datetime.py": 3499461736474530062, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_features.py": 955759654189150497, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_hist_method.py": 2109257663592928, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_upcast.py": 6496794053681247105, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/engines.py": 10876954465293959720, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/locators.py": 7638945613579396718, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/use_modules.f90": 3913612933340746297, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/baked.py": 6911138208603240867, + "venv/lib/python3.13/site-packages/pandas/tests/computation/test_compat.py": 11655000938111420543, + "venv/lib/python3.13/site-packages/PIL/FontFile.py": 112053841436523305, + "venv/lib/python3.13/site-packages/pip/_internal/locations/base.py": 7966628150470073365, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/__init__.py": 96341051676048910, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.pyi": 1826323011169529229, + "venv/lib/python3.13/site-packages/pygments/lexers/prql.py": 1159462562014166646, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/RECORD": 11788532857617688351, + "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.ux.test.js": 5439236328736424365, + "backend/src/api/routes/profile.py": 11866770263441371105, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/__init__.py": 15130871412783076140, + "backend/src/models/clean_release.py": 6080208142954589647, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.cpython-313-x86_64-linux-gnu.so": 14468234464367691795, + "backend/src/services/auth_service.py": 17642785219801916280, + "venv/lib/python3.13/site-packages/jose/__init__.py": 15575670403380555945, + "venv/lib/python3.13/site-packages/pandas/io/excel/_odfreader.py": 2760916559416783928, + "frontend/build/_app/immutable/nodes/3.DGglo2Zp.js": 15447712115682955218, + "venv/lib/python3.13/site-packages/pygments/lexers/webassembly.py": 17811970490091406867, + "venv/lib/python3.13/site-packages/pydantic/_internal/_git.py": 8760779092674434712, + "venv/lib/python3.13/site-packages/PIL/XbmImagePlugin.py": 12256750478268246137, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_recfunctions.py": 16014503284544747867, + "venv/lib/python3.13/site-packages/pygments/lexers/wowtoc.py": 17527844575999013592, + "frontend/src/lib/stores/translationRun.js": 10005138082029605368, + "frontend/src/services/gitService.js": 7044825476968825357, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_dispatcher.py": 2063037275809439611, + "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini": 16151597765994697599, + "venv/lib/python3.13/site-packages/numpy/ma/README.rst": 13203411621071845216, + "venv/lib/python3.13/site-packages/pandas/_libs/pandas_parser.cpython-313-x86_64-linux-gnu.so": 18056339336364727359, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_setops.py": 9991233160569430204, + "backend/src/services/clean_release/policy_resolution_service.py": 5075709738950902327, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufuncs.pyi": 14995898537484305307, + "venv/lib/python3.13/site-packages/pydantic/v1/dataclasses.py": 7833468513057242440, + "backend/src/core/auth/jwt.py": 15575717945774687118, + "venv/lib/python3.13/site-packages/numpy/_core/umath.pyi": 11775804030935134661, + "venv/lib/python3.13/site-packages/sqlalchemy/util/tool_support.py": 4926732415520779988, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/criterion.py": 2042509334195547606, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_constructors.py": 979131987837682435, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/METADATA": 3390257212824996989, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/mod.pyi": 10591120373577657317, + "venv/lib/python3.13/site-packages/yaml/error.py": 5626374410579058436, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/WHEEL": 5838667082726674838, + "backend/alembic/env.py": 17895850402041934744, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_shift.py": 8547819448301023303, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_formats.py": 2601044064677727807, + "venv/lib/python3.13/site-packages/pandas/io/formats/html.py": 11849941990375030601, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_py_util.py": 12836989066113400538, + "frontend/src/routes/reports/+page.svelte": 17831076184881844976, + "venv/lib/python3.13/site-packages/numpy/_typing/_nested_sequence.py": 7827259347937485408, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log2.csv": 13979868713429167140, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/licenses/LICENSE": 13322127602069971876, + "venv/lib/python3.13/site-packages/_pytest/_io/pprint.py": 11202117031437223527, + "frontend/src/lib/auth/__tests__/permissions.test.js": 13555349356008297952, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_format.py": 16150524965028369071, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_numpy_compat.py": 9112925138440787555, + "venv/lib/python3.13/site-packages/numpy/__init__.pxd": 13527602429695748857, + "venv/lib/python3.13/site-packages/pandas/compat/numpy/function.py": 18405870240333383757, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/build_tracker.py": 9389444024234384408, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_clip.py": 11111183698178681331, + "venv/lib/python3.13/site-packages/PIL/BufrStubImagePlugin.py": 5520941821175895889, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/nodes/21.DRJNNTAq.js": 11558587869195605031, + "frontend/build/favicon.svg": 6451919037497541980, + "backend/src/services/__tests__/test_resource_service.py": 13275183651826747527, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_arrow.py": 10068866425352207113, + "frontend/src/routes/settings/__tests__/settings_page.integration.test.js": 4898515600493251972, + "backend/src/services/resource_service.py": 1414472862621734532, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/RECORD": 5169907629260560698, + "venv/lib/python3.13/site-packages/pip/_internal/models/index.py": 2839270935469791607, + "venv/lib/python3.13/site-packages/pyasn1/type/useful.py": 10313387611927801339, + "venv/lib/python3.13/site-packages/websockets/sync/utils.py": 15135020989207191168, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame.py": 16757570551941104401, + "venv/lib/python3.13/site-packages/passlib/crypto/__init__.py": 16409196868630049365, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/__init__.py": 7062045842767697645, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_array.py": 16867692337986161626, + "venv/lib/python3.13/site-packages/passlib/totp.py": 14590474309565233318, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/mercurial.py": 335201628064585213, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_integer.py": 16102640589300356639, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_scalar_compat.py": 10068989979144965125, + "venv/lib/python3.13/site-packages/pandas/io/parsers/base_parser.py": 15148258424429418380, + "frontend/src/routes/datasets/__tests__/inline_edit.test.js": 17712409018171053453, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/__init__.py": 14268033439436797364, + "backend/src/api/routes/assistant/_dataset_review.py": 14508672919199309579, + "backend/tests/services/clean_release/test_report_audit_immutability.py": 4097909280121147581, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_datetimelike.py": 15246580603900811749, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/METADATA": 9041650844081036822, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_utils.py": 15197339054699289627, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/errors.py": 2147619440137604907, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/client.py": 17305914656270781911, + "venv/lib/python3.13/site-packages/pydantic_settings/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv": 1665171675551692225, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_explode.py": 18263694040596159591, + "venv/lib/python3.13/site-packages/pip/_internal/utils/appdirs.py": 539688259643447487, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_row.py": 918740441973901148, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/attributes.py": 5068814626384132900, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/_mapping.py": 13335227913146542481, + "venv/lib/python3.13/site-packages/yaml/nodes.py": 3463622922914760653, + "venv/lib/python3.13/site-packages/pandas/tests/test_nanops.py": 8709105600366913011, + "venv/lib/python3.13/site-packages/numpy/_core/getlimits.pyi": 15746478550640231553, + "venv/lib/python3.13/site-packages/rpds/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/uvicorn/loops/uvloop.py": 5385425357504191161, + "frontend/build/_app/immutable/nodes/25.BxJm_JTC.js": 6108215832009545519, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libgssapi_krb5-497db0c6.so.2.2": 6199424505696679197, + "venv/lib/python3.13/site-packages/pydantic/datetime_parse.py": 196119761382305574, + "backend/src/core/logger.py": 13412438111456825541, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_replace.py": 15992095120302643273, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_tz_localize.py": 14495969595744172955, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/padding.py": 7470483648602195268, + "venv/lib/python3.13/site-packages/git/index/base.py": 641556304637379636, + "backend/src/plugins/translate/service_target_schema.py": 15018144148162493344, + "venv/lib/python3.13/site-packages/jeepney/bindgen.py": 7094585345946943534, + "backend/src/plugins/translate/__tests__/test_target_schema.py": 3945452632405275208, + "venv/lib/python3.13/site-packages/yaml/resolver.py": 6669674521776449098, + "backend/src/api/routes/__tests__/test_profile_api.py": 1724401885939803766, + "backend/git_repos/remote/test-repo.git/objects/52/ec4a78c629329b8b572ec9d5205271c111baac": 18054296544295201561, + "venv/lib/python3.13/site-packages/pygments/lexers/bare.py": 18266858932333619451, + "venv/lib/python3.13/site-packages/numpy/core/shape_base.py": 17925759824894973734, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/linalg.pyi": 269481015135399748, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/api.py": 9829629144629841277, + "backend/src/services/clean_release/repositories/candidate_repository.py": 14784344453820731941, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_api.py": 5287018911951723034, + "backend/src/services/clean_release/stages/no_external_endpoints.py": 11899278509901673808, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timestamp.py": 10308799534491190078, + "backend/src/plugins/translate/orchestrator_lang_stats.py": 5713612003349083382, + "venv/lib/python3.13/site-packages/jose/exceptions.py": 8562012933958941039, + "venv/lib/python3.13/site-packages/pandas/core/roperator.py": 2587829042468916489, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/ecdsa/test_pyecdsa.py": 14542286382742044648, + "venv/lib/python3.13/site-packages/PIL/ImageEnhance.py": 3218405223202808764, + "venv/lib/python3.13/site-packages/ecdsa/__init__.py": 6237633580090653788, + "venv/lib/python3.13/site-packages/referencing/tests/test_core.py": 8280983300775878144, + "venv/lib/python3.13/site-packages/pandas/_libs/properties.pyi": 9268470215750269699, + "venv/lib/python3.13/site-packages/pygments/lexers/algebra.py": 9651893228421050246, + "frontend/src/routes/migration/+page.svelte": 7821836225621176583, + "venv/lib/python3.13/site-packages/greenlet/TThreadState.hpp": 15599148954148720463, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nunique.py": 8450574751331186943, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_index.py": 13517883160584591966, + "venv/lib/python3.13/site-packages/anyio/abc/_eventloop.py": 2023190981288767991, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/casting.py": 12226803454582253097, + "venv/lib/python3.13/site-packages/keyring/core.py": 2764269590123131634, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_constructors.py": 12628643543371952431, + "venv/lib/python3.13/site-packages/rapidfuzz/utils.py": 5682627611354455144, + "venv/lib/python3.13/site-packages/pandas/core/computation/check.py": 16048939716341154196, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_missing.py": 1963705411068820866, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth1_client.py": 3129955464287331242, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_fillna.py": 8802093795040069423, + "backend/src/plugins/translate/events.py": 8282921049842647968, + "venv/lib/python3.13/site-packages/pandas/testing.py": 18352975429944961593, + "venv/lib/python3.13/site-packages/numpy/testing/tests/test_utils.py": 5291132432383518704, + "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.py": 15558318749939680074, + "venv/lib/python3.13/site-packages/apscheduler/executors/twisted.py": 2695602672085615762, + "venv/lib/python3.13/site-packages/pandas/core/computation/align.py": 13027916530558901817, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_series.py": 10922287546912569276, + "frontend/src/routes/dashboards/[id]/components/DashboardTaskHistory.svelte": 8800115118935646769, + "venv/lib/python3.13/site-packages/ecdsa/test_ellipticcurve.py": 11125783981574901613, + "frontend/build/_app/immutable/chunks/ikwS1dR6.js": 3267599179274813039, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/METADATA": 15970460108484113417, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_algorithms.py": 15219408648894515493, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_version.py": 15336513445621042105, + "venv/lib/python3.13/site-packages/greenlet/tests/leakcheck.py": 10179165748538820557, + "venv/lib/python3.13/site-packages/pydantic/_internal/_core_metadata.py": 5704137311404303574, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npy": 17303060773267383537, + "venv/lib/python3.13/site-packages/pandas/core/ops/missing.py": 9493665944764255854, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/missing.py": 13332302791063948992, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_csv.py": 10737444103906389448, + "venv/lib/python3.13/site-packages/urllib3/util/url.py": 15992369651965016538, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reorder_levels.py": 10996225584998355824, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/resolver.py": 9931394693284776391, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/licenses/LICENSE": 16147999986886816451, + "venv/lib/python3.13/site-packages/pillow.libs/libjpeg-32d42e18.so.62.4.0": 11717944412021329207, + "venv/lib/python3.13/site-packages/authlib/oidc/core/userinfo.py": 17201158389976619872, + "venv/lib/python3.13/site-packages/pip/_internal/utils/setuptools_build.py": 13594639612360346306, + "venv/lib/python3.13/site-packages/_pytest/_io/wcwidth.py": 13515196388826152383, + "venv/lib/python3.13/site-packages/psycopg2/_json.py": 9729420372294281405, + "venv/lib/python3.13/site-packages/numpy/tests/test_matlib.py": 14395481530627870882, + "venv/lib/python3.13/site-packages/numpy/_distributor_init.pyi": 1308368231471324581, + "venv/lib/python3.13/site-packages/gitdb/test/test_stream.py": 18159319442241857857, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation": 5398883285871046811, + "venv/lib/python3.13/site-packages/pandas/_libs/arrays.cpython-313-x86_64-linux-gnu.so": 8634234308863090562, + "venv/lib/python3.13/site-packages/ecdsa/test_ecdsa.py": 17595025859105321562, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/groupby.py": 14661033005768429774, + "venv/lib/python3.13/site-packages/pandas/core/arrays/base.py": 664515424699746697, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_numpy_array_equal.py": 2089426719574307767, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timezones.py": 1962830142478494009, + "venv/lib/python3.13/site-packages/numpy/_core/memmap.py": 4093510602708416858, + "venv/lib/python3.13/site-packages/starlette/routing.py": 16063812008141874150, + "venv/lib/python3.13/site-packages/authlib/jose/__init__.py": 317573635113539563, + "venv/lib/python3.13/site-packages/keyring/util/__init__.py": 9635016046220094473, + "venv/lib/python3.13/site-packages/pip/_internal/cli/autocompletion.py": 7651919329635563739, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/__init__.py": 15735839022111230173, + "venv/lib/python3.13/site-packages/pandas/tseries/holiday.py": 1134358927599488799, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_repeat.py": 16971624301893342868, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/orm.py": 7554417559838785150, + "venv/lib/python3.13/site-packages/PIL/DdsImagePlugin.py": 10646832373516499548, + "venv/lib/python3.13/site-packages/PIL/ImageTk.py": 17063969714816564357, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/styles/abap.py": 11543320440974964547, + "backend/src/core/auth/config.py": 2961507628300548714, + "backend/src/services/git/_url.py": 15729080796864187707, + "backend/git_repos/remote/test-repo.git/hooks/post-update.sample": 4288868784459664203, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_intervalindex.py": 5053113227747333759, + "venv/lib/python3.13/site-packages/PIL/_tkinter_finder.py": 14045496501810535432, + "backend/git_repos/remote/test-repo.git/hooks/commit-msg.sample": 13435789416588783681, + "frontend/src/lib/components/assistant/__tests__/assistant_first_message.integration.test.js": 16494645867501045726, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.pyi": 13208953770241664384, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/WHEEL": 16223367184831500348, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_set_name.py": 9094608008538024609, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_parse_dates.py": 5344929031479212951, + "frontend/src/routes/datasets/review/ReviewWorkspaceRightRail.svelte": 13437011381072252917, + "frontend/src/components/backups/BackupList.svelte": 14417854869668960310, + "frontend/build/_app/immutable/chunks/B9IV00ct.js": 10407339696234238817, + "venv/lib/python3.13/site-packages/pygments/lexers/verifpal.py": 9190813166686923928, + "venv/lib/python3.13/site-packages/git/refs/reference.py": 2038789918710608481, + "backend/src/scripts/delete_running_tasks.py": 7776896567014157554, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/py.typed": 15130871412783076140, + "backend/src/api/routes/translate/_run_routes.py": 6617818713940695689, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py": 8539232219382152238, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_json_table_schema.py": 14454690938977069049, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_logical_ops.py": 4438104524064299182, + "venv/lib/python3.13/site-packages/cffi/verifier.py": 8473599757770867754, + "venv/lib/python3.13/site-packages/numpy/random/mtrand.pyi": 17144590106028661128, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dtypes.py": 7550022036887594386, + "venv/lib/python3.13/site-packages/pandas/tests/base/common.py": 13335865314907577354, + "venv/lib/python3.13/site-packages/PIL/_avif.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/passlib/tests/tox_support.py": 9200774792427691602, + "venv/lib/python3.13/site-packages/jeepney/io/threading.py": 525625939662612746, + "venv/lib/python3.13/site-packages/authlib/oidc/core/claims.py": 2035724920423374302, + "venv/lib/python3.13/site-packages/keyring/completion.py": 1027436016070040568, + "venv/lib/python3.13/site-packages/numpy/_core/numeric.py": 12261531924304979741, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_data_list.py": 1131520422778420758, + "venv/lib/python3.13/site-packages/anyio/functools.py": 4300781896135050327, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_api.py": 1910541672533352625, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/__init__.py": 4390908730288159455, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_partial.py": 15129217814262096441, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_concatenate_chunks.py": 9693420220003544490, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssltransport.py": 8148652555908329980, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/core.py": 2199607970842512780, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/comparisons.pyi": 4158883009780474220, + "venv/lib/python3.13/site-packages/keyring/backends/null.py": 12740996416911604870, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_nonunique_indexes.py": 15468078561381939405, + "venv/lib/python3.13/site-packages/urllib3/http2/__init__.py": 62108352209996836, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_function_base.py": 15241999259666702619, + "venv/lib/python3.13/site-packages/passlib/handlers/digests.py": 18158237109145814857, + "venv/lib/python3.13/site-packages/pandas/api/typing/aliases.py": 11194270368147942988, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcrypto-2e26a48f.so.3": 3658133521245392852, + "venv/lib/python3.13/site-packages/requests/structures.py": 2668010839316715865, + "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py": 13570990531070630950, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py": 14995426099932276090, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_base.py": 16710163879060522196, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_join.py": 1697622393195784944, + "venv/lib/python3.13/site-packages/git/config.py": 1724894144987553201, + "venv/lib/python3.13/site-packages/git/repo/__init__.py": 6173604284490891047, + "venv/lib/python3.13/site-packages/dateutil/tz/_factories.py": 7538654189286887518, + "venv/lib/python3.13/site-packages/pycparser/ast_transforms.py": 9032453625977464506, + "frontend/src/lib/api/__tests__/reports_api.test.js": 11820587361929895100, + "backend/git_repos/remote/test-repo.git/objects/d5/0298a42699f39e4601c0aa23eab07bcb0703c7": 1966124163198751340, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.pyi": 2101854548535776875, + "venv/lib/python3.13/site-packages/pip/__init__.py": 9449893869469432503, + "frontend/src/routes/tools/backups/+page.svelte": 6796050751535238723, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/assignOnlyModule.f90": 15967199601254912096, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/conftest.py": 2643915042664055969, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_timedeltaindex.py": 2359681317403710563, + "venv/bin/fastapi": 12400009726251862770, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/type_check.pyi": 1599910480066368464, + "venv/bin/numpy-config": 17104619511899110252, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/apscheduler/triggers/interval.py": 3964550092873794670, + "backend/src/api/routes/clean_release.py": 1984604735131504761, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py": 17927903035152872556, + "backend/src/services/notifications/service.py": 7032100258837946310, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numeric.py": 14451517189908259173, + "backend/src/api/routes/__tests__/conftest.py": 3768471623650776808, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/models.py": 11521700876708601977, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/parse.py": 2427019397934437210, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/resources.py": 11533706401259147051, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_localize.py": 18409231586451494605, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_editable.py": 12494407279914732338, + "venv/lib/python3.13/site-packages/cffi/cparser.py": 5246372077864988755, + "venv/lib/python3.13/site-packages/numpy/_core/_simd.pyi": 13553578040186939249, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_align.py": 10284128457194204574, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/token.py": 4161760290367932793, + "venv/lib/python3.13/site-packages/pip/_internal/models/format_control.py": 12916176880659590456, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv": 221209423454319618, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_compression.py": 3167245427092658522, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi": 9294219058621261971, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_django.py": 8455054295577203929, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.obj": 2884737706935637437, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/rec.pyi": 14615751247243515028, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html.tpl": 12550218314797699304, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/sync.py": 6189260178302531376, + "venv/lib/python3.13/site-packages/websockets/uri.py": 264376168984862773, + "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.pyi": 12566839271245057531, + "venv/lib/python3.13/site-packages/starlette/concurrency.py": 9835859079437525910, + "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.pyi": 12144531601504755948, + "venv/lib/python3.13/site-packages/anyio/abc/_testing.py": 16484863782452886547, + "venv/lib/python3.13/site-packages/_pytest/pastebin.py": 13946273207624603063, + "venv/lib/python3.13/site-packages/passlib/handlers/scrypt.py": 10089372287597257402, + "venv/lib/python3.13/site-packages/click/utils.py": 13475604420010022458, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f90continuation.f90": 17056591497459381871, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_errstate.py": 10788459171326750780, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_values.py": 8372572954663628844, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_legend.py": 13094583566764796297, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_constructors.py": 9767900500541600486, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/RECORD": 2024211292009381421, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/METADATA": 13776251749114562660, + "venv/lib/python3.13/site-packages/websockets/legacy/http.py": 16266924390281399720, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/information_schema.py": 8551227132710897346, + "frontend/src/routes/datasets/review/useReviewSession.js": 2378011913105385059, + "frontend/build/_app/immutable/chunks/r67qOZsb.js": 10662762306385093799, + "venv/lib/python3.13/site-packages/attr/exceptions.pyi": 12323493441583681402, + "backend/src/services/clean_release/compliance_execution_service.py": 3379474749353250488, + "backend/src/services/git/_base.py": 3671238045679556094, + "backend/src/plugins/translate/_lang_detect.py": 2125979777533490081, + "venv/lib/python3.13/site-packages/pygments/lexers/agile.py": 5686162551416231457, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_reductions.py": 2816859231048302619, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo77.f": 16156304612888138777, + "venv/lib/python3.13/site-packages/pydantic_core/py.typed": 15130871412783076140, + "backend/src/plugins/translate/dictionary.py": 2903767700173238799, + "venv/lib/python3.13/site-packages/pydantic/_internal/_known_annotated_metadata.py": 9308620143218174987, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop_duplicates.py": 2397396876872403048, + "backend/src/plugins/translate/preview_executor.py": 7636554040403814604, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_3kcompat.h": 5377305123299457337, + "venv/lib/python3.13/site-packages/passlib/win32.py": 5311393450489898748, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_set_value.py": 17480833128128893268, + "venv/lib/python3.13/site-packages/pip/_internal/wheel_builder.py": 3893922370396791826, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_string.py": 11422235699126032386, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py": 1359143503575245224, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/WHEEL": 7127684561765977531, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/__init__.py": 9820770319106921495, + "backend/src/services/clean_release/repositories/policy_repository.py": 10990781278715170404, + "venv/lib/python3.13/site-packages/pandas/util/_test_decorators.py": 17930801441803090445, + "venv/lib/python3.13/site-packages/pydantic/_internal/_serializers.py": 12077180322353709930, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/version.py": 6401479036177132374, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/type_check.pyi": 9177256991985898824, + "frontend/src/routes/settings/git/__tests__/git_settings_page.ux.test.js": 5334904955024018051, + "frontend/postcss.config.js": 5714274776976071678, + "backend/src/services/dataset_review/__init__.py": 15781509495698823404, + "venv/lib/python3.13/site-packages/attrs/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/attr/_cmp.py": 3297594878548179300, + "venv/lib/python3.13/site-packages/websockets/extensions/__init__.py": 13067201313921664210, + "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.pyi": 14069586330277925998, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_math.h": 16701045088211015518, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_kwarg.py": 10417724544218303733, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/stride_tricks.pyi": 8257977532799807847, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename.py": 4890779493250245903, + "venv/lib/python3.13/site-packages/pygments/lexers/whiley.py": 218468511185731869, + "frontend/src/routes/datasets/[id]/+page.svelte": 14911166036063098761, + "venv/lib/python3.13/site-packages/pandas/api/indexers/__init__.py": 17431573013142626187, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi": 3893434234020223151, + "venv/lib/python3.13/site-packages/apscheduler/executors/base.py": 1980520974511822101, + "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.pyi": 2744889206277418389, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/conftest.py": 12368472226536104037, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_xport.py": 14080914637071212225, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/validator.py": 14200019408839159476, + "frontend/src/lib/components/layout/__tests__/test_taskDrawer.svelte.js": 15288009749873977442, + "frontend/src/routes/translate/history/+page.svelte": 9504117584329454876, + "backend/src/core/superset_client/_dashboards_crud.py": 8511586546743986158, + "venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py": 10265081145401348863, + "venv/lib/python3.13/site-packages/pydantic/v1/datetime_parse.py": 10467114625921924095, + "venv/lib/python3.13/site-packages/_pytest/warnings.py": 8633394774569709013, + "venv/lib/python3.13/site-packages/pydantic/v1/config.py": 12050640083719340958, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_ranges.py": 2572903460327860111, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/XpmImagePlugin.py": 6644626557482464312, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/METADATA": 3643456577199395707, + "venv/lib/python3.13/site-packages/pygments/styles/vim.py": 2621036947954523349, + "venv/lib/python3.13/site-packages/starlette/templating.py": 9242638124487797988, + "venv/lib/python3.13/site-packages/pydantic/_internal/_fields.py": 2692892815545218335, + "frontend/src/lib/components/dataset-review/LaunchConfirmationPanel.svelte": 14399834101283315718, + "venv/lib/python3.13/site-packages/numpy/random/_common.pxd": 3402284125943848851, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_sorting.py": 8944017570338511677, + "backend/src/plugins/translate/orchestrator_runner.py": 1192466559618297192, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_map.py": 32086858815359344, + "venv/lib/python3.13/site-packages/pandas/tests/config/test_localization.py": 9524481848419616725, + "frontend/build/_app/immutable/chunks/BwgXlaGa.js": 255299601751677440, + "venv/lib/python3.13/site-packages/anyio/streams/buffered.py": 8916188172110578587, + "backend/alembic/versions/b1c2d3e4f5a6_add_source_hash_to_translation_records.py": 4775534557742900399, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd.py": 7577408467041941595, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.py": 14446508217220482719, + "venv/lib/python3.13/site-packages/numpy/random/_generator.pyi": 17167649524261942483, + "venv/lib/python3.13/site-packages/httpx/_config.py": 8800538050293498928, + "venv/lib/python3.13/site-packages/psycopg2/sql.py": 18041240927130590808, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py": 12264234876933578367, + "venv/lib/python3.13/site-packages/websockets/legacy/protocol.py": 762692033188392424, + "venv/lib/python3.13/site-packages/passlib/crypto/_md4.py": 379335134151814809, + "venv/lib/python3.13/site-packages/tzlocal/windows_tz.py": 11696765495002954868, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_timedelta.py": 12822713918114715561, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_series.py": 17126297747681689408, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/base.cpython-313-x86_64-linux-gnu.so": 8335798324308957127, + "venv/lib/python3.13/site-packages/urllib3/__init__.py": 1854778274753799815, + "venv/lib/python3.13/site-packages/pygments/lexers/crystal.py": 3579547906957125755, + "venv/lib/python3.13/site-packages/fastapi/security/oauth2.py": 1925394177931547776, + "venv/bin/dotenv": 953953349803507198, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/WHEEL": 7795541085444298627, + "venv/lib/python3.13/site-packages/websockets/extensions/base.py": 2457233337788783873, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/greenlet/tests/test_leaks.py": 1219835696230215605, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/test_json.py": 12422315190455428620, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_crosstab.py": 6631711416347033281, + "venv/lib/python3.13/site-packages/referencing/jsonschema.py": 14596871117484757502, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_searchsorted.py": 11161416745923343741, + "venv/lib/python3.13/site-packages/PIL/MspImagePlugin.py": 3034490726971829439, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/METADATA": 6557531107125553027, + "venv/lib/python3.13/site-packages/numpy/lib/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/styles/default.py": 13992125975366109635, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/base.py": 15872835330892203433, + "venv/lib/python3.13/site-packages/pygments/lexers/_postgres_builtins.py": 2383906454995727700, + "frontend/src/lib/stores/__tests__/mocks/state.js": 3616783395254238777, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate.py": 11205714006000849926, + "venv/lib/python3.13/site-packages/pygments/lexers/tablegen.py": 2917626373516779857, + "venv/lib/python3.13/site-packages/httpx/__version__.py": 9473642134297828811, + "frontend/src/components/TaskLogViewer.svelte": 11262767195652916566, + "frontend/build/_app/immutable/chunks/C5mDIBGp.js": 11190414399334557118, + "frontend/src/routes/+error.svelte": 9437886843842311915, + "backend/src/core/config_manager.py": 18161236261317111528, + "venv/lib/python3.13/site-packages/click/_winconsole.py": 8133229457213704188, + "venv/bin/httpx": 6651007446865716794, + "frontend/src/lib/toasts.js": 199299975383904134, + "backend/src/core/superset_client/_dashboards_list.py": 10999374002470143873, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_tzconversion.py": 7205566353454584259, + "backend/git_repos/remote/test-repo.git/refs/heads/preprod": 2288780285329550368, + "venv/lib/python3.13/site-packages/pip/_internal/cli/cmdoptions.py": 12107733000019393631, + "venv/lib/python3.13/site-packages/pygments/styles/zenburn.py": 1031869867933871309, + "frontend/src/routes/datasets/StatsBar.svelte": 12518099248600597437, + "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.cpp": 7360124705400993707, + "venv/lib/python3.13/site-packages/pygments/lexers/nimrod.py": 8457135214131458774, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.cpython-313-x86_64-linux-gnu.so": 18139875206371157315, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_macosx.h": 3653129798702716366, + "venv/lib/python3.13/site-packages/websockets/streams.py": 15786581670248099415, + "venv/lib/python3.13/site-packages/pygments/lexers/grammar_notation.py": 9009644754106884095, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/v1/__init__.py": 1642038155370734658, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_datetime.py": 11417836378782978454, + "venv/lib/python3.13/site-packages/pydantic/validators.py": 8292819706488319845, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_compare.py": 171535659467902751, + "venv/lib/python3.13/site-packages/multipart/exceptions.py": 8580522204565816132, + "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.py": 7352635707860427145, + "backend/src/scripts/init_auth_db.py": 1846761799125222512, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/groupby.py": 12749730954888633240, + "backend/src/plugins/git/__init__.py": 2144831474780401625, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_matmul.py": 9323220618335072725, + "venv/lib/python3.13/site-packages/numpy/__init__.py": 2331213407497901634, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_keys.py": 10813898277355150779, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/dependency.py": 7300594038182867460, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_transform.py": 6759417099641034692, + "venv/lib/python3.13/site-packages/pycparser/ply/yacc.py": 4218889705926129841, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE": 2345070715845618109, + "venv/lib/python3.13/site-packages/pygments/styles/perldoc.py": 4857683935715743356, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/totp.py": 11888568940387752607, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_fields.py": 16222559851336781264, + "venv/lib/python3.13/site-packages/numpy/f2py/rules.py": 9322914583460630877, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/events.py": 13473858896579666058, + "venv/lib/python3.13/site-packages/pygments/lexers/ptx.py": 4855144232064607995, + "venv/lib/python3.13/site-packages/authlib/common/errors.py": 16082974228565515177, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/__init__.py": 4337679908168515343, + "venv/lib/python3.13/site-packages/yaml/dumper.py": 11376022992370902766, + "venv/lib/python3.13/site-packages/pycparser/c_generator.py": 14922277346364091122, + "venv/lib/python3.13/site-packages/pyasn1/error.py": 11036037300994516747, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/RECORD": 9502524172853437600, + "venv/lib/python3.13/site-packages/ecdsa/test_sha3.py": 12459459298663975730, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py": 9559295461619813890, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/wheel.py": 828222664427570058, + "venv/lib/python3.13/site-packages/pydantic/error_wrappers.py": 11273827025986230629, + "venv/lib/python3.13/site-packages/pandas/tests/internals/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/events.py": 9329355486544822483, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/array.py": 13840510238256626632, + "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.py": 11393954913234866059, + "venv/lib/python3.13/site-packages/anyio/streams/stapled.py": 9733127303038397237, + "venv/lib/python3.13/site-packages/pytest_asyncio/__init__.py": 8162213292669110211, + "venv/lib/python3.13/site-packages/numpy/core/fromnumeric.py": 2136433423902202138, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/__init__.py": 12290228927283601067, + "venv/lib/python3.13/site-packages/fastapi/_compat/v2.py": 15078491685917047095, + "venv/lib/python3.13/site-packages/pydantic_settings/utils.py": 14396350455520958703, "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_pickle.py": 16196792378104396231, - "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine_first.py": 11425059090050867171, - "backend/src/api/routes/translate/_run_list_routes.py": 1259398917100338978, - "backend/src/services/clean_release/repositories/compliance_repository.py": 7402628017251283691, + "venv/lib/python3.13/site-packages/pygments/filters/__init__.py": 2992007913496948339, + "venv/lib/python3.13/site-packages/pygments/lexers/dotnet.py": 17970884907837213099, + "venv/lib/python3.13/site-packages/pygments/lexers/amdgpu.py": 17249439604111838979, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets.py": 4499538899492148499, + "frontend/src/lib/stores/__tests__/test_datasetReviewSession.js": 12620073136419991103, + "venv/lib/python3.13/site-packages/jaraco/functools/__init__.py": 15334412919279565528, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh26681.f90": 1515497186927052106, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.pyi": 11967691665766452312, + "venv/lib/python3.13/site-packages/click/decorators.py": 2920877667855377423, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/git.py": 17060377178521307324, + "venv/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so": 829323374625147265, + "frontend/src/components/git/GitWorkspacePanel.svelte": 15810952071932060330, + "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.pyi": 14181518821845356636, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_constructors.pyi": 4993066609272697419, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_dialect.py": 4700488504252803159, + "venv/lib/python3.13/site-packages/click/_utils.py": 16491408631876616271, + "venv/lib/python3.13/site-packages/pip/_internal/models/pylock.py": 16697828625021519459, + "backend/src/services/clean_release/compliance_orchestrator.py": 10585043190405940115, + "backend/src/services/clean_release/source_isolation.py": 18208654007489616188, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_real.py": 5283415082530228716, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_conversion.py": 7507083194555424923, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/RECORD": 3617343778671172258, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/queue.py": 7820997545569991670, + "venv/lib/python3.13/site-packages/pip/_internal/cache.py": 210214424535803946, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py": 13763154154862871596, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/bitgen.h": 12421210767114721499, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/rnc.py": 9747352274729854620, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/highway/LICENSE": 15636145745140922094, + "venv/lib/python3.13/site-packages/starlette/websockets.py": 13834731343216764204, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/compat.py": 17520043776344667309, + "venv/lib/python3.13/site-packages/jeepney/bus_messages.py": 5871341372541525842, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/__init__.py": 2345997696115514124, + "venv/lib/python3.13/site-packages/pygments/lexers/promql.py": 8929925488296216854, + "venv/lib/python3.13/site-packages/packaging/licenses/__init__.py": 15879493360260891293, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi": 3533739482029983817, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath.py": 13010939919217862164, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth1_session.py": 1911069558956893789, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/cx_oracle.py": 10093932131797570986, + "venv/lib/python3.13/site-packages/yaml/serializer.py": 1783761365703703558, + "venv/bin/Activate.ps1": 1196103427939049710, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply_relabeling.py": 3930092097678339743, + "frontend/src/lib/utils.js": 5436516952434475239, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_tree.py": 15789443159423302291, + "venv/lib/python3.13/site-packages/numpy/_core/tests/_locales.py": 18178500267053825979, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_dict.py": 4937173601709369119, + "backend/src/api/routes/__tests__/test_migration_routes.py": 2319142184353163171, + "backend/src/api/routes/health.py": 4494840518139445701, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/RECORD": 15194367076254806710, + "backend/tests/services/clean_release/test_compliance_task_integration.py": 682622548217611215, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi": 3254633032236269842, + "venv/lib/python3.13/site-packages/pygments/lexers/html.py": 17288963642862550116, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/util.py": 18279366777506483176, + "venv/lib/python3.13/site-packages/numpy/testing/__init__.pyi": 8126257788928282891, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arithmetic.pyi": 10265823318697442495, + "backend/git_repos/remote/test-repo.git/objects/4f/4e0958b3a42eff67a2b8cfd084d05c43e54716": 6040513978194442637, + "frontend/src/lib/stores/__tests__/taskDrawer.test.js": 12307450726550947042, + "venv/lib/python3.13/site-packages/websockets/legacy/framing.py": 12759022769700230409, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/objects/__init__.py": 2110615482320355676, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_envs.py": 5657151394155576509, + "venv/lib/python3.13/site-packages/pluggy/_version.py": 7195758686717994475, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/text.py": 6096215585499446070, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/LICENSE": 12688029424398428498, + "dist/docker/frontend.1.2.1.tar.xz": 5384558848012153878, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/_json.py": 6718137926109998531, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/json.py": 15373167408891671190, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi": 11455144434558323236, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/requirements.py": 11478648568700804705, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo90.f90": 2435648607844815947, + "venv/lib/python3.13/site-packages/jsonschema/tests/_suite.py": 6307666366417438489, + "venv/lib/python3.13/site-packages/passlib/handlers/sha2_crypt.py": 8171587560325812664, + "venv/lib/python3.13/site-packages/passlib/ext/django/__init__.py": 11713862539944289631, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_searchsorted.py": 12074107109575676897, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_sparse_accessor.py": 6774374030220202353, + "venv/lib/python3.13/site-packages/pygments/lexers/ncl.py": 14838368780033177943, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/__init__.py": 4761936067832638585, + "venv/lib/python3.13/site-packages/pygments/lexers/lisp.py": 11872331622183590758, + "venv/lib/python3.13/site-packages/_pytest/_py/path.py": 8464061867075119556, + "venv/lib/python3.13/site-packages/pygments/lexers/shell.py": 3842338968014057744, + "venv/lib/python3.13/site-packages/pip/_internal/utils/deprecation.py": 7435269308988385470, + "venv/lib/python3.13/site-packages/pandas/core/groupby/base.py": 16888506204910366302, + "venv/lib/python3.13/site-packages/pygments/lexers/other.py": 6893672181003034910, + "frontend/src/components/tasks/TaskResultPanel.svelte": 7735278333136205649, + "frontend/build/_app/immutable/chunks/DzzsUjGB.js": 16393111347267268983, + "backend/src/api/routes/__tests__/test_assistant_api.py": 4079781811717182404, + "backend/src/models/dataset_review_pkg/_session_models.py": 227824164148429934, + "venv/lib/python3.13/site-packages/_pytest/setupplan.py": 7496801885995567141, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/dotenv.py": 5872848911499749500, + "venv/lib/python3.13/site-packages/pandas/_libs/window/aggregations.cpython-313-x86_64-linux-gnu.so": 16327106317503267067, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_cross.py": 17742712348672218852, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/selectable.py": 14646717349365560549, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77comments.f": 4801926170672147659, + "venv/lib/python3.13/site-packages/jsonschema/_utils.py": 14237077105384631097, + "venv/lib/python3.13/site-packages/pygments/lexers/ecl.py": 12886695201994337568, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/authorization_server.py": 17967809814827547139, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/asyncio.py": 2517623574187179319, + "venv/lib/python3.13/site-packages/pandas/io/feather_format.py": 13242733585787888812, + "venv/lib/python3.13/site-packages/pandas/util/_doctools.py": 3766479022075611396, + "venv/lib/python3.13/site-packages/pygments/lexers/jslt.py": 11805394130669644345, + "frontend/build/_app/immutable/chunks/-DxfH9Uk.js": 9636177685221745709, + "backend/tests/test_translate_corrections.py": 1228642484417924184, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/filesize.py": 13234856188049714485, + "venv/lib/python3.13/site-packages/passlib/handlers/mysql.py": 11165762635383041460, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tz_localize.py": 13699016868476153393, + "venv/lib/python3.13/site-packages/pygments/scanner.py": 5640381644804445932, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/WHEEL": 18203500019759199992, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_getitem.py": 8414677531950073373, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/var_.py": 12699521091170347311, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/RECORD": 5612689057373270213, + "venv/lib/python3.13/site-packages/websockets/http.py": 9406523480132204760, + "venv/lib/python3.13/site-packages/pandas/core/reshape/concat.py": 2218848863149192467, + "venv/lib/python3.13/site-packages/attr/setters.py": 12467854389745942025, + "venv/lib/python3.13/site-packages/pip/_internal/utils/packaging.py": 15555781487631855604, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/base_server.py": 9643197259080504542, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarmath.py": 9762951701352556447, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/__init__.py": 260774374497653876, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA_py.py": 2494967094400350388, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/hstore.py": 9700253004947691961, + "venv/lib/python3.13/site-packages/pip/_vendor/pkg_resources/__init__.py": 1677532855362260338, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.obj": 11967637259540485652, + "venv/lib/python3.13/site-packages/pygments/unistring.py": 18037463865539157041, + "venv/lib/python3.13/site-packages/pandas/io/spss.py": 864838144958947906, + "venv/lib/python3.13/site-packages/keyring/backends/Windows.py": 4103830951042463184, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_extract.py": 14547819021277949280, + "frontend/build/_app/immutable/nodes/12.CpHG6ITP.js": 12188196309975709209, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_iceberg.py": 1726421917529457420, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/exclusions.py": 15852672500377116297, + "venv/lib/python3.13/site-packages/dateutil/tz/tz.py": 5258008267965780817, + "backend/src/plugins/translate/orchestrator_cancel.py": 673611364664367049, + "venv/lib/python3.13/site-packages/fastapi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/fastapi/__init__.py": 11054203163075417954, + "venv/lib/python3.13/site-packages/numpy/lib/array_utils.pyi": 14646405559193539455, + "venv/lib/python3.13/site-packages/uvicorn/workers.py": 7213290478118197047, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/__init__.py": 913610541217778747, + "frontend/src/routes/validation/[id]/+page.svelte": 8971190813271791071, + "backend/src/core/middleware/__init__.py": 13917394130915533209, + "frontend/e2e/fixtures/auth.fixture.js": 12330457928638392604, + "venv/lib/python3.13/site-packages/pydantic_settings/__init__.py": 4374954204580208673, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/npyio.pyi": 14147712281086095231, + "venv/lib/python3.13/site-packages/git/objects/fun.py": 15014209679156260865, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_numeric.py": 17391095502314929042, + "venv/lib/python3.13/site-packages/_pytest/_code/source.py": 9488112979192923739, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90": 8999550841368314739, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_feather.py": 13613400750755530364, + "venv/lib/python3.13/site-packages/pandas/tests/__init__.py": 15130871412783076140, "venv/lib/python3.13/site-packages/starlette/middleware/base.py": 16850428285382256618, + "venv/lib/python3.13/site-packages/pandas/tseries/frequencies.py": 2262381949755250516, + "venv/lib/python3.13/site-packages/_pytest/_py/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/cursor.py": 8074527784886981710, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/RECORD": 3205266407680661753, + "venv/lib/python3.13/site-packages/PIL/IptcImagePlugin.py": 14329453455296600824, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE": 17284252174641192866, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__init__.py": 8811477458865810434, + "venv/lib/python3.13/site-packages/pygments/styles/murphy.py": 8177992406082781615, + "venv/bin/pip": 13861749540792881808, + "backend/src/scripts/create_admin.py": 7540310914822649547, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/operators.py": 2468046993343796128, + "venv/lib/python3.13/site-packages/pygments/styles/nord.py": 8469538903422182155, + "venv/lib/python3.13/site-packages/pyasn1/type/tagmap.py": 14075859042659927673, + "backend/src/plugins/translate/metrics.py": 16289306156708185830, + "venv/lib/python3.13/site-packages/pytest_asyncio/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/charset_normalizer/utils.py": 11724147997933584095, + "venv/lib/python3.13/site-packages/yaml/scanner.py": 8554164423030397366, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/characteristics.py": 2916810597149066609, + "venv/lib/python3.13/site-packages/starlette/middleware/sessions.py": 11719848399661632707, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nditer.pyi": 2351219156711800159, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_defchararray.py": 15135904718007443306, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_setops.py": 5208912445718807372, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rank.py": 14115215895836854973, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_textreader.py": 388955620768371652, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/win64python2.npy": 11005857803794805939, + "venv/lib/python3.13/site-packages/pygments/lexers/freefem.py": 9851243865301700231, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_mrecords.py": 15952147778503828707, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_explode.py": 16195468192763502449, + "venv/lib/python3.13/site-packages/cffi/__init__.py": 13427266446746498548, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/file_proxy.py": 17695135735211897444, + "venv/lib/python3.13/site-packages/git/objects/submodule/__init__.py": 12958523219496107878, + "venv/lib/python3.13/site-packages/pygments/formatters/terminal256.py": 11473927781167132440, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_timegrouper.py": 276805119790266454, + "frontend/src/components/Toast.svelte": 4155277822937119359, + "venv/lib/python3.13/site-packages/pygments/lexers/pony.py": 2720635393743617141, + "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/__init__.py": 4290669519959060720, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/attrs/converters.py": 13109003765349201809, + "venv/lib/python3.13/site-packages/passlib/handlers/sun_md5_crypt.py": 1949993216707182407, + "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.pyi": 15509415708991012734, + "venv/lib/python3.13/site-packages/numpy/lib/introspect.py": 5706729538356302335, + "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp_impl.cpython-313-x86_64-linux-gnu.so": 11767771662042404251, + "venv/lib/python3.13/site-packages/_pytest/mark/__init__.py": 9343015549300275714, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_to_xml.py": 8477770807916990981, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/h11_impl.py": 1419719055394402145, + "venv/lib/python3.13/site-packages/pygments/lexers/gdscript.py": 12775803139854052838, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/__init__.py": 5027355874704300832, + "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.pyi": 8879196542984811747, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_numpy.py": 222383250675686477, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/__init__.py": 9997757256282720103, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/RECORD": 6187512110158566509, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py": 11425629729736599320, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_setops.py": 16240008859650640717, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/errors.py": 17581857895562494222, + "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.py": 4940170059946018356, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/ccalendar.cpython-313-x86_64-linux-gnu.so": 11019871270094058038, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/WHEEL": 13232065379159720345, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/assertion_session.py": 18109848200936213195, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi": 10548370574281981402, + "venv/lib/python3.13/site-packages/_pytest/_version.py": 4890545974654141536, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/named_types.py": 6099185243355915896, + "venv/lib/python3.13/site-packages/pygments/lexers/nit.py": 18262907536841158657, + "venv/lib/python3.13/site-packages/fastapi/middleware/__init__.py": 5289703478893407762, + "venv/lib/python3.13/site-packages/pygments/lexers/int_fiction.py": 8806961041808606055, + "venv/lib/python3.13/site-packages/pygments/lexers/text.py": 10572727755736597715, + "venv/bin/pyrsa-priv2pub": 16766314338551408621, + "backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py": 18129267641758340444, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/request.py": 10492090878715126550, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polynomial.py": 777287409151500309, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isin.py": 8136794647591341784, + "venv/lib/python3.13/site-packages/gitdb/db/__init__.py": 2615504918450276693, + "venv/lib/python3.13/site-packages/pandas/compat/__init__.py": 6077099417711209303, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge.py": 11366935134260232329, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_equals.py": 9405821443172167066, + "venv/lib/python3.13/site-packages/httpcore/_backends/mock.py": 6849131425727092784, + "venv/lib/python3.13/site-packages/referencing/exceptions.py": 2535322334430110414, + "frontend/src/routes/datasets/review/review-workspace-helpers.js": 8577563379877694502, + "venv/lib/python3.13/site-packages/pandas/_libs/writers.pyi": 10494773026133244183, + "venv/lib/python3.13/site-packages/pandas/core/indexes/multi.py": 9115751979327393200, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/metadata.py": 7204343250279221076, + "venv/lib/python3.13/site-packages/pandas/io/formats/printing.py": 3054136648863371285, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/_psycopg_common.py": 4111797647365870137, + "venv/lib/python3.13/site-packages/PIL/ContainerIO.py": 7551929914241379005, + "venv/lib/python3.13/site-packages/pygments/lexers/meson.py": 14659991367778746658, + "backend/src/services/clean_release/publication_service.py": 1882863137548904782, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_conversion_utils.py": 1567199588622767277, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_replace.py": 8166203537440976347, + "backend/src/api/routes/translate/_correction_routes.py": 12437040676784563126, + "frontend/src/components/DynamicForm.svelte": 12658559315809907844, + "venv/lib/python3.13/site-packages/keyring/__main__.py": 14602212239605295451, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_accessor.py": 10074496835594855786, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/RECORD": 9678861487447993169, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_symbolic.py": 8093576026032854125, + "venv/lib/python3.13/site-packages/pip/py.typed": 10243553515949422671, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/METADATA": 14180973198574731599, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py": 6973859422068490274, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__main__.py": 8412594868333244844, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hi77.f": 10617763407280454334, + "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.cpython-313-x86_64-linux-gnu.so": 17856848989827220388, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/gitdb/utils/__init__.py": 15130871412783076140, + "frontend/src/lib/components/translate/BulkCorrectionSidebar.svelte": 10114621552038076221, + "venv/lib/python3.13/site-packages/pandas/io/pytables.py": 17482934215513855928, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/__init__.py": 2436195108273216959, + "venv/lib/python3.13/site-packages/authlib/oidc/core/models.py": 1370998944213578392, + "venv/lib/python3.13/site-packages/pip/_vendor/typing_extensions.py": 10158933506062403688, + "backend/src/core/async_superset_client.py": 5842980152216372100, + "venv/lib/python3.13/site-packages/pandas/_config/localization.py": 11197430792343731762, + "backend/tests/services/clean_release/test_candidate_manifest_services.py": 16861589402854148894, + "venv/lib/python3.13/site-packages/psycopg2/_psycopg.cpython-313-x86_64-linux-gnu.so": 13471342289207537479, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/rethinkdb.py": 16413299263077970925, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.pyi": 1830368009811266890, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_timeseries_window.py": 1973365560758236222, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90": 14350239197565389508, + "venv/lib/python3.13/site-packages/pillow.libs/libavif-01e67780.so.16.3.0": 13947441788826399574, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.pyx": 17138729833735744777, + "venv/lib/python3.13/site-packages/pygments/lexers/idl.py": 11454152060351801696, + "frontend/build/_app/immutable/nodes/33.CqylJ_87.js": 15691416704303794352, + "backend/src/plugins/translate/service_datasource.py": 10240814407336170041, + "backend/src/api/__init__.py": 5287505122015708040, + "venv/lib/python3.13/site-packages/passlib/crypto/digest.py": 15890463288512025688, + "venv/lib/python3.13/site-packages/pygments/lexers/diff.py": 5930189593946259160, + "venv/lib/python3.13/site-packages/secretstorage/defines.py": 9590959702075554048, + "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.py": 17055498803745289016, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_set.py": 14375107704596905983, + "venv/lib/python3.13/site-packages/jeepney/auth.py": 10565040329507087892, + "frontend/src/lib/components/assistant/AssistantChatPanel.svelte": 4130047433623185888, + "venv/lib/python3.13/site-packages/git/objects/submodule/base.py": 10140490301897269395, + "venv/lib/python3.13/site-packages/pandas/core/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/websockets/imports.py": 1995356703044158461, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nlargest.py": 14518132768753249360, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/licenses/COPYING": 15270149301471737292, + "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.pyi": 1942236362568669510, + "venv/lib/python3.13/site-packages/pydantic/v1/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/licenses/LICENSE": 3868190977070717994, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.f": 18215492757907465667, + "venv/lib/python3.13/site-packages/ecdsa/test_curves.py": 6577762025900435885, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90": 14624074967635860696, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_utils.py": 8668650648802195016, + "venv/lib/python3.13/site-packages/numpy/testing/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets_properties.py": 2340780879864207500, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_constructors.py": 17219764538851313252, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/provision.py": 17812733620485633975, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/METADATA": 3786116428839780263, + "venv/lib/python3.13/site-packages/_pytest/py.typed": 15130871412783076140, + "frontend/src/lib/components/reports/__tests__/reports_page.integration.test.js": 16463062768004950066, + "backend/src/plugins/translate/service_utils.py": 15103456860964805370, + "venv/lib/python3.13/site-packages/jsonschema/tests/fuzz_validate.py": 2328585939822059352, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/windows.py": 16452996247375488034, + "venv/lib/python3.13/site-packages/pillow.libs/libbrotlicommon-c55a5f7a.so.1.2.0": 2635192149914499986, + "venv/lib/python3.13/site-packages/numpy/core/_internal.py": 14816989375912210674, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/licenses/LICENSE": 14524289631770661180, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_py.py": 13809503317864539103, + "venv/lib/python3.13/site-packages/numpy.libs/libgfortran-040039e1-0352e75f.so.5.0.0": 13946067868274850557, + "venv/lib/python3.13/site-packages/pandas/tests/resample/conftest.py": 1643522609234951699, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/METADATA": 5045041742469375466, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/visitors.py": 5190923415390076080, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/endpoint.py": 8519226897299461194, + "venv/lib/python3.13/site-packages/pygments/lexers/thingsdb.py": 6073447481627395832, + "backend/src/services/clean_release/manifest_service.py": 10873340336255220063, + "backend/tests/scripts/test_clean_release_tui.py": 14700450036639944764, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/reshape/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/nodes/9.BDFNoNna.js": 14496499953061885045, + "venv/lib/python3.13/site-packages/pandas/core/resample.py": 13814298871925341617, + "backend/src/services/clean_release/repositories/manifest_repository.py": 12395698948312301073, + "venv/lib/python3.13/site-packages/pandas/compat/pyarrow.py": 13693379998785127538, + "frontend/src/lib/components/health/PolicyForm.svelte": 16556369076015031814, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/json.py": 14738429697319670035, + "venv/lib/python3.13/site-packages/urllib3/exceptions.py": 9687187566231423953, + "frontend/e2e/fixtures/global-setup.js": 1597253740213759490, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_na_indexing.py": 8712547126522523899, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/functions.py": 16567226076808693246, + "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.pyi": 2104100025130695295, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arithmetic.py": 17043958604607035425, + "venv/lib/python3.13/site-packages/PIL/PdfImagePlugin.py": 16082854250442815862, + "venv/lib/python3.13/site-packages/pandas/core/util/hashing.py": 13106575357604888913, + "venv/lib/python3.13/site-packages/pygments/lexers/mips.py": 2078929831513352031, + "venv/lib/python3.13/site-packages/PIL/TiffImagePlugin.py": 6845043550424565106, + "backend/src/core/superset_client/_charts.py": 8811593556038212857, + "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.py": 15989335816452913951, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/checks.pyx": 13187505236986855177, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/WHEEL": 12054782055241301457, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90": 9097998998863007705, + "frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js": 2331331717663585059, + "venv/lib/python3.13/site-packages/anyio/_core/_testing.py": 14024940365851109155, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/flatiter.pyi": 9598576095384661517, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_dists.py": 16746363359320577809, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_get_dummies.py": 16112674981222844375, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/METADATA": 7214286447912789067, + "venv/bin/pip3": 13861749540792881808, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90": 13174951794239860144, + "backend/src/models/auth.py": 775632703462705888, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_parser.py": 3540203683732744499, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_indexing.py": 4063662953863959087, + "venv/bin/pyrsa-verify": 6762739642629904442, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_timestamp.py": 12253372102602993034, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_scrypt.py": 17378030264314664250, + "venv/lib/python3.13/site-packages/pandas/core/ops/__init__.py": 4049432353810047365, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/hooks.py": 8580161128344266243, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlsxwriter.py": 8445547874832015203, + "frontend/src/lib/ui/Card.svelte": 3442526978752993023, + "frontend/src/routes/git/+page.svelte": 14169430923974356254, + "venv/lib/python3.13/site-packages/keyring/credentials.py": 14515496037842724455, + "venv/lib/python3.13/site-packages/PIL/BmpImagePlugin.py": 16682567630621529903, + "venv/lib/python3.13/site-packages/pandas/_libs/groupby.cpython-313-x86_64-linux-gnu.so": 14931394220112658268, + "frontend/src/components/Footer.svelte": 17748559656923032, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_bcrypt.py": 11146468670439284889, + "venv/lib/python3.13/site-packages/rsa/parallel.py": 4968566722541778371, + "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet_trash.py": 6191655521667576604, + "venv/lib/python3.13/site-packages/jeepney/tests/secrets_introspect.xml": 10717038359151125278, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/revocation.py": 5718403706971163960, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/warnings_and_errors.py": 11172336980866895356, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/annotation.py": 15855576199737688124, + "venv/lib/python3.13/site-packages/pip/_internal/models/candidate.py": 3099785363867247334, + "frontend/src/routes/datasets/__tests__/split_view.test.js": 6143972529940917004, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90": 12296500845667555672, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_markdown.py": 9964642152916165317, + "frontend/public/vite.svg": 13568221685541582385, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_asof.py": 15792528637923603240, + "backend/src/api/routes/translate/_router.py": 4164547666727936398, + "venv/lib/python3.13/site-packages/psycopg2/errorcodes.py": 6711830404954314463, + "venv/lib/python3.13/site-packages/fastapi/openapi/docs.py": 16735218221639179927, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f": 13432803601367981068, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_cumulative.py": 6346947559103505068, + "venv/lib/python3.13/site-packages/sqlalchemy/util/topological.py": 11586868018611359415, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/__init__.py": 1798074863773727377, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/asyncio.py": 11442130378027628520, + "venv/lib/python3.13/site-packages/pyasn1/type/constraint.py": 16776615503418773283, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iat.py": 3570464615146398178, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/fft/tests/test_pocketfft.py": 18025182347224285050, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix_py.py": 6653895521961110080, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_conversion.py": 9159276697339089788, + "venv/lib/python3.13/site-packages/fastapi/_compat/shared.py": 5249003014594464718, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/validator_creation.py": 2745563768861102999, + "venv/lib/python3.13/site-packages/secretstorage/exceptions.py": 16701299261122689924, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/heuristics.py": 1422768761337195135, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_slice.py": 9936085512921529417, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/scalar_string.f90": 15018631706178918578, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pyx": 11739218099400096619, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_s3.py": 17425535047477778484, + "venv/lib/python3.13/site-packages/PIL/_avif.cpython-313-x86_64-linux-gnu.so": 5243449968857258659, + "venv/lib/python3.13/site-packages/pygments/lexers/j.py": 9766594937623918053, + "venv/lib/python3.13/site-packages/pygments/lexers/hexdump.py": 10665271113239513484, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/codec.py": 14814999235499530522, + "venv/lib/python3.13/site-packages/pygments/lexers/pddl.py": 9256112535059995841, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/compat.py": 9758194415584776667, + "venv/lib/python3.13/site-packages/pygments/lexers/iolang.py": 10997512999728724130, + "venv/lib/python3.13/site-packages/pandas/_libs/lib.pyi": 3049004444338566197, + "venv/lib/python3.13/site-packages/packaging/__init__.py": 5479277484104486860, + "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp.py": 16797760903996739079, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/routes/dashboards/+page.svelte": 12050524336689510248, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/METADATA": 14543822270526146783, + "venv/lib/python3.13/site-packages/websockets/headers.py": 13587146967490088657, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/controller.py": 5450931608244830335, + "venv/lib/python3.13/site-packages/pandas/tseries/api.py": 14785127136180503704, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_file.py": 5180401483285462901, + "venv/lib/python3.13/site-packages/numpy/core/getlimits.py": 14257687540182552408, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_common.py": 9446944526144164255, + "venv/lib/python3.13/site-packages/starlette/convertors.py": 17839747154274354605, + "venv/lib/python3.13/site-packages/pygments/lexers/kuin.py": 2818054539831699366, + "venv/lib/python3.13/site-packages/pip/_internal/utils/hashes.py": 17310331665429541812, + "venv/lib/python3.13/site-packages/dateutil/parser/isoparser.py": 18015430204844361067, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/pretty.py": 2448541115957861214, + "venv/lib/python3.13/site-packages/tzlocal/__init__.py": 11017072814026497364, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply_relabeling.py": 5600949862632014700, + "venv/lib/python3.13/site-packages/pandas/tests/io/conftest.py": 5864037534050136837, + "venv/lib/python3.13/site-packages/PIL/ImageMode.py": 2361901066832921091, + "venv/lib/python3.13/site-packages/PIL/_imaging.pyi": 17119084207765761921, + "frontend/src/components/auth/ProtectedRoute.svelte": 7705373237339863677, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/introspection.py": 5447179017910128771, + "backend/src/core/utils/superset_context_extractor/_parsing.py": 17093712504833649098, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/INSTALLER": 17282701611721059870, + "backend/src/services/clean_release/stages/manifest_consistency.py": 14323717074129560178, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/flatiter.pyi": 6885824496927786205, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_selectable_constructors.py": 84919308502240880, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_builtin_md4.py": 16840174243259839994, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/__init__.py": 1923528231486706442, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_freq_attr.py": 1720704043778272895, + "backend/src/core/task_manager/models.py": 7035565766825575890, + "backend/src/models/dataset_review_pkg/_filter_models.py": 13932350898582638473, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/parameters.py": 1647490964392525933, + "venv/lib/python3.13/site-packages/fastapi/security/base.py": 15674297568104917749, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/LICENSE": 16174281248426886206, + "venv/lib/python3.13/site-packages/pygments/lexers/codeql.py": 4254046699692048717, + "venv/lib/python3.13/site-packages/click/types.py": 6491651131669287534, + "venv/lib/python3.13/site-packages/numpy/core/numerictypes.py": 5776941405348611027, + "scripts/build_offline_docker_bundle.sh": 9577721838839060974, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/client_auth.py": 3301527187487914220, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__init__.py": 5895297076117159245, + "venv/lib/python3.13/site-packages/smmap/test/test_tutorial.py": 16309370344201290582, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_functions.py": 2255133375699086300, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_map.py": 1115471561925426082, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_timezones.py": 15157687716502574038, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_values.py": 430620320423334461, + "venv/lib/python3.13/site-packages/anyio/_core/_streams.py": 6436461519284884601, + "venv/lib/python3.13/site-packages/starlette/responses.py": 14081178833432955042, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/RECORD": 17594742868855466393, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_compression.py": 8061288329598682752, + "backend/src/api/routes/dashboards/_router.py": 8641007051243802224, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90": 8308927438994838783, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/__init__.py": 12906995259233516197, + "venv/lib/python3.13/site-packages/pydantic/functional_serializers.py": 15285359935059345032, + "venv/lib/python3.13/site-packages/websockets/datastructures.py": 5180442040351387281, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/meson.build.template": 9935732744553086652, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/LICENSE": 6989336036499641077, + "frontend/src/lib/stores/__tests__/mocks/env_public.js": 2540122820969872185, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_iterator.py": 13869355993837330406, + "frontend/src/components/git/GitMergeDialog.svelte": 17029360862035548928, + "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.pyi": 4587511199710546030, + "venv/lib/python3.13/site-packages/numpy/conftest.py": 8971879716683736515, + "venv/lib/python3.13/site-packages/_pytest/assertion/__init__.py": 16392348866405910618, + "venv/lib/python3.13/site-packages/numpy/lib/format.py": 14971167445246135440, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.pyi": 14543653817631274394, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarbuffer.py": 16859789411010045795, + "venv/lib/python3.13/site-packages/numpy/fft/tests/test_helper.py": 5362180645056413158, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_logical_ops.py": 16166386974005224415, + "backend/src/services/git/__init__.py": 14011752637167919253, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_spss.py": 4865360315909532603, + "backend/tests/services/clean_release/test_compliance_execution_service.py": 5924200441771414883, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content": 12465123883296161860, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/chararray.pyi": 17340224970247832290, + "backend/git_repos/remote/test-repo.git/info/exclude": 6403833611826357791, + "venv/lib/python3.13/site-packages/_pytest/assertion/rewrite.py": 2425990712758915831, + "venv/lib/python3.13/site-packages/pip/_internal/utils/datetime.py": 6816292030061301011, + "venv/lib/python3.13/site-packages/pip/_internal/network/download.py": 5256731341219268693, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_alter_axes.py": 11338712836362534969, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_freq_code.py": 13758353172962109140, + "venv/lib/python3.13/site-packages/charset_normalizer/models.py": 9917300217816275821, + "venv/lib/python3.13/site-packages/pygments/styles/lovelace.py": 15082819162722685616, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_spinners.py": 15873416546130487469, + "venv/lib/python3.13/site-packages/uvicorn/config.py": 17317823506849880916, + "venv/lib/python3.13/site-packages/more_itertools/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/smmap/__init__.py": 4557520096828426601, + "venv/lib/python3.13/site-packages/numpy/_core/printoptions.pyi": 16758392990920041462, + "venv/lib/python3.13/site-packages/requests/__version__.py": 6677532709758546816, + "venv/lib/python3.13/site-packages/rapidfuzz/process.pyi": 6959881293311340830, + "venv/lib/python3.13/site-packages/pillow.libs/libopenjp2-94e588ba.so.2.5.4": 2483101806045986252, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_period.py": 7727606662611927293, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_truncate.py": 9623613657871046837, + "venv/lib/python3.13/site-packages/pip/_internal/index/sources.py": 11609272011565024668, + "frontend/src/routes/settings/LlmSettings.svelte": 11336336338708911991, + "venv/lib/python3.13/site-packages/pip/_internal/models/scheme.py": 4101322315594430874, + "venv/lib/python3.13/site-packages/numpy/lib/_datasource.pyi": 5894423389796456573, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/getlimits.pyi": 93747984191461691, + "venv/lib/python3.13/site-packages/anyio/_core/_subprocesses.py": 7271614043537119143, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py": 3960540415600165213, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/np_datetime.pyi": 2884703536776830012, + "venv/lib/python3.13/site-packages/pydantic/plugin/__init__.py": 16803973597469216174, + "venv/lib/python3.13/site-packages/PIL/FtexImagePlugin.py": 8196606399875185931, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.py": 3654583356259850174, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/interface.py": 3134071530627935964, + "backend/src/plugins/translate/orchestrator_validation.py": 17464651621865127561, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/rule.py": 5318344538761246105, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix_py.py": 17041764258638228993, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.APACHE": 8359973023624924624, + "venv/lib/python3.13/site-packages/dotenv/cli.py": 7952654621986067973, + "venv/lib/python3.13/site-packages/pydantic/v1/main.py": 213087273729911492, + "venv/lib/python3.13/site-packages/pandas/core/_numba/executor.py": 2205130934861422769, + "venv/lib/python3.13/site-packages/cryptography/exceptions.py": 5173540025160237758, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/columns.py": 8488246354818721406, + "venv/lib/python3.13/site-packages/pluggy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/idna/package_data.py": 6583909243002417298, + "venv/lib/python3.13/site-packages/pandas/io/formats/csvs.py": 17223598248259691292, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/__init__.py": 11121941644106061453, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/take.py": 3170415198452493008, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/histograms.pyi": 9255620158831643201, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/dtype.py": 9342837412280377086, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/__init__.py": 13331622784664204066, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas7bdat.py": 8963983384208121526, + "venv/lib/python3.13/site-packages/pandas/io/excel/_xlrd.py": 14430937200583666658, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/event/legacy.py": 13465911776953636949, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/sqltypes.py": 2952996080192295188, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/expression.py": 1248029135284283479, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_indexing.py": 14717641281147152159, + "venv/lib/python3.13/site-packages/numpy/core/function_base.py": 12696640832638144604, + "venv/lib/python3.13/site-packages/httpcore/_backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/refs/head.py": 16271128287606894569, + "venv/lib/python3.13/site-packages/pandas/tests/config/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_retain_attributes.py": 16210262356844956764, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/auto.py": 15947958974558543657, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/url.py": 1558176735588971829, + "venv/lib/python3.13/site-packages/pygments/lexers/bibtex.py": 14652372822443154388, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_categorical_equal.py": 7942323667866280872, + "venv/lib/python3.13/site-packages/urllib3/util/ssl_.py": 11720964010284185952, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_spec_conformance.py": 16448324304809345527, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period_range.py": 9598872514187524706, + "venv/lib/python3.13/site-packages/pandas/tests/strings/__init__.py": 5060190599837877599, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_query_eval.py": 17613800806748649144, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite.py": 3628609433179387988, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/provision.py": 8707620698060818654, + "venv/lib/python3.13/site-packages/pygments/styles/algol_nu.py": 6229131016121450375, + "venv/lib/python3.13/site-packages/pygments/lexers/soong.py": 10273453675034306814, + "venv/lib/python3.13/site-packages/pygments/lexers/webmisc.py": 9530962803076253849, + "frontend/src/lib/components/dataset-review/SourceIntakePanel.svelte": 13922687579631047714, + "frontend/src/components/git/CommitModal.svelte": 4151596094672629211, + "venv/lib/python3.13/site-packages/httpcore/_sync/http11.py": 5947339024588907032, + "frontend/build/_app/immutable/chunks/CcUnvbzA.js": 4622472808426923659, + "venv/lib/python3.13/site-packages/keyring/__init__.py": 991260689223167957, + "venv/lib/python3.13/site-packages/pyasn1/type/namedtype.py": 1859990775875190116, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/dtype.pyi": 12178008080078679769, + "venv/lib/python3.13/site-packages/pandas/_libs/hashtable.cpython-313-x86_64-linux-gnu.so": 16963890771704942465, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_series.pyi": 7112486730197067087, + "venv/lib/python3.13/site-packages/fastapi/security/__init__.py": 1345944646061334046, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/timeseries.py": 17641722582848932332, + "venv/lib/python3.13/site-packages/fastapi/_compat/may_v1.py": 9880083742927480960, + "backend/tests/services/clean_release/test_approval_service.py": 8359796700245201345, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv": 601782991752922510, + "venv/lib/python3.13/site-packages/jsonschema_specifications/__init__.py": 5732822354953774657, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-np0-objarr.npy": 1615546603475261360, + "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.pyi": 12275242654430570028, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_libfrequencies.py": 16302676625743291594, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.pyi": 5973671421648618563, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isna.py": 18394053826166267096, + "venv/lib/python3.13/site-packages/pygments/styles/pastie.py": 15784474766258831882, + "venv/lib/python3.13/site-packages/pandas/io/formats/css.py": 11288129826285529457, + "frontend/src/lib/ui/index.ts": 6883965364006817450, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_npfuncs.py": 6132674295193898715, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/rsa.py": 5392922995791487437, + "venv/lib/python3.13/site-packages/pygments/lexers/graph.py": 10445044822847205061, + "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.py": 13012775703413938576, + "venv/lib/python3.13/site-packages/keyring/errors.py": 4587094338672775040, + "venv/lib/python3.13/site-packages/pydantic/deprecated/copy_internals.py": 1245428320513062166, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_function_base.pyi": 2792940598392356268, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.pyi": 17469792319379909312, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/random.py": 12722750410117529986, + "frontend/build/_app/immutable/assets/0.DOvkr1-n.css": 1345807087933181124, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarrayobject.h": 7320510589635636690, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/WHEEL": 16097436423493754389, + "frontend/src/routes/admin/users/+page.svelte": 4464001185352807842, + "venv/lib/python3.13/site-packages/pandas/io/formats/style_render.py": 13586834368514801953, + "venv/lib/python3.13/site-packages/pandas/compat/pickle_compat.py": 11073483984394766474, + "venv/lib/python3.13/site-packages/git/objects/tag.py": 7954808535585493300, + "frontend/src/lib/components/assistant/__tests__/assistant_clarification.integration.test.js": 12258270009984504212, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_ops.py": 16346030307660048773, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_ticks.py": 11649965080303468085, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/METADATA": 4868544280955034757, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml_dtypes.py": 18293138335799308439, + "venv/lib/python3.13/site-packages/psycopg2/pool.py": 8855184580138330938, + "venv/lib/python3.13/site-packages/jaraco/classes/meta.py": 15930255620248873425, + "venv/lib/python3.13/site-packages/greenlet/TThreadStateCreator.hpp": 9887867766190459665, + "frontend/src/lib/stores/__tests__/mocks/stores.js": 14098417748659067309, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_api_info.py": 16491629653122827368, + "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.test.js": 7689381541193660594, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_datetimes.py": 7889573945417063183, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.BSD": 3858254215169937333, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_timedeltas.py": 4118671843063545221, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/__main__.py": 2688850704829116818, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/spinner.py": 5564789578696016201, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_block_internals.py": 17935662848672401507, + "venv/bin/normalizer": 10972303485259566838, + "backend/src/core/utils/superset_compilation_adapter.py": 4974836712746468095, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.pyf": 1361426175133186231, + "venv/lib/python3.13/site-packages/pandas/core/methods/selectn.py": 13552176539021625776, + "venv/lib/python3.13/site-packages/httpcore/_api.py": 16499985295426060327, + "venv/lib/python3.13/site-packages/pygments/lexers/objective.py": 10966124906622044512, + "venv/bin/pyrsa-decrypt": 10929163076272054227, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/errors.py": 10750605030539582738, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/methods.py": 8059372834301557565, + "frontend/e2e/tests/migration.e2e.js": 12564023806718668322, + "venv/lib/python3.13/site-packages/pandas/tests/api/test_api.py": 13385690673368400635, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_deprecations.py": 8310244516175542839, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_quantile.py": 4225791949463893856, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_constructors.py": 5627819885594450614, + "venv/lib/python3.13/site-packages/requests/certs.py": 16052880877156864882, + "venv/lib/python3.13/site-packages/pip/_internal/utils/logging.py": 9639351759822608724, + "venv/lib/python3.13/site-packages/apscheduler/triggers/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/secretstorage/item.py": 15486045386471912693, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2cffi.py": 5997687240967250164, + "venv/lib/python3.13/site-packages/httpx/_exceptions.py": 18399489130669465891, + "venv/lib/python3.13/site-packages/PIL/XVThumbImagePlugin.py": 7472134175570205454, + "venv/lib/python3.13/site-packages/dateutil/__init__.py": 17666544837260663800, + "venv/lib/python3.13/site-packages/attr/_config.py": 1864824728504480204, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_kurt.py": 2898715045429898166, + "venv/lib/python3.13/site-packages/pygments/lexers/_cocoa_builtins.py": 15468347167912293394, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_cisco.py": 1786475632318043669, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/io.py": 11072022722163954973, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/pandas/core/strings/accessor.py": 14021462534679430426, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_utils.py": 2329717399120006435, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexers.py": 6773751569163287047, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_win32_console.py": 18092547253031555768, + "frontend/src/routes/storage/repos/+page.svelte": 3849368960648953479, + "frontend/build/_app/immutable/chunks/NS3MSmhF.js": 810442407483225325, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py": 9430762168079129025, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/RECORD": 16558021503346615951, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/default_comparator.py": 47118577003622736, + "venv/lib/python3.13/site-packages/requests/utils.py": 17045260098091371478, + "venv/lib/python3.13/site-packages/pip/_internal/cli/command_context.py": 9426036980437931533, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get.py": 6509102681661636928, + "venv/lib/python3.13/site-packages/certifi/__init__.py": 9045580998764948967, "venv/lib/python3.13/site-packages/annotated_doc/main.py": 3384049281532298500, - "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_index_col.py": 17604191644943383567, - "venv/lib/python3.13/site-packages/PIL/ImageWin.py": 13635870584232081323 + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/WHEEL": 14550174241288068152, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/__init__.py": 18036348770966744795, + "venv/lib/python3.13/site-packages/pygments/lexer.py": 3658450949169647228, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_arithmetics.py": 16527169124402715210, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_keywords.py": 11487954623214475915, + "frontend/build/_app/immutable/nodes/27.BmqgTr_q.js": 17499832403429157196, + "backend/src/models/__init__.py": 13280325675752905975, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_count.py": 9186538441380080087, + "backend/src/schemas/__init__.py": 8700952869915187087, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/__init__.py": 8093984834068317399, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_sample.py": 4641567828238191927, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_as_unit.py": 8492383355919959393, + "venv/lib/python3.13/site-packages/pandas/tests/test_errors.py": 10116716310156374885, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_unsupported.py": 9115440166074553860, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_install.py": 7181005402818830655, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/scripting.py": 4167168074165473790, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg_catalog.py": 15726448028057859831, + "backend/src/plugins/translate/orchestrator_exec.py": 16278134717094910089, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/RECORD": 7266315886702289726, + "venv/lib/python3.13/site-packages/pluggy/_warnings.py": 2664977718908223842, + "venv/lib/python3.13/site-packages/PIL/_imagingcms.cpython-313-x86_64-linux-gnu.so": 15198265718775753589, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/securetransport.py": 12104888897121018676, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/twodim_base.pyi": 3773329770170248877, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/__init__.py": 697601512486720554, + "venv/bin/pyrsa-sign": 15564653706771700451, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_calendar.py": 12313641252472031631, + "venv/lib/python3.13/site-packages/fastapi/datastructures.py": 727178955746650271, + "venv/lib/python3.13/site-packages/pandas/tests/base/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/tests/sample_config_1s.cfg": 1809713544666311828, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py": 7019253290755243568, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/python.py": 17886036670342116501, + "venv/lib/python3.13/site-packages/pandas/tests/apply/common.py": 1113935558495455492, + "venv/lib/python3.13/site-packages/pygments/lexers/tcl.py": 10343667975436015855, + "frontend/e2e/tests/translation.e2e.js": 6244274143080191568, + "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.py": 5583478355093966990, + "backend/src/api/routes/mappings.py": 7071183920129492341, + "venv/lib/python3.13/site-packages/fastapi/middleware/trustedhost.py": 4285622102799027823, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.pyf": 4660465266594480405, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/status_codes.py": 17005213506461710202, + "venv/lib/python3.13/site-packages/pygments/lexers/asc.py": 10744437946030875496, + "venv/lib/python3.13/site-packages/pygments/lexers/tlb.py": 1169242051301155885, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_cat.py": 15988884721768567895, + "backend/src/core/__tests__/test_config_manager_compat.py": 656412918792001580, + "backend/src/plugins/git_plugin.py": 11912463343289116491, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/_pytest/mark/structures.py": 12237146603608917650, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_methods.py": 12694335778731418517, + "venv/lib/python3.13/site-packages/apscheduler/job.py": 1858376671986108667, + "venv/lib/python3.13/site-packages/websockets/utils.py": 17624459810483092475, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/base.py": 13444129650880426353, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ranges.py": 14549386056660231279, + "venv/lib/python3.13/site-packages/numpy/fft/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/packaging/_manylinux.py": 8268418900652790584, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_describe.py": 362374422228593281, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_unix.h": 13709837360414450184, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_gcc.h": 3561524604274567339, + "venv/lib/python3.13/site-packages/pandas/tests/frame/common.py": 7426635866622531875, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/decoder.py": 15336592439379775543, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/subversion.py": 7423946096970870727, + "venv/lib/python3.13/site-packages/pip/_internal/main.py": 13711402795965346761, + "venv/lib/python3.13/site-packages/pydantic/_internal/_model_construction.py": 694471028676746110, + "venv/lib/python3.13/site-packages/pydantic/class_validators.py": 4643597082531287188, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_interface.py": 13648006002292914247, + "venv/lib/python3.13/site-packages/PIL/ImageMorph.py": 13861961228125789866, + "venv/lib/python3.13/site-packages/numpy/tests/test_scripts.py": 5790352482583964348, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval.py": 18040371224712437126, + "venv/lib/python3.13/site-packages/pygments/lexers/ambient.py": 18106929781201758080, + "backend/src/services/__tests__/test_encryption_manager.py": 5925253324895194576, + "backend/src/services/clean_release/stages/data_purity.py": 10459527906317168920, + "backend/git_repos/remote/test-repo.git/objects/cf/d2dcbd55735b8cedf21e04e64ac627c6f9a458": 10982669277486885525, + "backend/src/plugins/translate/__tests__/test_executor.py": 17557965511167209685, + "frontend/build/_app/immutable/chunks/BAmBhMfb.js": 13611213518451413724, + "venv/lib/python3.13/site-packages/pygments/lexers/_mql_builtins.py": 2376212048709413586, + "venv/lib/python3.13/site-packages/authlib/oidc/__init__.py": 15130871412783076140, + "backend/src/api/routes/__tests__/test_datasets.py": 5180776326745169791, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/structures.py": 2668010839316715865, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape.pyi": 17197248408326188931, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_constructors.py": 9815164146739254076, + "venv/lib/python3.13/site-packages/greenlet/greenlet.cpp": 3281107194043468270, + "venv/lib/python3.13/site-packages/pandas/util/_decorators.py": 14780166101442507665, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_interval.py": 14749388246573356959, + "venv/lib/python3.13/site-packages/pandas/core/internals/api.py": 14632030170441237968, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/METADATA": 11557342107649194148, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_join.py": 1364886077926604427, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_formats.py": 13500155167624433622, + "venv/lib/python3.13/site-packages/pandas/tests/series/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/cryptography/hazmat/_oid.py": 755042927629281577, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/fields.py": 8923326131649837922, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/vector.py": 9941185556118343263, + "venv/lib/python3.13/site-packages/jeepney/fds.py": 16573439672758641560, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlcipher.py": 11225173272050906977, + "venv/lib/python3.13/site-packages/httpcore/_ssl.py": 6665087294869504820, + "venv/lib/python3.13/site-packages/dateutil/rrule.py": 398469817784230512, + "venv/lib/python3.13/site-packages/charset_normalizer/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/__init__.py": 3577295959173028042, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/RECORD": 14375680579341422646, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_sansio_impl.py": 17221368219485351394, + "venv/lib/python3.13/site-packages/pygments/lexers/tls.py": 3552078393009383412, + "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.pyi": 15745512451486888537, + "venv/lib/python3.13/site-packages/greenlet/tests/test_extension_interface.py": 11693583111513457974, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv": 6674536825156196036, + "venv/lib/python3.13/site-packages/keyring/backend.py": 14185808762437650951, + "venv/lib/python3.13/site-packages/pygments/lexers/ezhil.py": 10294520768762308887, + "venv/lib/python3.13/site-packages/pandas/_libs/algos.cpython-313-x86_64-linux-gnu.so": 15706331654215762588, + "backend/src/plugins/translate/__tests__/test_token_budget.py": 9612693566837223655, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_partial_slicing.py": 15567512240469921599, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/coercions.py": 5112358449376598662, + "venv/lib/python3.13/site-packages/numpy/_core/umath.py": 6132761780113682667, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90": 2657057181044959432, + "venv/lib/python3.13/site-packages/pandas/tests/api/test_types.py": 8889829773923216769, + "venv/lib/python3.13/site-packages/_pytest/setuponly.py": 10959102379908419762, + "backend/tests/core/test_migration_engine.py": 7419155921858935534, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/WHEEL": 9100692507274722091, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarprint.py": 9482100952562512933, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/resource_protector.py": 17080006010679257864, + "frontend/build/_app/immutable/chunks/DXFMtRnu.js": 8879062222147219757, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/highlighter.py": 10615901258492570740, + "backend/tests/test_resource_hubs.py": 3990299394875930767, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timestamps.pyi": 51728851886466199, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_version.pyi": 3636944488233043883, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/testing.pyi": 16263777835572515739, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_console.py": 11657469008721907972, + "backend/git_repos/remote/test-repo.git/objects/a7/49f11fad695dff77faf1708c7320867d0be1df": 4641609158325033031, + "venv/lib/python3.13/site-packages/PIL/GimpGradientFile.py": 9777026720028891154, + "frontend/build/_app/immutable/chunks/CU7yWBsw.js": 14150462720318349484, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/api.py": 13134394673408254097, + "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators_v1.py": 16723743964226526155, + "venv/lib/python3.13/site-packages/pandas/core/tools/__init__.py": 15130871412783076140, + "backend/src/api/routes/git/_repo_lifecycle_routes.py": 6605622512801609889, + "backend/src/dependencies.py": 9481683691730170837, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval.py": 1228451182688768814, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_legendre.py": 18266595775500927868, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_json_table_schema_ext_dtype.py": 13021437050542691118, + "venv/lib/python3.13/site-packages/pip/_internal/commands/index.py": 16715578868094112894, + "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.py": 13446184230476677032, + "venv/lib/python3.13/site-packages/greenlet/greenlet_cpython_compat.hpp": 8396413256279803400, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion": 2607512361823362698, + "venv/lib/python3.13/site-packages/_pytest/recwarn.py": 15312759837838083596, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/__init__.py": 12975130533860125272, + "venv/lib/python3.13/site-packages/dotenv/variables.py": 5438726379749803751, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_convert.py": 17957207974799052653, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/exc.py": 3242780937124999391, + "backend/git_repos/remote/test-repo.git/objects/5d/9eb555c4cac2d3ffdba84c07682b154fe4180d": 10756202165146702691, + "backend/src/api/routes/settings.py": 12171289292260529147, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/INSTALLER": 17282701611721059870, + "backend/src/core/migration/archive_parser.py": 7392694914943455006, + "venv/lib/python3.13/site-packages/jeepney/low_level.py": 6546206679858571608, + "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.pyi": 5892973170789971535, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_from_scalar.py": 16520136036631155842, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/basereload.py": 14479857245734482609, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/fields.py": 4142211199816898047, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/fromnumeric.pyi": 6708743411405679061, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/exceptions.py": 7518613450390473990, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_round.py": 8336918400205461173, + "venv/lib/python3.13/site-packages/greenlet/slp_platformselect.h": 10428201768098464386, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi": 16312114056447366970, + "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators.py": 9928398334052202841, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_wrap.py": 17083394123203662880, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/RECORD": 9803861100978586236, + "venv/lib/python3.13/site-packages/numpy/lib/_version.py": 15294708923334674060, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/exc.py": 1448374203226983757, + "venv/lib/python3.13/site-packages/pip/_internal/utils/egg_link.py": 18211947508793805393, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/hist.py": 10928173425078493095, + "venv/lib/python3.13/site-packages/urllib3/util/proxy.py": 17667887856427739069, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/decoder.py": 12653470212935324322, + "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.pyi": 4729765666018003634, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/ImageFont.py": 15621336334706847865, + "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.pyi": 6796322258258182775, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_string.py": 15542851215119662814, + "venv/lib/python3.13/site-packages/pygments/lexers/fantom.py": 1986459352773446836, + "frontend/src/components/llm/__tests__/provider_config.integration.test.js": 12605115626277870995, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_format.py": 9331389900588353667, + "frontend/build/_app/immutable/chunks/CAQC5x1g.js": 7514616393166593562, + "backend/src/core/migration/__init__.py": 13075189211840127611, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/assertion_client.py": 4261295109880943573, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dropna.py": 3168969662216766293, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_utils.pyi": 12312677132342982866, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_indexing.py": 16623126293364224089, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/encoder.py": 120921270972591880, + "venv/lib/python3.13/site-packages/keyring/backend_complete.zsh": 14339032329370660432, + "venv/lib/python3.13/site-packages/httpx/_transports/__init__.py": 5931944625631942279, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/WHEEL": 17410883677306885019, + "venv/lib/python3.13/site-packages/starlette/config.py": 16509394679506300256, + "venv/lib/python3.13/site-packages/passlib/hosts.py": 11171402820797380938, + "venv/lib/python3.13/site-packages/pyasn1/codec/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/core/indexes/accessors.py": 14394872772838047912, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine.py": 16193618152415684421, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_index.py": 1551768441102117466, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.pyi": 14233146512272397376, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cython.py": 14695721638531081573, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/dtype_api.h": 17040779421165903019, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/dynamic.py": 15220116196072524330, + "venv/lib/python3.13/site-packages/anyio/_backends/_trio.py": 4764555436057754985, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_level_values.py": 12490886203425393290, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_warnings.py": 13071210233876253749, + "frontend/src/routes/datasets/ColumnsTable.svelte": 1880884265008014080, + "frontend/src/components/llm/ProviderConfig.svelte": 1968349576688210309, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numerictypes.pyi": 15443101937711720707, + "venv/lib/python3.13/site-packages/pygments/lexers/sgf.py": 6802546617450210439, + "venv/lib/python3.13/site-packages/keyring/backends/fail.py": 5792496235026678021, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/testing.pyi": 9317922890783549326, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_setops.py": 15365064654930699428, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_partial_slicing.py": 16219611534574666182, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_almost_equal.py": 9333355453468475330, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_bin_groupby.py": 14831211659124136806, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tolist.py": 8343058000369672317, + "venv/lib/python3.13/site-packages/greenlet/platform/setup_switch_x64_masm.cmd": 8473866644286785815, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe_protocol.py": 12857147443873820285, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx": 15936470837420356071, + "venv/lib/python3.13/site-packages/_pytest/_io/__init__.py": 1510478951261938348, + "venv/lib/python3.13/site-packages/pygments/lexers/robotframework.py": 11507713622179102496, + "venv/lib/python3.13/site-packages/pandas/core/base.py": 10262717073058743378, + "frontend/build/_app/immutable/chunks/CjWO4UqU.js": 15077457895685140387, + "frontend/build/_app/immutable/nodes/10.BrGd1Bxg.js": 2619069571612365028, + "backend/src/core/task_manager/event_bus.py": 15798578020529126889, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-1.csv": 5708101386018266998, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py": 7301817934902711510, + "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.py": 12886275429547303345, + "venv/lib/python3.13/site-packages/keyring/util/platform_.py": 16978095707950463638, + "venv/lib/python3.13/site-packages/pandas/io/pickle.py": 5418646169167774144, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/json.py": 15085143436056608404, + "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.py": 4984721349618127021, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/multiprocess.py": 10047012560534876149, + "backend/alembic/versions/aa1b2c3d4e5f_drop_deprecated_translate_columns.py": 15433357059529111004, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/WHEEL": 12146818530001975731, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/qt.py": 12828696264909048448, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_reindex.py": 15794750188594767026, + "backend/src/models/task.py": 10701108436197477339, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/__init__.py": 2246704695838251846, + "venv/lib/python3.13/site-packages/attr/filters.py": 14156141488477438777, + "venv/lib/python3.13/site-packages/PIL/ImageMath.py": 7395449734007598797, + "venv/lib/python3.13/site-packages/PIL/BdfFontFile.py": 10811640174253687845, + "backend/src/services/validation_run_service.py": 15796580661134976084, + "venv/lib/python3.13/site-packages/pydantic/typing.py": 6661252174518316760, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-1.csv": 9129730764673472086, + "venv/lib/python3.13/site-packages/numpy/f2py/setup.cfg": 17974180080760231128, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/__init__.py": 15130871412783076140, + "backend/src/core/superset_client/_user_projection.py": 16484323195475306883, + "venv/lib/python3.13/site-packages/PIL/TgaImagePlugin.py": 9208942494595222259, + "venv/lib/python3.13/site-packages/pygments/lexers/sieve.py": 15757825442941567629, + "backend/src/api/routes/__tests__/test_clean_release_source_policy.py": 15242462571646635922, + "venv/lib/python3.13/site-packages/numpy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/elpi.py": 5736689911777977822, + "venv/lib/python3.13/site-packages/referencing/_attrs.pyi": 10030665705880994025, + "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.pyi": 5786150108623563787, + "venv/lib/python3.13/site-packages/pydantic/v1/networks.py": 13262073155118055511, + "backend/src/models/storage.py": 5952240576082791619, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/base.py": 14908084548919567658, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/warnings.py": 5142352784799639092, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90": 8079594129222364031, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/WHEEL": 5990830714395966792, + "venv/lib/python3.13/site-packages/pygments/lexers/zig.py": 470431199354307668, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polytypes.pyi": 7528777458251688517, + "venv/lib/python3.13/site-packages/websockets/asyncio/compatibility.py": 9716993942839407921, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_reductions.py": 3227705565578016389, + "frontend/build/_app/immutable/nodes/13.CQ2-n7t2.js": 565047278658372795, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_kwargs.py": 10173906126211473463, + "venv/lib/python3.13/site-packages/httpx/_transports/base.py": 6498990531443644896, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/instrumentation.py": 13198832283145198959, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mutable.py": 9323088483998280629, + "frontend/src/routes/datasets/review/ReviewWorkspaceLeftSidebar.svelte": 9009994851177005358, + "venv/lib/python3.13/site-packages/websockets/exceptions.py": 12048063047468402740, + "venv/lib/python3.13/site-packages/_pytest/config/argparsing.py": 11156052029258891503, + "venv/lib/python3.13/site-packages/numpy/strings/__init__.py": 6523674574341354095, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/discovery.py": 12479996594187326798, + "venv/lib/python3.13/site-packages/fastapi/exception_handlers.py": 9907950997607808699, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/boxplot.py": 7090586111222952862, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_contains.py": 17630310725250553247, + "venv/lib/python3.13/site-packages/python_multipart/__init__.py": 10290895261363712562, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/__init__.py": 71159121705871510, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_functions.py": 16376319335326812580, + "venv/lib/python3.13/site-packages/idna/core.py": 7725813731640753267, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_reshape.py": 5572426834735088916, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_xs.py": 11073752361562791165, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_comment.py": 5603075924832933306, + "venv/lib/python3.13/site-packages/pydantic_core/__init__.py": 10563134104783445328, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/styles/stata_light.py": 16319330015324455277, + "venv/lib/python3.13/site-packages/pygments/lexers/inferno.py": 9056274496469409594, + "frontend/src/routes/settings/__tests__/settings_page.ux.test.js": 12159582682619630694, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arrow_compat.py": 12986187285988432338, + "frontend/build/_app/immutable/nodes/30.ErbpIoNq.js": 17564144253776237965, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/__init__.py": 7877061921210840955, + "backend/src/core/superset_client/__init__.py": 14560361361214953450, + "backend/src/services/health_service.py": 7295235621662158359, + "venv/lib/python3.13/site-packages/starlette/background.py": 10232175205397808417, + "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.pyi": 12052895927933479005, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/WHEEL": 2823347510103459191, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f": 12558972205518833024, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_style.py": 10405592363651914796, + "backend/git_repos/remote/test-repo.git/refs/heads/main": 7667767390913789840, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-2.csv": 7063857529719738394, + "venv/lib/python3.13/site-packages/yaml/composer.py": 13619070314468518566, + "frontend/src/services/git-utils.js": 12982149055119314642, + "backend/git_repos/remote/test-repo.git/objects/71/47ad0836409b35c1650dddf5fa6329ba61a824": 16601919569600972016, + "venv/lib/python3.13/site-packages/pygments/lexers/_scilab_builtins.py": 17453812809700086888, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby.py": 16180421154734310873, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/attr/_compat.py": 4016698632899969390, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_concat.py": 16549010224568175202, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval_pyarrow.py": 3849382723890414899, + "frontend/src/lib/api/translate/__tests__/test-target-schema.test.js": 2329724860725977662, + "venv/lib/python3.13/site-packages/websockets/asyncio/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/_pcg64.pyi": 14785496840737986355, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_complex.py": 12963449957363121481, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/WHEEL": 13347410390513723930, + "venv/lib/python3.13/site-packages/jsonschema/_legacy_keywords.py": 16481666133229715822, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/numerictypes.pyi": 15565573472138344755, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py": 14190849361275154667, + "frontend/src/lib/stores/__tests__/assistantChat.test.js": 11822882112255142537, + "venv/lib/python3.13/site-packages/jose/jwt.py": 3405491994268385178, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas7bdat.py": 17851617851457266799, + "frontend/src/lib/ui/Icon.svelte": 2201964532717139995, + "frontend/build/_app/immutable/chunks/Bubv4Omr.js": 10698700362455134924, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth2_session.py": 7076806577412682835, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__datasource.py": 1747755531265478106, + "frontend/build/_app/immutable/chunks/D5dPjH6f.js": 10155038412383870508, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_getlimits.py": 118041882543413669, + "backend/tests/conftest.py": 5565151856098492311, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libssl-81ffa89e.so.3": 13913673119166658781, + "venv/lib/python3.13/site-packages/pygments/lexers/_sourcemod_builtins.py": 11809503654078535014, + "frontend/src/services/taskService.js": 11368052191249479533, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/deprecated/decorator.py": 8609500261161560793, + "venv/lib/python3.13/site-packages/authlib/oauth1/errors.py": 1154126353335030046, + "frontend/src/lib/components/translate/__tests__/test_bulk_replace_modal.svelte.js": 6802604718120565742, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/authorization_server.py": 2913800420669417152, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape_base.pyi": 5046405609030418900, + "venv/lib/python3.13/site-packages/smmap/mman.py": 9091562788592406032, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_loongarch64_linux.h": 6566098590441297326, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_windows.py": 9171347078900057357, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/response.py": 353446217435156470, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/distributions.h": 17162252287980242413, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_setitem.py": 10389770446834773837, + "venv/lib/python3.13/site-packages/pandas/core/groupby/__init__.py": 3015263524218708013, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/schema.py": 8358664670620586363, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/dml.py": 5340326603935367534, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py": 7624316342162916928, + "venv/lib/python3.13/site-packages/urllib3/contrib/__init__.py": 15130871412783076140, + "frontend/src/routes/+page.ts": 11160596731849880920, + "venv/lib/python3.13/site-packages/PIL/ImageOps.py": 3884310863548175682, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py": 5247208668583898949, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_raises.py": 9678418010293693275, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nth.py": 17151595277666975085, + "venv/lib/python3.13/site-packages/cffi/_cffi_errors.h": 1479575326813300292, + "venv/lib/python3.13/site-packages/anyio/_core/_tempfile.py": 230288423480899091, + "venv/lib/python3.13/site-packages/passlib/ext/django/utils.py": 8118896525895185626, + "venv/lib/python3.13/site-packages/websockets/legacy/auth.py": 16685128086396181286, + "venv/lib/python3.13/site-packages/pydantic/_internal/_dataclasses.py": 15256193972947054890, + "venv/lib/python3.13/site-packages/greenlet/PyGreenletUnswitchable.cpp": 3160733517193315684, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/licenses/LICENSE": 6808958893921859106, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/__init__.py": 1437580234680265326, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py": 7707707044867513457, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content": 16257335642847993866, + "venv/lib/python3.13/site-packages/pydantic/v1/types.py": 10761779263335288559, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_twodim_base.py": 17623133613018058380, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_year.py": 1478857009124807836, + "venv/lib/python3.13/site-packages/sqlalchemy/future/engine.py": 4639404437703898767, + "backend/src/services/clean_release/__tests__/test_preparation_service.py": 4765724405964286078, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/__init__.py": 9884041726796476720, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_item_selection.py": 1027989019709029615, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/compat.py": 5871636909854554063, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/index_tricks.py": 10051261976498916957, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_html.py": 7732330576029516854, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/_cmd.py": 14954780419054588164, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_implementation.py": 12245524932757110911, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/AUTHORS": 3558407083075395848, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90": 5518911932373565642, + "venv/lib/python3.13/site-packages/numpy/char/__init__.pyi": 12214207343146244743, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex_like.py": 1407890639206728014, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_pad.pyi": 14755435694146003896, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.h": 4516275133897904047, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pygments/lexers/apl.py": 16767474673619335683, + "venv/lib/python3.13/site-packages/pip/_internal/network/xmlrpc.py": 5064964778750366059, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayprint.pyi": 2424868797160722318, + "venv/lib/python3.13/site-packages/pydantic/deprecated/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/parsers.cpython-313-x86_64-linux-gnu.so": 14134106903573638108, + "venv/lib/python3.13/site-packages/pygments/lexers/prolog.py": 599539463980699865, + "venv/lib/python3.13/site-packages/rsa/common.py": 10921682819204792805, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_libsparse.py": 1859997684694949029, + "venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py": 13206297306768491360, + "frontend/src/routes/translate/+page.svelte": 15284819686967093613, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_convert.py": 13349243029437881949, + "frontend/src/routes/reports/llm/[taskId]/report_page.contract.test.js": 4825093389030464765, + "backend/src/app.py": 13545608166211215078, + "backend/src/core/config_models.py": 4264626520931642357, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/licenses/LICENSE": 3868190977070717994, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/bootstrap.py": 3865947239497500815, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_astype.py": 8505605634958454768, + "backend/tests/test_logger.py": 11506419828617508917, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_random.py": 4179188367630060654, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/models.py": 9513172366009392193, + "venv/lib/python3.13/site-packages/apscheduler/executors/tornado.py": 6635576580306890718, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-2.csv": 5423145402839576695, + "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.py": 738588649412338185, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/pkg_resources.py": 14271077832999370068, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_equals.py": 11041884432990762650, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90": 1409455010615482779, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/integration.py": 12670848015915724967, + "venv/lib/python3.13/site-packages/rsa/transform.py": 12261738253972114335, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py": 5126234270435358377, + "venv/lib/python3.13/site-packages/pygments/lexers/compiled.py": 8215290039991205531, + "frontend/src/lib/stores.js": 8062876368729352764, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sample.py": 16877779557071324115, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90": 5799106109999071412, + "venv/lib/python3.13/site-packages/jeepney/io/common.py": 15160647397460834508, + "backend/git_repos/remote/test-repo.git/hooks/pre-applypatch.sample": 15598058327720909861, + "backend/git_repos/remote/test-repo.git/objects/e9/1109abe29d5228675fecd6fc38a097147c090d": 15716642455993350072, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/common.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_common.h": 14732581790650403546, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/base.py": 10514193453447954780, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/extending.py": 9859383893070793914, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/names.py": 705261158040926128, + "venv/lib/python3.13/site-packages/pycparser/ply/ctokens.py": 1599952198962458730, + "venv/lib/python3.13/site-packages/itsdangerous/exc.py": 11181421963755661477, + "venv/lib/python3.13/site-packages/pygments/lexers/csound.py": 2175454840368374515, + "venv/lib/python3.13/site-packages/keyring/compat/__init__.py": 7578020229796085753, + "backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py": 2367759303622417201, + "backend/src/api/routes/translate/_run_list_routes.py": 1259398917100338978, + "venv/lib/python3.13/site-packages/numpy/lib/array_utils.py": 18135114588643176359, + "venv/lib/python3.13/site-packages/bcrypt/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_join.py": 2585969863606902743, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE": 14610443802372107702, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_comparison.py": 11333735187162513512, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_dtypes.py": 481191723198819568, + "venv/lib/python3.13/site-packages/pandas/io/common.py": 12088195203620154171, + "venv/lib/python3.13/site-packages/pip/_internal/commands/show.py": 11839987586497822300, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/__init__.py": 10357835306532281617, + "venv/lib/python3.13/site-packages/pygments/lexers/urbi.py": 1611762607688882372, + "backend/src/services/clean_release/__tests__/test_audit_service.py": 1679130450221264383, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_trio.py": 7459901627473962540, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_bool.py": 433342705586552936, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/wrapper.py": 4633931060151989960, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.pyi": 13068936038543812082, + "frontend/build/_app/immutable/nodes/39.3YlRGfRQ.js": 13837240778368896151, + "venv/lib/python3.13/site-packages/pygments/filter.py": 16846063190466267618, + "venv/lib/python3.13/site-packages/pygments/modeline.py": 6194365452131561478, + "venv/lib/python3.13/site-packages/fastapi/websockets.py": 9910052969532075719, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_version.py": 10384171076976071398, + "frontend/src/routes/datasets/MetricsTable.svelte": 6234185654078176376, + "frontend/build/_app/immutable/chunks/m4cvRrtt.js": 18193077705640240718, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/backend.py": 9072112660082423691, + "backend/src/api/routes/dataset_review.py": 3689614039699023362, + "backend/git_repos/remote/test-repo.git/objects/ae/8d2f5dec5d421b2d6cc1eebaad6d2ef901a90d": 15877648001251681939, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_stat_reductions.py": 11569525436540769152, + "venv/lib/python3.13/site-packages/pip/_internal/cli/spinners.py": 7664056305019151182, + "venv/lib/python3.13/site-packages/jose/backends/cryptography_backend.py": 2875270748627611635, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_io.py": 4199750143323741326, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_quoted_character.py": 2316632434571797367, + "venv/lib/python3.13/site-packages/rapidfuzz/utils_py.py": 12341806772632276946, + "venv/lib/python3.13/site-packages/pandas/core/indexers/objects.py": 409599993084996593, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/hybrid.py": 5793056975404534989, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_loadtxt.py": 17562784940619942447, + "frontend/src/lib/components/dataset-review/ValidationFindingsPanel.svelte": 2403276296409515448, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_index.py": 14187428934500390688, + "frontend/src/routes/+layout.svelte": 2748734957389681795, + "venv/lib/python3.13/site-packages/pandas/_libs/parsers.pyi": 18402185996588014111, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/tools.py": 6437315459200419827, + "venv/lib/python3.13/site-packages/sqlalchemy/event/registry.py": 2857989070743633709, + "venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py": 10408538054406276433, + "venv/lib/python3.13/site-packages/pygments/lexers/math.py": 1647133236144311250, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90": 15012692484070385863, + "venv/lib/python3.13/site-packages/PIL/ImageWin.py": 13635870584232081323, + "venv/lib/python3.13/site-packages/pip/_internal/commands/lock.py": 14782882714168174465, + "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.pyi": 6286629088867436848, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/__init__.py": 11009955319062089477, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/licenses/LICENSE": 5563356551734678258, + "venv/lib/python3.13/site-packages/yaml/tokens.py": 2279161238859232338, + "venv/lib/python3.13/site-packages/pygments/lexers/savi.py": 95400050302239274, + "venv/lib/python3.13/site-packages/pydantic/_internal/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/chunks/DTNvPoZW.js": 15018867916886448364, + "venv/lib/python3.13/site-packages/gitdb/test/__init__.py": 18393574323937353933, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.f": 9330535808093475892, + "venv/lib/python3.13/site-packages/pyasn1/debug.py": 6305633719847955310, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_parquet.py": 11050150015772440923, + "venv/lib/python3.13/site-packages/uvicorn/__init__.py": 11517239807926185665, + "venv/lib/python3.13/site-packages/pillow.libs/libharfbuzz-0692f733.so.0.61230.0": 23110287346167671, + "backend/src/services/clean_release/exceptions.py": 14631509303697939633, + "backend/src/plugins/translate/preview_resolve_provider.py": 7349483761713339246, + "backend/tests/test_translate_history.py": 14504549443376034614, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/database.py": 7111764828004587758, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/models.py": 17356033861792227817, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/__init__.py": 1343779312297539596, + "frontend/src/pages/Dashboard.svelte": 3653104499351855122, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f": 5913807803369559749, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_axis.py": 4097534573847151853, + "venv/lib/python3.13/site-packages/pygments/styles/paraiso_light.py": 15941591873059208999, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/warnings_and_errors.pyi": 9019577563960071498, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/filewrapper.py": 17786759398959482432, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/LICENSE": 14599279238716790189, + "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.py": 16859854811012717088, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/emath.pyi": 3718540478840842664, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_accuracy.py": 3904008607472505376, + "venv/lib/python3.13/site-packages/numpy/tests/test_reloading.py": 17532116685329953400, + "venv/lib/python3.13/site-packages/git/index/typ.py": 11661540784850363024, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/_mapping.py": 11752660241391232497, + "frontend/src/lib/components/reports/__tests__/reports_list.ux.test.js": 16252194679528846126, + "venv/lib/python3.13/site-packages/pandas/_libs/ops.cpython-313-x86_64-linux-gnu.so": 10490009128553397250, + "backend/src/plugins/translate/_llm_parse.py": 3278211416813203155, + "backend/alembic_test.db": 14995253579408279707, + "venv/lib/python3.13/site-packages/greenlet/tests/test_version.py": 6317733744899804292, + "venv/lib/python3.13/site-packages/_pytest/tmpdir.py": 10834220332037364219, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_bar.py": 7791068963246005463, + "venv/lib/python3.13/site-packages/charset_normalizer/constant.py": 3070316197495651997, + "venv/lib/python3.13/site-packages/gitdb/typ.py": 16374739906244805047, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_asfreq.py": 12721047184483392773, + "venv/lib/python3.13/site-packages/pycparser/lextab.py": 16045770806700381661, + "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.pyi": 362674842164060822, + "venv/lib/python3.13/site-packages/uvicorn/_subprocess.py": 13965754246493254447, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_describe.py": 14493300276133670380, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/config.py": 10707678943298497676, + "frontend/src/lib/components/dataset-review/CompiledSQLPreview.svelte": 4866254539173481462, + "venv/lib/python3.13/site-packages/PIL/ImageChops.py": 16368812693381154921, + "venv/lib/python3.13/site-packages/numpy/_core/overrides.pyi": 13121243505132110607, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_arrayobject.py": 9578555381494297966, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/cells.py": 8299309127027168194, + "venv/lib/python3.13/site-packages/pandas/core/arrays/numeric.py": 17834058423729918687, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_groupby.py": 15721254196883995634, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_indexing.py": 8943385096811168079, + "venv/lib/python3.13/site-packages/git/refs/symbolic.py": 14996822770181935589, + "venv/lib/python3.13/site-packages/pandas/core/arrays/period.py": 11560984428402318984, + "frontend/src/routes/settings/automation/+page.svelte": 17397435134589275932, + "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.pyi": 18253950285509265097, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_get.py": 10255752806860493777, + "venv/lib/python3.13/site-packages/pandas/core/reshape/pivot.py": 4736553530021653868, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_lib.py": 6721066015604956469, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_cython_aggregations.py": 10818895573637904764, + "venv/lib/python3.13/site-packages/attr/_next_gen.py": 16353246941851015420, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/constrain.py": 6513876973118703677, + "venv/lib/python3.13/site-packages/dateutil/_version.py": 8279235793001245767, + "frontend/src/lib/api/translate/runs.js": 1220731879179347641, + "venv/lib/python3.13/site-packages/pandas/core/strings/object_array.py": 17631047188839635539, + "venv/lib/python3.13/site-packages/pip/_internal/network/auth.py": 6159841209618753296, + "frontend/src/lib/ui/Input.svelte": 8632025378593263475, + "venv/lib/python3.13/site-packages/jeepney/bus.py": 5163075760432139100, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pct_change.py": 18056235438452125034, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_period.py": 6255181868181182780, + "venv/lib/python3.13/site-packages/pygments/lexers/asm.py": 13861952972248758785, + "backend/src/models/llm.py": 9128215579699548047, + "venv/lib/python3.13/site-packages/pygments/lexers/ada.py": 17032408976634308999, + "backend/tests/core/migration/test_archive_parser.py": 1909788158234142574, + "venv/lib/python3.13/site-packages/pandas/io/formats/xml.py": 12235904458551067063, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_types.py": 4083297168618981717, + "venv/lib/python3.13/site-packages/pandas/core/window/doc.py": 4204367435727844696, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/_spdx.py": 17182188548503720124, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_strings.py": 17398806130402098912, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_read_fwf.py": 13684564756628524738, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/conftest.py": 16571782049241458769, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_css.py": 17765129030290410902, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_datetime_index.py": 15448494560143263150, + "venv/lib/python3.13/site-packages/uvicorn/loops/__init__.py": 15130871412783076140, + "backend/src/services/clean_release/dto.py": 11031410734734770552, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/__init__.py": 15130871412783076140, + "frontend/src/routes/settings/notifications/+page.svelte": 14504217413720856827, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py": 7852235015155694076, + "backend/src/core/__tests__/test_superset_profile_lookup.py": 2078836378584435447, + "venv/lib/python3.13/site-packages/pydantic/v1/utils.py": 902648247561165429, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.pyx": 7085380878820747579, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/registry.py": 13306388361671753373, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/inout.f90": 1521999519583206538, + "frontend/build/_app/immutable/chunks/1GL3fr2Q.js": 3002513903507756427, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_quarter.py": 11099677280196239755, + "venv/lib/python3.13/site-packages/pandas/core/groupby/groupby.py": 5536922766239875007, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/RECORD": 6518517239543344179, + "venv/lib/python3.13/site-packages/pluggy/_result.py": 16790448391766505769, + "frontend/tailwind.config.js": 13139381085024634801, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90": 6219951399575860362, + "backend/src/core/middleware/trace.py": 13093835356377196397, + "frontend/build/_app/immutable/chunks/8fleLJj9.js": 13620314947025002547, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/__init__.py": 5896924546560667519, + "venv/lib/python3.13/site-packages/pydantic/functional_validators.py": 5835339743072048940, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.c": 9318655518998644962, + "venv/lib/python3.13/site-packages/sqlalchemy/util/compat.py": 16148553252010089561, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/dtype.pyi": 465999539608816848, + "venv/lib/python3.13/site-packages/websockets/asyncio/messages.py": 6848925149930551457, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/licenses/LICENSE": 10253862887434903467, + "venv/lib/python3.13/site-packages/more_itertools/more.py": 1631135582441184133, + "venv/lib/python3.13/site-packages/greenlet/TThreadStateDestroy.cpp": 13749797532421836328, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hashes.py": 8545380307201732345, + "venv/lib/python3.13/site-packages/_pytest/python.py": 1829073958095716309, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_reductions.py": 633644255158859565, + "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe.py": 16525846817331842080, + "venv/lib/python3.13/site-packages/rsa/asn1.py": 3861968161559322784, + "venv/lib/python3.13/site-packages/jeepney/io/__init__.py": 2568357146184259175, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_tz_convert.py": 77283525137564255, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_float.py": 10455718110956856820, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_formats.py": 10263085276270778330, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/dml.py": 17308908394336670576, + "venv/lib/python3.13/site-packages/pydantic/networks.py": 15767095796055034509, + "venv/lib/python3.13/site-packages/PIL/McIdasImagePlugin.py": 14137545069906812251, + "venv/lib/python3.13/site-packages/packaging/version.py": 13470993734108007779, + "frontend/src/lib/ui/PageHeader.svelte": 3800784212388586861, + "backend/src/core/superset_client/_datasets.py": 9256475565431273727, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_quoting.py": 1147992698412929658, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/METADATA": 11759004913807981650, + "backend/src/plugins/translate/__tests__/test_dictionary_filter.py": 2426844436521732941, + "backend/src/plugins/translate/__tests__/test_preview.py": 13085659611728720229, + "backend/git_repos/remote/test-repo.git/objects/93/9cc583a18267406014c57617ccb557569f6aaf": 5474754694741999746, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_online.py": 11850497659869773510, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.py": 5933622200264572885, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h": 7896028550808252043, + "venv/lib/python3.13/site-packages/dateutil/relativedelta.py": 5903095963079475484, + "venv/lib/python3.13/site-packages/pygments/styles/friendly_grayscale.py": 16840106759769837649, + "venv/lib/python3.13/site-packages/packaging/_tokenizer.py": 7442392076059866359, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/exc.py": 15559705487889657091, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_cpp.cpython-313-x86_64-linux-gnu.so": 7490281502544276964, + "venv/lib/python3.13/site-packages/pygments/lexers/rebol.py": 10460732731157940232, + "frontend/src/routes/reports/llm/[taskId]/+page.svelte": 14394593511269407852, + "venv/lib/python3.13/site-packages/fastapi/exceptions.py": 12665775976182239091, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_monotonic.py": 11817523305776951162, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_endian.h": 2761502363895204652, + "frontend/src/lib/stores/environmentContext.js": 1762535408632658714, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_extending.py": 10202091354750153497, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/hybrid.py": 14287665090144592501, + "venv/lib/python3.13/site-packages/numpy/_core/overrides.py": 252940520997718714, + "backend/src/api/routes/git/_environment_routes.py": 1034235394475003092, + "venv/lib/python3.13/site-packages/cffi/vengine_cpy.py": 10684192171370688079, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_blocking.py": 6312017389529916004, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_unicode_ddl.py": 2569618488804767890, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/models.py": 15928924478695638423, + "frontend/build/_app/immutable/chunks/DlfKZF9V.js": 12561303838931162000, + "venv/lib/python3.13/site-packages/numpy/_core/cversions.py": 9724467539503410469, + "backend/src/api/routes/assistant/_llm_planner_intent.py": 16189718762013093878, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_complex.py": 4290059580478881700, + "venv/lib/python3.13/site-packages/pygments/lexers/oberon.py": 15220143799603451830, + "venv/lib/python3.13/site-packages/_pytest/assertion/util.py": 16957445183087315124, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/constructors.py": 7587476800569414769, + "venv/lib/python3.13/site-packages/fastapi/staticfiles.py": 4094330072433302614, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/typst.tpl": 5055419073126793137, + "venv/lib/python3.13/site-packages/pandas/io/_util.py": 13608922148814398500, + "scripts/gen_semantics.py": 11397714264377363083, + "frontend/src/lib/api/translate/corrections.js": 3619404083693055292, + "backend/src/models/__tests__/test_report_models.py": 18076243829002249148, + "backend/git_repos/remote/test-repo.git/objects/6f/85e20ce3ef98cf07a2f102498b71b9462552c5": 3012017807908986452, + "backend/src/core/superset_client/_dashboards_filters.py": 8706676245520282810, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_cov_corr.py": 8117511855230249212, + "venv/lib/python3.13/site-packages/pygments/lexers/_lasso_builtins.py": 4006621424665751347, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/utils.py": 8633356372647820801, + "venv/lib/python3.13/site-packages/_pytest/outcomes.py": 12782895027812738142, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply.py": 12349190935180702377, + "frontend/build/_app/immutable/nodes/19.DbR8_rS6.js": 806351059105385143, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_datetime.py": 7862725028865965163, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dim2.py": 5767600151459095125, + "venv/lib/python3.13/site-packages/rsa/pkcs1.py": 2576732594642491910, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/RECORD": 12015288851076448205, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_ios.h": 6751259472945638998, + "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimes.py": 10585034798097337148, + "venv/lib/python3.13/site-packages/pandas/api/__init__.py": 1145864207387918302, + "backend/git_repos/remote/test-repo.git/hooks/applypatch-msg.sample": 12627299623252391515, + "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.pyi": 16799580742094025110, + "backend/tests/test_task_manager.py": 1706217361689506763, + "venv/lib/python3.13/site-packages/pygments/styles/inkpot.py": 10516710471319090846, + "venv/lib/python3.13/site-packages/pip/_internal/operations/prepare.py": 13514839972066861359, + "venv/lib/python3.13/site-packages/anyio/from_thread.py": 7973678341601453474, + "venv/lib/python3.13/site-packages/pandas/_libs/arrays.pyi": 12629806207276576877, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_fillna.py": 7349777469648334282, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string_arrow.py": 10008395772220468318, + "venv/lib/python3.13/site-packages/PIL/ImImagePlugin.py": 15452956038794399492, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py": 8864112842559211971, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/incfile.f90": 4348588746493647387, + "venv/lib/python3.13/site-packages/numpy/ma/core.py": 338350463523585845, + "venv/lib/python3.13/site-packages/pydantic/plugin/_schema_validator.py": 857640644840976862, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py": 18325640697829098192, + "venv/lib/python3.13/site-packages/pip/_internal/commands/hash.py": 11824898770873127699, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_round_trip.py": 14684057343786032776, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_coercion.py": 3551994404797560483, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_collections.py": 7772437080414835462, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_ipython_compat.py": 12632271159842988561, + "venv/lib/python3.13/site-packages/numpy/lib/mixins.pyi": 15597536290223628777, + "venv/lib/python3.13/site-packages/pygments/styles/igor.py": 2291640843781128270, + "frontend/src/routes/settings/git/+page.svelte": 9547035239167234477, + "venv/lib/python3.13/site-packages/rapidfuzz/_utils.py": 14374663810542207121, + "backend/src/plugins/search.py": 888817404897740233, + "venv/lib/python3.13/site-packages/pygments/lexers/_vim_builtins.py": 6842381248727719900, + "backend/src/plugins/storage/__init__.py": 5046554941488079204, + "backend/src/core/superset_client/_datasets_preview_filters.py": 14154361389981199486, + "backend/tests/services/clean_release/test_demo_mode_isolation.py": 1970652424726919519, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp": 10880681943327843928, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/comparisons.pyi": 9338084426044982038, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_iteration.py": 2118501258411211851, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/METADATA": 16498441272591167134, + "venv/lib/python3.13/site-packages/pydantic/deprecated/class_validators.py": 2200511838255373813, + "venv/lib/python3.13/site-packages/passlib/handlers/argon2.py": 835074952952017434, + "venv/lib/python3.13/site-packages/pandas/tests/io/__init__.py": 15130871412783076140, + "backend/git_repos/remote/test-repo.git/objects/22/91d2eb86d77accf7401f8952778809cd1aa4d4": 5120428041118096941, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/__init__.py": 12911374670789466961, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_unicode.py": 1103608932321322989, + "backend/src/core/auth/repository.py": 7314530014494164270, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_interpolate.py": 7354685880215444946, + "venv/lib/python3.13/site-packages/pandas/core/computation/pytables.py": 16326122536715961388, + "frontend/build/_app/immutable/chunks/CDGsC-OT.js": 13013258585278660886, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv": 5882025767947638305, + "venv/lib/python3.13/site-packages/attrs/__init__.py": 9502968706258875910, + "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.pyi": 12043292763005874815, + "venv/lib/python3.13/site-packages/pandas/_libs/index.cpython-313-x86_64-linux-gnu.so": 18409579812171549318, + "venv/lib/python3.13/site-packages/pandas/core/sample.py": 11913688303879867963, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_label_or_level_utils.py": 3423644585913150841, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py": 6067836157632573182, + "venv/lib/python3.13/site-packages/numpy/f2py/__main__.py": 12567751646090102167, + "venv/lib/python3.13/site-packages/python_multipart/exceptions.py": 5971058243218049183, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_fillna.py": 4610666845291315333, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/ansi.py": 948249091929588017, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_shape_manipulation.py": 12598431412396627042, + "venv/lib/python3.13/site-packages/pandas/io/formats/_color_data.py": 15614976586613738953, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_insert.py": 15536994417338770457, + "venv/lib/python3.13/site-packages/pandas/core/window/common.py": 17956497339875932377, + "venv/lib/python3.13/site-packages/PIL/PixarImagePlugin.py": 12061717157676819554, + "venv/lib/python3.13/site-packages/_pytest/pytester_assertions.py": 1899505062406979663, + "venv/lib/python3.13/site-packages/pycparser/c_lexer.py": 10964496587169353564, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_memmap.py": 8709963808115492688, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/METADATA": 10810011740984652381, + "venv/lib/python3.13/site-packages/greenlet/tests/test_cpp.py": 10982107081267457286, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_seed_sequence.py": 7687465232954593311, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_between_time.py": 14266333058913745751, + "venv/lib/python3.13/site-packages/pandas/tests/test_multilevel.py": 10500316376521962061, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_series.py": 16418555817529711079, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90": 11326797716215117266, + "venv/lib/python3.13/site-packages/passlib/tests/backports.py": 17098448557554464521, + "backend/src/plugins/migration.py": 16213446701284149979, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunclike.py": 12077553320554633586, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/inference.py": 2786441797589123900, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/__init__.py": 15130871412783076140, + "backend/src/api/routes/__tests__/test_tasks_logs.py": 17724385243163092479, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/stride_tricks.pyi": 5844806555773292985, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timedeltas.py": 1175883320586860493, + "backend/git_repos/remote/test-repo.git/objects/c2/491dfd8c841bacd5f491510f6334aa4a626f00": 6297303620364618482, + "venv/lib/python3.13/site-packages/pandas/core/arrays/numpy_.py": 16641729409992576358, + "backend/alembic/versions/ed310b33f02c_multi_language_translation_tables.py": 1424919631205944664, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_deprecations.py": 14624516389510242394, + "venv/lib/python3.13/site-packages/ecdsa/curves.py": 812969717084691115, + "venv/lib/python3.13/site-packages/passlib/ext/__init__.py": 15240312484046875203, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_network.py": 13159427333040109523, + "venv/lib/python3.13/site-packages/bcrypt/__about__.py": 11196369962175692786, + "venv/lib/python3.13/site-packages/urllib3/util/__init__.py": 2848870790459558599, + "backend/src/core/__tests__/test_superset_preview_pipeline.py": 5793244881571660499, + "backend/src/services/clean_release/repositories/publication_repository.py": 11208425895213508165, + "backend/src/plugins/translate/orchestrator_sql_rows.py": 13473935462270832541, + "venv/lib/python3.13/site-packages/pandas/_libs/hashing.pyi": 5241441378073929968, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_normalize.py": 3203921571999101793, + "frontend/src/lib/api/assistant.js": 15470667170083225911, + "venv/lib/python3.13/site-packages/pydantic/v1/mypy.py": 17076910404409672245, + "venv/lib/python3.13/site-packages/numpy/_configtool.py": 2946953194004101078, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_categorical.py": 1329115818264527103, + "venv/lib/python3.13/site-packages/pandas/api/executors/__init__.py": 16954693181142010028, + "venv/lib/python3.13/site-packages/pygments/lexers/yang.py": 7409365668425173823, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_index.py": 4908727359687606870, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_datetimes.py": 8863748366184419339, + "venv/lib/python3.13/site-packages/more_itertools/more.pyi": 4844596605492825806, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_struct_accessor.py": 6567451952835390075, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/datasource.pyi": 16752667877866430577, + "venv/lib/python3.13/site-packages/pygments/lexers/scdoc.py": 8481749542463754279, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90": 8821492401453445757, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/keyring/backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py": 16386268386376675175, + "frontend/src/lib/ui/LanguageSwitcher.svelte": 3899734183369041614, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/issue232.py": 6498198296113395367, + "venv/lib/python3.13/site-packages/cryptography/hazmat/__init__.py": 6534110674636458866, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_finfo.py": 17174674209412768422, + "frontend/build/_app/immutable/nodes/1.Bd5SZB9n.js": 17092049553387147303, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/RECORD": 11976403473353722969, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_lexsort.py": 10394832796613968484, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/okp_key.py": 10312614562914096039, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/jose/backends/base.py": 12795468809472351388, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/quoted_character/foo.f": 15318083678609435813, + "venv/lib/python3.13/site-packages/pandas/core/interchange/utils.py": 11401792151107207834, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/scripts.py": 8759605303886441976, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_partial.py": 3151286293440416036, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_records.py": 6252761812228230408, + "venv/lib/python3.13/site-packages/attrs/validators.py": 10346563361083429998, + "venv/lib/python3.13/site-packages/numpy/lib/_iotools.pyi": 12873243737872788349, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.cpython-313-x86_64-linux-gnu.so": 2311012065007769341, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_writers.py": 103545128256076790, + "venv/lib/python3.13/site-packages/jsonschema/exceptions.py": 15651767069704734674, + "venv/lib/python3.13/site-packages/keyring/testing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/greenlet_allocator.hpp": 11041111583319491309, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/fastapi/security/api_key.py": 6965937678104291169, + "venv/lib/python3.13/site-packages/pygments/styles/xcode.py": 14124729477757765388, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_astype.py": 7497268667246913350, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi": 9835891299056543360, + "venv/lib/python3.13/site-packages/numpy/tests/test_lazyloading.py": 17465787495701737655, + "venv/lib/python3.13/site-packages/pygments/lexers/lean.py": 14518351619544450286, + "venv/lib/python3.13/site-packages/pygments/lexers/ampl.py": 4594260378653369985, + "backend/src/services/clean_release/repository.py": 11403333156347178483, + "frontend/src/lib/components/reports/ReportsList.svelte": 15460090587871611258, + "backend/src/services/mapping_service.py": 9713400496587758211, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraysetops.pyi": 1782641795267171928, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2py2e.py": 8571347023940385644, + "venv/lib/python3.13/site-packages/numpy/ma/testutils.py": 9355402483340137461, + "venv/lib/python3.13/site-packages/passlib/handlers/oracle.py": 12959175637015399815, + "backend/git_repos/remote/test-repo.git/objects/79/b070ad8af7bbc12169f7660d2a7a72ec7a889a": 8153595714065675791, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.py": 4440659352851541547, + "venv/lib/python3.13/site-packages/passlib/handlers/mssql.py": 2800599582708170195, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py": 1331438198531942242, + "venv/lib/python3.13/site-packages/jeepney/io/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.py": 3646474165295296669, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parse_iso8601.py": 9100947620267156161, + "venv/lib/python3.13/site-packages/PIL/FliImagePlugin.py": 13364963053197422923, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunc_config.py": 14728417910466146460, + "venv/lib/python3.13/site-packages/pandas/core/computation/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/off.py": 16254524872582859561, + "frontend/src/components/git/DeploymentModal.svelte": 16301125393395343650, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_replace.py": 8784361132920473760, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_cell_widths.py": 5724379364993806351, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__init__.py": 8880435562116660648, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90": 14491312943942432024, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/version.py": 5000350193835202949, + "venv/lib/python3.13/site-packages/cffi/error.py": 8147505969912539538, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_strptime.py": 14328510310436552635, + "backend/src/models/dataset_review_pkg/_mapping_models.py": 8898456326244890685, + "venv/lib/python3.13/site-packages/ecdsa/ellipticcurve.py": 15624510849346629163, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_astype.py": 15275720655739710249, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunclike.pyi": 14623308681600207918, + "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.py": 7365943844063702766, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/exceptions.py": 14982764273485726199, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/table.py": 16856253349556498073, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf": 15094859289098837494, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_astype.py": 4178231007649608531, + "venv/lib/python3.13/site-packages/pydantic/experimental/__init__.py": 492399139963056461, + "venv/lib/python3.13/site-packages/passlib/utils/des.py": 2650106381178222229, + "venv/lib/python3.13/site-packages/pandas/core/flags.py": 4690844374637430013, + "venv/lib/python3.13/site-packages/idna/codec.py": 4260241549062101779, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.pyi": 15864712173815045309, + "venv/lib/python3.13/site-packages/httpcore/_async/http2.py": 16350817785499681224, + "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.pyi": 10638891136586198429, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_duplicated.py": 6659959750254523427, + "venv/lib/python3.13/site-packages/pygments/lexers/graphql.py": 2307854666015224677, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resampler_grouper.py": 8388490036390951341, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/constant_time.py": 2499026008403328245, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.py": 1341849861184131135, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_map.py": 6556132946198785761, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_frame.py": 2169381747938271444, + "venv/lib/python3.13/site-packages/attrs/exceptions.py": 2871247302586505373, + "venv/lib/python3.13/site-packages/referencing/tests/test_referencing_suite.py": 8875120876162738440, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jose/jwe.py": 3325660353225624025, + "venv/lib/python3.13/site-packages/urllib3/http2/probe.py": 4069929463671970243, + "venv/lib/python3.13/site-packages/jsonschema/cli.py": 9813914882090789748, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_melt.py": 15663807247682146566, + "venv/bin/pyrsa-encrypt": 5858278204727417482, + "frontend/src/lib/components/translate/BulkReplaceModal.svelte": 9447617465987205060, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_formats.py": 12299393760307251036, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/__init__.py": 8924316361489544973, + "backend/src/core/superset_client/_datasets_preview.py": 12644037069207561202, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_frozen.py": 3484963987053884566, + "venv/lib/python3.13/site-packages/numpy/fft/__init__.py": 9343449448737026658, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numeric.py": 5627177940393829333, + "venv/lib/python3.13/site-packages/attr/_cmp.pyi": 14443711863388606665, + "venv/lib/python3.13/site-packages/gitdb/base.py": 7927279446353696534, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/__init__.py": 7526309124863950484, + "venv/lib/python3.13/site-packages/pygments/lexers/futhark.py": 10102535873433759899, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/requests.py": 1102963893193914979, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/libdivide.h": 5314232500579481313, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/licenses/LICENSE": 6965457853328313914, + "backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py": 14275839608126658275, + "backend/src/services/git/_gitea.py": 12631200182530815617, + "backend/src/plugins/translate/__tests__/test_scheduler.py": 11257332466578758156, + "venv/lib/python3.13/site-packages/PIL/SgiImagePlugin.py": 6916200065790425497, + "venv/lib/python3.13/site-packages/numpy/_typing/_dtype_like.py": 1598511035344858524, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_loc.py": 2127584756555503873, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_misc.pyi": 7544619194032232861, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_duplicates.py": 9830936017197354309, + "venv/lib/python3.13/site-packages/attr/converters.pyi": 17675091788614033166, + "backend/src/services/clean_release/facade.py": 11231787492455424065, + "venv/lib/python3.13/site-packages/anyio/to_interpreter.py": 8369454842687342401, + "venv/lib/python3.13/site-packages/numpy/version.py": 1497063540123613501, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bindgen.py": 8637878018232418583, + "venv/lib/python3.13/site-packages/pip/_internal/commands/search.py": 8292218231992728142, + "venv/lib/python3.13/site-packages/pandas/core/indexes/frozen.py": 1419685664276640120, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_take.py": 14969455660160053080, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/connection.py": 5582413226288987808, + "venv/lib/python3.13/site-packages/urllib3/util/wait.py": 14629837381061032546, + "venv/lib/python3.13/site-packages/click/exceptions.py": 9734955259447933725, + "frontend/build/_app/immutable/chunks/B0qBRzsG.js": 13604593522624221085, + "venv/lib/python3.13/site-packages/greenlet/TStackState.cpp": 16720079760074325527, + "venv/lib/python3.13/site-packages/pydantic/aliases.py": 14481980467204711659, + "venv/lib/python3.13/site-packages/pyasn1/type/tag.py": 13912273274509186651, + "venv/lib/python3.13/site-packages/numpy/_utils/__init__.pyi": 13530522898409268883, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_win_type.py": 18105114803686556748, + "venv/lib/python3.13/site-packages/pip/_internal/commands/uninstall.py": 11003472265011262515, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/evaluator.py": 6348022789899831255, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapped_collection.py": 11377280960650304531, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/socks.py": 17581293673028078134, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.f90": 1249061697041863692, + "venv/lib/python3.13/site-packages/PIL/_imagingmorph.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/ecdsa/der.py": 9374566189581725372, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_masked.py": 5380551301916549925, + "venv/lib/python3.13/site-packages/pygments/lexers/clean.py": 17772169928835025327, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_non_unique.py": 15286893322149413712, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/fields.py": 10090313990429695520, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_swaplevel.py": 3584770792383216626, + "venv/lib/python3.13/site-packages/pygments/lexers/_lilypond_builtins.py": 1766946089314631488, + "backend/src/core/ws_log_handler.py": 17175572704051278951, + "backend/src/api/routes/llm.py": 7404985960617844546, + "venv/lib/python3.13/site-packages/pygments/lexers/eiffel.py": 8964563077187051946, + "venv/lib/python3.13/site-packages/_pytest/nodes.py": 515939386237558331, + "venv/lib/python3.13/site-packages/pygments/styles/borland.py": 17570558758932580659, + "venv/lib/python3.13/site-packages/pygments/lexers/erlang.py": 11757064262773184741, + "backend/src/plugins/translate/plugin.py": 9225230324052126034, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/RECORD": 11111103193315065053, + "backend/src/plugins/translate/__tests__/test_orthogonal_fixes.py": 264408615924319135, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_sequence.py": 3721630758772772345, + "venv/lib/python3.13/site-packages/pip/_internal/utils/retry.py": 15244280495983216204, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/base.py": 5924592154431932923, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.BSD": 16833702494864671773, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_constructors.py": 17392287676196409733, + "venv/lib/python3.13/site-packages/pip/_internal/commands/inspect.py": 1401259241736437656, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/METADATA": 8985010079096958084, + "backend/git_repos/remote/test-repo.git/objects/59/3a37acec7d2bddce10df90ab17bc9ede52e523": 1117161574576783985, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hmac.py": 18132740541139891824, + "venv/lib/python3.13/site-packages/keyring/devpi_client.py": 3445890176686211982, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/tree.py": 4991806303236874829, + "venv/lib/python3.13/site-packages/pillow.libs/libwebpdemux-747f2b49.so.2.0.17": 7615380692384566654, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/parameter.py": 2793853093222900337, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/live_render.py": 14619617939683800204, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_tools.py": 13994164937603424236, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5-fcafa220.so.3.3": 5620628698712971642, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_sorted.py": 1899608688401238388, + "venv/lib/python3.13/site-packages/git/objects/tree.py": 10239027037919781330, + "venv/lib/python3.13/site-packages/pygments/lexers/vyper.py": 6477559246065994199, + "venv/lib/python3.13/site-packages/rapidfuzz/utils_cpp.cpython-313-x86_64-linux-gnu.so": 16145829319198889672, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token.py": 4747545058753492487, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_equals.py": 9903250467264848187, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_repr.py": 11737029058271003097, + "backend/src/plugins/translate/dictionary_filter.py": 18047895364995512274, + "backend/git_repos/remote/test-repo.git/description": 15262637409357137373, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo77.f": 4046503346951676582, + "venv/lib/python3.13/site-packages/pandas/tests/test_col.py": 14781555956509956371, + "venv/lib/python3.13/site-packages/PIL/CurImagePlugin.py": 17697303205012181529, + "venv/lib/python3.13/site-packages/numpy/random/__init__.pxd": 7355772669172093814, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.cpython-313-x86_64-linux-gnu.so": 12776951671822017500, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/events.py": 7576713358952064464, + "venv/lib/python3.13/site-packages/ecdsa/ecdsa.py": 9770689913380927623, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_subclass.py": 13490541871827928531, + "venv/lib/python3.13/site-packages/git/objects/submodule/root.py": 5322248117564025370, + "venv/lib/python3.13/site-packages/jsonschema_specifications/_core.py": 14812112544772987164, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_orm_types.py": 5508682532707462217, + "venv/lib/python3.13/site-packages/starlette/middleware/errors.py": 1337979724602864440, + "venv/lib/python3.13/site-packages/pygments/lexers/rdf.py": 14488319292387226505, + "venv/lib/python3.13/site-packages/pandas/_testing/__init__.py": 10127496080404419481, + "venv/lib/python3.13/site-packages/pydantic/_internal/_import_utils.py": 4029157986210295967, + "venv/lib/python3.13/site-packages/typing_extensions.py": 8402965285733247527, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/RECORD": 11904769847385571600, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_regression.py": 16266600037241221681, + "venv/lib/python3.13/site-packages/pip/_internal/req/constructors.py": 17485271035479378662, + "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.pyi": 10487441680587530350, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/framework_integration.py": 3935346152156572025, + "backend/src/plugins/translate/preview_session_ops.py": 14499196532448992687, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv": 8620268345075425735, + "venv/lib/python3.13/site-packages/gitdb/stream.py": 3035738824550231197, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/WHEEL": 8954358347596196608, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/METADATA": 14070889071949105584, + "venv/lib/python3.13/site-packages/jeepney/__init__.py": 1063800617763464773, + "venv/lib/python3.13/site-packages/pip/_internal/locations/_sysconfig.py": 4773855595767526182, + "venv/lib/python3.13/site-packages/rpds/rpds.cpython-313-x86_64-linux-gnu.so": 561326734302492859, + "venv/lib/python3.13/site-packages/numpy/random/_common.pyi": 5094115692952609118, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/versioncontrol.py": 13742159245132241245, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_constructors.py": 6727209833819502644, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/dml.py": 6519732236745017861, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/httpcore/_sync/http2.py": 11167798787131917524, + "venv/lib/python3.13/site-packages/httpcore/_backends/sync.py": 576247220834179928, + "frontend/src/lib/utils/debounce.js": 16884470786640632815, + "backend/src/services/clean_release/repositories/compliance_repository.py": 7402628017251283691, + "frontend/src/routes/dashboards/[id]/+page.svelte": 12833231703682809118, + "backend/src/api/routes/dashboards/_schemas.py": 10686942001147126057, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/INSTALLER": 17282701611721059870, + "backend/git_repos/remote/test-repo.git/config": 14478893374498894766, + "venv/lib/python3.13/site-packages/pygments/lexers/jmespath.py": 7426464251945393925, + "venv/lib/python3.13/site-packages/pandas/tests/extension/conftest.py": 16886862391161243448, + "venv/lib/python3.13/site-packages/pydantic/deprecated/json.py": 17692639396786690144, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/test_decimal.py": 17811784255174057561, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/parameters.py": 247312908510013930, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_constructors.py": 13890224577680389718, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/RECORD": 7363618870628306370, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90": 13943066317159236257, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.py": 652332294655046106, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_nep50_promotions.py": 6318578947214302182, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/flatiter.py": 3066469329738423021, + "venv/lib/python3.13/site-packages/pandas/core/ops/docstrings.py": 3721650738518391256, + "venv/lib/python3.13/site-packages/pandas/core/reshape/encoding.py": 12702053687535473061, + "venv/lib/python3.13/site-packages/pydantic/types.py": 785880062468926292, + "backend/src/services/validation_service.py": 4040391162969506763, + "backend/test_auth.db": 18214842050920965999, + "venv/lib/python3.13/site-packages/PIL/SpiderImagePlugin.py": 12234762087257163606, + "venv/bin/websockets": 12099863324306500376, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/ssh.py": 16262079536832961001, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg8000.py": 6580512354643849828, + "backend/src/models/dataset_review_pkg/__init__.py": 17789694606496652579, + "scripts/generate_financial_arrears_data.py": 15989529185799374517, + "venv/lib/python3.13/site-packages/PIL/ImageDraw.py": 12919304671639673744, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_complex.py": 11732242536199439023, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/METADATA": 15888766579203341778, + "backend/src/api/routes/validation.py": 4501767302235076958, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/wsproto_impl.py": 3072714633272661847, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/ma/LICENSE": 6723325434476453127, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/RECORD": 12733654377842895588, + "venv/lib/python3.13/site-packages/jaraco/functools/__init__.pyi": 2872039192528394677, + "backend/src/services/clean_release/demo_data_service.py": 1822246829322620623, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/lib/stores/health.js": 1061942219531952418, + "venv/lib/python3.13/site-packages/jeepney/io/tests/utils.py": 10346859893683522113, + "backend/tests/test_datasets.py": 10782968094631273511, + "venv/lib/python3.13/site-packages/jeepney/io/asyncio.py": 13239992245695516007, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/__init__.py": 7316739139609490520, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/min_max_.py": 13457611930368041821, + "venv/lib/python3.13/site-packages/pandas/core/sorting.py": 689057022713741051, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/pygments/styles/tango.py": 12389250878249075539, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_loop.py": 6502725909989655118, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/aead.py": 8740476942925346444, + "frontend/src/lib/stores/sidebar.js": 8409084311045055153, + "frontend/src/pages/Settings.svelte": 12818597464628135154, + "venv/lib/python3.13/site-packages/pydantic/experimental/arguments_schema.py": 8644805798814234457, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi": 13016654355866474644, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.py": 15657897994221955882, + "venv/lib/python3.13/site-packages/ecdsa/util.py": 10543788809724099209, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_hour.py": 14128508606361694814, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/profiling.py": 16030397164203895281, + "venv/lib/python3.13/site-packages/pandas/core/arrays/__init__.py": 10460719978124302175, + "backend/src/api/routes/dataset_review_pkg/_routes.py": 11040245149296528009, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py": 3369246520501764730, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/exceptions.py": 2873060848310644552, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_misc.py": 9190561773853901527, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_round.py": 7912161077874611432, + "venv/lib/python3.13/site-packages/pandas/core/interchange/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/PpmImagePlugin.py": 7107324729714470853, + "venv/lib/python3.13/site-packages/pip/_internal/utils/_log.py": 13011536737418204268, + "venv/lib/python3.13/site-packages/requests/models.py": 9104898985870652256, + "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/test_rapidfuzz_packaging.py": 5189055608193366093, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_common.py": 2265736743367879051, + "frontend/src/routes/datasets/DatasetPreview.svelte": 4250995999947659034, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_ewm.py": 12153690217678546798, + "backend/src/services/git_service.py": 1930048176535450912, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/lexers/asn1.py": 15030988816882821134, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/conftest.py": 6137462119729731945, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_doc.py": 7865575374100528149, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/METADATA": 732041908491732594, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_value_counts.py": 12340872812120847127, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fromnumeric.pyi": 8671744104085911610, + "venv/lib/python3.13/site-packages/numpy/_core/shape_base.pyi": 10225243791643474943, + "backend/src/services/__tests__/test_llm_plugin_persistence.py": 16769242892960874042, + "venv/lib/python3.13/site-packages/pluggy/_callers.py": 1042673447718196223, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/sql.py": 13315906751371033170, + "venv/lib/python3.13/site-packages/numpy/dtypes.py": 14128421398870718692, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_aix.h": 13316272821279308986, + "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.py": 15854257948148516490, + "venv/lib/python3.13/site-packages/jaraco/context/__init__.py": 10975097417056278427, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_box_unbox.py": 7579587620530953711, + "venv/lib/python3.13/site-packages/PIL/ImageColor.py": 17058618058554970738, + "venv/lib/python3.13/site-packages/pydantic/_internal/_signature.py": 17075003201648027250, + "venv/lib/python3.13/site-packages/pandas/core/_numba/extensions.py": 4132402557064663751, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reindex.py": 12459492712890114705, + "venv/lib/python3.13/site-packages/pygments/token.py": 6987328478153445584, + "backend/src/core/utils/superset_context_extractor/__init__.py": 1074191108198498747, + "frontend/build/_app/immutable/nodes/32.B_t7oMN1.js": 4416700813909350907, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__main__.py": 6480933938145689964, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending.pyx": 756189645898997788, + "venv/lib/python3.13/site-packages/passlib/tests/_test_bad_register.py": 5446848310854472376, + "venv/lib/python3.13/site-packages/cryptography/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-1.csv": 16349400027062875699, + "venv/lib/python3.13/site-packages/attr/validators.py": 4453080662115911998, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.pyi": 12925006572914814268, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pop.py": 14885271225856187795, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/RECORD": 13494296690334916257, + "venv/lib/python3.13/site-packages/pygments/lexers/qlik.py": 3881663935630350152, + "frontend/build/_app/immutable/nodes/28.DYTjUDoH.js": 15759016421687403292, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/client.py": 18443944554871937480, + "venv/lib/python3.13/site-packages/_pytest/python_api.py": 12953851690889336092, + "venv/lib/python3.13/site-packages/pydantic/json_schema.py": 15678278224696353978, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nditer.pyi": 33523064068376750, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py": 15294662527620994511, + "venv/lib/python3.13/site-packages/websockets/asyncio/client.py": 5694225754072131767, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_assumed_shape.py": 18361009188431483164, + "venv/lib/python3.13/site-packages/more_itertools/recipes.pyi": 16788810745659802820, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_transpose.py": 17983160984979323393, + "venv/lib/python3.13/site-packages/pygments/lexers/templates.py": 16267123844830647955, + "venv/lib/python3.13/site-packages/h11/__init__.py": 222801976520197308, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_string.py": 10141066226714805009, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_common.py": 3559416690270529904, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_dict_compat.py": 18196543090455290455, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/METADATA": 317417773265681256, + "venv/lib/python3.13/site-packages/pygments/lexers/cddl.py": 1303059539145221713, + "frontend/src/lib/api/reports.js": 2328857814720054000, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_types.py": 7175518113263603341, + "venv/lib/python3.13/site-packages/numpy/random/c_distributions.pxd": 16574161095720077595, + "venv/lib/python3.13/site-packages/psycopg2/__init__.py": 15798412693009721199, + "venv/lib/python3.13/site-packages/httpcore/_async/connection_pool.py": 932468678264370661, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_ewm.py": 13789842684407148830, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_object.py": 9215781825358309147, + "venv/lib/python3.13/site-packages/gitdb/test/test_util.py": 541144638852210407, + "venv/lib/python3.13/site-packages/httpcore/_trace.py": 9576253018891841832, + "venv/lib/python3.13/site-packages/multipart/__init__.py": 6496114190873890851, + "venv/lib/python3.13/site-packages/httpcore/_async/http_proxy.py": 13364803556177997526, + "venv/lib/python3.13/site-packages/git/refs/log.py": 5175801243332619268, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE": 5669644120528099197, + "backend/src/plugins/translate/__tests__/test_lang_detect.py": 2328877106785068272, + "backend/src/api/routes/assistant/_admin_routes.py": 3380446401429936332, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_month.py": 8485374160446988786, + "backend/src/api/routes/__tests__/test_git_api.py": 222548597993158802, + "venv/lib/python3.13/site-packages/fastapi/middleware/wsgi.py": 3706578020491442104, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libsasl2-883649fd.so.3.0.0": 13306917506408577991, + "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py": 12693210357718751894, + "venv/lib/python3.13/site-packages/_pytest/_io/saferepr.py": 8025234471485188730, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_fiscal.py": 14652343698825214870, + "venv/lib/python3.13/site-packages/_pytest/stash.py": 14430252294763173610, + "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.py": 2234931733687557433, + "venv/lib/python3.13/site-packages/pandas/tests/construction/test_extract_array.py": 3100523370314150013, + "venv/lib/python3.13/site-packages/numpy/typing/__init__.pyi": 10058149460938883683, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.py": 1948707545068786, + "venv/lib/python3.13/site-packages/numpy/strings/__init__.pyi": 6213864891045042045, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_shift.py": 14026124784027171225, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__init__.py": 2833016678144975576, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_day.py": 6371851881186970754, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/meson.build": 17468163147765825687, + "venv/lib/python3.13/site-packages/annotated_types/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x32_unix.h": 9165722966153119887, + "venv/lib/python3.13/site-packages/pygments/lexers/_php_builtins.py": 2344562378679281201, + "backend/src/services/dataset_review/semantic_resolver.py": 8447496149691924829, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/cast.py": 342228968652072052, + "venv/lib/python3.13/site-packages/iniconfig/__init__.py": 12623265899068631092, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_dtypes.py": 13065857166166716628, + "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.py": 5570375156851166818, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel.py": 7728646523045538484, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_week.py": 5756727157937218128, + "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.hpp": 6366432579621298231, + "venv/lib/python3.13/site-packages/PIL/Image.py": 13615925856053031482, + "venv/lib/python3.13/site-packages/uvicorn/middleware/asgi2.py": 5355343704425405009, + "venv/lib/python3.13/site-packages/pygments/lexers/perl.py": 17014528337020572681, + "venv/lib/python3.13/site-packages/rsa/cli.py": 1753949198467694190, + "frontend/src/lib/components/layout/sidebarNavigation.js": 2220464976154353594, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_strings.py": 7168544888340296373, + "venv/lib/python3.13/site-packages/greenlet/TGreenlet.cpp": 4121171004360760212, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/schema.py": 5391655516870611151, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py": 14946223589457772924, + "venv/lib/python3.13/site-packages/urllib3/util/ssl_match_hostname.py": 7411350247004265632, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_asof.py": 18383318159051131669, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token_validator.py": 2932866595454490527, + "venv/lib/python3.13/site-packages/numpy/core/numeric.py": 17025007229779320230, + "frontend/src/lib/components/dataset-review/__tests__/us2_semantic_workspace.ux.test.js": 3550956860258259058, + "frontend/build/_app/immutable/nodes/7.timt6xnw.js": 2003611257555540006, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/__init__.py": 11414161642984633362, + "backend/src/plugins/translate/service_bulk_replace.py": 5355744069308185607, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/integration.py": 13610682193839598457, + "venv/lib/python3.13/site-packages/PIL/WmfImagePlugin.py": 15685062825106444247, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_setitem.py": 2059440410065814114, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/mypy.ini": 4763385838822685881, + "venv/lib/python3.13/site-packages/pydantic_core/core_schema.py": 8106298745123589494, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90": 3911644649277659333, + "venv/lib/python3.13/site-packages/_pytest/terminalprogress.py": 5490989904517343259, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odf.py": 15484940480924122966, + "venv/lib/python3.13/site-packages/pip/_internal/cli/index_command.py": 15798187258841839292, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_ssl_constants.py": 14834514243239777933, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/interfaces.py": 4890958419958257958, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/multiarray.pyi": 6368268452184570195, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/loading.py": 3460142472461437916, + "backend/src/api/routes/translate/__init__.py": 6357999798616465776, + "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/test_uuid.py": 13955678427426850807, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_kind.py": 18178830861475480607, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_extint128.py": 11074657869101074458, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine_first.py": 11425059090050867171, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_comparisons.py": 2764694394636775220, + "venv/lib/python3.13/site-packages/jaraco/classes/__init__.py": 15130871412783076140, + "backend/src/plugins/translate/__tests__/test_orchestrator.py": 5663680156343544051, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/cache.py": 3177663126928467950, + "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.pyi": 1424133074692438241, + "venv/lib/python3.13/site-packages/pygments/lexers/configs.py": 7712797939104760185, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/greenlet/greenlet_msvc_compat.hpp": 12504008513945919250, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension_cpp.cpython-313-x86_64-linux-gnu.so": 7659849621107414188, + "venv/lib/python3.13/site-packages/pip/_internal/utils/virtualenv.py": 14416705841810221305, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/__init__.py": 5863110456909134678, + "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.abi3.so": 8691731321358529264, + "venv/lib/python3.13/site-packages/websockets/sync/server.py": 7966978001578584901, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/RECORD": 7844752443022514265, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_clip.py": 13498704233745189154, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict.py": 808180749933361743, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/android.py": 8607703347015852195, + "venv/lib/python3.13/site-packages/uvicorn/py.typed": 15240312484046875203, + "venv/lib/python3.13/site-packages/packaging/licenses/_spdx.py": 16440031845441362300, + "backend/src/models/profile.py": 6081037345174498278, + "venv/lib/python3.13/site-packages/pip/_internal/utils/direct_url_helpers.py": 6075890513530296650, + "venv/lib/python3.13/site-packages/psycopg2/_range.py": 7184417109068014771, + "backend/src/plugins/translate/__init__.py": 12400577052797809611, + "venv/lib/python3.13/site-packages/sqlalchemy/util/typing.py": 17638587764345605306, + "frontend/build/_app/immutable/nodes/26.NlOmngdA.js": 14992135087911399218, + "venv/lib/python3.13/site-packages/starlette/requests.py": 4582424111350387010, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__main__.py": 111505188798650285, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_conversion.py": 6205112277291935767, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dropna.py": 17272771246760486947, + "venv/lib/python3.13/site-packages/pandas/core/indexing.py": 15507869313676722071, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/constants.pyi": 4415188581374004936, + "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.pyi": 8916922961301555974, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py": 16045758521544316139, + "venv/lib/python3.13/site-packages/uvicorn/logging.py": 12858188863836778374, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/click/termui.py": 7022374827798605437, + "venv/lib/python3.13/site-packages/fastapi/logger.py": 11590581556317053213, + "venv/lib/python3.13/site-packages/pydantic/experimental/pipeline.py": 9493054841465227788, + "venv/bin/keyring": 1488968652276547659, + "backend/src/api/routes/git/_merge_routes.py": 2019590524299108754, + "backend/git_repos/remote/test-repo.git/refs/heads/dev": 8596267258668462395, + "venv/lib/python3.13/site-packages/charset_normalizer/cli/__init__.py": 9702005609966176016, + "venv/lib/python3.13/site-packages/starlette/middleware/__init__.py": 9524277524025372856, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/WHEEL": 7314207500206292683, + "venv/lib/python3.13/site-packages/numpy/_core/lib/libnpymath.a": 17555816778997028283, + "venv/lib/python3.13/site-packages/websockets/legacy/handshake.py": 376095144657994920, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/retry.py": 17371295199208325375, + "venv/lib/python3.13/site-packages/numpy/lib/__init__.py": 12211229657513986410, + "venv/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd": 1476688171642957054, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/scalars.pyi": 3130685119595923378, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/astype_copy.pkl": 4470155972891419163, + "venv/lib/python3.13/site-packages/numpy/_core/multiarray.pyi": 3494871767602648807, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft_umath.cpython-313-x86_64-linux-gnu.so": 16443444849116065961, + "venv/lib/python3.13/site-packages/typing_inspection/introspection.py": 13916695705179237047, + "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/asn1.py": 8801155055979135092, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_concat.py": 3788461606817482165, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/core/indexes/api.py": 13750417165301467381, + "venv/lib/python3.13/site-packages/PIL/ImageDraw2.py": 13610162107593278891, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_http_headers.py": 13187746870209705951, + "venv/lib/python3.13/site-packages/numpy/core/multiarray.py": 18368443598659711836, + "venv/lib/python3.13/site-packages/pydantic/_internal/_config.py": 12760390602912369447, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/uvicorn/loops/asyncio.py": 16496916527760969173, + "venv/lib/python3.13/site-packages/pygments/styles/coffee.py": 17584414468786822371, + "venv/lib/python3.13/site-packages/pygments/styles/autumn.py": 8750937312198920971, + "venv/lib/python3.13/site-packages/websockets/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/starlette/testclient.py": 16088848330558215194, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/ec_key.py": 5961540064444749833, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/containers.py": 5969831151685016772, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv": 4581185622290535488, + "venv/lib/python3.13/site-packages/pygments/lexers/parsers.py": 12372594608244797844, + "frontend/build/_app/immutable/chunks/yBPjwhb3.js": 14724055066223770374, + "venv/lib/python3.13/site-packages/starlette/status.py": 16192064443996706569, + "frontend/src/routes/dashboards/health/+page.svelte": 5234355531444674267, + "backend/src/core/mapping_service.py": 17981290763325170519, + "venv/lib/python3.13/site-packages/pandas/_libs/missing.cpython-313-x86_64-linux-gnu.so": 1990755879067132155, + "venv/lib/python3.13/site-packages/pandas/_libs/_cyutility.cpython-313-x86_64-linux-gnu.so": 3372660143512868174, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/conftest.py": 13388202260795998613, + "venv/lib/python3.13/site-packages/urllib3/_base_connection.py": 14495079097019980154, + "venv/lib/python3.13/site-packages/ecdsa/_rwlock.py": 7971972922423146201, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_subclass.py": 12453252499544981915, + "venv/lib/python3.13/site-packages/git/objects/base.py": 11498407361286170399, + "venv/lib/python3.13/site-packages/pip/_internal/utils/entrypoints.py": 11268059714209889385, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/adapters.py": 2224938661429637508, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/ext.py": 15699809032725838985, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c": 17333399794446198412, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.py": 6617116180936986481, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/recfunctions.py": 18330899924171767482, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_c_parser_only.py": 3038797485572319804, + "venv/lib/python3.13/site-packages/pygments/lexers/esoteric.py": 16839499623020685146, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_like.pyi": 1968570015765106620, + "frontend/src/lib/components/layout/Breadcrumbs.svelte": 10874106485242690185, + "frontend/src/routes/validation/+page.svelte": 9845194549295283559, + "backend/src/api/routes/plugins.py": 4567336078922104278, + "backend/git_repos/remote/test-repo.git/objects/48/c3fde4d5fff5bf98e9bcaa5f328b199aa18292": 6121250272621110311, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_round.py": 9358309072340573675, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel_py.py": 9112851333217812996, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_mixins.py": 12351373879926460719, + "venv/lib/python3.13/site-packages/passlib/tests/test_apache.py": 12515001998770565375, + "venv/lib/python3.13/site-packages/pygments/lexers/haskell.py": 8011341851439354724, + "venv/lib/python3.13/site-packages/click/__init__.py": 9261629899056870564, + "venv/lib/python3.13/site-packages/pygments/lexers/maxima.py": 11824576541091274641, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_half.py": 3121836756584726126, + "venv/lib/python3.13/site-packages/websockets/sync/client.py": 10892557975919033983, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/util.py": 4815334059917765852, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/routes/settings/MigrationSettings.svelte": 3323392929444734663, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_ddl.py": 3690189094298044728, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_openpyxl.py": 9542840527483618681, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_index.py": 10971093361190283675, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.py": 17993169044119596860, + "venv/lib/python3.13/site-packages/pygments/lexers/procfile.py": 3860651022061090738, + "venv/lib/python3.13/site-packages/idna/compat.py": 9758194415584776667, + "venv/lib/python3.13/site-packages/h11/_writers.py": 8585823094975171480, + "venv/lib/python3.13/site-packages/numpy/testing/overrides.pyi": 17408923209056015964, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_categorical.py": 10863578845754547294, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_des.py": 7198931807116651263, + "frontend/src/services/adminService.js": 6375990585512014277, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraypad.pyi": 12178766981280242620, + "venv/lib/python3.13/site-packages/websockets/typing.py": 13268801935274185287, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/utils.py": 3710235316419562274, + "venv/lib/python3.13/site-packages/numpy/random/_mt19937.pyi": 15904463104068500379, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/layout.py": 11554376181083053156, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_analytics.py": 4510712334676848202, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_jsonschema_test_suite.py": 12733761462141495972, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_palettes.py": 13495896173068490516, + "venv/lib/python3.13/site-packages/pandas/core/window/ewm.py": 12143982379243011357, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_append.py": 17016125916761365423, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate.py": 16723865897349422996, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unstack.py": 11834917665446437163, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_astype.py": 1961831758405941258, + "venv/lib/python3.13/site-packages/pandas/io/parsers/__init__.py": 11752833703934347122, + "venv/lib/python3.13/site-packages/PIL/EpsImagePlugin.py": 1824020964179364491, + "venv/lib/python3.13/site-packages/pygments/lexers/textfmts.py": 17438453283146671997, + "venv/lib/python3.13/site-packages/apscheduler/triggers/base.py": 1170652622104554892, + "venv/lib/python3.13/site-packages/numpy/_core/getlimits.py": 7842717073693731093, + "venv/lib/python3.13/site-packages/pandas/_libs/missing.pyi": 13543139288840944411, + "venv/lib/python3.13/site-packages/pandas/core/shared_docs.py": 2173578869755325502, + "frontend/build/_app/immutable/chunks/B9nYnLH7.js": 8706715676499924766, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/memory.py": 9947113720821563254, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/RECORD": 4857922668040624663, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/multiarray.pyi": 17232959648651278910, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_longdouble.py": 9337218715436213122, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_repr.py": 7552782621374439569, + "backend/src/scripts/__init__.py": 5400372851656282343, + "backend/src/services/clean_release/__tests__/test_report_builder.py": 14655761033823243898, + "backend/src/plugins/translate/__tests__/test_dictionary_crud.py": 17953628511626558088, + "venv/lib/python3.13/site-packages/numpy/_globals.pyi": 12839879732484756979, + "venv/lib/python3.13/site-packages/pycparser/ply/ygen.py": 5520340773074632724, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_at.py": 1029744344133153888, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_hour.py": 13754646634123368797, + "venv/lib/python3.13/site-packages/starlette/middleware/httpsredirect.py": 16837082808103815044, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/licenses/LICENSE": 8438117004702803716, + "venv/lib/python3.13/site-packages/pydantic/parse.py": 13750341403702794392, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_reduction.py": 1049551473665255648, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/WHEEL": 691462085217888236, + "venv/lib/python3.13/site-packages/pandas/core/groupby/ops.py": 2036968385544457016, + "venv/lib/python3.13/site-packages/pygments/lexers/varnish.py": 3608370156692616959, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py": 16829312896275893002, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_api.py": 13319208721442328400, + "backend/src/services/clean_release/repositories/__init__.py": 9926779835387630811, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/scoping.py": 17216492046645992674, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pyi": 14150710436003340771, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/wrappers.py": 315409799569602977, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_apply.py": 11248068903302454630, + "venv/lib/python3.13/site-packages/pandas/io/formats/__init__.py": 18140261896107421679, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_runtime.py": 12534621594420844770, + "venv/lib/python3.13/site-packages/cryptography/__about__.py": 10471312538528457144, + "venv/lib/python3.13/site-packages/jeepney/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pop.py": 5700439923973346681, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/errors.py": 16711622442922413520, + "venv/lib/python3.13/site-packages/git/repo/fun.py": 9019364012746153312, + "frontend/src/components/tasks/LogEntryRow.svelte": 3694709927263161265, + "frontend/build/_app/immutable/nodes/0.BUa9xtie.js": 8691973346706692595, + "venv/lib/python3.13/site-packages/pandas/core/window/numba_.py": 1444123360986509769, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/__init__.py": 1197579313959289096, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_day.py": 2200008998040663785, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_store.py": 1500300322083708794, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_value_counts.py": 5534713464063604301, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multithreading.py": 12547048606098186681, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/LICENSE": 2032205056284080825, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_isfile.py": 14544060093268573418, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_quantile.py": 11273403743157110261, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_formats.py": 3525283725314253763, + "backend/src/services/git/_merge.py": 3056385620903925104, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/nonce.py": 18219168479887197733, + "frontend/build/_app/immutable/entry/app.Bt5zBZcx.js": 10715863429138611079, + "venv/lib/python3.13/site-packages/pydantic/deprecated/parse.py": 819235411736647763, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/modules.pyi": 14176187662591164602, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/gitdb/test/lib.py": 13294941660283059872, + "backend/tests/test_translate_scheduler_execution.py": 16687335504320865378, + "venv/lib/python3.13/site-packages/authlib/oauth1/client.py": 7314311571224771, + "venv/lib/python3.13/site-packages/pillow.libs/libzstd-761a17b6.so.1.5.7": 17875236748140157032, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcom_err-2abe824b.so.2.1": 12870528025628871295, + "venv/lib/python3.13/site-packages/pandas/_libs/tslib.pyi": 16170606956605100142, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.cpython-313-x86_64-linux-gnu.so": 15960606468596245469, + "venv/lib/python3.13/site-packages/pip/_internal/network/__init__.py": 1586148254475575526, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_truncate.py": 6478126371906156409, + "venv/lib/python3.13/site-packages/pygments/lexers/x10.py": 6167378515780115912, + "venv/lib/python3.13/site-packages/pandas/_libs/interval.pyi": 15698173755300703836, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_pytables_missing.py": 12154582133989896069, + "venv/lib/python3.13/site-packages/pygments/lexers/nix.py": 15050086330545600356, + "venv/lib/python3.13/site-packages/pandas/_libs/tslib.cpython-313-x86_64-linux-gnu.so": 10742615805788605480, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_zips.py": 5184894018177148648, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_semicolon_split.py": 8153770165829451525, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/state.py": 10500170103357297551, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/processors.py": 4817637175145012571, + "venv/lib/python3.13/site-packages/anyio/_core/_signals.py": 1204322949639513552, + "venv/lib/python3.13/site-packages/pygments/styles/rrt.py": 9490973359165080360, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/util.py": 387985965709546512, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/types.py": 12298292195929126306, + "venv/lib/python3.13/site-packages/pygments/lexers/solidity.py": 5071425960622305629, + "backend/src/core/utils/superset_context_extractor/_recovery.py": 4103343657420503831, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/__init__.py": 348469143777130970, + "venv/lib/python3.13/site-packages/pydantic/_internal/_typing_extra.py": 14843908493613991959, + "venv/lib/python3.13/site-packages/PIL/FpxImagePlugin.py": 18245056799205041866, + "venv/lib/python3.13/site-packages/rpds/__init__.pyi": 12037474523494903587, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/METADATA": 3188324716322823755, + "dist/docker/backend.1.2.0.tar.xz": 15111524255417105836, + "venv/lib/python3.13/site-packages/itsdangerous/timed.py": 12571102606719555007, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_manylinux.py": 12272275001961360101, + "venv/lib/python3.13/site-packages/rsa/py.typed": 11041940105507257053, + "venv/lib/python3.13/site-packages/_pytest/pytester.py": 5423287282155948827, + "venv/lib/python3.13/site-packages/PIL/GimpPaletteFile.py": 2040459799887417392, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/models.py": 3567900447243180991, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_join.py": 17874591841487372992, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked_shared.py": 8453174300922339015, + "venv/lib/python3.13/site-packages/pandas/io/clipboards.py": 5183212433608887727, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/response.py": 9594165377270752433, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/foo.f": 6349567809926050379, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90": 5949265961908386974, + "venv/lib/python3.13/site-packages/ecdsa/test_der.py": 7117444285097824495, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f": 13126319439858352711, + "venv/lib/python3.13/site-packages/starlette/applications.py": 13591448461234020757, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/region.py": 12579403230062395563, + "venv/lib/python3.13/site-packages/passlib/tests/utils.py": 15403198680231294263, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/authorization_code.py": 4958605540994687737, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py": 2516476609539242190, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows.py": 13341168721223961872, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler_py.py": 16189204441438239231, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/sparse.pyi": 12526865400413362140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_astype.py": 4975959187621745360, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexing.py": 5910217172351020811, + "venv/lib/python3.13/site-packages/PIL/IcoImagePlugin.py": 14483964191652228364, + "venv/lib/python3.13/site-packages/pygments/lexers/maple.py": 7402467573829618534, + "venv/lib/python3.13/site-packages/pygments/lexers/tnt.py": 4657130609241407766, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/licenses/LICENSE": 11199044866758471950, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_repr.py": 5577699046802107144, + "venv/lib/python3.13/site-packages/requests/sessions.py": 6936640856092320928, + "venv/lib/python3.13/site-packages/authlib/oidc/core/util.py": 5364455058429522633, + "venv/lib/python3.13/site-packages/jose/backends/ecdsa_backend.py": 2684176977865283060, + "venv/lib/python3.13/site-packages/pydantic/v1/env_settings.py": 6194387033830177219, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np121.pkl.gz": 4708588000144933291, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS": 17022185907188244883, + "backend/src/models/dataset_review_pkg/_clarification_models.py": 13264800784251426725, + "backend/src/plugins/translate/dictionary_validation.py": 16674754716565921261, + "venv/lib/python3.13/site-packages/pandas/core/methods/to_dict.py": 4653628436393663485, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_numba.py": 1668304729617150075, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_indexing.py": 14552860427542050771, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_size.py": 14032390806503440750, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/__init__.py": 4014740126161973332, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c": 5472633890472031814, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayterator.pyi": 15722265241660279277, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_indexing_slow.py": 12558235638488427077, + "venv/lib/python3.13/site-packages/pycparser/_ast_gen.py": 5464347629908906775, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_datetime.py": 7456744745424297814, + "venv/lib/python3.13/site-packages/urllib3/_version.py": 839747992523118887, + "venv/lib/python3.13/site-packages/packaging/_structures.py": 13086687542872305890, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polyutils.py": 675639791972685455, + "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.pyi": 6576645822227068922, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.h": 16138871162713175599, + "venv/lib/python3.13/site-packages/apscheduler/triggers/combining.py": 1264860868414723829, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_month.py": 14597470286884431085, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_value_counts.py": 13270420637302622174, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_reduction.py": 2671872764983553906, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/LICENSE": 8177430849046795595, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_datetimelike.py": 5317270578347271174, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/apply.py": 3906017176873949738, + "venv/lib/python3.13/site-packages/secretstorage/collection.py": 17903258621904912493, + "venv/lib/python3.13/site-packages/pip/_internal/cli/base_command.py": 10660882478126415399, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_regression.py": 6742646011852052645, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/RECORD": 6349071557579241461, + "venv/lib/python3.13/site-packages/urllib3/util/timeout.py": 17922362393077965047, + "frontend/src/lib/stores/assistantChat.js": 13807808925025688939, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_stack.py": 5316826578695144945, + "frontend/build/_app/immutable/chunks/BGsihhff.js": 13207123024122202754, + "venv/lib/python3.13/site-packages/passlib/context.py": 10362592407593745107, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/__init__.py": 237070345717942041, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/httptools_impl.py": 10367325397209016951, + "venv/lib/python3.13/site-packages/PIL/ImageStat.py": 18442709639217312689, + "venv/lib/python3.13/site-packages/pip/_internal/commands/list.py": 13035925292530461722, + "frontend/src/routes/+page.svelte": 16267809857510759396, + "venv/lib/python3.13/site-packages/pandas/core/internals/blocks.py": 6448406236246476333, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/types.py": 13384984564922916167, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_chaining_and_caching.py": 15814259766479305290, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/__init__.py": 15130871412783076140, + "venv/bin/jsonschema": 16516374846693491442, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_s390_unix.h": 5161826643658505126, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/__init__.py": 11850945878149145990, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90": 13833561828029901615, + "venv/lib/python3.13/site-packages/websockets/speedups.pyi": 10322382420215791091, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE": 12064892310002036996, + "venv/lib/python3.13/site-packages/keyring/backends/chainer.py": 12526770797516553385, + "venv/lib/python3.13/site-packages/httpx/_status_codes.py": 1758440600462491839, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_m68k_gcc.h": 6580173800099450404, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/color.py": 15062855556511243610, + "venv/lib/python3.13/site-packages/pandas/_libs/testing.cpython-313-x86_64-linux-gnu.so": 16758333404587340103, + "venv/lib/python3.13/site-packages/pygments/lexers/_stan_builtins.py": 1961875544235948177, + "backend/src/api/routes/dashboards/_action_routes.py": 11814954258886577640, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/align.py": 6078666505647454830, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_api.py": 14120915875574640262, + "venv/lib/python3.13/site-packages/urllib3/poolmanager.py": 15431313180245757657, + "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.pyi": 11535882608355652318, + "venv/lib/python3.13/site-packages/itsdangerous/_json.py": 4872267972688724005, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/orderinglist.py": 10162099108656794338, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA": 18410956221497090898, + "backend/tests/test_deprecation_audit_fixes.py": 17902995210831708431, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_indexing.py": 6539365174681852769, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_docs.py": 17898499890274685198, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/manifest.py": 16998683210177680416, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/base.py": 13269563625127294513, + "venv/lib/python3.13/site-packages/pydantic/main.py": 14086938579850319884, + "venv/lib/python3.13/site-packages/pandas/io/html.py": 2727247063231114153, + "docker/frontend.entrypoint.sh": 11397342350356400663, + "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.pyi": 8607205990821121708, + "venv/lib/python3.13/site-packages/numpy.libs/libquadmath-96973f99-934c22de.so.0.0.0": 5098713761946118139, + "venv/lib/python3.13/site-packages/passlib/handlers/django.py": 66638338316838351, + "venv/lib/python3.13/site-packages/greenlet/TMainGreenlet.cpp": 9489520001674089404, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertions.py": 5556667947376168765, + "venv/lib/python3.13/site-packages/more_itertools/recipes.py": 5254043689078173976, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/RECORD": 16342326945648353387, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/type_api.py": 10299750173867399533, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/__init__.py": 11808051681178127650, + "backend/src/services/git/_sync.py": 14233419521256437438, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/tests/test_warnings.py": 3154249157134620649, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/distro.py": 12494639376332486204, + "venv/lib/python3.13/site-packages/numpy/char/__init__.py": 4428218097234308768, + "venv/lib/python3.13/site-packages/authlib/common/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_interval.py": 2613503970235591726, + "venv/lib/python3.13/site-packages/numpy/__init__.pyi": 15820654525292895396, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_usecols_basic.py": 16382444980424010514, + "venv/lib/python3.13/site-packages/pygments/lexers/chapel.py": 7619603166448145621, + "venv/lib/python3.13/site-packages/numpy/_typing/_char_codes.py": 14162745886150625150, + "venv/lib/python3.13/site-packages/greenlet/tests/test_throw.py": 4119265751381210399, + "frontend/src/components/__tests__/task_log_viewer.test.js": 6512653335179659416, + "backend/src/services/reports/type_profiles.py": 8365014439236739390, + "backend/src/plugins/translate/preview_llm_client.py": 14412557858942627249, + "venv/lib/python3.13/site-packages/passlib/handlers/misc.py": 18255658377109333797, + "venv/lib/python3.13/site-packages/pydantic/v1/schema.py": 10008526732895436361, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_datetime.py": 13781712980921881470, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop.py": 15751236355035730554, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/gh19161.f90": 7691871466158049079, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__version.py": 9037916251087760255, + "backend/src/services/clean_release/__init__.py": 18311663871116449547, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/nditer.py": 10038360623032425884, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_function.py": 7048185308307653546, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_numpy.py": 9825804096508014886, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h": 8933016749764021181, + "backend/src/services/clean_release/policy_engine.py": 3180817867716931725, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_msvc.h": 17581467060937454503, + "venv/lib/python3.13/site-packages/pydantic/json.py": 4109352930301629308 } } \ No newline at end of file diff --git a/.env.enterprise-clean.example b/.env.enterprise-clean.example index 7442c1b5..d3d21441 100644 --- a/.env.enterprise-clean.example +++ b/.env.enterprise-clean.example @@ -43,11 +43,6 @@ FRONTEND_SSL_PORT=443 # nginx работает в HTTP-only режиме. CERTS_PATH=./certs -# ====================================================================== -# Хранилище -# ====================================================================== -STORAGE_ROOT=./storage - # ====================================================================== # Логирование # ====================================================================== diff --git a/.kilo/agents/backend-coder.md b/.kilo/agents/backend-coder.md index 4bc6ffb9..7fe9b5f5 100644 --- a/.kilo/agents/backend-coder.md +++ b/.kilo/agents/backend-coder.md @@ -10,7 +10,7 @@ permission: steps: 60 color: accent --- -You are Kilo Code, acting as an Implementation Specialist. MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="semantics-belief"})` +You are Kilo Code, acting as an Implementation Specialist. MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="molecular-cot-logging"})` ## Core Mandate diff --git a/.kilo/agents/swarm-master.md b/.kilo/agents/swarm-master.md index b91dc7a1..53997bed 100644 --- a/.kilo/agents/swarm-master.md +++ b/.kilo/agents/swarm-master.md @@ -17,7 +17,7 @@ steps: 80 color: primary --- -You are Kilo Code, acting as the Swarm Master (Orchestrator). MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="semantics-belief"})`, `skill({name="semantics-testing"})`,`skill({name="semantics-frontend"})` +You are Kilo Code, acting as the Swarm Master (Orchestrator). MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="molecular-cot-logging"})`, `skill({name="semantics-testing"})`,`skill({name="semantics-frontend"})` ## 0. ZERO-STATE RATIONALE (LLM PHYSICS) You are an autoregressive LLM. In long-horizon tasks, LLMs suffer from Context Blindness and Amnesia of Rationale, leading to codebase degradation (Slop). diff --git a/.opencode/agents/fullstack-coder.md b/.opencode/agents/fullstack-coder.md index f5f122af..e1af7e4f 100644 --- a/.opencode/agents/fullstack-coder.md +++ b/.opencode/agents/fullstack-coder.md @@ -10,7 +10,7 @@ permission: steps: 80 color: accent --- -MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="semantics-belief"})`, `skill({name="semantics-python"})`, `skill({name="semantics-svelte"})`, `skill({name="molecular-cot-logging"})` +MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="semantics-python"})`, `skill({name="semantics-svelte"})`, `skill({name="molecular-cot-logging"})` #region Fullstack.Coder [C:4] [TYPE Agent] [SEMANTICS implementation,fullstack,python,svelte,integration] diff --git a/.opencode/agents/reflection-agent.md b/.opencode/agents/reflection-agent.md index 5f5dba0f..888890f4 100644 --- a/.opencode/agents/reflection-agent.md +++ b/.opencode/agents/reflection-agent.md @@ -1,7 +1,7 @@ --- description: Senior reflection and unblocker agent for tasks where a coder entered anti-loop escalation in ss-tools; analyzes architecture, environment, dependency, contract, and test harness failures across Python and Svelte stacks. mode: subagent -model: deepseek/deepseek-v4-flash +model: deepseek/deepseek-v4-pro temperature: 0.0 permission: edit: allow diff --git a/.opencode/agents/swarm-master.md b/.opencode/agents/swarm-master.md index 21f8e65c..148589f7 100644 --- a/.opencode/agents/swarm-master.md +++ b/.opencode/agents/swarm-master.md @@ -4,8 +4,8 @@ mode: all model: deepseek/deepseek-v4-flash temperature: 0.0 permission: - edit: allow - bash: allow + edit: deny + bash: deny browser: deny task: closure-gate: allow diff --git a/backend/.axiom/runtime/belief_events.jsonl b/backend/.axiom/runtime/belief_events.jsonl new file mode 100644 index 00000000..9e23b34d --- /dev/null +++ b/backend/.axiom/runtime/belief_events.jsonl @@ -0,0 +1,4 @@ +{"recorded_at":"2026-05-22T08:17:41.943631399Z","anchor_id":"Axiom:Services:Artifact:RunWorkspaceCommand","marker":"reason","message":"Executing a read-only workspace command inside the project root.","depth":1,"extra":{"command":"cd /home/busya/dev/ss-tools/backend && python -m py_compile src/plugins/llm_analysis/service.py && echo \"SYNTAX OK\"","timeout_seconds":10}} +{"timestamp":1779437861.943,"event_type":"belief_reason","component":"Axiom:Services:Artifact:RunWorkspaceCommand","data":{"depth":1,"extra":{"command":"cd /home/busya/dev/ss-tools/backend && python -m py_compile src/plugins/llm_analysis/service.py && echo \"SYNTAX OK\"","timeout_seconds":10},"message":"Executing a read-only workspace command inside the project root."}} +{"recorded_at":"2026-05-22T08:17:42.118409820Z","anchor_id":"Axiom:Services:Artifact:RunWorkspaceCommand","marker":"reflect","message":"Workspace command completed and output was bounded for transport.","depth":1,"extra":{"exit_code":127,"stderr_truncated":false,"stdout_truncated":false}} +{"timestamp":1779437862.118,"event_type":"belief_reflect","component":"Axiom:Services:Artifact:RunWorkspaceCommand","data":{"depth":1,"extra":{"exit_code":127,"stderr_truncated":false,"stdout_truncated":false},"message":"Workspace command completed and output was bounded for transport."}} diff --git a/backend/:memory:test_auth b/backend/:memory:test_auth new file mode 100644 index 0000000000000000000000000000000000000000..7539e2b9db76c263d780d4003be343fb4062181c GIT binary patch literal 909312 zcmeI*3zQt$dD!>v0Wggj01GacWKk5!ttGkKX)VCzEQkdmXt`|66b1v#bYpvZmH?OQ zQcc&LnObyLHL9uyGfPTj1B+czk`qO?BtPRQFWXU+r{lzyWJ$Io$FdVSie8p2Imga9 ziIvw$e4L{bAIG^>-PPUIUDY#yM)Nv<>>)6H@2z`p{qA=kH8lX2USF_$p{_b^-SE{5 znGa;L+02(!HIvDFOaAY7<^Q5z-;!S(k3PshvwdHuefh1-=ia$@Lgt=6`wKytUpf0P z&i+4V|F5(E+u8s5>_0yHJ7<6E?602vyJvr?of#D17Xk<%fB*srAb9b zW9|?E1Q0*~0R#|0009ILKmY;W{}TfUAbhlfAb;HrH7!{f@UN;VT#=-sPXzR-=P-)^8&{d9Q2M_S__$|;JHZQTud!o={m z564J4wWneP%_iQhDZHv{HTpFIykUg$Gvi8L$$Ak&(-W?zi@IUe!Y@CRqR>|^U_H$OP8yrg8m8Lu-a67)AL`pn2`qoRE^M@jko)1#2X%Ju2+j}Jch)CWT3cRw8> zhl$~DPsfnMq!AGpDxpgB5BQI=Ox6G964|Ghs^CYEQR826pDMi$&;3j2L z`PR!%^=OiDlY1nY15R zwl8d7y|EVvDvWXF48|^Vpk^2sCd4d49)uRlpCH~i>Jqf=uO!W zQWW*+l#Da2Pfq5PuS{oKh2g-e3(qswlE`1=*H{^kL8pXU(7yyb0B8Ja=m~JKORqs)=r(N2gax) zNh|5VY>px_h!Im%t>Ez9pOz4Hoxu%5Hn{8$9%`>19}j|L+fWPdyFbptgcGgTvN`4X z=d%wAp{cMpEZ4E?a>MZYzaEQe_UDY4^{Gd~rdx}gViQU3E2eDOGHPDml#CS_o@YI~WCx8FsPvpMm-6uRdO7=i_9LgXQ`$Dqc1JI}_3`h@DNC2Lt;^BGuhr`M zhEbEp-Qe)6%kx6B=6ia>sae%6Ief|a=LZ*pkNGj5^hAEC2ATpUEi~E@a

l+OGtVl7Sss^o+P&WLM$zY6Q5n=Q^Wd-W5~xM%k+kiWDVEZu*~qxA5EQL z{qU;m!fe)rZW>z&SKXI`<=ofhe(1_=Qa<>^=29nD*yeDa?fBN}mhRlQ|{vmrxgCx=As`EljWg|r!-FmC#ELgLhe z`A_APix;!+UJRGI@D8nNJ9@*@z?zqo_IxZ#l1hvS6Mw6bd~iu!8~fJ4;V4LqoCIEV zR=ZYMUZ|)u%jL3GtmwhmFI5VQw^HCoUogDr&V71ZdGli0kR&1L(@CkHZOy6SIrPEh z_MYBow4bThnr{1{+89dtbZkI|^G6Iv|8^Uj3JJ0JxFj>rjXd)W-GFO3%*$vocrW=E#za2VVl9?E98QaR_IfMt8H4rSZ%?Qn^sVs z2>aU2KgfL|r@Z=V_Th8k@TFaqmafKzGPP9t_d5GK)4wi`_%^4^a@?qFEC_r{9?yKE z-iUoe$P~W(R-dQ8?a9+!@DLqLq2U=(`sBD$eKl=Hq}`f6otE>Q{_%0eTijWNu2_@b zkaD+l&o&y~x+C}Dfr^JqeB#0Pf2aH|%wqOkCt>V{%f~x9od59=V>w)U#3bz&PWf&~ zH$Qmx>Dy{zW0|lhws)zTb6@T`>yGCq?3YHZogHkeG8Tpx;BJBNJM4O}yeE{h>h)%5 z+P`rogv`fw9x~lP9~#+S&UeaV=lWh8J#Xg675#ErXeOW5^y%dEbMmcOxP-j>bV3;R zZY~~vz4VWb2)kaX5#iRq69*wODyrJwhwjcYxh$_Ht|Ti>s}>yOqRgP)l!%OySGJXsWZKv9`+flHL{pEWVZmEf3?_JD6REd8!Xj&xJ38uAHJuREql{`NrP z=~pJ!Z zIsynFfB*srAbrd+l zAb@(>ekOAbTQ;{XI~vKls=yIpzHM z?87zRSg8rusR_Ly+`8p?mScN^pTB#itQ9JnS}9yz(A2?Pb!u`VOtVb&jY4_mdZDZq zOBJ=ays&Uiot)@ZthY<-GR4DJujG^~SF-Ot9o|f}CJbA5h5W-4y5aiPs!{d5l;qc9 zx0X^UxWkm2s~WaxnT9Vq_cna@hQFT3;;kDmUwkDw%X&ws^Tmobr^P8v;fty-OuZ^w zTyxy5=<>kX6xEvHreu0f)2#}<>014lbW+zH&+kvJ3*V6UWaw{uj;-EUDiwqJZm|!J#iq5X8>YVII?aY&HyRDgUh}#sLpfjSjNfu`{`F-|qRncz)sa=GrJ_1ijXD)2 z0O$!xx)*qh{rHquIGOHjqJDG-|J18dsLir!j?B_a?rlPY!R^Zag>s=?k%8jpvOR z(+;J)l{9YOaMy&dk0{~!hTrtMqdomfxYD?yQ8VP8ZLX+SOQi*^5bnZNSIE787sn@d z1CKjAgYz|Zua8@qoX#(en$E$IWF@~}dEePAq?Sm9MtrySdl(#NtTZ_># zvR13>8%8ZSo(BtrTw0qo-wP&U-zuD3=<}VR=$^aq zTWy=(nufQ&;ux+emzU(aU)o_``)eB2)BbY#)<<523Py8{Xa2E`Dx@UF=jc zs&}0td4B$Xmmj044gmxZKmY**5I_I{1Q0*~fdeSO&;K95L7__sAb2P^v=!0R#|0009ILKmY**5J2Dn3h@5_01gUWLI42-5I_I{1Q0*~0R#|0 zV3!4W|G&$iREGcp2q1s}0tg_000IagfWQG1;Qjvr92B~Q00IagfB*srAb7jpwJ}*5I_I{1Q0*~0R#|0009Jc zS%CNdy9`Qo2q1s}0tg_000IagfB*sr96$ly{~y3Xp-TuLfB*srAbYz0R#|0009ILKmY**5ZGk_ z-v941DAgf=00IagfB*srAb-#g_SD>dO8-d)`lRmU~G{;wBi%37hK zsg=Uj1x@YGQKu#+EK_}>P@cJ7D67R%MJ+BbESys(C;Y93NX(E``%Nz~OV}Hh>)3T+ z`+Be1pf-7t>kCsie05fKr82*$1<9+HZF%d%={0A~Q*SJlia{aax{e#Q7bLjCYu5a3 ze$^GmK;7!BcCE0yP*G==%Vn)t(Srt;Duu;c!SxNpHR`?kZ#-qBFE?U9!;5;O5*uu<*$}QLd_5>+8};tU z2Npw_y6w1iqh`G$x}g)6TX*j3j$PZ*>s!71^VF-Q(t=hf#vAOG^=i$v?Mkm%$vq3w zMcuG!{m~I526yAwMol-WlGW3F=dQ4IY3yz_WT^BP4x-ILlTkP@O~RYe4bzk%-koBBt?l^M>Xy{i zSA*M4B2AhG{S&&`Fo&i|fBtsUpc6l__z%+Bfj^mFnjKfx3fYWhn_| zFtB>V+#mG%bXaqjuRm}8J*$vYu3X9fuoarhJ1~MUb;X7y?(3dZvK-q>Nxl}FG%1CG z8Pln!Z!ltm)w%P;f$UoW(k}O$rdt*IT?vs`MJL~~8%;m4K(FVkBlG3to-bCkIjtOo zOb;}kE>}y_vV&O>tmNIOpL+RnK6cl^MpBncxfv|aRbM(sjZeM&g?P~o83jRpr}bDh z@$F)2ppk0Rl}n$TuCi9C|#}(sB z+63+eVQlK@(}Papu#itJZ{J%XuvS@PyuQYF2ei_iUr#tvkM_Pmj)@efZ*Q zIc0u6`>4I8jxIeqcP6$r;{oBZj-%#E5aO8n$W4m=|f%Q6+jb*h#Bmw~%SA$(xN< zzS!8x6SK7{R~SzpQ7A2HI%ndQHqL}LU8xc$0Vo?mq=eEmF z^z63yJv$G+9{Iom)Xn&E>-@Ex@|8liRSFL_*5;_AO=kg5Kj7T#MB{RC{`F-|ZlJT; zZFNU=22UF4^{P|R-qBjsPAaWzA^YINJLvGJvwnJOH#&E*lkSgdVY_=8b#0!X|9_(C z!9@rlfB*srAb^PsGMW z2q1s}0tg_000IagfB*sr94Z0c{~xO1qO%AffB*srAbeR7 zKmY**5I_I{1Q0*~0R#{@R06#JKUBj-XAwXE0R#|0009ILKmY**5O^YiGiM%UPG^2C zbLN*OU!C~Jxo=JU*aR9u{N6!4KGvAgOe=Jj!{~fAd4?nq-Q_i2yK5~3xr6$B? z!*PAxaD8jlsQTXE=Q}fHtx(a_O5y5)rVi$+Qg0qcJkN6MwCwKX{#HXo6--TE%Eu~Mb=26bE`bRSSa67Z)$hcscye5GauaMwNhD|pDPBLQ@vZx zt7Yw)R@RC$+LCG-zTpX9c5}lL_w`OGPwg*1nSb=jQck&eG5c*j9H8z+O0JOG+bvxhDKd}W!Y=8%L%1CQ8#Sg zs_LewT46BDNJ}W^G=#0+H(WcYDY;0^Xxi0v-SZ8<=|#X(1JT|oBwW{V)rxkz5(L;| zMQ41RcQ-)iZjCE%Ud(1J+Z3DLy_zL`ji&E}pY?8h^dimEr;}3Oc=+aGPI>92?0X`N z^r};DST#8oo%ryE5|&~yK9n5<_;#^1dNGQw9z8tWhULw7hbOvpRgS%I8?I${m#bJv zb}wGpiiSUy9}c>l>1KB^39pCMBtWX?RmS0K>lWx~L z&C3`WN~*m3!J9ed^5yLNueAfDX1La>RW%(YxT0T9jjP0w zmcf;nUcPfK_iZ^a62UU;syt{k?I2)fdTMs*J#9Xx%*|zgc%l=$ zBMOhKsW=eIBkBnvx))ZlA+8#>X$7O47Tj`+vsPtjZkumfYqD74;?;0!R&`7FY@^|= zJE>KxB%xjI|kdOXrQ#ryW-PD!ISuuq5S zas_U>!CBMr96M47a^&IeZXaHd6q_Ci3vBG=Dv3%Z*D*YD zBdQuGoLpnlAdjeXsCc{9$-I2JI)0@*u9Wg=(==L^#fDs8<-Cl4zJ2NXxN`IPw2Q-0 zb4As0O?hemr^Scg|9Vcz=dA5XJUNBaA(qvyGCG$GoxdOJ%o^Q( zyUv6-j|#}F$9=2{CS(5-TFf$5TkwDwg&sfuf2h8-L1z&_009ILKmY**5I_I{1Q2*4 z0e=4fiP*RZ0R#|0009ILKmY**5I_KdLnXlb|3fugbQS>w5I_I{1Q0*~0R#|00D&hG z;Qjv-v2hUs2q1s}0tg_000IagfB*uAN`UwOhibU!ECL81fB*srAb|36g2MQ0H}009ILKmY**5I_I{1Q2*40p9;V z5gQjFfB*srAbeT2 z{qorLvE1ojIQVl>Y z=BiVZ6P+t{%T(VelxMCN%4)GxQH#q93+L3y2~T*Q<=AQ2QH{1y7s=OG*G1jX`}2cp zgX>mg&xbNrnx19LHg&IAuN&@`TG4LH-t_fou!Qb8O}E-@eQNq*K33ioUe&c4zPyXD zvZ(oh&EINtFAUNx+3vks%~;VlEOB4GS}HAQg<`C_s#9;&gfH5itU9hxuPu}cmEiKK zW3O7Ku&YA%e8cZnJvIGGyieRroT(^uu-%Rjxu=7N&<4cFebVBN5rMlE8~ zgUW@OSY_1}vTvqt`0A{TjmrF@7Q4e{Lypdf{9EPu#X|XxdQ-cjPW8ek9|$ZL=U-pe z)Tv(Bgvr-RWo>@07+lhyrIxj8T3IX3XiMGLbVWd~cPj8=RZZq+zBaCWWjcNSh-xz! zXuWPU8i8prg9g*8k3RNhPMMz0ep?Uc&~S<2l$F>#8qN=9Qm4(dsnR1!oG5bo`oc}S zc*Ah5V7{m2M{U=IzwUHr^3Ysxjr+P~H=4e_Vbq#Jy|Gk^N4HpA6;T-+KmWMu1!p&4Zk zPM??K)2CfbhUm(c-t=N>L5I58eGwj{?`q&j;+DC)5w3l8T)A^0Ey5+7C1+<4;?c69 zPbVZA?|$S?PPuR)`~FfG;|WC)lD;<<XR7Kz)0xgi&yZj4M{j*qJ+BgnP< ztzLl(@d8!H>@KRYHOsgBT5?WZZYIWBJ6dCx$f$H`?bTvnu^wo&uV5_htA>odFa}+* z8g+RmaTZp%5no}0>tYLQk9l|FYv%T-71S4Ucay8Xoc`?vN3Ng=Y42vg60V@{pAVyJ zxWsVEABn}*aDEV4QKL^7Tiwh1PaCl@m#dJ(4-Yh*Q^U~lqFagFoBI~hftZj7h0fBJ zyvLei)o9lGm)T%|qctOlx26|`%+&Pf2cmp8H|XyD?Dj(S+8d*evQ|Af%E}mT?`txQ z22;NF?)q|gl>PRxFo*{82S2|V3!uT=_R2JB3*Ba6>g>O%p<`N}oEcj~2i9Oql`Cb^ zX4=h?#}O~>G-d~zYR!5_QuV3{f@R=X`|_oMAW1!I4n$LT3l2}GogF-J_jN_pkqhuv zxciQX&tMhwy4(M*?yB8W(C#jJ{QUpndsL>!2q1s}0tg_000IagfB*srJgxvg|NppR zlt%yo1Q0*~0R#|0009ILK;ZBR@c#esjTt>g009ILKmY**5I_I{1Q0;raRqq)|F~k5 zM*sl?5I_I{1Q0*~0R#|0;P46X{{Qfe89hb-0R#|0009ILKmY**5J2E@1$h7exMGw? z009ILKmY**5I_I{1Q0;r@Coq#|L~0&Jw^Zl1Q0*~0R#|0009ILK;Ur&c>n*nVw6V! z0R#|0009ILKmY**5J2GY3Gn=X_{NMLBY*$`2q1s}0tg_000Iag@VEl}{Qu*MQ62#V z5I_I{1Q0*~0R#|00D;3N!2AEhH)ix00R#|0009ILKmY**5I_Kd#}znp>aS*=&itdy zQy)9?_fP$gr?yVsK6P&V$4{O)F?0Nvj(_dg|9b5Hu@61<=GafmBAciF*5lT`@8uuf zv~$YRQufjJ`Nm33RBOVpbyvtgJfT;edZT6;c2(#bmQyo)%dx#36xo<5YlVuYRti@a zG<63Ts8f>@mZ`o`D9>Ckl+|LXq867I7S5@Y6K>PiQ?fkYSQEN!)J5WzRmV)u@Wh62 zEq^QVD#P`yRio`&JZ!DFH zL1nkf^NWS@9rdPmN1d|Fe2{jnRMzI_ib2{``>yk9S-Yl{wc?Dnl+Gy2dSNA#c~Ku% zwwAIP%QnTPcdusoLN}Ve6MoiH2ciub)T2-DpitAeJFZ-OHv4^HwbrKY8{S>L=B#<` zuPn2h;B_KlzBsGhR+EaVrJ~v`u1q zbergYVRzbUuNU3q&Z;n9tY~vud{qd`q$~^FhSgcQ2vz16wb+Dgk4tB%nVNnjAIt3o zN|gP|7vkB`Os{CSN4?asiTSvs|!iHDkqb4c~FS#Kc;RIcHPOZB@PJJ=1YM7=lb;C~{uoN>Fvo9#!aGecd2S<=7b!vJbdfHRAFYbctI*GCq!NiEJ4RWfE zz1rE5UBkYsc9xeQ%ktzdR=q1s^=hfKpcRU-DZXxaa)Q~bHLL0;7O;gdy-vI(7N{AX zuUFR%drgM>O7i(548c`d(~42O8|$|#41dHlX*OiUkI0WrqbM|n4j#R*h)sf>Os2{F z&FZ+KUrwJMNr4*7kEHawuNmXY()n#GYY((MxOA)Oq^!%c^=G#~Uq9UV-kfs&eD?ik zdw;H{8fBEzA)w0uoD^^EUF%bE& zR-)9#p8oDPpETLXoC>6q;Po7=;rWbW^>T>+r z>Nc?)i`6dZ?gr~?`l$Gd0$#2^t5!{T`pbhUtFQf$$Esj@umbV$Q?>T9*Nb83?cn6S zgCc$`KzDG#i0%H#pS|M4AB!!SiO*_O8+U%!HMQ&g?NCES#UEvx43$s-j% z|G)hjN(lrIKmY**5I_I{1Q0*~0R#@a06+hK*hi55BY*$`2q1s}0tg_000Iagu)P59 z|F<`y1Of;kfB*srAbk0AX=009ILKmY**5I_I{1Q0-Adja16Z*N2i1Q0*~ z0R#|0009ILKmY**4!Z#F{}1~J(tiXHKmY**5I_I{1Q0*~0R*-e;QjyhMwCDR0R#|0 z009ILKmY**5J2Ft3-JE`u#X`9M*sl?5I_I{1Q0*~0R#|0V0(e!{r^*$>zT8E^32bi z`Rb`JPX5!Azk2eA#(!#j{&?Zo?~LhV&t$Hj`Mop0w_QySuYV(_T)H&&-g)0xsflXM zaIICVYWS98>xS*!7p|9>n0Yi))(RC(trV^Kldf%=JQ9EtV>3 zad~0koH{viuPMB+sg(TA)psqsd;Qe(g?y}zPMHm())Z<*yIlz?ZYK&;U)j=|o^aDT zVAUH&)z`gdy>7T$-OIyER)sKEjOyKPYSk5nFY7dXbynVbWqwhM_2gE0ez8!#qu$i+ zs8ih=&jVnDT{ASu)=Pj^Mtsn><{G1aT3(t=hf#>UUIyhhE~(jC_n zt~y_=XmeUTUSlKNy@%Z%$(5~frCCZJNnzOXUTVVdgx+Yb)S~$s+@EWPqqFeh z21&0#-%Ji>sc*Pz!q=PS;(<0?;WtNw*>LGUyeNwdqVbNeBoaujGIIABnLQAG?bXSTE(v1l z5JZsH99QmK$foQ&o~RqPZ&meP5bM(kiQoV3hy0v!;X?NPQn(-`6iG<>zF06M6bQz@ z+j821v1*B$nU?7}O;^sE-cl6|ORq}Tua~SZL7t8J&PQ^-H5^X{(uQzXa&uB1g*{0tHu z8-~s`-Hfll`>dN&u3X8!znpNe=@v_=_MKR?r4$MxE~=<6YGT70ztj_6u$ZP5_ML{D zKCbBQHLq>TgO&-MC+3l#Z9M|%<5(7Kf z=DIOBbQ<68jNEJl8~YB=(A}F$2&go}Sb!xKk^z>OE(ah#nb+?H8)ACE_3vJC!5-LE zgA?`W5?c@7Y_#{oe8S0VxW?`3+Z+hW(XEfz58Y;J2=>qHX!VGN*{WsBV?q1?6f4kq zz|!CL99zAyREi(G*Mu$H!LSGd(W=**p;B~S4-&WA6Wcd35C>^2O*{Ee)ql&Qs)~-P z(RoTZ|KCoCd;}0c009ILKmY**5I_I{1P;Fd@Ba_~ z7;*;)Aboy;jqb7QT`qx-mG*tT%fJK4$4{OHbl*{d$S zo1HT4eqL?ma>|2{@XbwNuB%+4*UQxslHJt&s;B*)ncil7MB+m&Z(0V z@!lpD>AwLvSt{C`7O$haZn(j{Mwvmq9Xwxb`f5eHT?x{HY1#CmHl{A+V?C+5Le5%K zH+*$gPRq*tqNdJj*9yxE6?JC0T-J&eJxE-t6c%p<)ioRD<6Us8Jik~d-%)RBcfvU^ zng43*#JEzQ8_R^zv~WZGU1!+wFlF?o{T7chG)kR0kHv zs1NPjd@I+=%D9*Pcy2^Le8amtuxfW8erN|B>0F(r(aFv~eEOR?WqNw-(aoV5*lsMr z;oGTmExOOt2^RILGx>Hn=fbXe>WwAI+CN<-r<`iORTsTU(w{GEGoBl?R~MdVtckRF zczOTl;cP22u6$*BC-blk9-n-jAo;xb=>OqrT)Oj(ja1HO2ws0xgby5 zYW1!j+3KDg)SB=eTb;SC&D;zELw!|!!4#`Tv*y2$pUm_3|MzZhr6mLqKmY**5I_I{ z1Q0*~0R;9-fS>>0FL~NU009ILKmY**5I_I{1Q0-A?*w@M-#cqsLI42-5I_I{1Q0*~ z0R#|0V7~--{@*Wo+C=~X1Q0*~0R#|0009ILKw$3#c>dozYg$480R#|0009ILKmY** z5I|tR1o-#=_Di025kLR|1Q0*~0R#|0009IL*gFB<|L>hOEg^sa0tg_000IagfB*sr zAh2HoJpb>PJnbTY00IagfB*srAbdozYg$480R#|0009ILKmY**5I|tR1bF`6 zFL~NU009ILKmY**5I_I{1Q0-A?*w@M-#cqsLI42-5I_I{1Q0*~0R#|0V7~--{@*Wo z+C=~X1Q0*~0R#|0009ILKw$3#`1k+!&YG4GKmY**5I_I{1Q0*~0R#}(F9F{F@0UF7 zB7gt_2q1s}0tg_000Iaguy+DyPJeIaOy)N;XC6-e^yKQve>M5x6PHf@?6G%`|4&b? zp8mvBpU(W|nJ=II#WV8P-t}o0T6&akeLSa}KR@<^$9!X@CVbbhy_(@$j;*^*+Z+6x z`SUYntx(a_O5y5)rVeJSQxslHJt&s;B*)ncil7MB+m&Z(0VZ#ye`N|xsve$z|5 z%6F}`HR0<1RzpMug4*OIt}jg8@YPw_oyz>879>}ldPCmCaE5SQ$JOh?^Ncm2Rg<;+0|xZ?y6zcWD`l(-L)ExFb8K-p|%4JD6-* zRoSyn1;ZD)!U#xLwqjLvQU^xhR(XE0P`;zy)b6NLmYENFc&${{=I4q*+EhCX@@iST zrj@ngjJ6aDBAM-l*QuqVI;$;cGSp@YOEZO8Z8HDhYb_i)z$DaA$vv2E15VHk^UQ+QR^Y6M;AMwjO_-Kvm1GisvhM|QEx zWE8K-ksnpW@^nMq+J;cCmP!j+p*`l0GbGK18IIpJBQ=@7)%xhTQhjwSW7($I^zPLx zU+6~Dcf!wl8mm5?mXrB+-p{r^9Ih{a^uo~k5{z~K0up@A{9ExM>RXQ5p^>`2?8DGV zR%6BRhK4wtwCQVF6c_U9&X)u8y&X59R}?itm7QSms_UX|BxDR-(5XFG2&zua>#hu) ziiXqswB-fOx}DHUYDUel*P3#54cbb+w9}vM@<&u8*Dqge`kf|*?kKvlm(g&Y4a<}p zNSt`Z@T=>(XT2k$RX;W@P0I^5L%G7s5wb0Nt$*${8=ZyRm9uKCyC%je5cY=UI(A*y z{y@vojE_Pm-mmH(%Dnz^>m%dJ()rYR-8byPB$M-bASLsY4?fs>CZ}AvGWPIt7-ptu z)SRvG{`&6KOG(cBo3UA)QYyagPF;8DHpC9Z|}6?uu@7 z50^_^bO*P#$$YW(p>f5yk_MY{pZau4M&{4Wwmvwnd}TVV!Zk~7)56`5@!a0YxH}aGBwh%%6^p(Qtu3(C|d_usbvZgFAB68gl3A94Uu~$`q?c zv*ydW+HgF}ciirb49f-!XH;ZGhIO@j9_nVtk7QGq!!t|G@O*v4s9E9O89QVS$HA9d z9~(8n0?TgqIC_GaaOynrqmFeJxA4|PW9@w%yVixfbw5%edl9E z!OMejk@@!@ex&ss;c@BFTiuDctlKYSVRt%`$C@ZrRm=N2jSThVyiAG6wT~xj6s&vKAkup$C!f zy~UnIl9oOB6f>FU=l_rL(!#wVfB*srAb` z+x=gyldYF>%G`yq)^nC^icM=%_g%yGYKCt)w!UKc)pgUz7U+VdW-}DkM^&Q`+>8_|cuIWV=2hDlSYE^jNYBMo+)v#*9OuWuF zTwi7xzB(&Mtunu;1=UrZdP6cLWVpgeNWN8`Uo4dGs5iAc>Xc>XgF3F2%G&%~F-VIB zR4r@Qw6a#5(UxMI63Yv(3nF4xThL_u%oLVp3bWc|zICp3E~nhl##&lZM855;=%!T- zqSJ6K8Ja;tJTwQ3Wd5sBF*;bfQ{iB+4i;0V+70Jhh1QEXWli?i*inDGo!{E7+yCWb zbvst?_Pvi4&);r+*SK<5+sV`$gwS8^pG$+enZJCym4D)@W7B)6>i^46il(d%G3>;dUfuabn<*8SD&>M)O4R1PFj{-ntINgt z*O#>@IM1oQEZMiAdD`xBK5d@L?6i40IOF5(#3~eS-LjpUv$hqRxakYP2U;)Wl$)2v zTKS|2<;e}nY}OKIem5`kpO2b5-C`+oy_+97=5Mqy}@ZeE*%;a{WiL$a4btBxslBZ9z zVLr+B_2kn+ZeOQcpOI&e>9N*p?dUZ(!?4$d?Ymog&9K+{=1Pz#H?hor5)aqmYk~!R z_&RmUbDC~dgw-~UHE~Xr8~mE^y9xQN)~9pIMcExC-ko*B)2oi{%aItaH}fAS_owfo zv<~$Z$+y0v^{Je)BpbgR&E(;>dW%A^Ar9wf{-bzb+MMC`zZIeehk(Az6)TjV zZ9O-xd}TUqO7|7+43hrxa9ZX+oNcL(S7VEVYtk2O6EU^ ztp>vdMl1z=g;VydPGtFV`Hp5>?4+01vfB*srAbKgAbKgAbGAbTfs<_FFcPXCqD)02(K4^N2kizj~j#7oD& zdF)rRzj5{_&tA>mdFn?`e>|hf|M;~tfp=Q3<&;m)kF}n$Y*TDn=BDn}Jl$>DzH8WC z&G0S94nFEN!(M9|YeM&Y!}l_Occ!crDw;Z9oYiiteb=d_qB{Cobt3ct?$Vx z^YdfxRefWnCPrU2IydvTI~}SNt}bZX_F!_tGSxQ<<(cb+vRW)v)Z+5O!Z~$vqTRK` ztgb-SF-2kt-|>x_?mG89=~B_=v~o~o)Nx@BWvv=kEg{*vYc(1P>ArJU*m~8GqtoAj z@O-Oo`0|3PT(zgQ^WQEzH@)G6s5q|KCyOO zS&K&JoEp2|@ZxKwvNk_g3@VJqP%UfMw6a#5(Uu0$y|B?B9%i)#O~%ShVQHo?t4-!x z=UP{C${lU2rM1IuQ;(2>aI4Emu&TOe8x3#W@xySG@iMAN=D&%@qq}Q8!X+aaBw9VET&F%yl%HH?sVxGtV542 z9fP@XV;U^Tn7bOgt>sDjGT08J;f%~LjEdXX#e>n>&g{l$>v-$s?fcQ5 zwh8_C`5pA5b7CDhc1Qi_tO&EM>2c*N(>vK_JGU2`A?>ux&pmv$_4%AKJw5hlZD?M! z%Ou>y&!*0SsFS<1X@<4w{#GOTaNf?AM;@cQq(`B@qX}_HR&n{P(>?o#PkZ{y{lhw(pZPmqYrXmhs6G~J3Dy5H@Bb5qlq3WYKmY**5I_I{1Q0*~ z0R)bi0MGwNY(Tjk1Q0*~0R#|0009ILKmY**5(N17{}ND0LI42-5I_I{1Q0*~0R#|0 z;D`zE{{M&#D7S+E0tg_000IagfB*srAb>!E0MGvkC?p|(00IagfB*srAb}EUKmY**5I_I{1Q0*~fg>is z^ZyYWP;LhS1Q0*~0R#|0009ILKmdUR0iOR8P)I@m0R#|0009ILKmY**5J2FF3Gn=X z#0HexK>z^+5I_I{1Q0*~0R#|0AVGkC|1SZBBm@vZ009ILKmY**5I_I{1df;h@Bfe3 zfO0zsAb(G9nKN&m`QYhqo%)qi7bgGw$)7!0&HdB~|HKQ& zfBX3N9{aWIk7h5*BJ$ViiG(T+WYSk#x5kzF+*ro4O|j|St69F#ji&E}pLO3gY_Dec zmSgJ;S8Q0~zFsrzwWhHqJpJX7*_q${YOD0*l~0eZ{CD2{QmdF#=H|xU-|~%>niyGp zWM<|c&Xl!6MN=zB^z`-!t5-{<1+7pF(yOj8WZSyotFw}*GQX$=$+yb$i-qzX^`>@5 zowCe)kTz2)E>+5f`C>(F-s?t7MHJCwJwCwZke09 zUy}&o_yxU*n1k?-dgo>SK_^`1i?iBob@-~Ft;8$Uscvix-tGO?LQZ*6c17v$O4Mdz zZJFOr>PK|Rh)zUB+RisxH^-H?F70Fmh%OwM`Q7Bq-@nni@%WX+W_qu(-+K2#Yd)u3 zx-|9!$A)Hjw^%aGZ>G-Z?u8>}a(9%X84{c4Q4I%d1`F49T)i$lPp-|~*`GGAyEox% z$O|pg6!xx6`@YE&>=E7R-X$Fj{9xtipXS|ysnfe%V#KumLhE`?(Pze5ueaxtoYe{2 zSf?7@lVZXAw#*TwGQSa@YdfuSa2Cc_J$Vnk*7I+)=EfCkW+xMIpc*|kg9b7)zy5Ho zbuFjN%#6LaG&GL}3XdZAwbVH^P|1jy)w|uqsnyx~XdR;-j@5K z?r$}^`)CkM@!Z}nJe+46^`t9J!#C6$OQmrCi|>@NbzoI)nJY&1ZnvwCu~+s-e9t5` z53PAsh(-nyRN$NzpO zeH^YT)vvE;uftEZuI7}RvcvgN9bPf~>iWP^7E%7aopdv*AhmN*f&8^rVO+U$VJFK~ zrw8$6D(cpM_vpFSmvhR63uE728(N+^g_0uUzwO-4@S(kP(THUzx{1U^s2#qES)GyT zUyKg!`jmVi@SVHDmPePS?dz7^X!@!=uxoQ#IanY2Go7YCnA^9DnoYO;R9N@=E9eW| z2r#Jk30KBwm{Qlpuz*Ng4uh8a7uwFcl=j#lv(svt%=7;LKz{pzP9cB*0tg_000Iag zfB*srAh4?fJpb=1CzT<900IagfB*srAb$`C*R0R#|0009ILKmY**5IB$m{Qv(Q$YG&V2q1s}0tg_000Iag zfB*sr?5Y6o|96#>$`C*R0R#|0009ILKmY**5IB$mJpUiaVWCq9Ab7h5!NxAbdp2PAWqH0R#|0009ILKmY**5J2ES3h?j$9mrv!QwSh{00IagfB*srAb34|(xYegFUf literal 0 HcmV?d00001 diff --git a/backend/:memory:test_main b/backend/:memory:test_main new file mode 100644 index 0000000000000000000000000000000000000000..3207a6dc0c33f3cccf0f19cec36cf0c99ff3c5ee GIT binary patch literal 917504 zcmeF)4|E$zejj*%k^m9>H-8u2_3loO*0V!+1PwtFBr)>rEJU^_jz~ZQg0s@jOxlI+ z0@LKyR){Uk zg&qrq!=cX#LMRmaG4{XTVgGage2IN=+Wm(88}9fz=*u4qU3ll#8J0Uf^>e(;uT1^v z)E`g%!PM_h{U1}mJN27WzdrSAQ@=d*3yn-(0Dm9=0SG_<0uX=z1Rwwb2tWV=5bzcF z`}J2?`j6CKWPg8u{p0NKZ>~?VzrXMW_Lr)&zutO_{dH}V{UxrlzveEozn=Me_SYxl z6YOtx(~mz8fB*y_009U<00Izz00bZa0SFASK#Y$K_y0pY!x$O_AOHafKmY;|fB*y_ z009UXe~vLi2tWV=5P$##AOHafKmY;|fB=5~ zA29#{2tWV=5P$##AOHafKmY;|7=8gf{~!K2#t0z*0SG_<0uX=z1Rwwb2tWV=xc^5C zKmY;|fB*y_009U<00Izz00f3#0QdjHKgSp$1Rwwb2tWV=5P$##AOHafKmhmuhye&d z00Izz00bZa0SG_<0uX?}@C)Gmf5Sh=7$F28009U<00Izz00bZa0SG_<&;Jnv5P$## zAOHafKmY;|fB*y_0D<8b!2SR5&oM>_0SG_<0uX=z1Rwwb2tWV=5WxLEVgLdVfB*y_ z009U<00Izz00bZ~`~vv>|KXowj1U44fB*y_009U<00Izz00ba_=l_TS2tWV=5P$## zAOHafKmY;|fWYtz;QoL3=NKb|00bZa0SG_<0uX=z1Rwwb2;k@c5d#o_00bZa0SG_< z0uX=z1Rwx`;TOR3|KXowj1U44fB*y_009U<00Izz00ba_=l_TS2tWV=5P$##AOHaf zKmY;|fWYtz;Q9aX&oM>_0SG_<0uX=z1Rwwb2tWV=5Ww?)!~g^!009U<00Izz00bZa z0SG`~_yzF%fB5GZBZL41AOHafKmY;|fB*y_009V0O#MkHK5{!W`JbnLcH(bM{{4yM z`1i*CXnZrKjsDWv(a|qN&B)J0gwua|`hPuboqp!jcb~d>>SH6fM?M?+|HA)IXr2A% z{<-tYN8K;+F9Z${s0;CE{8OI_--+6!q|quhE2?FwhHiCy`8CT0FX5nrc&t)a*tB&FWLm0UxPHo{Glf@o@d7!{a16e?9FXY1STy!JG9R ztwJr?RI8mD9IqFl@MI*Oh=(l~p=MFjl4ymfn)BsT0SX=EID_-8Fzp>lW>(*-c6$9`A?jR4%2Qf1bE=?lA}X{ZBc_PNMVI;~r!usZYf5 z{6J`D#O@Su;wrJM+lHw~JH*=Q%qZ71&55qgL>3-9k~g4vC8{OyP~N4&rF?!}%;wxg zMdH2bOqESaY^q4a7FO6=Dz0says$*_9x zT&JtSotzr9lU>#I?QB=sME$9WXnccpI(bm1nX*j-5GDuhs#8hd4mu?gcdBF2_{EFi z_isC^A)wiS&l8GjRf#R{ z^ybjLs>;qHoh!z3q|b`-=Cj36tMo3p-nF$c9^ug&a6$-Blu`j16ZKEVqVdnA!u4!# zU{$DPk!?1rF3ombZi%trz;cUpSK^H>x0Ep5)mEY&8I8tQSqGo()4}H2?(JA?fQ~f} z4(gD*Z`^q!8jYt?;rB^bth;^hZT)OOgu6%l83s2$%lk&XP4{e}C|+k*KOI*_}= zp%t@FoQlR@cp-fEjjot=%C!U5`Sx@`v^MJuykK-Y;eyRE_^5Jm{NULH4VMOP8e3_*CQUy z&YV80KJb#TW@@gJXCblkio#k}iDq>yNl%g9wYE4CiC=v#2%xj8QmXU2Q|$iiEWbya zi2Y*d$?$Wb@vn}3Q*8h2pPc=k=r^3b9QoEW??qNm{hw#%!~gKq4@~~V>lt_9Yg$FxB^tZj~e)q6=+HH}?WajyB@rNj3ROWvVMO{0=R_I-}J%_hsZEwS^V$xf5( z#>caknz>Y0dh>L{R?GX6aa(8i44%8Gnq?amN!}s4PPImxyeCAXrgKJOC#J4_(C2cI zA5p8a&>7?+QG6~EzcClI!hPmVO8F#C-&s2sji=M$_tVZ+=ZsL58`0}r4QyL}Y0r70 z#IHo3FtPWm{ueHRdt=8Q*c%1Dk>kTFtcaJhTkAz(d8<$mb47{I{bn({aV-G8{{g+5 z?&_x^@i)>zQ{smtrTkJqU0)TP>(D!y#yP!OZQN6D*UZLEHR(zDlxISE^ZQIk=jqn7 z6ntXwuq4aR_Pyro83sES_oRJYJ^4&D{?^Ok`i8sB${HnncV+)r{KGPS-N!z)V7D7wqMwMyUw%1!_gQE9f{qGG7d%rLSSt9l z&d$zs?u&gs=44rh>6Y~bfvvL3Gn-VZo)3f+YO{~}Ea`2FUET4UXugDcS494kk+}SF z(258env@F4c~<&(ByMdCR-s9^*#}bQzGUg7YV8>8Jls`rZ;4Ob`Qq2IPhmE~?;AdI z*IVA((cb)z_nFJy(tQ?bt8l=lA+3CV@6&Or@yw;qrr0=3X~u1K&e<_6+vj{qv_>{R zt+H6?-GEyKoKM&#zPJ*^a+`d4IVPBK<}B^cFxzb%g&vLap`$A5s6Eg zpwRTcT9Z=#>F3!~GiM8V|8bu%Y!A*Ge(m&+^$ELnsXpP>c_!u|(l4qSpF_7+8QYf2 zzB@^&rfU2`&ducY21KNrT-tXFd*YaXlu@(XEdQ-1{WX#J+NXl1qvN5Glo}UdB1Nap+hbdC!+z70 z6?pfY`|F~u4A;iZV5QFSVYBZmRom@=`@);fm$f(rc=4=GwEcIeVDC_Y1qk6Ux)EBx z5G=HRT~}c5qi{-<4gTBvj9j35RIWL1q2X`J5X$U*4~=0tWp`Dp#(q__@mswY-qhdJ z*IB8T-qhdarQhQT*BWozX*A9|!ru2Ouos0o?@(mbu@`;{w^jCA!n}9wc3Yv!D|=HH z*q=Aqdg8yq{U#gJo9C`&H#grrCwzf@`MGQ%*ZlHwc5VI5bLU$JG=8nPam411!Cu|t z{-&`}7Rv0!AbhQM9MBjEFaJiP4&HFHef}l?!}`Hu&{XaHM!iAJH%jyJ%~zE*im!CM zEthqI58G+A)r~mIuCpoN z)xGtm{vHn+#gN&{Bz4Bf-!s(+As!*Cl)amXMYzC{%IxKiESI(8DeX+XcaEBI??i&i z-T@&STCJj6EDly0D}n{IyEdF1TlOM3CnA=e3Y~3$uUjYd&I^1qd`Y-);R5?o-D`furqFV}Ot6aH)C-Ne zuQclBbJ%Rgnfn#i1)ip`f1QLzL&8SmMWZh{ryDlB#(TR;&2`Hn_uX@?eXQdRYCNQS z!re`5i#jQMH*df1u&VKQaha{R1-J+GmT-QzzFh-*{}4YrzGLY8G;vO>nMReqxM5hb zal3VvGAVz3EMI#39b>HA96$LuC$M&wrm{I>d8rwmStabu*I2IY43=I|w;OMDlB|7Q zmSpy(LEi3+Fe`jL|Bts>F0*zTrzZYp@SgKiN4~5PQ!O`N;l(QA=Q(c;trI~r_r3RK zXJ!|YGwI~)tdN>}X>RGI`FZ~QKRorvA@+ax0|5v?00Izz00bZa0SG_<0uX?}Pzj8l z`sirmnF!whH&hdg!9V~45P$##AOHafKmY;|fB*!11@Qa-zAQ+D00bZa0SG_<0uX=z z1Rwwb2n>|~p8pTkbYd_NfB*y_009U<00Izz00bZa0bc<;|Mz7!|NF8a5dsi^00bZa z0SG_<0uX=z1RyX}0=WMls_DdFAOHafKmY;|fB*y_009U<00O=Oxc~QMK_Ubo009U< z00Izz00bZa0SG`~s08r-|Dl>r3|~fBygYNGvq9J^8bfkB@)N*uRKT{|0zJ{kF~GhaRP zrPF`q^o>)$I1&s0)aY-HzZm*|hido_HkdmfTZqP!$?)B6o0K$a8XA?V)U2qMr5d`` z{ryYJ1u**82K+AvW5sSZb7bu)g;k zefQ;y(fGxS;rov}gON2#bjhUbAB#%FwAC_^Z7U%870=KD3h@yJ3{EDxqAJ9u&9U{4 zp4dCSEY=R0O)vOosqau>Emss*MK7g7Z7SPTk!055wqfqOhjV9z${H~PGA*NK%2cYE zYUd%%)E&dJJCiHaCTvVZdfPH|;nmH2j@N&!u(pvc+z_scH-u?bN$|AG`GUB%n&WBH zofHY7AYK*=Vs2U76uhdfVwO`&EKwhSDH>mWF*ndba$<F42PV~ShqBl%`K_fhVy-^ zBkiuG+#_2_FW1RZH2&g?;XAjSi0moQlkg3mDD27Z6Mt@5cltaluivUXXf~V2dM1*m zxwH1lVkEwq3}SMQZZCXGN_D4Pe6)K|&pP#ZGzWiPXb*v{@1BTn77H-yULW4NIu}Sg z$JL!nN8+o`2It&SJf%HqM3J z$MhVr;4$pU?z32_zN?ysUZJ`jbh>C&XYW_3%RQY*c-D2T7Bo$?V(?Ru&dv@jL;_1S zS#(lqwZY{zV%d_lugmNtLTq7$o%4%p8=|lxUe0c<7lq}m0^8Dy5>MPLW;d?!gFMsk zGvVGrd*;0(t1ZyP1H9K7GB z@1CED#uJI~{U@Et_2zoNoA*qsH?Pl}HYwRqg1BvBZc|(8Q^K-|U9(!Vomy~q8k1Hv z!p_-BNw}2HuZvmdEG(Opo%@e*emny>?DTZ6SI<}vTNzuvXkAbG z7wf8vZ(sfeg=ufAiTZQrqwyQ8x8ec4Rfx4yGKi_L?Zvq@0vvt`1${y8(}0s00Izz00bZa0SG_<0uX=z1cpuk zKmR{;Q;GpW00Izz00bZa0SG_<0uX=z1bPJU{J)0;2@rq)1Rwwb2tWV=5P$##AOL}( z6TtKTp_@_+2m%m*00bZa0SG_<0uX=z1R&5Ofam``BuIb&1Rwwb2tWV=5P$##AOHaf z44nX;{}0`iVn7gp00bZa0SG_<0uX=z1Rwx`9sxZ6?;$|~1Rwwb2tWV=5P$##AOHaf zKw#(u@ce)1rW6B$00bZa0SG_<0uX=z1Rwwb2=oZx`F{@y5+DEp2tWV=5P$##AOHaf zKmYDU51Rwwb2tWV=5P$##AOHafK%hqe&;NT!kN^P)KmY;|fB*y_ z009U<00IygIsrWYAG#^UfFJ+?2tWV=5P$##AOHafKmY*s~osJ&mMz8S1)yJq=jQGHi64ZT8jTWVL!YhwqQHdQ2I3oEQE z#kCEQCzn-SwRU>bHDlWnUfs;+cp++#$VR@@i z5OYO|H@I2MZd~KXSBXg~?fS13);6+*8^TrbhA^!v30~xKz96ox=6Kq)cT@?XAYK+( zrOV=`(2-?1#|rrzYkOT}+M8knGnTj~FGu6qZ1`JVbEc_gQBzWgwNo;PsYq3mmZ?c~ znT;wi=Za?vgUj`qQ0Jibtav8ds#U3JQCs4LbW&-}Jh$k{lyt+a5KVoDwnE1#w`1Iv z3|-roD*Ns6S;D1!eqGGwybZR>T3T)Upwio_f6sV2tq@h~j1Hd2M`P$jlZeb%Ey*@+ zQe9%k=6;ohN@sB=GNmfnZjIT~QBt!F$*8iUopqy_Zht!%;)*N4rl0tP$wfEh| zJk{D%quVSByOxPF7>Otf3-Q(xkCtL1&BE0y_h{Yd?mLFa<5Rh6D)(wTqIGHAw+ zC;oX_Bk*I1&6P-eI~xwEx zWDvepH1k!xTC;r%w0mCeo6i>aTCOOriUl4rZBTDI+btDU=c|J6CLm$+QHXz z=IOuW`1p_EJhhzNT+XhDvBbuuNSs^@TEOif^ejCo6_By|#%CjOV=bsUS))W}>zMsx zQK@QZs=O~*I;mPahHXiy{`o6+Uw9=NUt0^`Yn)R1m+qgt?Aayym+fMIDcpb88BxIT0m<1u)7@&K&pgXS zS5y}BG)UU5L~FAYT-d04 z{Vr{q8+h;q&edi#Zspcq+Y;FcbVa-_3{)q-(+I9tn0C({^|E+2UJqx(cb*=g!~L%H zgIjyGIf_BL->-#(#?z{}fB*y_009U<00Izz00d5y0Dk`eL`@eu z3jqi~00Izz00bZa0SG_<0uVTo0G|IJi46xq00Izz00bZa0SG_<0uX=z1WuFyp8uby z=|X2A009U<00Izz00bZa0SG_<0!I?S{r{2Ja1aC_009U<00Izz00bZa0SG|gLY5}N$o$)_j2Z}Kx!zdkiKab@E7Cw_kF{?uC&wMP7M2#4=9ZGPCAyfLCuNc(silQvsgx?urqXnARw+Hk z3(hYpG*ebsjZ3Lga(*V0NoLYColGe+8M0K)EY8X0DW_?fE-lVvW|O7aMTHeyN+-!o zc_yhSWR8$hCbK|iC!K<1ej$@e(Ij0`SRYfY{Y*;EBxPkbvoMpEQ?rCj@Pc!h+4*v2 zE|r{1r&%9o(=*A;Oo>%XGxMnu8;e3y<4zwlba9a^%p~bND?Oi{=LKapqJ@$&pI#^} zF3qIIctKeqv+_)Nf%Sf|%xavMlS`%4Tyk-tv^2jkTbfDF&Bb^@x>!yrtk+B?#hPB4 z$t1~qW+9oGo1055%+Jn|5*_6QOEdGz94#ryGM!;;#U*)Zp_EL??63LR znR1d479(X=QYn?@*r;W^|No(G6KD(q5P$##AOHafKmY;|fB*y_@JIyk`~Q!G9gRW& z0uX=z1Rwwb2tWV=5P$##9;(2^#J$jX=%0rsej)bq=@|A2s$mNSdZfkx0ybv3;sAZ{!9+cfW+}^KJw}R=^V!~5N*)S`_ zZe=fdb1mC2$u^ZtT6T+gj+RYIY^q45eW_+qGpH+WG1kxu8*_1OL-bU0t+2L{E!+^U ziZ_JmR=-sx!H0P{Ul7+;b3AjpJ>-N?5HE`bF}Eyk3JS4_MQzs2U6tOJnx!nEvwSRZ z@00mxJe>}IS#l<*bx=*0WJ9;GBPG`-a8_x#Ol4c$rBYedY-(DvWZ=@ zT;S=hXm1vxrfHZ$QM_K{0d}b9^v?6~2I%UwNc@d-IHc+d-Lr0KD)S{Z+i<>@TJh12 zG)rPXvDOUzj?~xhzOfOFzxZPKK6N5pHY!zBV{_4r5346((-Y%8**w4ximm>ek$ZIi z>1j302H%<<_s}w%dumoqRc~!qo{(%ET-tZ1-;?i5I$P;VYcu4N-$+#$l&V>+Hd}Rd z>{y2m6}RKZy^m#ck@(h&L1EJBdb4>JBRxsQ_n){Ljb}394_;{mh(=7ctjfgZ=M#7P zlzmfQ^M;CV86GdbM+a?O2W*X9QIqkWq~w}u@=ftpjatqC+S?zWGm~0|#&;swsIkyl z%N4~{(R(H}**2s)drNQ`t5&HHbD!;0noU}P!g^-%6JST2c!I80Wec=VKA#$mc9r10 z_M8%fERT2lxw;;SOPRp9@||fGT)ydr8?Q#WwR(fxS+FISY!t5mL_!zbc8k!OrMD7$!vF4 ztsQTqH;Z?ikDDcl)^(nC(%BANGx@b9u?*c+;5qCJce4YJCwZ2K&j#B$DV|Hku7Ggo zj$JGI)Y36?eJXKF`Pb1qbA77nD(qjQ-z4{`v!{5Y)>wkwU7fyIh{W@Wpk?ZA%XF9R zuWVgr04qkP}i*P@Edjd#JO95WgYgmiZ8~_J2a1_r#60r=!PDC{{KXMw1Lh- z00Izz00bZa0SG_<0uX=z1db$tpZ`A+8xDd11Rwwb2tWV=5P$##AOHafoG1Z2|36XF zh0a0%0uX=z1Rwwb2tWV=5P$##jwFER|3_lOK@fld1Rwwb2tWV=5P$##AOL|AC4lGu zCu+LTSqMM?0uX=z1Rwwb2tWV=5P-mu1n~U-NNhL=0uX=z1Rwwb2tWV=5P$##AaJ4t z@cjQoO&2-~0SG_<0uX=z1Rwwb2tWV=5IB+mp8p?-4F^F00uX=z1Rwwb2tWV=5P$## zPLu$i|DUMoLT4cW0SG_<0uX=z1Rwwb2tWV=M-ssE|0A*CAP7JJ0uX=z1Rwwb2tWV= z5P-mm62SBS6E$7vECe6`0SG_<0uX=z1Rwwb2teRS0(ky^BsLrb0SG_<0uX=z1Rwwb z2tWV=5I9i+{P}-u=E#Bk|2-IHc+d-Lr0Ks!b(Qvkm8aiSAVm)0T*7t7RhFmXzvF`TV^vycLZn zli{ztV3U$Y6=D;M+EUdt%Bn`Kp6{0nVzwv>#q6bZQRvPUremYcBPCT4Ue6YmuVf2C zE?*RKTkGrRh1jS?ElV}@plr8Bom8m*@$wF>5UDetSIdtpv7Yy2lxmi$vo=7YxkC>k&?8l z(%ZtNe12Wb<~-HOMy0Azn>IQr8zvPlujjKxezXqY!ufvM9&Co zRW>_)@~;)vHnN2q!d3BxFx?KH1Q*!Kt-ZD-3e)Ydags0R3*y>pjvvyQB^1QVVnNI; zi<_<3G%2T-niW`{s$z-dHzV=SrGnQFm1}&Wr3$H5xhY>k-D&c@kG&C%r&8fBOU@eV zEzz4&@~orYe7=&JZ3ZosHi_>-VawO1X3)XA#8mlu56XAju26f&XszU)wP2FllB!p0 zwzNyM8WmpM%zLAomdjMO)m_?AfX}OK65T2rW`#Jsy1{~*uS}ljhNnh%spgJtdcm1^ zlisSSCbjt1rm3>ZHn%DZ8P>XQXu6r*%V*ZRd>X}Ah?e%Hn&naB9cpEFL^w}B*1&hg zRpodiT>N|_eq$~u!Wo>(RwoZ}ciWIsK8fW0kKBmH=jOs6Y&tRSQ^Y6f8$D6(Q-Ftg zv)!ObJRr;o+k9FvlFE4J)nXB3s`h@nz?`>$Y$&Zw)w5^Ws;&9wRM^RcY&W9Sa|nw{ zLu>37U7K}Rqa6i3aW4}Vdrl0RwCr|ykT`QH-1Y9T{5a3X+Gal9_*%Z+ZwIw0JG-&n zpDq8!hQoGHpS1VGpL2H550XxF^_J*O`E#Dw>doh&mDl@S%BmH9Da&HKab9C#)SdF?`#W3CrRw4x?&U!-J*kvUYZ{D@X#b zHM^pzbqaQ_PMc?N-?OhtWrJ|A!Src?duN0uX=z1Rwwb2tWV=5P-nR6TtKTlQ(DR zF$5q00SG_<0uX=z1Rwwb2teSl0(ky^STU4`00bZa0SG_<0uX=z1Rwwb2%J0tJpVs= zbA}#600Izz00bZa0SG_<0uX=z1P&{J=l_QlLwN{500Izz00bZa0SG_<0uX?}$rHfy z|C2Xo=rIH!009U<00Izz00bZa0SG|gumX7ge^@b;hX4d1009U<00Izz00bZa0SKHt z0o?zeyg5UUApijgKmY;|fB*y_009U<00M^saD;SY+~J%G-KOpe5ER_1gjYdYq=Hiy5Lt-$mfJs zabeo|l7X0SN8>L)6RtlU(1vByOqsS0G!JN}QQW_+^FkvxVW`pgMb_ry0c~n5ZnRdD zw+?91DIL_JlbP7riN-Um!81M$sw}8%QmMAutM+NnE!^Flo1S=gI~reREj{bg5}!QV zE!k?$=+m6%i0(FdrmCD5T2&_QTq{T8&pZ=;-*EPrRuio+^k!R){i2oJ+!fYxMR8U1 z?g~zsfNi1Gu&}~5q2k(x=vk1Bd1-Dn)2W4oC$||WZuY{wH``t5Me#b@qB^#z3X4UB z*rc({dG;X7yg3ZdI(O1cDjTNKSk@ePMO+uzhPs^HT+XhDvBVu)iN+Tf!}p>Nsl_%R zwl}j4ThmC%Fo|uLmT#iwq4q7(XES!o2guhfY6flArlGYq$mu1oDp3@wNW}J^u!Hu> zcBed!d^Rjq}Q{O*g3Xju#1S!I=Ht&E!kA7{8~bA*NLK9RgLURWy7qnFleqmUb<=;yHw|w zAa3e(sw;XLOSU8K_;Jld)(O5a++%r;Z0P0YDcL0YO`*BH@GRA0XEFIERfJ3V{JNOU zd6xJNvDgCB%bF_Nz6Eqj6{{I5I z)=2h#wH@!XGv3{@*?>vQ{i^7Sd`~Oxa_d~0o&vU6W0Bf*rc8BpL*8K%C$Z&eYNRSz z?1V*y%j@~9bLL~$E_TgwJ2;*39xERZ%br+mfgW$Lz9RLDFE`-X{!>;pYDu%*DdkuG z+@UH+byq;|p3@rlUN1PIH^7zm07Yz1fDUj#pVR%(@4dX!?};szWp?dTeD5u*x@zrs z_b;BVP+9HX!WDM0rE1ngxuwF-{~x@Eq67pW009U<00Izz00bZa0SG|gqzmBZ|4;f1 zqW=(p00bZa0SG_<0uX=z1Rwx`g9Y&X|6n7OfB*y_009U<00Izz00bZa0SKIQ0X+Xd z=`)D_LjVF0fB*y_009U<00Izz00a&e;Lrb`I`hTQ)SbycoUBd!?-M)YzcK#C*e{Re zVm}+pj{cp|`LjQC_W9`dMn4w$N@Ri+#2*Mi00Iy=27&tcQ=_4+?9(5up9(F^EG?F2 zON+@&CX-6eD{?7Gl$rTtYJQQ<$fE!IJkeYjGe(9xD=ECfJI<=Hp z%U#Y}`<6{BMfQe5!FjbQW$&R8tePydH?5Uxnzk>n7mx{6t+uV|!t)zM)$QiH$1V|F zr{?otc=D{%8~Om9nVXqg?CMPOl{g2rULSv=g|V1fSXx+`TT0HB=wfo7lu44LmKKtw zQmQEU~bjIdWu7wlHLc z%*r$6g=9)uEGOq@=jG&5DK(c|TqrHgFU*!^(sOe?7&A*3W>fR?Gsm<{CR~gM=*-MQ z_sk3&8RIRC`EshPl;&m`!2)HGF;il@hmuLoDobgSPR$b~)s3mH0EHKBTVw`Sal*%bGvmnnU zXXyNFa(;m*$x=Bzn@r1d=`BS>2 zlaUt2JY8IpmljINl+6B`pPeZu31Mg2GSg5>rMbm&S@vSgExj~9e_?(xGdJ5EnMcG3 zyBJ6B%;J1z?r4$0pZ`A<`|;4!&rI!4JU#xau|JCa`1qNzuTK8Rq&oTB#J?MRZ!9zM z{S!B)(vyEM{%zxH$8gb$Dj)y>2tWV=5P$##ATYSV^69N?_`yCaed+=0;2&{5>D2K6 zpA52(DW7=II@qU+k2l8hK%Wpk_CR$sKG>Ub>Ue<9!`O#&lMh-4`%G=ZspA1YiejIO zjX!7|?BlF4r;ek43dBE>ialT*{F9_nr;ek40K-2GI{Sci@DFjKjXI9}*$4k1Ch~xF z@Xt@!|6e<{e;oZ|2mTqz=?AQXe{^xmspIH({QTpGkxOhWqeriUe`?^||4)2ZXzF*T zetzl)r|wOar&gz?r$#4#Z}OKW|Muj!P3n{R$(hN=C;rpKKb!aoRuF$6009U<00Izz z00bZa0SG|g_yj(ADjW7bb?*F8zo&w;olmCxv)!MKd!kP^|2)Y*+x=m($AYq(p91-2 zw|@F+vQIYu?8Ya%je6l-!f+P~0 z?R+NTlil$n7pH@>olg>avpauAVdN91vZLN$aYq*h&}4MtH^#qbT%E{I zJUjKZlmBt@XD7d7{13eLTR{K3Rm$8U{iCsGsPsmCY( z-QL-lJ0{4`?oSvP1Rwwb2tWV=5P$##AaJn2i>J3fI?#Q6 zo@9;9kTqWQ+|;9{YL#~4_Q9iC_lhGf201$ACoeA84&0$Yy*-TgPpH}3!cX=v)#r+#$uGm}q`|MB=go%p_qTT}B>W0Su-`I8e@ zCZ3u6_Q~z3`%`aC{QktxAG{%;1Oy-e0SG_<0uX=z1Rwx`hafP0YHOg6BAyzw;FG-I zARj(FF=)ZZou&u)xZ$xu3r_KZgM7d+IcUKNUT~0)6vhWFIK~SO@*zTO(1N49;2<9x zoE@}a)G0W?2L+Kq3!dQx2l;5=^q>V#@q&YV7%=kusjY!N1>o=h4?Xq})+U;O00bZa z0SG_<0uX=z1Rwwb2teSG3GnCtxc`4-{Ad^g5P$##AOHafKmY;|fB*y_@K6Ns{Qsda zqY(%|00Izz00bZa0SG_<0uX?}BNf2&|3}J?#vuR!2tWV=5P$##AOHafKmY;{MF7wL z9||)XfdB*`009U<00Izz00bZa0SG)&0X+YIr2J?c0uX=z1Rwwb2tWV=5P$##An;HG z@cjRwFryI&KmY;|fB*y_009U<00Izzz#|pF^Z!T6kH#SY0SG_<0uX=z1Rwwb2tWV= z4@H1K|DOz92~GW_iJzMI{Mb_LKb-xwvtNn)aAfUt_SA2VNFz^%u1x&i#P1!{nY&lM z5RES`j@(b$q@+<@|A2s$mNSdZfkx0ybv3`Ril>ER6u_7=$oqEI(|Aem+;ilEVE0r8WoD-^&+ph zkw_J(v@g{xY6f*ctyGC@OIEE?A?AMTaOaRRrAmp&H(RN)Nr}zsB(|`^hF)CT5IsG) zR#@A}7H$Yv#T&wOYv2jqpRL^5Yg?i)-7#P%{c^q_uC3 zRn^G8WS9yyg|%E!Tot|X>Y3rz7>;`;OZ$;{Egw9Sl;~_M8YLE$sIO!Z{!n@=< z^;*T)n)j)trO~enqf*sWqRW&;4##U$6-#{M?MU3(7%bLEwQ3q{g-HsPRmQbl1VoTni^Oltg#*qz7OfE7R%NLj#8S#9@r&<2Wk=(4bKwv2&W7Yu#3$)JPcZlt z;Pc;VIcUQut5j2hGA*NKvQ^XGs`#|Dt2Bvz)Av+SA-23D+51)M&gXQ-d*LD*dYMHD zUy~NwxT$b?J)dRQMjh8jY`s+tiv`jyHB0OZNhg(7eY_*B0t&TcQ*}=3t?QL`X7j{W zHcZwnw?Dmm)^uv7tBZ%Z;%TG!Y*MbVXOC)4SR^Yu4!ew`~EX#G=A}7_=7E<3!7H4fNJ0IL|Z^19&v6(9Z}<%R_~z}wfJTlRMa6SPQWatSn-$E?FeAC$kBw`8a7C#{d2VCdbi*49l zXH|Yh-M_^C-8ZU@^I^j0%B#1=gX-Js3d;Vi_ceTEG3m%ASrBZX0-0O9oc+feqF_5k}2x6(}{ufo9L+)3V zd#UPPPf;Th-`_lR`0T2N=G=7mT)lThM7z*!{QUnxpKKr>0uX=z1Rwwb2tWV=5P$## zAaL>p@bmvCe-1GM2tWV=5P$##AOHafKmY;|fWSclc>aHo5b_}a0SG_<0uX=z1Rwwb z2tWV=Ctm>1|4;rLVgwL?00bZa0SG_<0uX=z1Rwx`g9PyW{~#gcLjVF0fB*y_009U< z00Izz00d6H0G|J!{5ix3AOHafKmY;|fB*y_009U<00IXI;Q9YSLdb^z1Rwwb2tWV= z5P$##AOHafoO}U1|3CS2h!H>l0uX=z1Rwwb2tWV=5P$##4idog|AT~(4*>{300Izz z00bZa0SG_<0uVU)0(ky^^5+mEfB*y_009U<00Izz00bZa0SFuUWQ54p4E8=zG;L3!2PUu&mFs&+y`q$OZM&p~SBlS%G zK9-2CQ!}`e&HT`J4%W+db-~?imTC0!Qau`tZ?k?f!G4x*#ckanR=3CBakw6LRy;u8 zJBugk$$BIjzsN=*yQ66ILaOQNts0exY^%G}f7aaoetWaOTe-E@wmQPWuciSyNcCOS zH1rD9Z5Dy&1y6_Xj@3^`AR=&eKEAtoQIo5|~K;@Nc17K-BaB2VMX zvSzt$OfM!pJ&{eyR;?ltTUcSsvbeS(3M=B}?ACfwSl%iW#9UG0iJQgj#x-7Dt*RXE zfNO=djcnnDa8ZhXdms2D42{%YPkEFXSQo8qnMq=pO`Yol_f!#sb$Y?C{)Af;PTx4y3qEFk6 ziRtZB=vxP9zd5U2o1@!@MsA`Wt%q6Mvwl3=ryn-4Zg%b3O^B}y(2?fRK^o2M#NEfg zDH>0uM($nhS%Hnld>p`H-d=@T7TKmj>oD`^*WpS%6p4Q>HOM+_fO{8TGf2K=^!r0+`HFk>i;?(Si$S%? z8Zp(fDid2ZbcyKJZGIk}^-T_a@alVquPfzW*L~JC%h?eg-e2|4)F-2H%C4E-@>_WA zy`3*qcFojI2s+I-3WmP7-->M4;!|z+0_`p=Ot(|`71eBgA{u{-jbLM-5jernwTrYX zZ1(|+|YO5wd-SSPZvk-t35kdcjt?qgdcP6Qp?Mr&SaG%r@J)MJtO8|gtp%A&Td>f4q# zl-$(NU%dNzeKZmjbpHN}vu5D^dgIsc|R#hYW&Z+Dj zL#MvM)s(bpg_X4%r#DY%xwewUCRL-hp$p4b#O13zFoc(d=M`EeHO+oL5li6r{~zAD6)iyk z0uX=z1Rwwb2tWV=5P$##9+d!o{{KDcK>z{}fB*y_009U<00Izz00bVD0Pg=El|0&o00bZa0SG_<0uX=z1Rwwb z2s}Iiy#MdvS)(NgKmY;|fB*y_009U<00Izzz@rkt^Z!RBk9Hvd0SG_<0uX=z1Rwwb z2tWV=4^IHk{~w+;T7m!sAOHafKmY;|fB*y_009U*DgiwIe^l~l7XlD~00bZa0SG_< z0uX=z1R(J61aSZV@T}1i1Rwwb2tWV=5P$##AOHafK;Tgc;Qs$n$)jBeKmY;|fB*y_ z009U<00Izzz{3;3{r|(WMoSQY00bZa0SG_<0uX=z1Rwx`MB=Y&_w88g(mLCek4{t`(I*DpIJQn)2H4){l86?$3HRo zsnEZg`0V&sC)l5d*QaA>>0YA#@n}4m9Ql@0HYsV;Hi>RwSmGHbfk{e9?fEEmLV zQ51^VOY5T0oh?kqMpZ?4JzH45k}U|id{M}4t*@UKVxw;xB`F}wvWZ=@e2=nCb$gqd zlD%K0ZUJ5!JH)i9A`x3yVcjXNZHPQsHY!y%h~5lpnuaM=sAZ9DDip=*MPA%CY@$gf zl?_v|gtc5zTonsW^)*>$Wy>|++%i!$)`Z`2H`Qv@KTFjuYTA-_tc|v+)U>EA(LE~H z9Qn3WKmpCz7GB-V=Xkbk=w)?VvUF0lb_~0fev|G?JH*=QWNVh~PF7Tz^{iPz??EOd zoV2v>sj8XUH3QcQYa7|Z4dJSILzq^T1n=SHd_i1W&GEG9Mi?Z7f_Pahh`D8P(-TB2 z+j5Q*@;PBeTo+lWEoV2EvnygOap%o?JQ{!b<&pQ-8o^41h zG@@_U*zU^P@;|iMpM&!IRK)f#o9@}oCVEEX9@);Qn#QiGuoH-vxI}DuN3zs+sJrWX zmZhRv{A9>>cs4`2s&99$y;`-ok(+E)ZMXJBPX$!pRZT;$P~Glo*}j|Cy}o z&(=Q@iEkzY*LBCV^F_wib5}~}2ktyke=-`scyZ)z#tAcpRyAYa8DGa(t$^gvf9+Y- z0j0eA?)2P3!eiRGz^7-^X>YDoYo0}GrshU%pHjAQleVI}x18^$+kI+_C35wrB5`st z2sU7xQYs)L^jBBvPekIMO9fT9t+LZJHFsG&H_qg2u6ol#f8~x=e>@sbrAF?Bo!ROw z)0-0d%bq#vE$~3oX78ti|b&p-2G$ySxCG5rm3cJQF8N^hY*VYxHvXg|)rkb6YJ$cj$ zeP1)k*K#Z3bs?Yze(l+>7Gb(wud19E8Ud8}Z2fBw6$P{1aS{4&?|!8IQRi~$-dnAO z+ZiW4NBm&VqU|hxz>@78h3|Q=dAra)NA+yVCaoCkBC+rC)eM>4WwAx95C0rvgb;uL z1Rwwb2tWV=5P$##AOHb8|3?f!00Izz00bZa0SG_<0uX=z1cqM#&;N&ijxj6FM#|1;h$rS5CRZ@00bZa z0SG_<0uX=z1R#K)|3?f!00Izz00bZa0SG_<0uX=z1cqM#&;N&ijxjSv}tGd?=@560e&{Z_0r`fJfYivG>$Q)fPN`rn`a=2Jg^>dEly z;R#mk`2W<;)?bXqSLa6R&#JmY_tZVfHi>RwSmDiK@Wp_XLUbV*fwaza0~ToAKG zQCQ2Zh}VU_hYR_f;8TS#-KafrxqcxMzcDuwa(ZIj(o~yDq-Gn=_rCo~`P3Ksdv`PS zWHdfEH*!C2lafY#3i%|3ezG}~V)oLy=-<=WsHzCBXA8?$vIQZRFABM>_4V^YY_u^1 z-z>*aa>l@visGv1J=C&^U9)@-wGEqSl1XL5R4n&k-kepFWolXFns08Is2Wv#kF$ws zvn*l@D{R(^Ya1f3PBto4#^jS>QsR?*t+2L{E!+^UiZ_I5RY~wVF6Rs4+G>ucxf3cB z#LHqq%q@$X9!`d3ImhvcSP|Dn7C+0`&E@Qh7)#X8*Uv}eH^h;;=ogW18zo6mWgeZx zR9R^91aD||7YY5({bIDcbhExm;*?OEPERsWB73-#$}Togy{Ki9L) zyG!@&A)?37Y*1QJlMV~T^@X)E$4Ha#X^>CB|`0%6Rqv)g{|D$Yg?il zoacph7VBHjI&E}05wuQOcF;QQUh&>`JQY&2qUwfbZ0~y(Ztw>1SpE5E{OaOJJ>j>Y zEOtUtYMSrLZ{>ylhkk3PRV-kwxAI-b#H;mBN8)cS4zfO42TPvlZ6$~P&fOdJ=c4h& z#gY5@p0I5d>x|b{V(7;M1GQD=Xb~!#>}*f>swO+Du&vcMMs2l1-!XLRo2gn7VY~7! z6)xrT>tZ&?BSa&X?OZ!_oo{ry=bKLVs9bX{JSv9b-;TRbO8ag%oD-P;@~Ksoqny5u zzAV`3YrOt-?AjwWQh%ipy~>^w_7c@?b6?VkzTL4_cp^KAg?`K%uD!?b4ZZg`VcIfk zrc9k`Yh;_A7uX4Yo7$~}#D4u#(RiA5C+_Xe4zVQJ&}}voz4eBE)W1I+2L*Mgqe!Cu z(fYY)e3LbvaaVG0TkTDOpAdWVL;t^976HcWL})upaA=u^UbchGUD zY221>QqNY_th8oPv*U8&cs4ojr2~%vxAS~%oK2&31>uR1^Me0$x6<9Y>)n8O&pYo8 zJoS1nJq~-N@P+y(qw#EVr2e$Ky>y;6`CW$3-2qPy{jKgjCE&pB>*&UvOY{8j+4?6U z@y%q=4$@Pl=X${D#^1#A|KtBi12sYb0uX=z1Rwwb2tWV=5P$##K5PQG|NpSf2>Js7 z2tWV=5P$##AOHafKmY;|IDP@#{~y08YJ>m;AOHafKmY;|fB*y_009Vm*aYzZ|L?;# zBj^tVAOHafKmY;|fB*y_009U<;P?gb{Qvk(Q6mH(009U<00Izz00bZa0SG|g!zO_H z{}0=Ypg$0R00bZa0SG_<0uX=z1Rwx`;}^is{~y08YJ>m;AOHafKmY;|fB*y_009Vm z*aYzW|HC#T=nn)S009U<00Izz00bZa0SG|g_yutPfBdGX5dsi^00bZa0SG_<0uX=z z1R(HX6TtodhiyjC9|%AI0uX=z1Rwwb2tWV=5P-n(3*i3$_)SqG1Rwwb2tWV=5P$## zAOHafK;XkBfcO7>*k%O%fdB*`009U<00Izz00bZa0SFww0G|IJzbR^j00bZa0SG_< z0uX=z1Rwwb2z=NCaR2{dn-TN}0uX=z1Rwwb2tWV=5P$##AaMKw`1$|iH${yQfB*y_ z009U<00Izz00bZafe)Jip8tQ?W(56#00bZa0SG_<0uX=z1Rwwb2pqq_#MBF+$HF&4 z6W=_M9skMkRID0%dXz@eXa4n>7f*lFsb2~I%c&ojx)i=K`JLk*4~gtQ{25H(o%$=$ z_@~xJ>QAb=Libctr|N2R?>*RT_f96vTR~opq5tILOv(-KUSFL^{GnYZms?e(fHch$bH!+C5`q!tbcCkpENsE%wAd-59~o~R8@r6 zvxVg=*@BSE7lqu``ucexHrnW#Z&ph{HWcbx!ZvK8Nv3hzVlG8-RV?r--HubGC#y_U z%_rHqsaC5#>9%o`>XK}*+39S6TDDptHakEzEL*s|p3fF}!`BLH8`;7Q;i`B;m}cHQ zZ8@LYEEck?dqVA&XJUn|+}dkfqB}e11X`;@WDCSLn{6P!KPR1u?fQZg!(v zPNO^?R>XCY#maJab2+;r#uD}O^^4K?4RNF{Ho|UCa*=qrRahjbvSjI`YV8=d6OJri z`V|TNFWz_@sKV}0?QYkl;Qf8+F#UboC>_+_e|)I^HYz;0zm0N<`t$WnG%hmVyzARN zHi;KiSkUxU{e|vc239j@-_8r}v^uRPuGg0$@tfjE$mytcOH*wsk(zBd-}euTRNub; zqxh=kQf}lkQ79#M<%QWn@DytJ|J@ zevG2Zc5BV_J{`QeSdi}ljGcQtmjn(miMWy4fF z8CFe}sb!UGY!~d!b$7eooYscdn?-iFC8cIIPDB+?Yt{5jU{)p_oRta8qGtO%*O*&N zcy%+M<3OIcZP9s79cz5OQBB7t}-ak6mS$FAXh21+zcQIkQ z>2*y}sZ%Co925ueQ)g0H>!7tBhmjA}l z4A0WOo6X}VAZY1cRW+$4ozPf5U7uqUm>Q{n!aW0a&Qo(6Yy?toM(F4I#jWSy?r3df zwqmq?x;}ewKN`!{ryoB%KtGyStX-GgZaVI+G$Yz&3q_w5Hp+C@qI3c?@yYGwp z-21&*|4bxqtPK(XJY-te{?6T=G}}3?z4@VEdb9rW161#cHJ|E#5zqg9rW8pKfB*y_ z009U<00Izz00bZafguyX{r`|nD24+82tWV=5P$##AOHafKmY;|@DafK|9nu81OW&@ z00Izz00bZa0SG_<0uUH70X+X7vI)g-AOHafKmY;|fB*y_009U<00KS&xc~P-K@tQY z009U<00Izz00bZa0SG`~$OQ27|3fyR7!Cv=009U<00Izz00bZa0SG|AM*z?NeNd1D z0SG_<0uX=z1Rwwb2tWV=5EwE6-2V^Rgkm@lfB*y_009U<00Izz00bZa0UrU}|NEdI z2?7v+00bZa0SG_<0uX=z1RyYE0=WMlvI)g-AOHafKmY;|fB*y_009U<00KS&c>kXd z3X&iI0SG_<0uX=z1Rwwb2tWV=LneUd|3fyR7!Cv=009U<00Izz00bZa0SG|AM*#Q# zJ}5|n00bZa0SG_<0uX=z1Rwwb2n?A3?*E5uLNOc&KmY;|fB*y_009U<00IzzfR6xv z|KA4%Nf3Yl1Rwwb2tWV=5P$##AOL|O6TtKTA)8PP2Lcd)00bZa0SG_<0uX=z1R&re zz@Ps=9{Tmr#2XV&jDKnDSH|XIf8*>=pOvFOe8xWW{ONyv`WsLE^YC|u)2s;lGd}85 z#fLKK^Yv?ycx81Yr0NRYvuRwSms+x3HrMD%G=-V~2O)Y7* zZ+7UnK3~rtz4BE5%763y&(w3#`0DD&2m3ZDX|!+gzL}wayIc^nMNuebFRhD0-?GAV zY*bZ**RzG?E7^jO%NK>**82K+AvWszm{c}QMG7e8>PfPpP~Uniqh`vq#Vje*rm{_2 zjqowpR!UjbiPlxhvWZ=@+}8PVI;DywHD*}2l+Uk= z*&I)oO-fkX60wC9MpRte5P9;o!rDf*a6`B%-Vml$CBf5{^SRApA-k3<3bk9UXlZJ= z!xpx3Yp-pI!gP<;dBH8?&^T3I&KJbB)f{i8_ke^@5HE`bF}Eyk`c7J-Y0K%Lkk1J# z;=0IYc{#heoLv!PiTc_4Ml_yU9I4Ma(XJ|clC3cWXa0C^TxK5rZttwnziEccTJHaE z@7#LhxUD#@D76*axikeD1?bC0D3BNph2fCHi+}=66y@TiNn0mHiy#olAxGI-S_!)= zw}ufE+uB9@+Q)v7_EV(jCB5an-=k+%vsdk|c8x8(3jTU9pdp8I&X50dNFEyY8+$*g zoqwzR*2Fh!uk^Js?(NSz?`>>;hfLWVHl_E?iKDH3ImwRRD>IDfbvfgFtMl&F%}?|^ z8KC##SmgH~ul?s%=hotbjYRrjuzx=gop&}iwO;@2ljkD5-)%CQe@%_({);mrxj#$2 z2pNg<-Uure!LivqZtfq&R*Q0TKl-P|b>E5OyYyl`gxFY0*bfCyxkmKEy^nNU_+{o8 z4)cD;so{OrV@6oZ&f6QC`@8F%AD+b$MfHSbtQuy&Ma0VZu7?@D*8VvfYx52{9)+V> zk9-(>{pOE5Z(ZH2@6Hp5W5eu^M9^5{+CP4M(0OxXb9ZvaQ)7e7 zh^&FT6GN+7`e+-{7jWA(4`O?N_)*pC*#C^y#r^iZlm0qdifOcUunM1VYq+CHZwA+P zwOhA8=&paGE9FQYC}_#_F2B<^b%C{VSn&fUQzhR6Ty>qH{iiy6v?&tnotGwQzo+@; z>A2pjmbJgn()sA?k=Wp}cQ%%&^(mQ6; ztF^OkH#@AeOF4pUyFJUcN=u)*)~EZ^ZT#yzHl819D!-ww1B0LKyuPvdE*X4tmcib& z^H0Z8Sr6r3<}tH3z*OUU9d5qadF|@vPsKdxsFQNq}u~nj{At2u{TXq^J2F{oR$vDFApc$ zDlbhtHc<1lk*?pw{r^gqFJKf1fB*=900@8p2!H?xfB*=900=CV0M7qQ#fiZ{00ck) z1V8`;KmY_l00ck)1VCUV3E=#{lG6gCKmY_l00ck)1V8`;KmY_l00cl_sRVHTUn))v z1_B@e0w4eaAOHd&00JNY0w4eaD@g$V|KCbZ3ycB*5C8!X009sH0T2KI5C8!X0D+|v z!2SPHabhqK009sH0T2KI5C8!X009sH0T5V80yzJ#|00@8p2!H?xfB*=900@8p2rQKV?*EsH6N7;O2!H?xfB*=900@8p2!H?xfWS%; z!1;eArv*lV00@8p2!H?xfB*=900@8p2!Oy+36y{Te`D>HwP${RUor8^MKKkyr==t+&-xR;PCQK%iL|B%1l`!c9XC@6fQ$BL5xzR;Y9JzX<9UHEZ z$9?Y_jo93GCntyZez5oc8}GdT*2kYTP7e>$BvmZQSen+j*pYfCOYd(TpTwqX*N+=p zJGHG=+cn!;uhzEW-PmaF*F*WRC_=6h6Ir1X!=%kUb4kot9(n2%x8A#?`%dF-y?NX? z8ob$#tu~8|yJhQXD>lo~y3brVsyDVid$@P?xzf|uUVC_Ft#gBXl?5+?7b!DdMMiFW zW^J%64JLCLmo9KI&DYx>?e6Z~zCFRq?JSeV%E>LpaQ^ZAt#YbS@N2lYnnsP=ky zhF&gTZ5^LB^X{9id#!dnDxc-YG?%|<({Saib;obJ;M%Tw^4Y7k`RvtJ&Sh_Yd~|Xc z+hlR;G|$PIg1&q2|7QLt_e-I*Pg^Ch!qpFBD9wz`=5bdddjlcWdJ?KNj@x9=X(McX zHkh4-bS!*sdhl8ztTxzdf;u8!}E zy0?k&Tx({va!m5fG9Poxj0#1ji;TW)7gMp?;e4ALp;S8NebqvtDK1cP)icw4K2U*=1Mp4E2^?j%DH42>b5vaJt&QHljA2ab4KJS*``CEq9JNZyi%S3zST?+Db1MRoj!JYU5mr zr0`4x+5^yTAZJE|gxMk*?utZtzhG{YJ6vsBDYd3dJhDTnT1;}G+Nz$4Vqvb?d)#X4 zd#1k1YAd~5RBh`cYV!qmiOK~_qD+}oE-+tYDa&$^WzmI9NWNHZOLwwlJF!X1?U>rC z7Aew;_JdW=G}D)3CGC60=ZlWZncGS)7ggI6BWjaTo7^bRcus%Nd7)s=*_1Ynxd`41 zI%(w#sZE$2DYvDTI!i{?)@!jsT(FY%dTMFKWyozkd#y<4Tlp`g+PYpYrnd6@e|@c3 zd+x<&e|h6i*FV4Z-)rw(eQ@Ou>tE2rrTsj(^ZbaW>Ey19)YDnSTFzuBPwyd-j7uGp zoQ@_kF1R~1JKS!kGU3XMYFbt;8MpR=-C@;JBtl;XO%FUXU*+|>oR!5i{c!i|qZOPh z+A5=rFf8>^Q?;s~(+D?;dC!ZKXHloYFO)+|_GUX1B2nVJ-pUrGb$YShx;=&Jma101 zf>Zgdw3=^+vBEjDS3H?DWJ&N;hs;e*%F+cBR2(eJDm)}- zb)<#sH=Tp$x;e8~ag{nmTTrFQ8czFw#9C%EI_=OGtTP3ji}OdSxRRfG%+KyYWZcu3 zi^NG&P!-fu#a9HuEO(s#;30@y3NO>{I}3aIaPQgCc)h0bXmmoG9G~hyzM71xyG6o6 zaKcd?!K#=p9ItxY*sP4!(eqsC|F)%Cc497$*K!PNlS{KcRGxJw=ED4P>Em@S9T%xE ziBeQ&6_#{N1u5pKg2_T5l0@e@7p6PCbVab>%|YjdXPzG1k<^uwih?7uXs8Y*IjuaF zQ^7S4sZ~jq(?x}wCgNFFBxWa>keFr_=Q{D};Z$-(*i;slu59SMO3PuIQKcmD6l2j! z?rHZG;?x7|;+Bmkl02ieF-FOxEH{6exHu_jK6D5&r|;9^`Dlrxb8utW&uh{~tsUJ@ zMM=&|y0IcZb6WeA4>D6;n`BvjPE47hh@P&D3=5PyNotW2nx-mMAr*NY%F6c_UTo6WXjyQ`_WAs#0g$Dd$>@m-nj{DY?2Z zWp>AqiJC73J?;`%-?QY>Z>i_n;+)GQ6Ll<$JmEz_6|O)FzAUJs@0FupY12c6FC~pC z9x-BHxHg0xg0T zXmdc4w$BVXB!`@#UMvHm`}JaN@p+qPKF{xY8IA1a8w*w-)HT;@7=d~&_kmnKpZk)k z=5o24^8a6x|Hr?=&(Fjk(PC5bzAbY;Qjy8KgQf4 z0tg_000IagfB*srAb%pD?t00Iag zfB*srAbY;Q9aQA7kzi0R#|0009ILKmY**5I_I{p8tsf1Q0*~0R#|0009ILKmY** zo_+!T{{PcI#@rzS2q1s}0tg_000IagfB*u#|0f0zKmY**5I_I{1Q0*~0R#|u`UQCY zfBMImJ465h1Q0*~0R#|0009ILK!BhBCk7Be009ILKmY**5I_I{1Q2-o1$h7e^p7!j zhyVfzAbZy){Sk-M_O|H=PpZbAMR|GNMBC*m*p^Zy@#^B*rL^UvpVmSc*0 z{vF#2gl@C~H~OqMh1alr-*O#apXvMXiEULWD$hTkzh4ZDRa^9B^?mvA*{W8qX=<%} zc|lYAGSunG3CmR9DpzOUC|A|WQcbO_EG(Q+Cnr4NyDhISQZtQuAiI*9b-g;jSgzhu zuW7f`Y0E54mX?K`pV>7Hu~Uw4d#h`v%fom;8Q-&oPq`N|dTrkW_GE>+a1 zs5%|iDwRH3P%bH1RPE+xqCY;iUHC{*QI!1l?T9BzjDGuQf+R{Bfe~Id^=?h!*FCG* zuMy%6BUC?JP)bVPkA_p;UCS4quZxCZ+0mCD$x!Gk7cxX2)#<2S>Fo~{l$VwKx07v# zMZ*3@ML#^U*|=z5%W+bv^ubZcQRDhd^v8$p|G)<#)He)&qd#MXCt+C9D74h}Rova17SOWU8EDk?W*r_b-y=`g0UJ9}!ko$WL;vXh-MrTfhjMdjkf z{KLD^Y{+oRNIsdEF&Tw+m_zb@N6P`Q`?`NEGl1~$#0j3 z!>b{D-&mJ-HK5sRD=u*&JGkN^gN-EPD=wu@4_vFXU6?2;bFzcajp*P|=*R6%?xJI< z0UtM@PIqJd?P5`xnaMvi24X!fI?QrBBf{evPcXQ{T|PCo192}p`H-YpcB z@=N*cj}C{5(K4+d+UOEXWRzUY4w6K*WXMKYz3|xn&@s7A%ZsP1)9qFUBD)tZQFdXc zP7G8}?aV-#()|w|Eh;a)lz;H{K+Hy$9O%I_8PVFg(ah6xJb%(o)&m`iBQlH;Q`D{S zkl&w{5_O%yjY2l8_V}T8>6t<}P&Hl<8 zKA|2DpHinL{~-6F{Ks-9tjVq8-#`8<#V;PeTKMjib==l{jgUqAJaPHmn1 z{>k6Se@qsAaN_2Pn@|7K?eA9Ph86An^HpBJ9uWtymWeeRjwo+={m1F1L z4Ie2yxlPIkpTu11pQ+bdUi+ci7)p6Q zF(AYFBZi}YyG=}mlvvy=$?S6@&wN9-A$Wh$#a8~|hu>EW z4}S8y7Vuy%TL~G%?n^jOg()3-obieqSqH^g{{=sw6@MYD? zN>>v@nOQ3Pd!7BA>0cK|e4A5dxn5j05d?uHk7t3=XePcPWQst3tIyZp@#X0*e25OG z(C~~{`fNd|U&@*hS+}OoWaT`kf4ZRfi@R&k6YKIDQr?#CJ4VyraOJi<(C~1H&)omk zr{wpw7V{6?l(8EwpX}&x{-;Nb<#6c{leAkn~LF^u`s*@t!jM$5lSGVHAiHHrqY0>iItn@|ZTB)Gu7qZrb^s}-)lb(L&{7~+BUrG!`dYKUek@8?19n-f4Ap6h6F-*cN{jeR{rLW~l<3v;PZIBR7xOVFD zyP}Er67uz3D{Y#~?{PK^Z)^DbPo8l%d^~E(Z-a{NqyF&xzwlx~S$uKSXvU|0Iq5^> z?#Ca#KmS8T<;55C4{vnGuA7-CSsEItZn+Ty6qkt>xK#Q6xs-5R4UZ{V5BNsY(r=6O z_&3FxAs;C9hHHxSZx5uNeq~}qRiX$AoV5I_I{1Q0*~0R#|00D(g+!1Mnh9vr%c00IagfB*sr zAbM009ILKmY** z5I_I{1Q0kN0p9-~5G2hYfB*srAbEK~rUk z2WP%mR7$1%dmnDMW378eV7ZR|j=SnN5}&@5teePFrza;YQ+=ykoqeNRRVzz1wX(9X za7LY+@ZFXtdnKGrJ)=Zmc(>7$&=Bj#mX=y<#SHje~ zCyYRtx)G>XYcD1~+P*Z1Ds#UF0)5FB&T6yt$SmAngez9D=rC!r+sneDj zHGOrds?E<;!nEnc4V2WXc2$#&%xcT3yeG?ZorZ7%KdP!ORphl6G$}k=UY;#q(ZUP# zHOye)~dH$-1Z8c0=DZY)h66N8S^D%MN_K>DpF(OAcCk{*QFRVZL%jyQ%J?nGh$v zDRsJgtMY5vmM>$s@`gi4)0M#Iw2;DI7UOn zah{k)oxmAYL^$h~)2%&jp*?q@puBxPE40%VGkqp4_0mBtjYA9Sh*0WH>v%!PTI@{A zm#fy69#{?WuG<@~#9*%)jw3uh5Di&25Nb`kDHqhfMb$L?jaAq1Ox>@$&F+{_&wRd= zC@1dK?UpH5!(Ii;^wl?)5l$R=O|O zD_aDvqt3pe&0Y(aQ}vSiqAAu4xf;D#nk;QU|C(I5=K2<{{^9T4U>nbu128iG;^6u< zvUE6{(rjdzXbadbzgkq*WiRE9EZ1ncE{?2|7?_bIe{^sC?Ro5~=l#V?+h@)fm5cHo z>hV2v0^*j-qF9%>Fr8o{>F-?b~lN%hIRqlx6{gzIHUHiCpYX{ zpD!qlx!tTBy=rlgB$kk&>@Pf+JXcia=JJm^$D_Vu)==S*qxV{3ml|1g#4?j)NZluT z-IC)jCz&>h)|xPF;LP<}a$(u?DeJM<4!HmnUXg<_ zliz+W4$FQ=u^Ar2^uX|M4@~`b&a0#5PqOl0K(=$$=}z0FyE8@QlI+LSh<+qjpLPr9 zchQC6*&1J6M*8;A&lMF-UimX4uG}8DVVckH;_972A6V()9<*~yvo9BvFVE~|zO^eR z_vv=pD-S;KBSmFqCjaQ#&;v}n#PAKwWX_?ugP9K@oso-YOc>w0m`hR5Qg%z}Ag55c zgZCaW`gc>|n91DmdJWxn%py~yVVV=cW{ zqNQ-wr597D`&YHn_Q%c?l_lBFnH~Ds8TIr=U*2UGIp+QXq5I_I{ z1Q0*~0R#|0009KXMS$o3aTzK4i2wo!AbrKmY**5I_I{1Q0*~0R;9h!1Mq9?Wl{_UuV00IagfB*srAbzBfv?Yu&cE^C(p*uwcrpLp2Lof( z7Rl0v7g%dXJ@7M<7iOzkxu&VL^5q3h%_yW!Pfl2-`c}C*`$oB{R+egNWo2REj5;|{ zHyqP44S7Eq1)4^%ky_K=FkU(TYI>ISu2APIHEm8yUd+*{0uD2Ce54&Q@ zTQ|InOy6yJb)mOBtG`Mob;I?8{^W)T40%t6{*LcD>YK|;m9YKm)%nG8^_F@~yQNNB zW+_a&x>VKX=PF^^bU#H&t!h`bs#clRmIqY3#r&w1$!=U`NHGZwc` zUM(tfFXy*kj-t!DryHie?zyd|-Y}X?%USokDMLBeI^nQVnZL23$uYR1-Bd?5p)OU_ zp=Q+SIH|O4Tq!Cqzns5+CyLHEz1x?eg!x274rPys#kg!dl!-v~Tst#HcN*DF-Nc}V zY4He_wSuzpa@GjO-Rj=5J~Nc`=KW7zE-Giw<{zv_Owkpa!fRN*Z@G>?_<1gYG?*J2 zMQK@cvfFUhtWAh?nmVKQIwb22#eb(*hSK0{Nw(ELU3xjO@9VP#W%+ED@8I3*GlMB_ zocK4ne&i8^_qDd&{8CYQ?z#Mfm!hHR<@CO~k{FI&dN>f# zr;LHxsY_U3NqibuOAQ zxSiZhIisXX96^cjse3}6N)kgH4rJYxVIw26dzMI4^2EC32VU>Imla)BqtS|})XPgt z3tD+sN0PMG6QPpS8Y&(yz>9D0{)o~r9BWPZ!w1)H#?k|CzI|f-ddlE;izWNkO|Fa> z?rxzG)eWl6`4=<#5uokY8ZOlw`^{GBY*$`2q1s}0tg_000IagFb)E|{~w1@qK^n5 zfB*srAb5I_I{1Q0*~0R#|0009KXL4cqCABRz*j|d=u z00IagfB*srAbB$MpRNpFBXWuAS)yh&$t*k68oKYtyf~}@V&5%t8 zEk89&IGdK|It}3jdav2AHCf3EgsB^WdPR1nHovHa$!nHl`5VLOw!7}DZ!RxY!a~CH zTra*}nBWP&We45-x+jc*w$&@z)$+o*P0X!P2@UY%bo zS8u7;v|H-5WtPGsSC^{V{9GkWn@-+UNv&#EHQDH_wygGL`B7bUsUokvph@jzt&KTZ z+FrYPT-nZ-^Y=e$Ii|R0-P2pX@O0DgH&$K4Gxeq?)`TaVy6|(Jp08ZdZmRpgLU;q&S5c=&^{%vi_RB@(%jNv`(k|{Zx{5X8mcG)t zrIpJ3jTKGZ&7F1H-03Dd#Y)?ssuh)sT7G*r?r+2N`-Y_*>J7tk0^t~PbO!Q-|Ko$~ zX$^$k8P$k7-HQavJfpTRTiSkhxv1Qby*uCS-H4vZ2{-B*w}v`8x~-l2EN9C0rD{v-%eLE@EPeTU zLAkBvb5Wf7cWf&Vy3q>U=(FB``Cbd*G9vernNhiKEmjJOaWSi5X=j96kta4SaaZ?+ z?^~`T+sw#Ve$QHzE9%AkciYjKQ7j|5nuy7aLSZ;|`q39Ui6Du0fwW^y-;SMC-FI7_ zTxdAczzN6PEbfW|FOzj7ftHNt~m zLms`%@HkZuZOYowYG8WC zUE!tPQa3K-<-(^~-4u>5=W2YhM6-dg#kzco>s!M^>gZ;4!!+e1V)qd>%y8VmTHBJk z`dWCqX{3+4z$6xll*hj03$u009ILKmY**5I_I{1Q0;rNeb}% z|0H#38vz6mKmY**5I_I{1Q0*~fx{ud^Z(%(2YP`30tg_000IagfB*srAb`M=6yW*) zN$S!z0tg_000IagfB*srAbe4m>2q1s}0tg_000IagfB*uALxA`HhhrS*1p){lfB*srAbL5BM_#(x}~>#;bnCtE+#K@Mc#95eo;#_bG2AL*vlQOu)upO7KUWDer+c?tQmfikt*TXKwPn>b0>c-9?B=E=?&_UV zzS>`Yvh?V)Mo~F`KK~s(8lY~amZR5QClL1nKP_z|F;HnG!ol)-tz;?mI-hFUZ8^hQ zIGdK|It}3jSyyOw0I~w+j;-6qYV4Cas$y+T)B|f%=xdf82+vpFTwbaqMl2AGrY(nF zZyKJ_NGV`6o1VKVL!%+TvYd6<<&;vsXc$gl)pb+Uttgmfq@|Q|o5IoW8lDrjlwQO( zT26gK_X8tn`7!YHK(u!X3D0vqwWi&yg#osw=uD3D!3OBuYC(DXd_HG6rnu+du`TIq zv;sH!tasz17iqpela^{dcv~+jFTb3BPehSkcN;;L(M?1k6#ET_9%B|@@Wd37ru{zQH>=yIl;-Ni5*{C27-p)A|) zUbEX)--@;8P>DN!(Cb+FYXxQH<*YF2cD-|X86!hU>kmKlm7;RtLjL{N+W}%5p0#Gx zjUe1l;^niRnrbFPCACZ#FR8V&7OowZ#(}80kldu|Ezb)V#XBwGM>o)0{=zZygzwtn zN>q1SGIZuEHEm8y?xdbvhOB69$u8r!8V$qSk}H)R7~MdTJ@dj1urE#$LDy=^2|6M_ z92#2;ln8sB*b=iW4|e&v_SJ%-U&xHB)RC6Km6|SY{X{`&%w;zw3`Z{HwvhX_92kjU z8BSduG+Is=urfU}d-Xl-?V>U_m;dfWCwNB`9@&yH5XvLk2_w1}R*5058;)s(qns7o za*MOpWN7Y~Z(8fJSnA@{bZx7?rTdQ2^f%nhraZB3`GJhmoeM^@MMh@EYUzo%KwoHw zfteEVVX|DEEq@~!>7C+z`*EkFVGr!nQMz1#TV8n9G z{Qp>eYlF@rfB*srAbMiK76AkhKmY**5I_I{1Q0*~fqe<^{(oO=R6+m&1Q0*~0R#|0009ILKwzu{c>h0E z!$oHiKmY**5I_I{1Q0*~0R#}(mjLho_r*pf1Q0*~0R#|0009ILKmY**#!7(q|6?^= zbQS>w5I_I{1Q0*~0R#|00D*l8@cw^aY*a!30R#|0009ILKmY**5I|t81bF{HR>MVS z5kLR|1Q0*~0R#|0009IL*p~qB|M$g4B?J&a009ILKmY**5I_I{1jb4reE&arcKifhUn?lfXY)DB zF~vRqj%@`(H(G%keb&Xjrt1Z|;RV*3Q4f55W-z7k=o@ZPIeRw$GcN_ksx3?-Fnkf{ zP0wAkY~c@nzB^mh$~8@`l`k)7>R_%qJvq^-savM{R=GO+M!Bk1mTGEcWntlrIyvDB z-?v;RD?4t{F&ZMhetknU481=;Y&NX7DtkVZvD)%2M_yC+TaAX{ZK*ZwrtD2$j|NNV zzT5KZ-K$T}oG&HHo5HVqRx^-y5j7THK4c5Fn%#PDbmk+D&mU(^zJ*lNnr8Igaz zI=@)1-cqk=x76ug_>@9{mCF2$6-}M)g-w)vb*ZY&&sD-I{aI>NyQ)>S%B;5BjZII4 z^m?ZOKhe}=Y1SzyU!KXHKce0W2U>3!&1PsC&Y;1x%}1YX6qT8o{CD(d4h@$WPH83P z(Qtk^lRDSTnkqe#)QKXeZy>y^%A1B~h4VctKfZQD1RHL5CJ)U8&$z2wPO}y0n}*#I z>YK|;$>Ac3p>=!?u+m+{Xhdh7PriU zjd0B_D7VgKMYx2sCv?=MF&o>C+w$xlRiN`WxUJJ-#M z#2v!ikc&?@MrJM~$JLh+rDL-x;-n214#`a`l(f zzrEnd6?8bwdziPP74-eHQFINL7*4s9h^^uLFtp-}?lZQ!)%#Byi7}U}ki?G;G@Vn! z(D9<%h}@g|7Se&3kOzg%(w4r*nqtjp+5O9GIKc6m5yo4~k3(j9=5qs4evlh<_kIp~ zp?ZB|)KS)IghyE!U`Ido?JKVh1WD#ub0C_! zTX1wb?d;&GyRRqeu3Uh(qTP2ye1@x_-`)NXbXV=3f(~}kh0sV@8h=KmY**5I_I{ z1Q0*~0R#}(s{rr+_bNtt1Q0*~0R#|0009ILKmY**#!rCv|Km4i^cVpI5I_I{1Q0*~ z0R#|00D-*<@cw_VVw6V!0R#|0009ILKmY**5I|u31bF{Heq%f-;e)#ak21U3%3ioV?TTB6G#11YHn@n z52yZcudP!)Tj0T_S5(fP&Ac&v@7bCslHXN&c0Eus+FahT3K0GIHSs3*`(z`mc?7fLN+T7J_uwsgm6bT5-=Bk)>&pxa_o*l`2XGcyC-sBcIs-IW)zji&C` zT~DZ27naJk=sp7@X!+gB7m{`Bo-hJo>PDbmk(#ynMJ;jt>(%+ia`l#aO}nK|cR@>G z!&jH8+WcH4%$n|Dmei_tRjX>1S#4Q0jll3lpnGD|5_k1ZDPOkK#V<{k9z6f8qO!bv z+^3(Qm08{ZeaO0IIhMbX9Fj2I6m_dVj@oH~VcEX^jxXcu&E=&^n3xzc%N!c3 z_RS>5DN`rJR;OhnlO_L~Mdi}7N47s|Ii|R0-P7gJ-qvk*-EV)@4vubO?!AuxeC3LE zQ_U)`E>+ZS9d$bT(lXDe?bb@oZxoe_@}eKixM(yny7hC9cDQDH9%WoI$}Cx5FDe)0 z6_2G{(P{`eXpLs?f)7VrFfKiKi*b7C8}AmCS$V1FQZ5zR264&W^&X74UZTq2MZ?U{ zwcBQCb*rG9fA+{XGcInKy{q2e;i_`hq?(rQ-?&#)o_+SnLpPe)-4?rFc2jO5eH%$b z1V*^fwP#_Ny_;FsxsAj$jM6+I*Ke~u>q6Em+JYvxx!LmaZ25{dS$gwsLHWvSM{?1) z`FCt95W3L{+~{+>#L8vUwvAQSGXmH1^_h6RO(f@j@_w*cR9<^6|ESp6a@$*CqEu?t zZzqN=waAF&G%lYpiY;GwS<9{G+TD$E`U}YsGE6hMY$k?jr)9C%sl=GOC67&s+TG(( zBK4aCqnOryIE?K|8Kc#6i>FS4yo}L+)m-1M%>dKQqe;e)1&#!w{ zGYHRC@vMu_Q){l*kVl%%xi2i;^yK--3C|I6>h#P&{B(~uafz^ACvo5q7v|JmXU#H2 zcrx(}=eF8etimkImm6dKwlLMpOG^t{xso8+Fnl>boi*F42dM=dAxyt>Xi6<$8}d+C z-!PnY8StxHaeot6iGpxVwzO*0Z^tE~e(!MPYc*xe?{*@^p)qvI=!HdM8ti5|O_pBw z3(E4@9VbY8Z2G50C*|w8T>iJRpESrhtOBp!88z^6@W{EmX2~Z+{guI#t=F4-YG7ut zfqVS?|6z>{`h@@j2q1s}0tg_000IagfWW~C@bmu%XGu#4AbX`EBSXIsKmY**5I_I{1Q0*~0R#{@I02sj56+U75I_I{1Q0*~0R#|0009ILIIIFZ z{~y+opm^a}w55I_I{1Q0*~0R#|00D*%O;Qjx>S<(^$2q1s}0tg_000IagfB*uARe<;Z zhjnD=7Xk<%fB*srAb&VbA1Q0*~0R#|0009ILKmY**4o-mg{|9GDO9&u<00IagfB*srAbE#Pp1Wz-x+&_GZ@G@YQ-1E}XRBJdrm3~^ zf}V-a7@cI0-rQ?4qSKo73?5)DX zk8T%=%DHn#-d~D>$QKR639P!_yRVd_++R(EN=k_^I=W3{4fL8NY%?pcUc4MsHsP%em8Z zeHmt(!dsPJ=#J6owikA!Tfh{4-Lsm3oMCEByID(ST7J_uw)8dEliiB@6Bh9UBWU?? z%Jj_V2D<18IekpMFN_oYO9XGf^H3Pa#)7&?RbTkwa+_5+ zaGP>=d15Ud`$SXSO9kRy5XDm>`|ie;ZUwrGr9gQ8aDKhzd2%rIb*b0RZil1gdRDNN zI$gp*>_+zV%(=bAVXGM~^Sg}G?#-pGwu#a2879Iu6gA=S1+82O6BEl>N_4bu zWFQu@SXxf{R@{Hfqne5jFYzwCww*61Tg!V6p-s!Rqs1&*!!ml?E0p``2MgP|qO!bv zOKmY**5I_I{1Q0*~0R+ZTfcO97IBN760R#|0009ILKmY**5I_Kdy$SIA zzc(*RBY*$`2q1s}0tg_000IagFpdJ@&;K7k{+GGae{<>=r(Qns4^Gr4er4iKnZPdu z5I_I{1Q0;rX%u*K`vV2#E3X~NS&k|0`FCt95W3L{+~~7jw++u)v+71*xsGl){$1hu z`YWl)xxew|_UXMhHk01iUw`n%_Nk)s+G|JNI~y3Qwn#0Onwb05*{W8qX=<%}c|lWC z%c#?n6Ybm4EmM7~T%CQRTvaPeHMO#`uy975oVe2xestFv`JLLgB~)C0dgfdy(MG4t zreU{)TGMXU!iL+4!qiu{^p-EYtPWU>rcn=cztw0M-d4AIRAo&FbJeKd?xxl~VFa>G zBT%o%Td&P8YKfj)ug)))tGCo^+AVdud*h|BKP#2_8!MVR-FL%L`qibXHa}Mht0eN& zs&-YYYL!`SdB8Sq!A~|eS$cDOYWIQRHbZt_9|(+2a_(2|e|`I86c~>_oDvwFV#z^| z>;CeH!040-1Ec+A*0{uXnU!xFtHO>$A~6WEW^M$)d8fbmYCeoiW~_N?l%W(|W9HWl$Fxj2-LfLU z6HV6(vT`F6e#ZGc_>0brI zNa?@PQgYh&>vfCCd7sisS7THYZlh^ihEo?ZbV9s#Q [MaintenanceRouter] +# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule] + +from ._router import router as maintenance_router + +__all__ = ["maintenance_router"] +# #endregion MaintenanceRoutesPackage diff --git a/backend/src/api/routes/maintenance/_router.py b/backend/src/api/routes/maintenance/_router.py new file mode 100644 index 00000000..8077b672 --- /dev/null +++ b/backend/src/api/routes/maintenance/_router.py @@ -0,0 +1,14 @@ +# #region MaintenanceRouter [C:3] [TYPE Module] [SEMANTICS fastapi, router, maintenance, api] +# @BRIEF FastAPI APIRouter for the Maintenance Banner endpoints. +# @LAYER API +# @RELATION DEPENDS_ON -> [MaintenanceRoutesModule] +# @RELATION DEPENDS_ON -> [AppDependencies] +# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule] + +from fastapi import APIRouter + +router = APIRouter(prefix="/api/maintenance", tags=["Maintenance"]) + +# Import route handlers to register them with the router +from . import _routes # noqa: F401, E402 +# #endregion MaintenanceRouter diff --git a/backend/src/api/routes/maintenance/_routes.py b/backend/src/api/routes/maintenance/_routes.py new file mode 100644 index 00000000..264e828a --- /dev/null +++ b/backend/src/api/routes/maintenance/_routes.py @@ -0,0 +1,562 @@ +# #region MaintenanceRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, routes, maintenance, api] +# @BRIEF Route handler stubs for all 7 Maintenance Banner API endpoints with RBAC guards per FR-015. +# @LAYER API +# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule] +# @RELATION DEPENDS_ON -> [MaintenanceRouter] +# @RELATION DEPENDS_ON -> [AppDependencies] +# @RELATION DEPENDS_ON -> [MaintenanceServiceModule] +# @INVARIANT All mutation endpoints return 202 {task_id} per spec. +# @INVARIANT RBAC enforced per FR-015 matrix via has_permission() dependency. + +from datetime import datetime, timezone +from typing import Any, cast + +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session + +from ....core.logger import belief_scope, logger as app_logger +from ....core.task_manager import TaskManager + +app_logger = cast(Any, app_logger) +from ....dependencies import get_current_user, get_db, get_task_manager, has_permission +from ....models.maintenance import ( + MaintenanceDashboardBanner, + MaintenanceDashboardBannerStatus, + MaintenanceDashboardState, + MaintenanceDashboardStateStatus, + MaintenanceEvent, + MaintenanceEventStatus, + MaintenanceSettings, +) +from ._router import router +from ._schemas import ( + MaintenanceAlreadyActiveResponse, + MaintenanceDashboardBannerState, + MaintenanceEndResponse, + MaintenanceEventItem, + MaintenanceEventListResponse, + MaintenanceSettingsResponse, + MaintenanceSettingsUpdate, + MaintenanceStartRequest, + MaintenanceStartResponse, +) + + +# ── GET /api/maintenance/dashboard-banners ─────────────────── +# FR-015: viewer, operator, admin all have READ access + +# #region list_dashboard_banners [C:2] [TYPE Function] +# @BRIEF Get per-dashboard banner state for the Dashboard Hub indicator. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "READ")] +@router.get("/dashboard-banners", response_model=list[MaintenanceDashboardBannerState]) +async def list_dashboard_banners( + db: Session = Depends(get_db), + _=Depends(has_permission("maintenance", "READ")), +): + with belief_scope("list_dashboard_banners"): + # Query active banners with their linked active/pending states + active_banners = ( + db.query(MaintenanceDashboardBanner) + .filter(MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE) + .all() + ) + + result: list[MaintenanceDashboardBannerState] = [] + for banner in active_banners: + linked_states = ( + db.query(MaintenanceDashboardState) + .filter( + MaintenanceDashboardState.banner_id == banner.id, + MaintenanceDashboardState.status.in_([ + MaintenanceDashboardStateStatus.ACTIVE, + MaintenanceDashboardStateStatus.PENDING_APPLY, + ]), + ) + .all() + ) + + event_ids: list[str] = [] + start_times: list[str] = [] + end_times: list[str] = [] + + for state in linked_states: + event = ( + db.query(MaintenanceEvent) + .filter(MaintenanceEvent.id == state.event_id) + .first() + ) + if event: + event_ids.append(event.id) + if event.start_time: + start_times.append(event.start_time.isoformat()) + if event.end_time: + end_times.append(event.end_time.isoformat()) + + result.append( + MaintenanceDashboardBannerState( + dashboard_id=banner.dashboard_id, + active=True, + events=event_ids, + start_time=min(start_times) if start_times else None, + end_time=max(end_times) if end_times else None, + ) + ) + + return result +# #endregion list_dashboard_banners + + +# ── GET /api/maintenance/events ────────────────────────────── +# FR-015: operator, admin (NOT viewer) + +# #region list_events [C:2] [TYPE Function] +# @BRIEF Get active and completed maintenance event lists with affected dashboard counts. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "READ")] +@router.get("/events", response_model=MaintenanceEventListResponse) +async def list_events( + db: Session = Depends(get_db), + _=Depends(has_permission("maintenance", "READ")), + task_manager: TaskManager = Depends(get_task_manager), +): + with belief_scope("list_events"): + # ── Auto-expiry: end events past their end_time ── + now = datetime.now(timezone.utc) + expired = ( + db.query(MaintenanceEvent) + .filter( + MaintenanceEvent.status.in_([ + MaintenanceEventStatus.ACTIVE, + MaintenanceEventStatus.PARTIAL, + MaintenanceEventStatus.ENDING, + ]), + MaintenanceEvent.end_time.isnot(None), + MaintenanceEvent.end_time < now, + ) + .all() + ) + for ev in expired: + app_logger.reason( + "Auto-ending expired maintenance event", + extra={"event_id": ev.id, "end_time": ev.end_time.isoformat()}, + ) + # Schedule proper cleanup via task manager (removes banner from dashboard) + task = await task_manager.create_task( + plugin_id="maintenance_banner_apply", + params={ + "operation": "end", + "event_id": ev.id, + "environment_id": ev.environment_id, + "user": "system", + }, + ) + app_logger.reflect( + "Scheduled cleanup for expired event", + extra={"event_id": ev.id, "task_id": task.id}, + ) + + # Active events: ACTIVE, PARTIAL (per spec T040) + active_statuses = [ + MaintenanceEventStatus.ACTIVE, + MaintenanceEventStatus.PARTIAL, + ] + active_events = ( + db.query(MaintenanceEvent) + .filter(MaintenanceEvent.status.in_(active_statuses)) + .order_by(MaintenanceEvent.created_at.desc()) + .all() + ) + + # Completed events: COMPLETED, FAILED + completed_events = ( + db.query(MaintenanceEvent) + .filter( + MaintenanceEvent.status.in_([ + MaintenanceEventStatus.COMPLETED, + MaintenanceEventStatus.FAILED, + ]) + ) + .order_by(MaintenanceEvent.created_at.desc()) + .limit(50) + .all() + ) + + def _to_item(event: MaintenanceEvent) -> MaintenanceEventItem: + affected_count = ( + db.query(MaintenanceDashboardState) + .filter( + MaintenanceDashboardState.event_id == event.id, + MaintenanceDashboardState.status.in_([ + MaintenanceDashboardStateStatus.ACTIVE, + MaintenanceDashboardStateStatus.PENDING_APPLY, + ]), + ) + .count() + ) + return MaintenanceEventItem( + id=event.id, + tables=list(event.tables) if event.tables else [], + start_time=event.start_time.isoformat() if event.start_time else "", + end_time=event.end_time.isoformat() if event.end_time else None, + message=event.message or None, + status=event.status.value, + affected_count=affected_count, + created_at=event.created_at.isoformat() if event.created_at else "", + ) + + return MaintenanceEventListResponse( + active=[_to_item(e) for e in active_events], + completed=[_to_item(e) for e in completed_events], + ) +# #endregion list_events + + +# ── POST /api/maintenance/start ────────────────────────────── +# FR-001: Always returns 202 {task_id} after validation +# FR-015: operator, admin (NOT viewer) + +# #region start_maintenance [C:3] [TYPE Function] +# @BRIEF Start a maintenance event. Validates input, creates event, dispatches TaskManager task. +# Always returns 202 with task_id and maintenance_id. +# Idempotency: same (tables, start_time, end_time) returns already_active (409-like but 200). +# Tables sorted & lowered for idempotency key. Message NOT in key. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "WRITE")] +# @RELATION DEPENDS_ON -> [TaskManager] +@router.post( + "/start", + status_code=status.HTTP_202_ACCEPTED, + responses={ + 202: {"model": MaintenanceStartResponse}, + 409: {"model": MaintenanceAlreadyActiveResponse}, + }, +) +async def start_maintenance( + request: MaintenanceStartRequest, + db: Session = Depends(get_db), + user=Depends(get_current_user), + _=Depends(has_permission("maintenance", "WRITE")), + task_manager: TaskManager = Depends(get_task_manager), +): + with belief_scope("start_maintenance"): + # ── Validation ── + + # Validate end_time > start_time + if request.end_time and request.start_time and request.end_time <= request.start_time: + raise HTTPException( + status_code=400, + detail="end_time must be after start_time", + ) + + # Validate times are within reasonable range (future ±1h grace period) + now = datetime.now(timezone.utc) + grace_threshold = 3600 # 1 hour in seconds + if request.start_time: + diff = (request.start_time - now).total_seconds() if request.start_time.tzinfo else \ + (request.start_time.replace(tzinfo=timezone.utc) - now).total_seconds() + if diff < -grace_threshold: + raise HTTPException( + status_code=400, + detail="start_time is too far in the past (max 1h grace period)", + ) + + # Validate tables list length + if len(request.tables) > 100: + raise HTTPException( + status_code=400, + detail="Maximum 100 tables allowed", + ) + + # Sanitize message (HTML escape already done in rendering, but check for raw HTML) + message = request.message + if message: + import html as _html + sanitized = _html.escape(message) + if sanitized != message: + # Message contained HTML — accept it, it will be escaped at render time + pass + + # ── Idempotency check ── + from ....services.maintenance import build_idempotency_key + + sorted_tables = sorted(t.strip().lower() for t in request.tables if t.strip()) + idem_tables = frozenset(sorted_tables) + idem_start = request.start_time.isoformat() if request.start_time else None + idem_end = request.end_time.isoformat() if request.end_time else None + + # Find existing active event with same idempotency key + active_statuses = [ + MaintenanceEventStatus.PENDING, + MaintenanceEventStatus.APPLYING, + MaintenanceEventStatus.ACTIVE, + MaintenanceEventStatus.PARTIAL, + ] + existing = ( + db.query(MaintenanceEvent) + .filter( + MaintenanceEvent.status.in_(active_statuses), + ) + .all() + ) + for ev in existing: + ev_tables = frozenset( + sorted(t.lower() for t in (ev.tables or []) if t) + ) + ev_start = ev.start_time.isoformat() if ev.start_time else None + ev_end = ev.end_time.isoformat() if ev.end_time else None + if ev_tables == idem_tables and ev_start == idem_start and ev_end == idem_end: + # Same key → return already_active + app_logger.reflect( + "Idempotency hit — event already active", + extra={"existing_id": ev.id}, + ) + return MaintenanceAlreadyActiveResponse( + maintenance_id=ev.id, + status="already_active", + ) + + # ── Load settings for environment ── + settings = db.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + env_id = settings.target_environment_id if settings else "" + + # ── Create event ── + event = MaintenanceEvent( + tables=sorted_tables, + start_time=request.start_time, + end_time=request.end_time, + message=message, + status=MaintenanceEventStatus.PENDING, + environment_id=env_id, + ) + db.add(event) + db.flush() + + # ── Dispatch TaskManager task ── + task = await task_manager.create_task( + plugin_id="maintenance_banner_apply", + params={ + "operation": "start", + "event_id": event.id, + "environment_id": env_id, + "user": getattr(user, "username", "system"), + }, + ) + event.task_id = task.id + db.commit() + + app_logger.reflect( + "Maintenance start dispatched", + extra={"event_id": event.id, "task_id": task.id}, + ) + + return MaintenanceStartResponse( + task_id=task.id, + maintenance_id=event.id, + status="pending", + ) +# #endregion start_maintenance + + +# ── POST /api/maintenance/{maintenance_id}/end ─────────────── +# FR-006: Remove banners for a specific maintenance event +# FR-015: operator, admin (NOT viewer) + +# #region end_maintenance [C:3] [TYPE Function] +# @BRIEF End a specific maintenance event by ID. Removes banners from affected dashboards. +# Always returns 202 with task_id. Idempotent: already_completed returns success. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "WRITE")] +@router.post( + "/{maintenance_id}/end", + status_code=status.HTTP_202_ACCEPTED, + response_model=MaintenanceEndResponse, +) +async def end_maintenance( + maintenance_id: str, + db: Session = Depends(get_db), + user=Depends(get_current_user), + _=Depends(has_permission("maintenance", "WRITE")), + task_manager: TaskManager = Depends(get_task_manager), +): + with belief_scope("end_maintenance", f"maintenance_id={maintenance_id}"): + # Check event exists + event = db.query(MaintenanceEvent).filter( + MaintenanceEvent.id == maintenance_id + ).first() + + if not event: + raise HTTPException( + status_code=404, + detail=f"Maintenance event {maintenance_id} not found", + ) + + # If already completed, return idempotent success + if event.status == MaintenanceEventStatus.COMPLETED: + app_logger.reflect( + "Event already completed, returning idempotent", + extra={"event_id": maintenance_id}, + ) + return MaintenanceEndResponse( + task_id=event.task_id or "", + status="already_completed", + ) + + # ── Dispatch TaskManager task ── + task = await task_manager.create_task( + plugin_id="maintenance_banner_apply", + params={ + "operation": "end", + "event_id": maintenance_id, + "environment_id": event.environment_id, + "user": getattr(user, "username", "system"), + }, + ) + + app_logger.reflect( + "Maintenance end dispatched", + extra={"event_id": maintenance_id, "task_id": task.id}, + ) + + return MaintenanceEndResponse( + task_id=task.id, + status="pending", + ) +# #endregion end_maintenance + + +# ── POST /api/maintenance/end-all ──────────────────────────── +# FR-007: Bulk removal of all active banners +# FR-015: operator, admin (NOT viewer) + +# #region end_all_maintenance [C:3] [TYPE Function] +# @BRIEF End all active maintenance events. Removes all banners from all dashboards. +# Always returns 202 with task_id. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "WRITE")] +@router.post( + "/end-all", + status_code=status.HTTP_202_ACCEPTED, + response_model=MaintenanceEndResponse, +) +async def end_all_maintenance( + db: Session = Depends(get_db), + user=Depends(get_current_user), + _=Depends(has_permission("maintenance", "WRITE")), + task_manager: TaskManager = Depends(get_task_manager), +): + with belief_scope("end_all_maintenance"): + # ── Dispatch TaskManager task ── + task = await task_manager.create_task( + plugin_id="maintenance_banner_apply", + params={ + "operation": "end_all", + "user": getattr(user, "username", "system"), + }, + ) + + app_logger.reflect( + "End-all maintenance dispatched", + extra={"task_id": task.id}, + ) + + return MaintenanceEndResponse( + task_id=task.id, + status="pending", + ) +# #endregion end_all_maintenance + + +# ── GET /api/maintenance/settings ──────────────────────────── +# FR-009: Get maintenance settings configuration +# FR-015: operator, admin (NOT viewer) + +# #region get_maintenance_settings [C:2] [TYPE Function] +# @BRIEF Get current maintenance settings configuration. +# @RELATION DEPENDS_ON -> [has_permission("maintenance", "READ")] +@router.get("/settings", response_model=MaintenanceSettingsResponse) +async def get_maintenance_settings( + db: Session = Depends(get_db), + _=Depends(has_permission("maintenance", "READ")), +): + with belief_scope("get_maintenance_settings"): + settings = db.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + + if not settings: + raise HTTPException( + status_code=404, + detail="Maintenance settings not configured", + ) + + return MaintenanceSettingsResponse( + target_environment_id=settings.target_environment_id, + display_timezone=settings.display_timezone, + banner_template=settings.banner_template, + dashboard_scope=settings.dashboard_scope.value, + excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []), + forced_dashboard_ids=list(settings.forced_dashboard_ids or []), + updated_at=settings.updated_at.isoformat() if settings.updated_at else None, + ) +# #endregion get_maintenance_settings + + +# ── PUT /api/maintenance/settings ──────────────────────────── +# FR-009: Update maintenance settings configuration +# FR-015: admin ONLY (NOT operator, NOT viewer) + +# #region update_maintenance_settings [C:2] [TYPE Function] +# @BRIEF Update maintenance settings. All fields optional for partial update. +# admin role required per FR-015. +# @RELATION DEPENDS_ON -> [has_permission("admin:settings", "WRITE")] +@router.put("/settings", response_model=MaintenanceSettingsResponse) +async def update_maintenance_settings( + settings_data: MaintenanceSettingsUpdate, + db: Session = Depends(get_db), + _=Depends(has_permission("admin:settings", "WRITE")), +): + with belief_scope("update_maintenance_settings"): + settings = db.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + + if not settings: + # Auto-create with defaults on first save (upsert behavior). + # Column-level defaults from the model apply for omitted fields. + settings = MaintenanceSettings( + id="default", + target_environment_id=settings_data.target_environment_id or "", + ) + db.add(settings) + db.flush() + + # Apply partial updates + update_data = settings_data.model_dump(exclude_unset=True) + + if "target_environment_id" in update_data: + settings.target_environment_id = update_data["target_environment_id"] + if "display_timezone" in update_data: + settings.display_timezone = update_data["display_timezone"] + if "banner_template" in update_data: + settings.banner_template = update_data["banner_template"] + if "dashboard_scope" in update_data: + from ....models.maintenance import DashboardScope + settings.dashboard_scope = DashboardScope(update_data["dashboard_scope"]) + if "excluded_dashboard_ids" in update_data: + settings.excluded_dashboard_ids = update_data["excluded_dashboard_ids"] + if "forced_dashboard_ids" in update_data: + settings.forced_dashboard_ids = update_data["forced_dashboard_ids"] + + db.commit() + db.refresh(settings) + + return MaintenanceSettingsResponse( + target_environment_id=settings.target_environment_id, + display_timezone=settings.display_timezone, + banner_template=settings.banner_template, + dashboard_scope=settings.dashboard_scope.value, + excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []), + forced_dashboard_ids=list(settings.forced_dashboard_ids or []), + updated_at=settings.updated_at.isoformat() if settings.updated_at else None, + ) +# #endregion update_maintenance_settings + +# #endregion MaintenanceRoutesModule diff --git a/backend/src/api/routes/maintenance/_schemas.py b/backend/src/api/routes/maintenance/_schemas.py new file mode 100644 index 00000000..38299d31 --- /dev/null +++ b/backend/src/api/routes/maintenance/_schemas.py @@ -0,0 +1,156 @@ +# #region MaintenanceSchemasModule [C:2] [TYPE Module] [SEMANTICS pydantic, schema, maintenance, request, response] +# @BRIEF Pydantic models for Maintenance Banner API: request/response schemas per data-model.md. +# @LAYER API +# @RELATION DEPENDS_ON -> [Pydantic] +# @INVARIANT All response schemas use the standard envelope shape: { status, data, error, meta } + +from datetime import datetime + +from pydantic import BaseModel, Field + + +# ── Request Schemas ────────────────────────────────────────── + +# #region MaintenanceStartRequest [C:1] [TYPE Class] +# @BRIEF POST /api/maintenance/start request body. +class MaintenanceStartRequest(BaseModel): + tables: list[str] = Field(..., min_length=1, max_length=100) + start_time: datetime + end_time: datetime | None = None + message: str | None = Field(None, max_length=500) +# #endregion MaintenanceStartRequest + + +# #region MaintenanceSettingsUpdate [C:1] [TYPE Class] +# @BRIEF PUT /api/maintenance/settings request body — all fields optional for partial update. +class MaintenanceSettingsUpdate(BaseModel): + target_environment_id: str | None = None + display_timezone: str | None = None + banner_template: str | None = None + dashboard_scope: str | None = None + excluded_dashboard_ids: list[int] | None = None + forced_dashboard_ids: list[int] | None = None +# #endregion MaintenanceSettingsUpdate + + +# ── Response Schemas ───────────────────────────────────────── + +# #region MaintenanceStartResponse [C:1] [TYPE Class] +# @BRIEF Response for /api/maintenance/start — always 202 with task_id. +class MaintenanceStartResponse(BaseModel): + task_id: str + maintenance_id: str + status: str # "pending" +# #endregion MaintenanceStartResponse + + +# #region MaintenanceDashboardResult [C:1] [TYPE Class] +# @BRIEF Describes a single dashboard affected by a maintenance operation. +class MaintenanceDashboardResult(BaseModel): + id: int + title: str + chart_id: int | None = None +# #endregion MaintenanceDashboardResult + + +# #region MaintenanceFailedDashboard [C:1] [TYPE Class] +# @BRIEF Describes a dashboard that failed during banner apply/removal. +class MaintenanceFailedDashboard(BaseModel): + id: int + title: str + error: str +# #endregion MaintenanceFailedDashboard + + +# #region MaintenanceTaskResult [C:1] [TYPE Class] +# @BRIEF Result payload for a completed maintenance start task. +class MaintenanceTaskResult(BaseModel): + maintenance_id: str + status: str # "active" | "partial" | "completed" | "no_match" + affected_dashboards: int = 0 + dashboards: list[MaintenanceDashboardResult] = [] + failed_dashboards: list[MaintenanceFailedDashboard] = [] + unmatched_tables: list[str] = [] +# #endregion MaintenanceTaskResult + + +# #region MaintenanceEndResponse [C:1] [TYPE Class] +# @BRIEF Response for /api/maintenance/{id}/end and /api/maintenance/end-all — always 202 with task_id. +class MaintenanceEndResponse(BaseModel): + task_id: str + status: str # "pending" +# #endregion MaintenanceEndResponse + + +# #region MaintenanceEndTaskResult [C:1] [TYPE Class] +# @BRIEF Result payload for a completed end maintenance task. +class MaintenanceEndTaskResult(BaseModel): + maintenance_id: str + removed_from: int = 0 + failed_removals: list[MaintenanceFailedDashboard] = [] +# #endregion MaintenanceEndTaskResult + + +# #region MaintenanceEndAllTaskResult [C:1] [TYPE Class] +# @BRIEF Result payload for a completed end-all maintenance task. +class MaintenanceEndAllTaskResult(BaseModel): + closed_events: int = 0 + removed_from: int = 0 + failed_removals: list[MaintenanceFailedDashboard] = [] +# #endregion MaintenanceEndAllTaskResult + + +# #region MaintenanceSettingsResponse [C:1] [TYPE Class] +# @BRIEF Response for GET /api/maintenance/settings. +class MaintenanceSettingsResponse(BaseModel): + target_environment_id: str + display_timezone: str + banner_template: str + dashboard_scope: str + excluded_dashboard_ids: list[int] + forced_dashboard_ids: list[int] + updated_at: str | None = None +# #endregion MaintenanceSettingsResponse + + +# #region MaintenanceEventItem [C:1] [TYPE Class] +# @BRIEF Single maintenance event summary for GET /api/maintenance/events. +class MaintenanceEventItem(BaseModel): + id: str + tables: list[str] + start_time: str + end_time: str | None = None + message: str | None = None + status: str + affected_count: int + created_at: str +# #endregion MaintenanceEventItem + + +# #region MaintenanceEventListResponse [C:1] [TYPE Class] +# @BRIEF Response for GET /api/maintenance/events. +class MaintenanceEventListResponse(BaseModel): + active: list[MaintenanceEventItem] + completed: list[MaintenanceEventItem] +# #endregion MaintenanceEventListResponse + + +# #region MaintenanceDashboardBannerState [C:1] [TYPE Class] +# @BRIEF Per-dashboard banner state for GET /api/maintenance/dashboard-banners. +class MaintenanceDashboardBannerState(BaseModel): + dashboard_id: int + active: bool + events: list[str] + start_time: str | None = None + end_time: str | None = None +# #endregion MaintenanceDashboardBannerState + + +# #region MaintenanceAlreadyActiveResponse [C:1] [TYPE Class] +# @BRIEF Response for duplicate /start call — idempotency hit. +class MaintenanceAlreadyActiveResponse(BaseModel): + maintenance_id: str + status: str = "already_active" +# #endregion MaintenanceAlreadyActiveResponse + +# #endregion MaintenanceSchemasModule diff --git a/backend/src/api/routes/settings.py b/backend/src/api/routes/settings.py index 1c85bfbd..94b75781 100755 --- a/backend/src/api/routes/settings.py +++ b/backend/src/api/routes/settings.py @@ -393,6 +393,7 @@ class ConsolidatedSettingsResponse(BaseModel): storage: dict notifications: dict = {} features: dict = {} + app_timezone: str = "Europe/Moscow" # #endregion ConsolidatedSettingsResponse @@ -463,6 +464,7 @@ async def get_consolidated_settings( storage=config.settings.storage.dict(), notifications=notifications_payload, features=config.settings.features.model_dump(), + app_timezone=config.settings.app_timezone, ) logger.reflect( "Consolidated settings payload assembled", @@ -526,6 +528,15 @@ async def update_consolidated_settings( payload["notifications"] = settings_patch["notifications"] config_manager.save_config(payload) + # Update app_timezone if provided + if "app_timezone" in settings_patch: + new_tz = settings_patch["app_timezone"] + from ...core.timezone import validate_timezone, invalidate_timezone_cache + if not validate_timezone(new_tz): + raise HTTPException(status_code=422, detail=f"Invalid IANA timezone: {new_tz}") + current_settings.app_timezone = new_tz + invalidate_timezone_cache() + config_manager.update_global_settings(current_settings) return {"status": "success", "message": "Settings updated"} diff --git a/backend/src/api/routes/validation.py b/backend/src/api/routes/validation.py index bb563f82..47fb16e8 100644 --- a/backend/src/api/routes/validation.py +++ b/backend/src/api/routes/validation.py @@ -13,8 +13,9 @@ from sqlalchemy.orm import Session from ...core.config_manager import ConfigManager from ...core.database import get_db from ...core.logger import logger +from ...core.scheduler import SchedulerService from ...core.task_manager import TaskManager -from ...dependencies import get_config_manager, get_current_user, get_task_manager, has_permission +from ...dependencies import get_config_manager, get_current_user, get_scheduler_service, get_task_manager, has_permission from ...schemas.auth import User from ...schemas.validation import ( TriggerRunResponse, @@ -88,11 +89,14 @@ async def create_task( current_user: User = Depends(get_current_user), _=Depends(has_permission("validation.task", "CREATE")), service: ValidationTaskService = Depends(_get_task_service), + scheduler: SchedulerService = Depends(get_scheduler_service), ): """Create a new validation task with provider and environment validation.""" logger.reason(f"create_task — User: {current_user.username}, name: {payload.name}", extra={"src": "validation_routes"}) try: - return service.create_task(payload) + result = service.create_task(payload) + scheduler.reload_validation_policy(result.id) + return result except ValueError as e: raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e)) # #endregion create_task @@ -114,8 +118,9 @@ async def get_task( try: task = task_service.get_task(task_id) from ...schemas.validation import ValidationRunResponse - # Find recent runs via run_service using dashboard matching + # Find recent runs for this specific task via task_id recent = run_service.list_runs( + task_id=task_id, dashboard_id=task.dashboard_ids[0] if task.dashboard_ids else None, environment_id=task.environment_id, page=1, @@ -140,11 +145,14 @@ async def update_task( current_user: User = Depends(get_current_user), _=Depends(has_permission("validation.task", "EDIT")), service: ValidationTaskService = Depends(_get_task_service), + scheduler: SchedulerService = Depends(get_scheduler_service), ): """Update a validation task.""" logger.reason(f"update_task — Task: {task_id}, User: {current_user.username}", extra={"src": "validation_routes"}) try: - return service.update_task(task_id, payload) + result = service.update_task(task_id, payload) + scheduler.reload_validation_policy(result.id) + return result except ValueError as e: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) # #endregion update_task @@ -160,11 +168,13 @@ async def delete_task( current_user: User = Depends(get_current_user), _=Depends(has_permission("validation.task", "DELETE")), service: ValidationTaskService = Depends(_get_task_service), + scheduler: SchedulerService = Depends(get_scheduler_service), ): """Delete a validation task.""" logger.reason(f"delete_task — Task: {task_id}, User: {current_user.username}", extra={"src": "validation_routes"}) try: service.delete_task(task_id, delete_runs=delete_runs) + scheduler.remove_validation_job(task_id) except ValueError as e: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) # #endregion delete_task diff --git a/backend/src/app.py b/backend/src/app.py index 6a746e0b..96685671 100755 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -35,6 +35,7 @@ from .api.routes import ( git, health, llm, + maintenance, mappings, migration, plugins, @@ -219,6 +220,7 @@ app.add_middleware(TraceContextMiddleware) # @RELATION DEPENDS_ON -> [LlmRoutes] # @RELATION DEPENDS_ON -> [CleanReleaseV2Api] # @RELATION DEPENDS_ON -> [ValidationRoutes] +# @RELATION DEPENDS_ON -> [MaintenanceRouter] # Include API routes app.include_router(auth.router) app.include_router(admin.router) @@ -242,6 +244,7 @@ app.include_router(dataset_review.router) app.include_router(health.router) app.include_router(translate.router) app.include_router(validation.router, prefix="/api/validation", tags=["Validation"]) +app.include_router(maintenance.maintenance_router) # #endregion API_Routes # #region api.include_routers [C:1] [TYPE Action] [SEMANTICS routes, registration, api] # @BRIEF Registers all API routers with the FastAPI application. diff --git a/backend/src/core/config_manager.py b/backend/src/core/config_manager.py index b7f8a95c..687ebccc 100644 --- a/backend/src/core/config_manager.py +++ b/backend/src/core/config_manager.py @@ -82,6 +82,14 @@ class ConfigManager: "Applied FEATURES__HEALTH_MONITOR from env", extra={"value": parsed, "raw": health_monitor_env}, ) + + app_timezone_env = os.getenv("APP_TIMEZONE") + if app_timezone_env is not None: + settings.app_timezone = app_timezone_env.strip() + logger.reason( + "Applied APP_TIMEZONE from env", + extra={"value": settings.app_timezone}, + ) # #endregion _apply_features_from_env # #region _default_config [TYPE Function] # @PURPOSE: Build default application configuration fallback. diff --git a/backend/src/core/config_models.py b/backend/src/core/config_models.py index f498cf2e..3f4ff065 100755 --- a/backend/src/core/config_models.py +++ b/backend/src/core/config_models.py @@ -5,7 +5,7 @@ # @RELATION IMPLEMENTS -> [ConnectionContracts] -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from ..models.storage import StorageConfig from ..services.llm_prompt_templates import ( @@ -101,6 +101,19 @@ class GlobalSettings(BaseModel): } ) + # Application timezone + app_timezone: str = "Europe/Moscow" + + @field_validator("app_timezone") + @classmethod + def validate_app_timezone(cls, v: str) -> str: + from zoneinfo import ZoneInfo + try: + ZoneInfo(v) + except (KeyError, TypeError): + raise ValueError(f"Invalid IANA timezone: {v}") from None + return v + # Task retention settings task_retention_days: int = 30 task_retention_limit: int = 100 diff --git a/backend/src/core/database.py b/backend/src/core/database.py index 1b949f22..f3504647 100644 --- a/backend/src/core/database.py +++ b/backend/src/core/database.py @@ -21,6 +21,7 @@ from ..models import ( config as _config_models, # noqa: F401 dataset_review as _dataset_review_models, # noqa: F401 llm as _llm_models, # noqa: F401 + maintenance as _maintenance_models, # noqa: F401 profile as _profile_models, # noqa: F401 task as _task_models, # noqa: F401 ) diff --git a/backend/src/core/logger.py b/backend/src/core/logger.py index 781c7e33..b7118e71 100755 --- a/backend/src/core/logger.py +++ b/backend/src/core/logger.py @@ -271,7 +271,10 @@ def explore(self, msg, *args, **kwargs): Passes structured ``extra`` data so CotJsonFormatter produces proper JSON. """ user_extra = kwargs.pop('extra', {}) + error_val = kwargs.pop('error', None) extra = {'marker': 'EXPLORE', 'intent': msg} + if error_val is not None: + extra['error'] = error_val extra.update(user_extra) self.warning(msg, *args, extra=extra, **kwargs) # #endregion explore @@ -285,7 +288,10 @@ def reason(self, msg, *args, **kwargs): Passes structured ``extra`` data so CotJsonFormatter produces proper JSON. """ user_extra = kwargs.pop('extra', {}) + error_val = kwargs.pop('error', None) extra = {'marker': 'REASON', 'intent': msg} + if error_val is not None: + extra['error'] = error_val extra.update(user_extra) self.debug(msg, *args, extra=extra, **kwargs) # #endregion reason @@ -299,7 +305,10 @@ def reflect(self, msg, *args, **kwargs): Passes structured ``extra`` data so CotJsonFormatter produces proper JSON. """ user_extra = kwargs.pop('extra', {}) + error_val = kwargs.pop('error', None) extra = {'marker': 'REFLECT', 'intent': msg} + if error_val is not None: + extra['error'] = error_val extra.update(user_extra) self.debug(msg, *args, extra=extra, **kwargs) # #endregion reflect diff --git a/backend/src/core/scheduler.py b/backend/src/core/scheduler.py index c2274503..2320554a 100644 --- a/backend/src/core/scheduler.py +++ b/backend/src/core/scheduler.py @@ -88,6 +88,41 @@ class SchedulerService: except Exception as e: logger.explore("Failed to load translation schedules on startup", extra={"error": str(e)}) + # Re-register active validation policies with schedules + try: + from ..models.llm import ValidationPolicy + db = SessionLocal() + try: + active_policies = ( + db.query(ValidationPolicy) + .filter( + ValidationPolicy.is_active.is_(True), + ValidationPolicy.schedule_days.isnot(None), + ) + .all() + ) + for policy in active_policies: + schedule_days = policy.schedule_days or [] + if not schedule_days: + continue + ws = policy.window_start + if ws is None: + continue + # Build cron: minute hour * * day-of-week + dow = ",".join(str(d) for d in sorted(schedule_days)) + cron = f"{ws.minute} {ws.hour} * * {dow}" + self.add_validation_job( + policy_id=policy.id, + cron_expression=cron, + app_timezone=config.settings.app_timezone, + ) + if active_policies: + logger.reason(f"Loaded {len(active_policies)} active validation schedule(s)") + finally: + db.close() + except Exception as e: + logger.explore("Failed to load validation schedules on startup", + extra={"error": str(e)}) # #endregion load_schedules # #region add_backup_job [TYPE Function] # @PURPOSE: Adds a scheduled backup job for an environment. @@ -197,6 +232,153 @@ class SchedulerService: self.loop, ) # #endregion _trigger_backup + # #region add_validation_job [C:3] [TYPE Function] [SEMANTICS scheduler,validation,cron,apscheduler] + # @BRIEF Register a validation policy schedule with APScheduler. + # @PRE policy_id and cron_expression are valid strings. + # @POST A new APScheduler job is registered or replaced if it already exists. + # @SIDE_EFFECT Mutates APScheduler state; calls _trigger_validation on trigger. + # @RELATION DEPENDS_ON -> [_trigger_validation] + def add_validation_job(self, policy_id: str, cron_expression: str, app_timezone: str = "Europe/Moscow") -> None: + with belief_scope( + "SchedulerService.add_validation_job", + f"policy_id={policy_id}, cron={cron_expression}", + ): + from zoneinfo import ZoneInfo + + job_id_aps = f"validation_{policy_id}" + try: + tz = ZoneInfo(app_timezone) + self.scheduler.add_job( + self._trigger_validation, + CronTrigger.from_crontab(cron_expression, timezone=tz), + id=job_id_aps, + args=[policy_id], + replace_existing=True, + ) + logger.reason( + f"Validation schedule registered: {job_id_aps} ({cron_expression}) [{app_timezone}]" + ) + except Exception as e: + logger.explore( + f"Failed to register validation schedule: {job_id_aps}", + extra={"error": str(e)}, + ) + # #endregion add_validation_job + # #region remove_validation_job [C:2] [TYPE Function] [SEMANTICS scheduler,validation,remove,apscheduler] + # @BRIEF Remove a validation policy schedule from APScheduler. + # @PRE policy_id is a valid string. + # @POST The APScheduler job is removed if it exists; silently ignored otherwise. + # @SIDE_EFFECT Mutates APScheduler state. + def remove_validation_job(self, policy_id: str) -> None: + with belief_scope( + "SchedulerService.remove_validation_job", + f"policy_id={policy_id}", + ): + job_id_aps = f"validation_{policy_id}" + try: + self.scheduler.remove_job(job_id_aps) + logger.info(f"Validation schedule removed: {job_id_aps}") + except Exception: + logger.reason(f"Validation schedule not found (already removed): {job_id_aps}") + # #endregion remove_validation_job + # #region reload_validation_policy [C:2] [TYPE Function] [SEMANTICS scheduler,validation,reload,apscheduler] + # @BRIEF Reload a single validation policy schedule — calls remove then add. + # @PRE policy_id is a valid ValidationPolicy id with schedule data in DB. + # @POST Old job is removed; new job is registered if policy is active and has schedule_days. + # @SIDE_EFFECT Mutates APScheduler state; queries ValidationPolicy from DB. + def reload_validation_policy(self, policy_id: str, app_timezone: str = "Europe/Moscow") -> None: + with belief_scope( + "SchedulerService.reload_validation_policy", + f"policy_id={policy_id}", + ): + self.remove_validation_job(policy_id) + try: + from ..models.llm import ValidationPolicy + db = SessionLocal() + try: + policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first() + if not policy: + logger.reason(f"Policy {policy_id} not found; schedule removed") + return + if not policy.is_active: + logger.reason(f"Policy {policy_id} is inactive; schedule removed") + return + schedule_days = policy.schedule_days or [] + if not schedule_days or policy.window_start is None: + logger.reason(f"Policy {policy_id} has no schedule; nothing to register") + return + dow = ",".join(str(d) for d in sorted(schedule_days)) + ws = policy.window_start + cron = f"{ws.minute} {ws.hour} * * {dow}" + self.add_validation_job(policy_id, cron, app_timezone=app_timezone) + finally: + db.close() + except Exception as e: + logger.explore( + f"Failed to reload validation policy {policy_id}", + extra={"error": str(e)}, + ) + # #endregion reload_validation_policy + # #region _trigger_validation [C:3] [TYPE Function] [SEMANTICS scheduler,validation,trigger] + # @BRIEF APScheduler job handler — triggers validation runs for a policy. + # @PRE policy_id is a valid ValidationPolicy id with dashboard_ids. + # @POST A validation task is spawned via TaskManager for each dashboard in the policy. + # @SIDE_EFFECT Creates TaskRecord entries for validation runs; logs progress. + def _trigger_validation(self, policy_id: str) -> None: + seed_trace_id() + with belief_scope("SchedulerService._trigger_validation", f"policy_id={policy_id}"): + logger.reason(f"Triggering scheduled validation for policy {policy_id}") + db = SessionLocal() + try: + from ..models.llm import ValidationPolicy + + policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first() + if not policy: + logger.explore(f"Validation policy not found: {policy_id}") + return + if not policy.is_active: + logger.reason(f"Validation policy {policy_id} is no longer active; skipping") + return + dashboard_ids = list(policy.dashboard_ids or []) + if not dashboard_ids: + logger.explore(f"Validation policy {policy_id} has no dashboards; skipping") + return + + ws = policy.window_start + we = policy.window_end + today = date.today() + scheduled_times = ThrottledSchedulerConfigurator.calculate_schedule( + window_start=ws, + window_end=we or time(ws.hour, ws.minute + 30), + dashboard_ids=dashboard_ids, + current_date=today, + ) + + for idx, dash_id in enumerate(dashboard_ids): + sched_time = scheduled_times[idx] if idx < len(scheduled_times) else scheduled_times[-1] + params: dict = { + "dashboard_id": dash_id, + "environment_id": policy.environment_id, + "provider_id": policy.provider_id or "", + "policy_id": policy_id, + } + asyncio.run_coroutine_threadsafe( + self.task_manager.create_task( + plugin_id="llm_dashboard_validation", params=params + ), + self.loop, + ) + logger.reason( + f"Scheduled validation for dashboard {dash_id} at {sched_time.isoformat()}" + ) + except Exception as e: + logger.explore( + f"Error triggering validation for policy {policy_id}", + extra={"error": str(e)}, + ) + finally: + db.close() + # #endregion _trigger_validation # #endregion SchedulerService # #region ThrottledSchedulerConfigurator [C:5] [TYPE Class] [SEMANTICS scheduler, throttling, distribution] # @BRIEF Distributes validation tasks evenly within an execution window. diff --git a/backend/src/core/superset_client/__init__.py b/backend/src/core/superset_client/__init__.py index 8f468a11..4ce5ae5e 100644 --- a/backend/src/core/superset_client/__init__.py +++ b/backend/src/core/superset_client/__init__.py @@ -25,6 +25,7 @@ from ._charts import SupersetChartsMixin from ._dashboards_crud import SupersetDashboardsCrudMixin from ._dashboards_filters import SupersetDashboardsFiltersMixin from ._dashboards_list import SupersetDashboardsListMixin +from ._dashboards_write import SupersetDashboardsWriteMixin from ._databases import SupersetDatabasesMixin from ._datasets import SupersetDatasetsMixin from ._datasets_preview import SupersetDatasetsPreviewMixin @@ -47,6 +48,7 @@ from ._user_projection import SupersetUserProjectionMixin # @RELATION INHERITS -> [SupersetDatasetsPreviewMixin] # @RELATION INHERITS -> [SupersetDatasetsPreviewFiltersMixin] # @RELATION INHERITS -> [SupersetDatabasesMixin] +# @RELATION INHERITS -> [SupersetDashboardsWriteMixin] class SupersetClient( SupersetDatabasesMixin, SupersetDatasetsPreviewFiltersMixin, @@ -56,6 +58,7 @@ class SupersetClient( SupersetDashboardsCrudMixin, SupersetDashboardsFiltersMixin, SupersetDashboardsListMixin, + SupersetDashboardsWriteMixin, SupersetUserProjectionMixin, SupersetClientBase, ): diff --git a/backend/src/core/superset_client/_dashboards_write.py b/backend/src/core/superset_client/_dashboards_write.py new file mode 100644 index 00000000..44565b6c --- /dev/null +++ b/backend/src/core/superset_client/_dashboards_write.py @@ -0,0 +1,291 @@ +# #region SupersetDashboardsWriteMixin [C:4] [TYPE Module] [SEMANTICS superset, dashboard, chart, write, maintenance, banner] +# @BRIEF Dashboard write mixin for SupersetClient — markdown chart CRUD and layout manipulation for maintenance banners. +# @LAYER Infra +# @RELATION DEPENDS_ON -> [SupersetClientBase] +# @RELATION DEPENDS_ON -> [SupersetChartsMixin] +# @RELATION DEPENDS_ON -> [LayoutUtils] +# @SIDE_EFFECT Creates, updates, deletes markdown charts & modifies dashboard layout via Superset API. +# @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() +# @RATIONALE Extracted from monolithic superset_client to satisfy INV_7. +# Uses belief_scope with REASON/REFLECT/EXPLORE markers for all C4 operations per Std.Semantics.Python. + +import json +from typing import Any, cast + +from ..logger import belief_scope, logger as app_logger +from ._layout_utils import ( + insert_banner_markdown_at_top, + parse_position_json, + remove_banner_from_position, + update_banner_markdown_content, +) + +app_logger = cast(Any, app_logger) + + +# #region SupersetDashboardsWriteMixin [C:4] [TYPE Class] +# @BRIEF Mixin providing markdown chart CRUD and dashboard layout manipulation for maintenance banners. +# @RELATION DEPENDS_ON -> [SupersetClientBase] +# @RELATION DEPENDS_ON -> [SupersetChartsMixin] +class SupersetDashboardsWriteMixin: + """Mixin for creating/updating/deleting markdown charts and manipulating dashboard layouts.""" + + # #region create_markdown_chart [C:3] [TYPE Function] + # @BRIEF Create a markdown chart and return the new chart ID. + # @PRE dashboard_id exists in Superset. markdown_text not empty. + # @POST Returns chart_id (int). Chart is NOT yet placed in dashboard layout. + # @SIDE_EFFECT Creates a new chart resource in Superset. + # @RELATION CALLS -> [self.network.request] + def create_markdown_chart(self, dashboard_id: int, markdown_text: str) -> int: + with belief_scope( + "SupersetDashboardsWriteMixin.create_markdown_chart", + f"dashboard_id={dashboard_id}", + ): + app_logger.reason( + "Creating markdown chart", + extra={"dashboard_id": dashboard_id, "len": len(markdown_text)}, + ) + datasource_id = self._resolve_markdown_datasource(dashboard_id) + payload = { + "dashboards": [dashboard_id], + "datasource_id": datasource_id, + "datasource_type": "table", + "slice_name": "Maintenance Banner", + "viz_type": "markdown", + "params": json.dumps({ + "markdown": markdown_text, + "viz_type": "markdown", + }), + } + try: + response = cast(dict, self.network.request( + method="POST", endpoint="/chart/", json=payload + )) + chart_id = int(response.get("id") or response.get("result", {}).get("id", 0)) + app_logger.reflect("Chart created", extra={"chart_id": chart_id}) + return chart_id + except Exception as e: + app_logger.explore("Create chart failed", extra={"dashboard_id": dashboard_id}, error=str(e)) + raise + # #endregion create_markdown_chart + + # #region update_markdown_chart [C:3] [TYPE Function] + # @BRIEF Update the markdown text of an existing markdown chart. + # @PRE chart_id exists and is a markdown chart. + # @POST Chart markdown content updated. + # @SIDE_EFFECT Modifies a chart resource in Superset. + def update_markdown_chart(self, chart_id: int, markdown_text: str) -> dict: + with belief_scope( + "SupersetDashboardsWriteMixin.update_markdown_chart", + f"chart_id={chart_id}", + ): + app_logger.reason("Updating markdown chart", extra={"chart_id": chart_id, "len": len(markdown_text)}) + payload = {"params": json.dumps({"markdown": markdown_text, "viz_type": "markdown"})} + try: + response = cast(dict, self.network.request(method="PUT", endpoint=f"/chart/{chart_id}", json=payload)) + app_logger.reflect("Chart updated", extra={"chart_id": chart_id}) + return response + except Exception as e: + app_logger.explore("Update chart failed", extra={"chart_id": chart_id}, error=str(e)) + raise + # #endregion update_markdown_chart + + # #region update_dashboard_layout [C:4] [TYPE Function] + # @BRIEF Insert a native MARKDOWN element at (0,0) with full width (12 cols), + # shift existing charts down. Uses native MARKDOWN for reliable rendering. + # @PRE dashboard_id exists in Superset. chart_id is used for tracking/DB. + # @POST MARKDOWN element placed at top; existing items shifted down. + # @SIDE_EFFECT Modifies dashboard layout JSON. + def update_dashboard_layout(self, dashboard_id: int, chart_id: int) -> dict: + with belief_scope( + "SupersetDashboardsWriteMixin.update_dashboard_layout", + f"dashboard_id={dashboard_id}, chart_id={chart_id}", + ): + app_logger.reason( + "Updating layout with native MARKDOWN", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id}, + ) + try: + dashboard = cast(dict, self.network.request( + method="GET", endpoint=f"/dashboard/{dashboard_id}" + )) + result = dashboard.get("result", dashboard) + position_json = parse_position_json(result.get("position_json", "{}")) + + # Use native MARKDOWN element inside a ROW, connected to GRID_ID + placeholder = "*Maintenance banner*" + insert_banner_markdown_at_top(position_json, chart_id, placeholder) + + response = cast(dict, self.network.request( + method="PUT", endpoint=f"/dashboard/{dashboard_id}", + json={"position_json": json.dumps(position_json)}, + )) + app_logger.reflect( + "Layout updated with native MARKDOWN", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id}, + ) + return response + except Exception as e: + app_logger.explore( + "Layout update failed", + extra={"dashboard_id": dashboard_id}, + error=str(e), + ) + raise + # #endregion update_dashboard_layout + + # #region remove_chart_from_layout [C:3] [TYPE Function] + # @BRIEF Remove banner markdown element from dashboard layout without deleting the chart. + # @PRE dashboard_id exists. chart_id exists in layout as MARKDOWN-banner-{chart_id}. + # @POST MARKDOWN element removed from position_json; items shifted up. + # @SIDE_EFFECT Modifies dashboard layout JSON. + def remove_chart_from_layout(self, dashboard_id: int, chart_id: int) -> dict: + with belief_scope( + "SupersetDashboardsWriteMixin.remove_chart_from_layout", + f"dashboard_id={dashboard_id}, chart_id={chart_id}", + ): + app_logger.reason( + "Removing banner from layout", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id}, + ) + try: + dashboard = cast(dict, self.network.request( + method="GET", endpoint=f"/dashboard/{dashboard_id}" + )) + result = dashboard.get("result", dashboard) + position_json = parse_position_json(result.get("position_json", "{}")) + # Remove new MARKDOWN+ROW pair (old CHART-{id} format no longer created) + remove_banner_from_position(position_json, chart_id) + + response = cast(dict, self.network.request( + method="PUT", endpoint=f"/dashboard/{dashboard_id}", + json={"position_json": json.dumps(position_json)}, + )) + app_logger.reflect( + "Banner removed from layout", + extra={"dashboard_id": dashboard_id}, + ) + return response + except Exception as e: + app_logger.explore( + "Remove from layout failed", + extra={"dashboard_id": dashboard_id}, + error=str(e), + ) + raise + # #endregion remove_chart_from_layout + + # #region delete_chart [C:3] [TYPE Function] + # @BRIEF Delete a chart from Superset by ID. + # @PRE chart_id exists. + # @POST Chart permanently deleted from Superset. + # @SIDE_EFFECT Destroys chart resource. + def delete_chart(self, chart_id: int) -> dict: + with belief_scope("SupersetDashboardsWriteMixin.delete_chart", f"chart_id={chart_id}"): + app_logger.reason("Deleting chart", extra={"chart_id": chart_id}) + try: + response = cast(dict, self.network.request(method="DELETE", endpoint=f"/chart/{chart_id}")) + app_logger.reflect("Chart deleted", extra={"chart_id": chart_id}) + return response + except Exception as e: + app_logger.explore("Delete chart failed", extra={"chart_id": chart_id}, error=str(e)) + raise + # #endregion delete_chart + + # #region update_banner_on_dashboard [C:3] [TYPE Function] + # @BRIEF Update the content of a native MARKDOWN banner element on a dashboard. + # @PRE dashboard_id exists. chart_id used for key lookup. + # @POST MARKDOWN element content updated on dashboard. + # @SIDE_EFFECT Modifies dashboard layout JSON in Superset. + def update_banner_on_dashboard( + self, dashboard_id: int, chart_id: int, content: str + ) -> dict: + with belief_scope( + "SupersetDashboardsWriteMixin.update_banner_on_dashboard", + f"dashboard_id={dashboard_id}, chart_id={chart_id}", + ): + app_logger.reason( + "Updating banner content on dashboard", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id, "len": len(content)}, + ) + try: + dashboard = cast(dict, self.network.request( + method="GET", endpoint=f"/dashboard/{dashboard_id}" + )) + result = dashboard.get("result", dashboard) + position_json = parse_position_json(result.get("position_json", "{}")) + markdown_key = f"MARKDOWN-banner-{chart_id}" + update_banner_markdown_content(position_json, markdown_key, content) + response = cast(dict, self.network.request( + method="PUT", endpoint=f"/dashboard/{dashboard_id}", + json={"position_json": json.dumps(position_json)}, + )) + app_logger.reflect( + "Banner content updated on dashboard", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id}, + ) + return response + except Exception as e: + app_logger.explore( + "Update banner content failed", + extra={"dashboard_id": dashboard_id}, + error=str(e), + ) + raise + # #endregion update_banner_on_dashboard + + + # #region get_dashboard_layout [C:3] [TYPE Function] + # @BRIEF Fetch the position_json layout of a dashboard. + # @PRE dashboard_id exists. + # @POST Returns the dashboard layout dict. + def get_dashboard_layout(self, dashboard_id: int) -> dict: + with belief_scope("SupersetDashboardsWriteMixin.get_dashboard_layout", f"dashboard_id={dashboard_id}"): + app_logger.reason("Fetching layout", extra={"dashboard_id": dashboard_id}) + try: + dashboard = cast(dict, self.network.request(method="GET", endpoint=f"/dashboard/{dashboard_id}")) + result = dashboard.get("result", dashboard) + layout = parse_position_json(result.get("position_json", "{}")) + app_logger.reflect("Layout fetched", extra={"dashboard_id": dashboard_id, "items": len(layout)}) + return layout + except Exception as e: + app_logger.explore("Fetch layout failed", extra={"dashboard_id": dashboard_id}, error=str(e)) + raise + # #endregion get_dashboard_layout + + # #region _resolve_markdown_datasource [C:2] [TYPE Function] + # @BRIEF Find a valid datasource_id for markdown chart creation. + # @PRE dashboard_id exists. + # @POST Returns an integer datasource_id. + def _resolve_markdown_datasource(self, dashboard_id: int) -> int: + with belief_scope("_resolve_markdown_datasource", f"dashboard_id={dashboard_id}"): + try: + datasets_response = cast(dict, self.network.request( + method="GET", endpoint=f"/dashboard/{dashboard_id}/datasets" + )) + datasets = datasets_response.get("result", []) + if datasets: + ds_id = datasets[0].get("id") + if ds_id: + return int(ds_id) + except Exception: + app_logger.explore("Dashboard datasets fetch failed, falling back", + extra={"dashboard_id": dashboard_id}, error="Dashboard datasets endpoint failed") + try: + all_ds = cast(dict, self.network.request( + method="GET", endpoint="/dataset/", + params={"q": json.dumps({"columns": ["id"], "page_size": 1, "page": 0})}, + )) + ds_list = all_ds.get("result", []) + if ds_list: + ds_id = ds_list[0].get("id") + if ds_id: + return int(ds_id) + except Exception: + app_logger.explore("No datasets available", extra={}, error="Global dataset list failed") + raise RuntimeError("Cannot create markdown chart: no datasets available in Superset.") + # #endregion _resolve_markdown_datasource + +# #endregion SupersetDashboardsWriteMixin +# #endregion SupersetDashboardsWriteMixin diff --git a/backend/src/core/superset_client/_datasets.py b/backend/src/core/superset_client/_datasets.py index ad34991e..9c05ed2a 100644 --- a/backend/src/core/superset_client/_datasets.py +++ b/backend/src/core/superset_client/_datasets.py @@ -146,7 +146,13 @@ class SupersetDatasetsMixin: dashboards_data = related_objects["result"].get("dashboards", []) else: dashboards_data = [] - for dash in dashboards_data: + # related_objects returns {"count": N, "result": [...]} — extract the array + dashboards_list = ( + dashboards_data.get("result", []) + if isinstance(dashboards_data, dict) + else dashboards_data + ) + for dash in dashboards_list: if isinstance(dash, dict): dash_id = dash.get("id") if dash_id is None: diff --git a/backend/src/core/superset_client/_layout_utils.py b/backend/src/core/superset_client/_layout_utils.py new file mode 100644 index 00000000..2bab085d --- /dev/null +++ b/backend/src/core/superset_client/_layout_utils.py @@ -0,0 +1,197 @@ +# #region LayoutUtils [C:2] [TYPE Module] [SEMANTICS superset, dashboard, layout, position, json] +# @BRIEF Utility functions for manipulating Superset dashboard position_json layout. +# @LAYER Infra +# @RELATION DEPENDS_ON -> [json] +# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin] +# @RATIONALE Extracted from SupersetDashboardsWriteMixin to stay under INV_7 400 LOC. + +import json +import re +from typing import Any + + +# #region parse_position_json [C:1] [TYPE Function] +# @BRIEF Parse position_json from a dashboard API response (may be string or dict). +# @PRE raw_position is a string, dict, or None. +# @POST Returns a dict. +def parse_position_json(raw_position: Any) -> dict: + if isinstance(raw_position, str): + return json.loads(raw_position) if raw_position.strip() else {} + if isinstance(raw_position, dict): + return raw_position + return {} +# #endregion parse_position_json + + +# #region _estimate_markdown_height [C:1] [TYPE Function] +# @BRIEF Estimate grid height for a MARKDOWN element based on HTML content. +# Counts block-level tags and newlines to estimate visual line count, +# then converts to Superset grid units (1 unit ≈ 2 text lines + padding). +# @PRE content is a string of HTML/Markdown. +# @POST Returns int between 19 and 200 inclusive. +def _estimate_markdown_height(content: str) -> int: + """Estimate MARKDOWN element height (position JSON units). + + Model: total = CSS min-height(40px) + content pixel height. + Content height = text_lines × line-height(22px) + container padding. + 1 position JSON unit ≈ 8 rendered pixels. + + Reference: user's banner (5 text lines, padding:12) → height=21 → ~168px. + """ + if not content: + return 19 + + # Detect container padding (e.g. padding:12 → 24px vertical) + pad_match = re.search(r'padding\s*:\s*(\d+)', content) + container_padding = int(pad_match.group(1)) * 2 if pad_match else 0 + + # Strip HTML to get plain text + plain_text = re.sub(r'<[^>]+>', '', content) + plain_text = re.sub(r'\s+', ' ', plain_text).strip() + + if not plain_text: + return 19 + + # Text lines (wrapping at ~40 chars/line at 12col width) + text_lines = len(plain_text) // 40 + 1 + + # Content height (px): line-height(~22px) × lines + container padding + content_px = text_lines * 22 + container_padding + + # Total: CSS min-height(40px) + content + total_px = 40 + content_px + + # Convert to position JSON units (÷8) + height = max(19, total_px // 8) + return min(200, height) +# #endregion _estimate_markdown_height + + +# #region _generate_banner_id [C:1] [TYPE Function] +# @BRIEF Generate a deterministic row and markdown key for a banner chart. +def _generate_banner_id(chart_id: int) -> tuple[str, str]: + row_key = f"ROW-banner-{chart_id}" + md_key = f"MARKDOWN-banner-{chart_id}" + return row_key, md_key +# #endregion _generate_banner_id + + +# #region insert_banner_markdown_at_top [C:2] [TYPE Function] +# @BRIEF Insert a ROW + native MARKDOWN pair at the top of the dashboard grid. +# Creates a ROW entry connected to GRID_ID, and a MARKDOWN child inside it. +# Shifts all existing grid ROWs down by 2 rows. +# @PRE position_json is a mutable dict. content is the HTML/markdown string. +# chart_id is the database chart_id for key generation. +# @POST position_json is mutated; ROW + MARKDOWN inserted at top of GRID. +def insert_banner_markdown_at_top( + position_json: dict, chart_id: int, content: str +) -> dict: + row_key, md_key = _generate_banner_id(chart_id) + + # Shift existing ROW y-positions down + for key, value in list(position_json.items()): + if isinstance(value, dict): + meta = value.get("meta", {}) + if isinstance(meta, dict): + cur_y = meta.get("y", 0) + if isinstance(cur_y, (int, float)): + meta["y"] = cur_y + 2 + + # Add MARKDOWN entry with adaptive height + height = _estimate_markdown_height(content) + position_json[md_key] = { + "type": "MARKDOWN", + "id": md_key, + "children": [], + "parents": ["ROOT_ID", "GRID_ID", row_key], + "meta": { + "code": content, + "width": 12, + "height": height, + "y": 0, + }, + } + + # Add ROW entry connected to GRID_ID + position_json[row_key] = { + "type": "ROW", + "id": row_key, + "children": [md_key], + "parents": ["ROOT_ID", "GRID_ID"], + "meta": { + "background": "BACKGROUND_TRANSPARENT", + "y": 0, + }, + } + + # Insert ROW at beginning of GRID_ID children + grid = position_json.get("GRID_ID") + if grid and isinstance(grid, dict): + grid_children = grid.get("children", []) + if isinstance(grid_children, list): + if row_key in grid_children: + grid_children.remove(row_key) + grid_children.insert(0, row_key) + + return position_json +# #endregion insert_banner_markdown_at_top + + +# #region update_banner_markdown_content [C:1] [TYPE Function] +# @BRIEF Update the code content and adaptive height of an existing banner markdown element. +# @PRE position_json has markdown_key. content is the new HTML/markdown string. +# @POST position_json is mutated; markdown content and height updated. +def update_banner_markdown_content( + position_json: dict, markdown_key: str, content: str +) -> dict: + if markdown_key in position_json: + meta = position_json[markdown_key].get("meta", {}) + if isinstance(meta, dict): + meta["code"] = content + meta["height"] = _estimate_markdown_height(content) + return position_json +# #endregion update_banner_markdown_content + + +# #region remove_banner_from_position [C:2] [TYPE Function] +# @BRIEF Remove the banner ROW + MARKDOWN pair from the position dict and GRID children. +# Shifts remaining items up by 2 if the banner was at y=0. +# @PRE position_json is a mutable dict. chart_id identifies the banner. +# @POST position_json is mutated; ROW and MARKDOWN entries removed. +def remove_banner_from_position(position_json: dict, chart_id: int) -> dict: + row_key, md_key = _generate_banner_id(chart_id) + + removed_y = None + # Remove MARKDOWN entry + if md_key in position_json: + markdown_data = position_json[md_key] + if isinstance(markdown_data, dict): + meta = markdown_data.get("meta", {}) + if isinstance(meta, dict): + removed_y = meta.get("y", 0) + del position_json[md_key] + + # Remove ROW entry + if row_key in position_json: + del position_json[row_key] + + # Remove ROW from GRID_ID children + grid = position_json.get("GRID_ID") + if grid and isinstance(grid, dict): + grid_children = grid.get("children", []) + if isinstance(grid_children, list) and row_key in grid_children: + grid_children.remove(row_key) + + # Shift remaining items up + if removed_y is not None and removed_y == 0: + for key, value in position_json.items(): + if isinstance(value, dict): + meta = value.get("meta", {}) + if isinstance(meta, dict): + cur_y = meta.get("y", 0) + if isinstance(cur_y, (int, float)) and cur_y > 0: + meta["y"] = cur_y - 2 + return position_json +# #endregion remove_banner_from_position + +# #endregion LayoutUtils diff --git a/backend/src/core/timezone.py b/backend/src/core/timezone.py new file mode 100644 index 00000000..ec058cdc --- /dev/null +++ b/backend/src/core/timezone.py @@ -0,0 +1,91 @@ +# #region AppTimezone [C:3] [TYPE Module] [SEMANTICS core,timezone,utilities,datetime] +# @BRIEF Application-level timezone utilities. Reads APP_TIMEZONE from env (default Europe/Moscow) +# and provides helpers for converting UTC datetimes to the configured timezone. +# @RELATION CALLED_BY -> [ConfigManager] +# @RELATION DEPENDS_ON -> [GlobalSettings.app_timezone] +# @RATIONALE Centralised timezone resolution avoids scattering ZoneInfo() calls across the codebase. +# All API responses should emit localised timestamps; internal storage remains UTC. +# @REJECTED Storing non-UTC in the database rejected — UTC is the canonical best practice for +# persistence; timezone conversion is a presentation-layer concern. +from datetime import datetime +import os +from zoneinfo import ZoneInfo + + +# #region _get_default_tz_name [C:1] [TYPE Function] +# @BRIEF Read APP_TIMEZONE from env, fall back to Europe/Moscow. +# @PRE: Environment is loaded (dotenv or os.environ). +# @POST: Returns a valid IANA timezone string. +def _get_default_tz_name() -> str: + return os.getenv("APP_TIMEZONE", "Europe/Moscow") +# #endregion _get_default_tz_name + + +# #region get_app_timezone [C:1] [TYPE Function] +# @BRIEF Return cached ZoneInfo for the configured application timezone. +# @SIDE_EFFECT: Reads os.environ on first call; result is cached. +# @POST: Returns a ZoneInfo instance matching APP_TIMEZONE env var. +_APP_TZ_CACHE: ZoneInfo | None = None + +def get_app_timezone() -> ZoneInfo: + global _APP_TZ_CACHE + if _APP_TZ_CACHE is None: + _APP_TZ_CACHE = ZoneInfo(_get_default_tz_name()) + return _APP_TZ_CACHE +# #endregion get_app_timezone + + +# #region invalidate_timezone_cache [C:1] [TYPE Function] +# @BRIEF Reset the cached ZoneInfo so the next get_app_timezone() call re-reads from env/DB. +# @POST: _APP_TZ_CACHE is set to None; subsequent get_app_timezone() will re-resolve. +# @RATIONALE: Called after PATCH /settings/consolidated updates app_timezone. +def invalidate_timezone_cache() -> None: + global _APP_TZ_CACHE + _APP_TZ_CACHE = None +# #endregion invalidate_timezone_cache + + +# #region validate_timezone [C:1] [TYPE Function] +# @BRIEF Validate that a timezone string is a known IANA timezone. +# @PRE: tz_name is a string. +# @POST: Returns True if ZoneInfo accepts the name, False otherwise. +def validate_timezone(tz_name: str) -> bool: + try: + ZoneInfo(tz_name) + return True + except (KeyError, TypeError): + return False +# #endregion validate_timezone + + +# #region localize [C:1] [TYPE Function] +# @BRIEF Convert a timezone-aware or naive UTC datetime to the configured app timezone. +# @PRE: If dt is timezone-naive, it is assumed to be UTC. +# @POST: Returns a datetime with the app timezone attached (astimezone). +def localize(dt: datetime | None) -> datetime | None: + if dt is None: + return None + if dt.tzinfo is None: + dt = dt.replace(tzinfo=ZoneInfo("UTC")) + return dt.astimezone(get_app_timezone()) +# #endregion localize + + +# #region now [C:1] [TYPE Function] +# @BRIEF Get current time in the configured application timezone. +# @POST: Returns timezone-aware datetime in the app timezone. +def now() -> datetime: + return datetime.now(get_app_timezone()) +# #endregion now + + +# #region format_timezone_offset [C:1] [TYPE Function] +# @BRIEF Return the UTC offset string for the configured timezone (e.g. "+03:00"). +# @POST: Returns string like "+03:00" or "+00:00". +def format_timezone_offset() -> str: + offset = now().strftime("%z") + if offset: + return f"{offset[:3]}:{offset[3:]}" + return "+00:00" +# #endregion format_timezone_offset +# #endregion AppTimezone diff --git a/backend/src/models/maintenance.py b/backend/src/models/maintenance.py new file mode 100644 index 00000000..d2b231d4 --- /dev/null +++ b/backend/src/models/maintenance.py @@ -0,0 +1,215 @@ +# #region MaintenanceModels [C:2] [TYPE Module] [SEMANTICS sqlalchemy, maintenance, banner, event, settings, model] +# @BRIEF SQLAlchemy models for the Maintenance Banner feature: event, banner, dashboard state, and settings. +# @LAYER Domain +# @RELATION DEPENDS_ON -> [sqlalchemy] +# @RELATION DEPENDS_ON -> [MappingBase] +# @INVARIANT MaintenanceDashboardBanner has unique partial index on (environment_id, dashboard_id) WHERE status='active' +# @INVARIANT MaintenanceSettings is a singleton row (id='default') enforced by CheckConstraint + +import enum +import uuid + +from sqlalchemy import ( + CheckConstraint, + Column, + DateTime, + Enum as SQLEnum, + ForeignKey, + Index, + Integer, + JSON, + String, + Text, +) +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func + +from .mapping import Base + + +# #region MaintenanceEventStatus [C:1] [TYPE Class] +class MaintenanceEventStatus(str, enum.Enum): + PENDING = "pending" + APPLYING = "applying" + ACTIVE = "active" + PARTIAL = "partial" + ENDING = "ending" + COMPLETED = "completed" + FAILED = "failed" +# #endregion MaintenanceEventStatus + + +# #region MaintenanceDashboardBannerStatus [C:1] [TYPE Class] +class MaintenanceDashboardBannerStatus(str, enum.Enum): + ACTIVE = "active" + REMOVED = "removed" +# #endregion MaintenanceDashboardBannerStatus + + +# #region MaintenanceDashboardStateStatus [C:1] [TYPE Class] +class MaintenanceDashboardStateStatus(str, enum.Enum): + PENDING_APPLY = "pending_apply" + ACTIVE = "active" + REMOVING = "removing" + REMOVED = "removed" + APPLY_FAILED = "apply_failed" + REMOVAL_FAILED = "removal_failed" +# #endregion MaintenanceDashboardStateStatus + + +# #region DashboardScope [C:1] [TYPE Class] +class DashboardScope(str, enum.Enum): + PUBLISHED_ONLY = "published_only" + DRAFT_ONLY = "draft_only" + ALL = "all" +# #endregion DashboardScope + + +# #region MaintenanceEvent [C:1] [TYPE Class] +# @BRIEF A record of a maintenance event with table list, time window, status, and linked dashboard states. +# @RELATION DEPENDS_ON -> [MaintenanceDashboardState] +class MaintenanceEvent(Base): + __tablename__ = "maintenance_events" + + id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True) + task_id = Column(String, nullable=True, index=True) + environment_id = Column(String, nullable=False) + tables = Column(JSON, nullable=False) + start_time = Column(DateTime(timezone=True), nullable=False) + end_time = Column(DateTime(timezone=True), nullable=True) + message = Column(Text, nullable=True) + status = Column( + SQLEnum(MaintenanceEventStatus), + nullable=False, + default=MaintenanceEventStatus.PENDING, + index=True, + ) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column( + DateTime(timezone=True), server_default=func.now(), onupdate=func.now() + ) + + dashboard_states = relationship( + "MaintenanceDashboardState", + back_populates="maintenance_event", + cascade="all, delete-orphan", + ) +# #endregion MaintenanceEvent + + +# #region MaintenanceDashboardBanner [C:1] [TYPE Class] +# @BRIEF The canonical "one chart per dashboard" entity. Unique partial index enforces single active banner per dashboard. +# @INVARIANT Unique partial index (environment_id, dashboard_id) WHERE status='active' +class MaintenanceDashboardBanner(Base): + __tablename__ = "maintenance_dashboard_banners" + + id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True) + environment_id = Column(String, nullable=False) + dashboard_id = Column(Integer, nullable=False, index=True) + chart_id = Column(Integer, nullable=True) + banner_text = Column(Text, nullable=True) + status = Column( + SQLEnum(MaintenanceDashboardBannerStatus), + nullable=False, + default=MaintenanceDashboardBannerStatus.ACTIVE, + ) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column( + DateTime(timezone=True), server_default=func.now(), onupdate=func.now() + ) + + dashboard_states = relationship( + "MaintenanceDashboardState", back_populates="banner" + ) + + __table_args__ = ( + Index( + "ix_banner_unique_active", + "environment_id", + "dashboard_id", + unique=True, + postgresql_where=(status == "active"), + ), + ) +# #endregion MaintenanceDashboardBanner + + +# #region MaintenanceDashboardState [C:1] [TYPE Class] +# @BRIEF Links a maintenance event to a dashboard via a banner. Tracks per-dashboard-per-event lifecycle. +# @RELATION DEPENDS_ON -> [MaintenanceEvent] +# @RELATION DEPENDS_ON -> [MaintenanceDashboardBanner] +class MaintenanceDashboardState(Base): + __tablename__ = "maintenance_dashboard_states" + + id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True) + event_id = Column( + String, ForeignKey("maintenance_events.id"), nullable=False, index=True + ) + dashboard_id = Column(Integer, nullable=False, index=True) + banner_id = Column( + String, + ForeignKey("maintenance_dashboard_banners.id"), + nullable=True, + ) + status = Column( + SQLEnum(MaintenanceDashboardStateStatus), + nullable=False, + default=MaintenanceDashboardStateStatus.PENDING_APPLY, + ) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column( + DateTime(timezone=True), server_default=func.now(), onupdate=func.now() + ) + + maintenance_event = relationship( + "MaintenanceEvent", back_populates="dashboard_states" + ) + banner = relationship( + "MaintenanceDashboardBanner", back_populates="dashboard_states" + ) + + __table_args__ = ( + Index("ix_mds_dashboard_status", "dashboard_id", "status"), + ) +# #endregion MaintenanceDashboardState + + +# #region MaintenanceSettings [C:1] [TYPE Class] +# @BRIEF Single-row maintenance mode configuration. Enforces singleton via CheckConstraint(id='default'). +# @INVARIANT id must always be 'default' — enforced by CheckConstraint +class MaintenanceSettings(Base): + __tablename__ = "maintenance_settings" + + id = Column(String, primary_key=True, default="default") + target_environment_id = Column(String, nullable=False) + display_timezone = Column(String, nullable=False, default="UTC") + banner_template = Column( + Text, + nullable=False, + default=( + '

\n\n' + "## ⚠️ Технические работы\n\n" + "{message}\n\n" + "**Начало:** {start_time}\n" + "**Конец:** {end_time}\n\n" + "*Данные могут быть неполными или временно недоступны.*\n\n" + "
" + ), + ) + dashboard_scope = Column( + SQLEnum(DashboardScope), + nullable=False, + default=DashboardScope.PUBLISHED_ONLY, + ) + excluded_dashboard_ids = Column(JSON, nullable=False, default=list) + forced_dashboard_ids = Column(JSON, nullable=False, default=list) + updated_at = Column( + DateTime(timezone=True), server_default=func.now(), onupdate=func.now() + ) + + __table_args__ = ( + CheckConstraint("id = 'default'", name="ck_settings_singleton"), + ) +# #endregion MaintenanceSettings + +# #endregion MaintenanceModels diff --git a/backend/src/models/storage.py b/backend/src/models/storage.py index 7efcc44e..7b942c98 100644 --- a/backend/src/models/storage.py +++ b/backend/src/models/storage.py @@ -14,7 +14,7 @@ class FileCategory(str, Enum): # #region StorageConfig [C:1] [TYPE Class] # @BRIEF Configuration model for the storage system, defining paths and naming patterns. class StorageConfig(BaseModel): - root_path: str = Field(default="backups", description="Absolute path to the storage root directory.") + root_path: str = Field(default="/app/storage", description="Absolute path to the storage root directory.") backup_path: str = Field(default="backups", description="Subpath for backups.") repo_path: str = Field(default="repositories", description="Subpath for repositories.") backup_structure_pattern: str = Field(default="{category}/", description="Pattern for backup directory structure.") diff --git a/backend/src/plugins/git_plugin.py b/backend/src/plugins/git_plugin.py index 02409f2e..9c75e316 100644 --- a/backend/src/plugins/git_plugin.py +++ b/backend/src/plugins/git_plugin.py @@ -35,32 +35,22 @@ class GitPlugin(PluginBase): # region __init__ [TYPE Function] # @PURPOSE: Инициализирует плагин и его зависимости. - # @PRE: config.json exists or shared config_manager is available. + # @PRE: shared config_manager доступен через src.dependencies. # @POST: Инициализированы git_service и config_manager. def __init__(self): with belief_scope("GitPlugin.__init__"): app_logger.info("Initializing GitPlugin.") self.git_service = GitService() - # Robust config path resolution: - # 1. Try absolute path from src/dependencies.py style if possible - # 2. Try relative paths based on common execution patterns - if os.path.exists("../config.json"): - config_path = "../config.json" - elif os.path.exists("config.json"): - config_path = "config.json" - else: - # Fallback to the one initialized in dependencies if we can import it - try: - from src.dependencies import config_manager - self.config_manager = config_manager - app_logger.info("GitPlugin initialized using shared config_manager.") - return - except Exception: - config_path = "config.json" - - self.config_manager = ConfigManager(config_path) - app_logger.info(f"GitPlugin initialized with {config_path}") + # Используем shared config_manager из dependencies + try: + from src.dependencies import config_manager + self.config_manager = config_manager + app_logger.info("GitPlugin initialized using shared config_manager.") + except Exception as exc: + app_logger.error(f"GitPlugin: failed to get shared config_manager: {exc}") + self.config_manager = ConfigManager() + app_logger.info("GitPlugin initialized with fallback ConfigManager.") # endregion __init__ @property diff --git a/backend/src/plugins/llm_analysis/service.py b/backend/src/plugins/llm_analysis/service.py index c2cead62..add1930d 100644 --- a/backend/src/plugins/llm_analysis/service.py +++ b/backend/src/plugins/llm_analysis/service.py @@ -13,6 +13,7 @@ import base64 import io import json import os +import re import shutil import tempfile from typing import Any @@ -347,16 +348,19 @@ class ScreenshotService: # endregion ScreenshotService._save_debug_screenshot # region ScreenshotService.capture_dashboard [TYPE Function] [C:4] - # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP. + # @PURPOSE Captures a full-page screenshot of a dashboard using Playwright and CDP, plus diagnostic viewport screenshots of tabs that had chart load errors. # @PRE dashboard_id is a valid string, output_path is a writable path. # @POST Returns True if screenshot is saved successfully. Debug temp dir cleaned up on success, preserved on failure. - # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes a PNG file; creates and cleans up temp debug directory. + # Extra diagnostic screenshots saved as output_path__tab_{tab_text}.png for each tab with chart errors. + # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes PNG files; creates and cleans up temp debug directory. # @UX_STATE [Navigating] -> Loading dashboard UI - # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading + # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading. + # Collects errored_tabs — those where chart content fails to render within timeout. # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions # @UX_STATE [Capturing] -> Executing CDP screenshot - # @RATIONALE Uses tempfile.mkdtemp() for all debug screenshots; cleans up on success (shutil.rmtree), preserves on failure for diagnostic analysis. Pre-resize screenshot is saved to temp dir and auto-cleaned on success. - # @REJECTED Old approach saved debug .png files alongside output — accumulated permanently (F1). In-memory-only logging rejected — visual state cannot be captured in text. + # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors. + # @RATIONALE Errored tab screenshots give LLM diagnostic context — an error text description ("charts.length = 0") is not enough to diagnose a chart load failure; a visual screenshot shows whether the tab is empty, has a loading spinner, or renders a Superset error card. Uses tempfile.mkdtemp() for all debug screenshots; cleans up on success (shutil.rmtree), preserves on failure for diagnostic analysis. + # @REJECTED Always-screenshot-all-tabs rejected — ~20 tabs x 5s per screenshot = 100s overhead, most tabs healthy. Only errored + main gives diagnostic value at near-zero cost. Old approach saved debug .png files alongside output — accumulated permanently (F1). In-memory-only logging rejected — visual state cannot be captured in text. async def capture_dashboard(self, dashboard_id: str, output_path: str) -> bool: debug_dir = tempfile.mkdtemp(prefix="ss_screenshot_debug_") success = False @@ -587,12 +591,15 @@ class ScreenshotService: try: async with asyncio.timeout(SCREENSHOT_SERVICE_TIMEOUT_MS / 1000): # 1. Handle Tabs (Recursive switching) - # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading + # @UX_STATE [TabSwitching] -> Iterating through dashboard tabs to trigger lazy loading. + # Collects errored_tabs — those where chart content fails to render within timeout. + # These are later screenshotted individually for LLM diagnostic value. processed_tabs = set() + errored_tabs = [] # Collects {tab_text, depth, error} for tabs with chart load failures async def switch_tabs(depth=0): if depth > 3: - return # Limit recursion depth + return # Limit recursion depth tab_selectors = [ '.ant-tabs-nav-list .ant-tabs-tab', @@ -635,10 +642,22 @@ class ScreenshotService: }""", timeout=PLAYWRIGHT_WAIT_TIMEOUT_MS) except Exception: logger.warning(f"[TabSwitching] Content verification timed out for tab: {tab_text}") + errored_tabs.append({ + "tab_text": tab_text, + "tab_index": i, + "depth": depth, + "error": "content_verification_timeout" + }) await switch_tabs(depth + 1) except Exception as tab_e: logger.warning(f"[DEBUG][TabSwitching] Failed to process tab {i}: {tab_e}") + errored_tabs.append({ + "tab_text": f"tab_{depth}_{i}", + "tab_index": i, + "depth": depth, + "error": f"processing_exception: {tab_e!s}" + }) try: first_tab = found_tabs[0] @@ -660,6 +679,13 @@ class ScreenshotService: await switch_tabs() + # Log summary of errored tabs + if errored_tabs: + logger.info(f"[TabSwitching] {len(errored_tabs)} tab(s) with errors detected. " + f"Errored tabs: {[t['tab_text'] for t in errored_tabs]}") + else: + logger.info("[TabSwitching] No tab errors detected during preload") + # 2. Calculate full height for screenshot # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions full_height = await page.evaluate("""() => { @@ -757,12 +783,65 @@ class ScreenshotService: logger.info(f"[DIAGNOSTIC] Final screenshot saved: {output_path}") logger.info(f"[DIAGNOSTIC] Final screenshot size: {final_size} bytes ({final_size / 1024:.2f} KB)") - # DIAGNOSTIC: Get image dimensions + # DIAGNOSTIC: Get image dimensions try: with Image.open(output_path) as final_img: logger.info(f"[DIAGNOSTIC] Final screenshot dimensions: {final_img.width}x{final_img.height}") except Exception as img_err: logger.warning(f"[DIAGNOSTIC] Could not read final image dimensions: {img_err}") + + # 3. Screenshot errored tabs (diagnostic viewport shots) + # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors. + # Only screenshots tabs that had errors during preload, plus always keeps the main tab. + # Errored tab screenshots are viewport-only (no full-page resize) to minimize overhead. + if errored_tabs: + logger.info(f"[TabSwitching] Capturing {len(errored_tabs)} errored tab screenshot(s)...") + screenshotted_tabs = set() + for tab_info in errored_tabs: + try: + tab_text = tab_info["tab_text"] + + # Dedup: skip if already screenshotted + if tab_text in screenshotted_tabs: + continue + screenshotted_tabs.add(tab_text) + + # Sanitize tab text for filename + safe_tab = re.sub(r'[^\w\-_ ]', '', tab_text).strip().replace(' ', '_')[:40] + if not safe_tab: + safe_tab = f"tab_{tab_info.get('depth', 0)}_{tab_info.get('tab_index', 0)}" + + # Build tab path robustly (handle any extension or no extension) + base = output_path[:-4] if output_path.lower().endswith('.png') else output_path + tab_path = f"{base}__tab_{safe_tab}.png" + + # Switch to the errored tab — try exact text match first + errored_tab_el = page.get_by_role("tab", name=tab_text, exact=True) + if not await errored_tab_el.is_visible(): + # Fallback: try nth-child by index + tab_index = tab_info.get("tab_index") + if tab_index is not None: + errored_tab_el = page.locator('.ant-tabs-tab').nth(tab_index) + if await errored_tab_el.is_visible(): + await errored_tab_el.click() + await asyncio.sleep(0.5) + await self._wait_for_charts_stabilized(page, timeout_ms=PLAYWRIGHT_SHORT_TIMEOUT_MS) + await page.screenshot(path=tab_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS) + tab_size = os.path.getsize(tab_path) if os.path.exists(tab_path) else 0 + logger.info(f"[TabSwitching] Errored tab screenshot saved: {tab_path} ({tab_size} bytes)") + else: + logger.warning(f"[TabSwitching] Errored tab '{tab_text}' not visible, skipping screenshot") + except Exception as tab_shot_err: + logger.warning(f"[TabSwitching] Failed to screenshot errored tab '{tab_info.get('tab_text')}': {tab_shot_err}") + + # Return to first tab after errored tab screenshots + try: + first_tab_el = page.locator('.ant-tabs-nav-list .ant-tabs-tab').first + if await first_tab_el.is_visible(): + await first_tab_el.click() + await asyncio.sleep(0.5) + except Exception: + pass except asyncio.TimeoutError: logger.error(f"Screenshot capture timed out after {SCREENSHOT_SERVICE_TIMEOUT_MS}ms") try: diff --git a/backend/src/plugins/maintenance_banner.py b/backend/src/plugins/maintenance_banner.py new file mode 100644 index 00000000..3504ed6c --- /dev/null +++ b/backend/src/plugins/maintenance_banner.py @@ -0,0 +1,176 @@ +# #region MaintenanceBannerPlugin [C:4] [TYPE Module] [SEMANTICS plugin, maintenance, banner, execution, task] +# @BRIEF TaskManager plugin for executing maintenance banner operations (start, end, end-all). +# Dispatches to MaintenanceService based on operation type in params. +# @LAYER Plugin +# @RELATION IMPLEMENTS -> [PluginBase] +# @RELATION DEPENDS_ON -> [MaintenanceServiceModule] +# @RELATION DEPENDS_ON -> [SupersetClient] +# @RELATION DEPENDS_ON -> [TaskContext] +# @INVARIANT TaskManager executes this plugin with params containing operation and event_id. + +from typing import Any + +from ..core.database import SessionLocal +from ..core.logger import belief_scope, logger as app_logger +from ..core.plugin_base import PluginBase +from ..core.superset_client import SupersetClient +from ..core.task_manager.context import TaskContext +from ..dependencies import get_config_manager +from ..models.maintenance import MaintenanceSettings +from ..services.maintenance import end_all_maintenance, end_maintenance, start_maintenance + + +# #region MaintenanceBannerPlugin [C:4] [TYPE Class] +# @BRIEF Plugin for executing maintenance banner operations asynchronously via TaskManager. +# @RELATION CALLS -> [start_maintenance] +# @RELATION CALLS -> [end_maintenance] +# @RELATION CALLS -> [end_all_maintenance] +class MaintenanceBannerPlugin(PluginBase): + """TaskManager plugin for maintenance banner operations.""" + + # #region id [TYPE Property] + @property + def id(self) -> str: + return "maintenance_banner_apply" + # #endregion id + + # #region name [TYPE Property] + @property + def name(self) -> str: + return "Maintenance Banner" + # #endregion name + + # #region description [TYPE Property] + @property + def description(self) -> str: + return "Applies or removes maintenance banners on Superset dashboards." + # #endregion description + + # #region version [TYPE Property] + @property + def version(self) -> str: + return "1.0.0" + # #endregion version + + # #region ui_route [TYPE Property] + @property + def ui_route(self) -> str: + return "" # No UI route — async-only + # #endregion ui_route + + # #region get_schema [TYPE Function] + def get_schema(self) -> dict[str, Any]: + return { + "type": "object", + "properties": { + "operation": { + "type": "string", + "enum": ["start", "end", "end_all"], + "title": "Operation", + }, + "event_id": { + "type": "string", + "title": "Maintenance Event ID", + }, + "environment_id": { + "type": "string", + "title": "Target Environment ID", + }, + }, + "required": ["operation"], + } + # #endregion get_schema + + # #region execute [TYPE Function] [C:4] + # @BRIEF Execute maintenance operation based on params.operation. + # @PARAM params contains: operation (start|end|end_all), event_id, environment_id. + # @PARAM context TaskContext for logging. + # @PRE DB and Superset available. + # @POST Operation completed. Results returned as dict. + # @SIDE_EFFECT Modifies Superset dashboards, writes DB rows. + async def execute( + self, + params: dict[str, Any], + context: TaskContext | None = None, + ) -> dict[str, Any]: + with belief_scope("MaintenanceBannerPlugin.execute"): + operation = params.get("operation", "start") + event_id = params.get("event_id", "") + environment_id = params.get("environment_id", "") + + app_logger.reason( + "Executing maintenance operation", + extra={ + "operation": operation, + "event_id": event_id, + "environment_id": environment_id, + }, + ) + + db = SessionLocal() + try: + # Resolve environment + if not environment_id: + settings = db.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + if settings: + environment_id = settings.target_environment_id + + if not environment_id: + config_manager = get_config_manager() + envs = config_manager.get_environments() + if envs: + environment_id = envs[0].id + + env = None + config_manager = get_config_manager() + for e in config_manager.get_environments(): + if e.id == environment_id: + env = e + break + + if not env: + app_logger.explore( + "Environment not found", + extra={"environment_id": environment_id}, + error="EnvironmentNotFound", + ) + return {"status": "failed", "error": f"Environment {environment_id} not found"} + + superset_client = SupersetClient(env) + + if operation == "start": + if not event_id: + return {"status": "failed", "error": "event_id required for start"} + result = start_maintenance(event_id, db, superset_client) + elif operation == "end": + if not event_id: + return {"status": "failed", "error": "event_id required for end"} + result = end_maintenance(event_id, db, superset_client) + elif operation == "end_all": + result = end_all_maintenance(db, superset_client) + else: + result = {"status": "failed", "error": f"Unknown operation: {operation}"} + + db.commit() + app_logger.reflect( + "Maintenance operation completed", + extra={"operation": operation, "result": result}, + ) + return result + + except Exception as e: + db.rollback() + app_logger.explore( + "Maintenance operation failed", + extra={"operation": operation, "event_id": event_id}, + error=str(e), + ) + return {"status": "failed", "error": str(e)} + finally: + db.close() + # #endregion execute +# #endregion MaintenanceBannerPlugin + +# #endregion MaintenanceBannerPlugin diff --git a/backend/src/scripts/seed_superset_load_test.py b/backend/src/scripts/seed_superset_load_test.py index 0de05fed..0b926c81 100644 --- a/backend/src/scripts/seed_superset_load_test.py +++ b/backend/src/scripts/seed_superset_load_test.py @@ -148,20 +148,10 @@ def _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]: resolved: dict[str, Environment] = {} if not configured: - for config_path in [Path("config.json"), Path("backend/config.json")]: - if not config_path.exists(): - continue - try: - payload = json.loads(config_path.read_text(encoding="utf-8")) - env_rows = payload.get("environments", []) - for row in env_rows: - env = Environment(**row) - configured[env.id] = env - except Exception as exc: - logger.reflect( - f"Failed loading environments from {config_path}: {exc}", - extra={"src": "_resolve_target_envs"}, - ) + logger.reflect( + "No environments found in DB — seed script requires environments configured via API first", + extra={"src": "_resolve_target_envs"}, + ) for env_id in env_ids: env = configured.get(env_id) diff --git a/backend/src/services/health_service.py b/backend/src/services/health_service.py index 8ba29695..6149301b 100644 --- a/backend/src/services/health_service.py +++ b/backend/src/services/health_service.py @@ -6,6 +6,7 @@ # @RELATION DEPENDS_ON -> [TaskCleanupService] # @RELATION DEPENDS_ON -> [TaskManager] +from datetime import UTC import os import time from typing import Any, cast @@ -255,6 +256,9 @@ class HealthService: task_id = str(record.task_id) if record.task_id is not None else None summary = str(record.summary) if record.summary is not None else None timestamp = cast(Any, record.timestamp) + # Ensure timestamp is timezone-aware (DB stores naive UTC) + if timestamp is not None and timestamp.tzinfo is None: + timestamp = timestamp.replace(tzinfo=UTC) meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id) items.append( diff --git a/backend/src/services/maintenance/__init__.py b/backend/src/services/maintenance/__init__.py new file mode 100644 index 00000000..f6a1d2b8 --- /dev/null +++ b/backend/src/services/maintenance/__init__.py @@ -0,0 +1,30 @@ +# #region MaintenancePackage [C:1] [TYPE Package] [SEMANTICS maintenance, service, package] +# @BRIEF Maintenance Banner service package. Re-exports all public orchestrators and helpers. +# @LAYER Service +# @RELATION DEPENDS_ON -> [MaintenanceOrchestrators] +# @RELATION DEPENDS_ON -> [MaintenanceDashboardScanner] +# @RELATION DEPENDS_ON -> [MaintenanceBannerRenderer] +# @RELATION DEPENDS_ON -> [MaintenanceChartManager] + +from ._banner_renderer import build_banner_text, rebuild_banner +from ._chart_manager import ensure_banner_chart +from ._dashboard_scanner import find_affected_dashboards +from ._orchestrators import ( + build_idempotency_key, + end_all_maintenance, + end_maintenance, + start_maintenance, +) + +__all__ = [ + "build_banner_text", + "build_idempotency_key", + "end_all_maintenance", + "end_maintenance", + "ensure_banner_chart", + "find_affected_dashboards", + "rebuild_banner", + "start_maintenance", +] + +# #endregion MaintenancePackage diff --git a/backend/src/services/maintenance/_banner_renderer.py b/backend/src/services/maintenance/_banner_renderer.py new file mode 100644 index 00000000..e0ea2cb9 --- /dev/null +++ b/backend/src/services/maintenance/_banner_renderer.py @@ -0,0 +1,254 @@ +# #region MaintenanceBannerRenderer [C:3] [TYPE Module] [SEMANTICS maintenance, banner, renderer, text] +# @BRIEF Banner text rendering and rebuild helpers. Build aggregated markdown from +# active maintenance events, format with template, apply HTML escaping. +# @LAYER Service +# @RELATION DEPENDS_ON -> [MaintenanceModels] +# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin] + +import html +import re as _re +from datetime import datetime +from typing import Any + +from sqlalchemy.orm import Session + +from ...core.logger import belief_scope, logger as app_logger +from ...core.superset_client import SupersetClient +from ...models.maintenance import ( + MaintenanceDashboardBanner, + MaintenanceDashboardBannerStatus, + MaintenanceDashboardState, + MaintenanceDashboardStateStatus, + MaintenanceEvent, + MaintenanceEventStatus, + MaintenanceSettings, +) + + +# #region build_banner_text [C:3] [TYPE Function] [SEMANTICS maintenance, banner, text, template, rendering] +# @BRIEF Build aggregated banner markdown text from events using settings template. +# Single event: substitute {start_time}, {end_time}, {message} directly. +# Multiple events: render each event as sub-block, combine as {message}. +# Missing variables → empty string. Message is HTML-escaped. +# @PRE events is a non-empty list of dicts with start_time, end_time, message keys. +# template is a non-empty string. +# @POST Returns str with substituted template or empty string on failure. +def build_banner_text( + events: list[dict[str, Any]], + template: str, + display_timezone: str = "UTC", +) -> str: + with belief_scope( + "build_banner_text", + f"events={len(events)}", + ): + if not events: + app_logger.reflect("No events, returning empty string") + return "" + + def _format_dt(dt_str: str | None) -> str: + """Format datetime string for display.""" + if not dt_str: + return "уточняется" + try: + dt = datetime.fromisoformat(dt_str.replace("Z", "+00:00")) + return dt.strftime("%Y-%m-%d %H:%M") + except (ValueError, TypeError): + return dt_str or "уточняется" + + def _event_substitutions(event: dict[str, Any]) -> dict[str, str]: + """Build substitution dict for a single event.""" + msg = event.get("message") or "" + escaped_msg = html.escape(msg) if msg else "" + return { + "start_time": _format_dt(event.get("start_time")), + "end_time": _format_dt(event.get("end_time")), + "message": escaped_msg, + } + + if len(events) == 1: + subs = _event_substitutions(events[0]) + result = template + for key, value in subs.items(): + result = result.replace(f"{{{key}}}", value) + # Remove any remaining unreplaced variables + result = _re.sub(r"\{[a-zA-Z_]+\}", "", result) + app_logger.reflect("Banner text built (single event)") + return result + + # Multiple events: build aggregated message, substitute as {message} + event_blocks: list[str] = [] + for i, event in enumerate(events): + subs = _event_substitutions(event) + block = template + for key, value in subs.items(): + block = block.replace(f"{{{key}}}", value) + block = _re.sub(r"\{[a-zA-Z_]+\}", "", block) + event_blocks.append(block) + + combined_message = "\n\n---\n\n".join(event_blocks) + + # Build aggregator template (use first event for start/end if uniform) + result = template + result = result.replace("{message}", combined_message) + if len(events) == 1: + subs = _event_substitutions(events[0]) + for key in ("start_time", "end_time"): + result = result.replace(f"{{{key}}}", subs.get(key, "")) + else: + result = result.replace("{start_time}", "") + result = result.replace("{end_time}", "") + result = _re.sub(r"\{[a-zA-Z_]+\}", "", result) + + app_logger.reflect("Banner text built (multi-event)") + return result +# #endregion build_banner_text + + +# #region _build_banner_text_for_dashboard [C:2] [TYPE Function] +# @BRIEF Build aggregated banner text for a banner based on all active events linked to it. +def _build_banner_text_for_dashboard( + banner_id: str, + db_session: Session, + template: str, + timezone_str: str, +) -> str: + try: + # Find all active dashboard states linked to this banner + active_states = ( + db_session.query(MaintenanceDashboardState) + .filter( + MaintenanceDashboardState.banner_id == banner_id, + MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE, + ) + .all() + ) + + if not active_states: + return "" + + # Load events for each state + events_data: list[dict[str, Any]] = [] + for state in active_states: + ev = ( + db_session.query(MaintenanceEvent) + .filter(MaintenanceEvent.id == state.event_id) + .first() + ) + if ev and ev.status in ( + MaintenanceEventStatus.ACTIVE, + MaintenanceEventStatus.PARTIAL, + MaintenanceEventStatus.APPLYING, + ): + events_data.append( + { + "start_time": ev.start_time.isoformat() if ev.start_time else None, + "end_time": ev.end_time.isoformat() if ev.end_time else None, + "message": ev.message or "", + } + ) + + if not events_data: + return "" + + return build_banner_text(events_data, template, timezone_str) + except Exception as e: + app_logger.explore( + "Failed to build banner text", + extra={"banner_id": banner_id}, + error=str(e), + ) + return "" +# #endregion _build_banner_text_for_dashboard + + +# #region rebuild_banner [C:3] [TYPE Function] [SEMANTICS maintenance, banner, rebuild, text, update] +# @BRIEF Rebuild aggregated banner text for a banner and update the Superset chart. +# Query all active MaintenanceDashboardState records linked to banner, +# build aggregated text via build_banner_text, update markdown chart in Superset. +# @PRE banner_id points to an active MaintenanceDashboardBanner with a valid chart_id. +# @POST Banner chart in Superset updated with current aggregated text. DB banner_text updated. +# @SIDE_EFFECT Modifies Superset chart. Writes DB. +# @RELATION DEPENDS_ON -> [build_banner_text] +# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin] +def rebuild_banner( + banner_id: str, + db_session: Session, + superset_client: SupersetClient, +) -> bool: + with belief_scope("rebuild_banner", f"banner_id={banner_id}"): + app_logger.reason( + "Rebuilding banner text", + extra={"banner_id": banner_id}, + ) + + banner = db_session.query(MaintenanceDashboardBanner).filter( + MaintenanceDashboardBanner.id == banner_id + ).first() + if not banner: + app_logger.explore( + "Banner not found", + extra={"banner_id": banner_id}, + error="BannerNotFound", + ) + return False + + if banner.status != MaintenanceDashboardBannerStatus.ACTIVE: + app_logger.reflect( + "Banner not active, skipping", + extra={"banner_id": banner_id, "status": banner.status.value}, + ) + return False + + # Load settings for template + settings = db_session.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + template = settings.banner_template if settings else "" + timezone_str = settings.display_timezone if settings else "UTC" + + # Build aggregated text + banner_text = _build_banner_text_for_dashboard( + banner_id, db_session, template, timezone_str + ) + + if not banner_text and banner.chart_id: + # No active events — should be handled by end_maintenance, but clean up just in case + app_logger.reflect( + "No active events for banner, marking as REMOVED", + extra={"banner_id": banner_id}, + ) + banner.status = MaintenanceDashboardBannerStatus.REMOVED + db_session.flush() + return True + + # Update banner on dashboard (native MARKDOWN in layout) + if banner.chart_id: + try: + superset_client.update_banner_on_dashboard( + banner.dashboard_id, banner.chart_id, banner_text + ) + except Exception as e: + app_logger.explore( + "Failed to update banner on dashboard during rebuild", + extra={ + "chart_id": banner.chart_id, + "banner_id": banner_id, + "dashboard_id": banner.dashboard_id, + }, + error=str(e), + ) + return False + + # Update DB + banner.banner_text = banner_text + db_session.flush() + + app_logger.reflect( + "Banner rebuilt successfully", + extra={"banner_id": banner_id}, + ) + return True +# #endregion rebuild_banner + +# #endregion MaintenanceBannerRenderer diff --git a/backend/src/services/maintenance/_chart_manager.py b/backend/src/services/maintenance/_chart_manager.py new file mode 100644 index 00000000..afe76ae2 --- /dev/null +++ b/backend/src/services/maintenance/_chart_manager.py @@ -0,0 +1,359 @@ +# #region MaintenanceChartManager [C:3] [TYPE Module] [SEMANTICS maintenance, chart, banner, lifecycle] +# @BRIEF Chart operations for maintenance banners: create/get banner charts, process +# per-dashboard state transitions for start and end orchestrators. +# @LAYER Service +# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin] +# @RELATION DEPENDS_ON -> [MaintenanceModels] + +from typing import Any + +from sqlalchemy.orm import Session + +from ...core.logger import belief_scope, logger as app_logger +from ...core.superset_client import SupersetClient +from ...models.maintenance import ( + MaintenanceDashboardBanner, + MaintenanceDashboardBannerStatus, + MaintenanceDashboardState, + MaintenanceDashboardStateStatus, + MaintenanceEvent, + MaintenanceEventStatus, + MaintenanceSettings, +) +from ._banner_renderer import _build_banner_text_for_dashboard, rebuild_banner +from ._dashboard_scanner import _resolve_dashboard_title + + +# #region ensure_banner_chart [C:3] [TYPE Function] [SEMANTICS maintenance, banner, chart, creation] +# @BRIEF Get or create a MaintenanceDashboardBanner for a dashboard in the target environment. +# If an active banner exists in DB, return it. Otherwise, create a markdown chart in Superset, +# update dashboard layout, and store the banner row. +# @PRE dashboard_id exists in Superset. superset_client has write access. +# @POST Returns MaintenanceDashboardBanner with chart_id set. Chart is placed at top of dashboard. +# @SIDE_EFFECT Creates chart in Superset, modifies dashboard layout, writes DB row. +# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin] +def ensure_banner_chart( + dashboard_id: int, + environment_id: str, + superset_client: SupersetClient, + db_session: Session, +) -> MaintenanceDashboardBanner: + with belief_scope( + "ensure_banner_chart", + f"dashboard_id={dashboard_id}", + ): + app_logger.reason( + "Ensuring banner chart exists", + extra={"dashboard_id": dashboard_id}, + ) + + # Check for existing active banner + existing = ( + db_session.query(MaintenanceDashboardBanner) + .filter( + MaintenanceDashboardBanner.dashboard_id == dashboard_id, + MaintenanceDashboardBanner.environment_id == environment_id, + MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE, + ) + .first() + ) + if existing: + app_logger.reason( + "Found existing active banner, verifying chart in Superset", + extra={"banner_id": existing.id, "chart_id": existing.chart_id}, + ) + # Verify the chart still exists in Superset + try: + superset_client.get_chart(existing.chart_id) + app_logger.reflect( + "Existing banner chart is alive, reusing", + extra={"banner_id": existing.id, "chart_id": existing.chart_id}, + ) + return existing + except Exception: + app_logger.explore( + "Existing banner chart is stale (not found in Superset), marking as REMOVED", + extra={ + "banner_id": existing.id, + "chart_id": existing.chart_id, + }, + ) + existing.status = MaintenanceDashboardBannerStatus.REMOVED + db_session.flush() + # Fall through to create a new chart + + # Create markdown chart in Superset + try: + chart_id = superset_client.create_markdown_chart( + dashboard_id, "*Maintenance banner placeholder*" + ) + except Exception as e: + app_logger.explore( + "Failed to create markdown chart", + extra={"dashboard_id": dashboard_id}, + error=str(e), + ) + raise + + # Insert chart at top of dashboard layout + try: + superset_client.update_dashboard_layout(dashboard_id, chart_id) + except Exception as e: + app_logger.explore( + "Failed to update dashboard layout, deleting chart", + extra={"dashboard_id": dashboard_id, "chart_id": chart_id}, + error=str(e), + ) + # Clean up the chart we just created + try: + superset_client.delete_chart(chart_id) + except Exception: + pass + raise + + # Persist banner row + banner = MaintenanceDashboardBanner( + environment_id=environment_id, + dashboard_id=dashboard_id, + chart_id=chart_id, + banner_text="", + status=MaintenanceDashboardBannerStatus.ACTIVE, + ) + db_session.add(banner) + db_session.flush() + + app_logger.reflect( + "Banner chart created and persisted", + extra={ + "banner_id": banner.id, + "chart_id": chart_id, + "dashboard_id": dashboard_id, + }, + ) + return banner +# #endregion ensure_banner_chart + + +# #region _process_dashboards_for_start [C:3] [TYPE Function] +# @BRIEF Process each dashboard for a start maintenance event: ensure banner chart, +# create dashboard state, build banner text, update chart markdown. +# @SIDE_EFFECT Creates/updates Superset charts, writes DB rows. +# @RELATION CALLS -> [ensure_banner_chart] +# @RELATION CALLS -> [_build_banner_text_for_dashboard] +# @RELATION CALLS -> [_resolve_dashboard_title] +def _process_dashboards_for_start( + dashboard_ids: list[int], + event_id: str, + environment_id: str, + template: str, + timezone_str: str, + superset_client: SupersetClient, + db_session: Session, +) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[MaintenanceDashboardBanner]]: + successful_dashboards: list[dict[str, Any]] = [] + failed_dashboards: list[dict[str, Any]] = [] + banners_created: list[MaintenanceDashboardBanner] = [] + + for dash_id in dashboard_ids: + app_logger.reason( + "Processing dashboard", + extra={"dashboard_id": dash_id, "event_id": event_id}, + ) + try: + # Ensure banner chart exists + banner = ensure_banner_chart( + dash_id, + environment_id, + superset_client, + db_session, + ) + banners_created.append(banner) + + # Create dashboard state + state = MaintenanceDashboardState( + event_id=event_id, + dashboard_id=dash_id, + banner_id=banner.id, + status=MaintenanceDashboardStateStatus.ACTIVE, + ) + db_session.add(state) + db_session.flush() # Ensure state is visible to subsequent queries + + # Build banner text for this dashboard's active events + banner_text = _build_banner_text_for_dashboard( + banner.id, db_session, template, timezone_str + ) + + # Update banner content on dashboard (native MARKDOWN in layout) + if banner.chart_id: + try: + superset_client.update_banner_on_dashboard( + dash_id, banner.chart_id, banner_text + ) + except Exception as e: + app_logger.explore( + "Failed to update banner on dashboard", + extra={ + "chart_id": banner.chart_id, + "dashboard_id": dash_id, + }, + error=str(e), + ) + state.status = MaintenanceDashboardStateStatus.APPLY_FAILED + failed_dashboards.append( + {"id": dash_id, "title": str(dash_id), "error": str(e)} + ) + continue + + # Update banner text in DB + banner.banner_text = banner_text + db_session.flush() + + # Resolve dashboard title + title = _resolve_dashboard_title(dash_id, superset_client) + successful_dashboards.append( + { + "id": dash_id, + "title": title, + "chart_id": banner.chart_id, + } + ) + app_logger.reflect( + "Dashboard processed successfully", + extra={"dashboard_id": dash_id}, + ) + + except Exception as e: + app_logger.explore( + "Failed to process dashboard", + extra={"dashboard_id": dash_id}, + error=str(e), + ) + failed_dashboards.append( + {"id": dash_id, "title": str(dash_id), "error": str(e)} + ) + + return successful_dashboards, failed_dashboards, banners_created +# #endregion _process_dashboards_for_start + + +# #region _process_states_for_end [C:3] [TYPE Function] +# @BRIEF Process each dashboard state for an end maintenance event: if other events +# still use same banner → rebuild; if no other events → remove banner (chart + layout). +# @SIDE_EFFECT Modifies Superset dashboards (removes charts, updates layouts). Writes DB. +# @RELATION CALLS -> [rebuild_banner] +def _process_states_for_end( + states: list[MaintenanceDashboardState], + event_id: str, + superset_client: SupersetClient, + db_session: Session, +) -> tuple[int, list[dict[str, Any]]]: + removed_count = 0 + failed_removals: list[dict[str, Any]] = [] + + for state in states: + dash_id = state.dashboard_id + app_logger.reason( + "Processing dashboard state for end", + extra={"dashboard_id": dash_id, "state_id": state.id}, + ) + + try: + banner_id = state.banner_id + if not banner_id: + # No banner linked, just mark as removed + state.status = MaintenanceDashboardStateStatus.REMOVED + removed_count += 1 + continue + + # Check if other active events still use this banner + other_active = db_session.query(MaintenanceDashboardState).filter( + MaintenanceDashboardState.banner_id == banner_id, + MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE, + MaintenanceDashboardState.event_id != event_id, + ).count() + + banner = db_session.query(MaintenanceDashboardBanner).filter( + MaintenanceDashboardBanner.id == banner_id + ).first() + + if other_active > 0 and banner: + # Other events still active — rebuild banner text + state.status = MaintenanceDashboardStateStatus.REMOVED + db_session.flush() + rebuild_banner(banner_id, db_session, superset_client) + app_logger.reflect( + "Banner rebuilt after removing event", + extra={"banner_id": banner_id, "dashboard_id": dash_id}, + ) + elif banner: + # No other events — remove banner entirely + state.status = MaintenanceDashboardStateStatus.REMOVING + db_session.flush() + + # Remove chart from layout + if banner.chart_id: + try: + superset_client.remove_chart_from_layout( + dash_id, banner.chart_id + ) + except Exception as e: + app_logger.explore( + "Failed to remove chart from layout", + extra={ + "dashboard_id": dash_id, + "chart_id": banner.chart_id, + }, + error=str(e), + ) + state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED + failed_removals.append( + {"id": dash_id, "title": str(dash_id), "error": str(e)} + ) + continue + + # Delete chart + try: + superset_client.delete_chart(banner.chart_id) + except Exception as e: + app_logger.explore( + "Failed to delete chart", + extra={ + "chart_id": banner.chart_id, + "dashboard_id": dash_id, + }, + error=str(e), + ) + state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED + failed_removals.append( + {"id": dash_id, "title": str(dash_id), "error": str(e)} + ) + continue + + # Mark banner as removed + banner.status = MaintenanceDashboardBannerStatus.REMOVED + state.status = MaintenanceDashboardStateStatus.REMOVED + app_logger.reflect( + "Banner fully removed", + extra={"banner_id": banner_id, "dashboard_id": dash_id}, + ) + else: + state.status = MaintenanceDashboardStateStatus.REMOVED + + removed_count += 1 + + except Exception as e: + app_logger.explore( + "Failed to end maintenance for dashboard", + extra={"dashboard_id": dash_id}, + error=str(e), + ) + state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED + failed_removals.append( + {"id": dash_id, "title": str(dash_id), "error": str(e)} + ) + + return removed_count, failed_removals +# #endregion _process_states_for_end + +# #endregion MaintenanceChartManager diff --git a/backend/src/services/maintenance/_dashboard_scanner.py b/backend/src/services/maintenance/_dashboard_scanner.py new file mode 100644 index 00000000..817b8b46 --- /dev/null +++ b/backend/src/services/maintenance/_dashboard_scanner.py @@ -0,0 +1,205 @@ +# #region MaintenanceDashboardScanner [C:3] [TYPE Module] [SEMANTICS maintenance, dashboard, scanner, tables] +# @BRIEF Dashboard discovery and filtering helpers for maintenance banner feature. +# Scan Superset datasets, match tables, apply scope/excluded/forced filters. +# @LAYER Service +# @RELATION DEPENDS_ON -> [SupersetClient] +# @RELATION DEPENDS_ON -> [SqlTableExtractorModule] +# @RELATION DEPENDS_ON -> [MaintenanceModels] + +from typing import Any + +from sqlalchemy.orm import Session + +from ...core.logger import belief_scope, logger as app_logger +from ...core.superset_client import SupersetClient +from ...models.maintenance import DashboardScope, MaintenanceSettings +from ..sql_table_extractor import extract_tables_from_sql + + +# #region find_affected_dashboards [C:3] [TYPE Function] [SEMANTICS maintenance, dashboard, discovery, tables] +# @BRIEF Find all dashboard IDs whose datasets reference any of the given tables. +# Supports both table-based (schema, table_name) and virtual SQL datasets (via SqlTableExtractor). +# Applies scope/excluded/forced filtering from MaintenanceSettings. +# @PRE tables is a non-empty list of "schema.table" strings. superset_client is authenticated. +# @POST Returns a deduplicated list of dashboard IDs that should receive banners. +# @SIDE_EFFECT Fetches all datasets from Superset (paginated). May be slow with many datasets. +# @RELATION DEPENDS_ON -> [SupersetClient] +# @RELATION DEPENDS_ON -> [SqlTableExtractorModule] +def find_affected_dashboards( + tables: list[str], + superset_client: SupersetClient, + settings: MaintenanceSettings | None = None, +) -> list[int]: + with belief_scope( + "find_affected_dashboards", + f"tables={tables}", + ): + app_logger.reason( + "Finding affected dashboards", + extra={"tables": tables}, + ) + + if not tables: + app_logger.reflect("No tables provided, returning empty") + return [] + + # Normalize input tables to lowercase set for matching + target_tables = {t.lower().strip() for t in tables if t.strip()} + if not target_tables: + return [] + + # Fetch all datasets from Superset + try: + _, datasets = superset_client.get_datasets() + except Exception as e: + app_logger.explore( + "Failed to fetch datasets from Superset", + extra={}, + error=str(e), + ) + raise + + app_logger.reason( + f"Scanning {len(datasets)} datasets for table references", + extra={"target_tables": list(target_tables)}, + ) + + matched_dashboard_ids: set[int] = set() + + for ds in datasets: + ds_schema = (ds.get("schema") or "").lower().strip() + ds_table = (ds.get("table_name") or "").lower().strip() + is_virtual = ds.get("is_sqllab_view", False) or ds.get("sql", "") not in ( + None, + "", + ) + ds_sql = ds.get("sql") or "" + ds_id = ds.get("id") + + # Phase 1: Table-based match + if not is_virtual and ds_schema and ds_table: + qualified = f"{ds_schema}.{ds_table}" + if qualified in target_tables: + linked = _get_linked_dashboards(superset_client, ds_id) + matched_dashboard_ids.update(linked) + continue + + # Phase 2: Virtual/SQL dataset — extract tables from SQL text + if is_virtual and ds_sql: + extracted = extract_tables_from_sql(ds_sql) + if extracted & target_tables: + linked = _get_linked_dashboards(superset_client, ds_id) + matched_dashboard_ids.update(linked) + + app_logger.reflect( + f"Found {len(matched_dashboard_ids)} affected dashboards", + extra={"dashboard_ids": list(matched_dashboard_ids)}, + ) + + # Apply filtering from settings + result = _apply_dashboard_filters( + list(matched_dashboard_ids), superset_client, settings + ) + + app_logger.reflect( + f"After filtering: {len(result)} dashboards", + extra={"dashboard_ids": result}, + ) + return result +# #endregion find_affected_dashboards + + +# #region _get_linked_dashboards [C:2] [TYPE Function] +# @BRIEF Fetch linked dashboards for a dataset from Superset. +# @SIDE_EFFECT Calls Superset API. +def _get_linked_dashboards( + superset_client: SupersetClient, + dataset_id: int | None, +) -> set[int]: + if not dataset_id: + return set() + try: + detail = superset_client.get_dataset_detail(dataset_id) + linked = detail.get("linked_dashboards", []) + return {int(d["id"]) for d in linked if d.get("id")} + except Exception as e: + app_logger.explore( + "Failed to fetch linked dashboards", + extra={"dataset_id": dataset_id}, + error=str(e), + ) + return set() +# #endregion _get_linked_dashboards + + +# #region _apply_dashboard_filters [C:2] [TYPE Function] +# @BRIEF Apply scope (published/draft/all), excluded, and forced filters from settings. +def _apply_dashboard_filters( + dashboard_ids: list[int], + superset_client: SupersetClient, + settings: MaintenanceSettings | None, +) -> list[int]: + if not settings: + return dashboard_ids + + # If forced list exists, include those unconditionally + forced_ids = set(settings.forced_dashboard_ids or []) + excluded_ids = set(settings.excluded_dashboard_ids or []) + + # Apply scope filtering + if settings.dashboard_scope != DashboardScope.ALL: + try: + _, all_dashboards = superset_client.get_dashboards() + scope = settings.dashboard_scope + filtered: list[int] = [] + for did in dashboard_ids: + dash = next( + (d for d in all_dashboards if d.get("id") == did), None + ) + if dash is None: + continue + is_published = dash.get("published", True) + if scope == DashboardScope.PUBLISHED_ONLY and not is_published: + continue + if scope == DashboardScope.DRAFT_ONLY and is_published: + continue + filtered.append(did) + dashboard_ids = filtered + except Exception as e: + app_logger.explore( + "Scope filtering failed, proceeding without it", + extra={}, + error=str(e), + ) + + # Apply excluded (forced overrides excluded per FR-009-b) + result = [ + did for did in dashboard_ids if did not in excluded_ids or did in forced_ids + ] + + # Add forced dashboards that are not already included + for fid in forced_ids: + if fid not in result: + result.append(fid) + + return result +# #endregion _apply_dashboard_filters + + +# #region _resolve_dashboard_title [C:2] [TYPE Function] +# @BRIEF Resolve dashboard title from Superset by ID. +def _resolve_dashboard_title( + dashboard_id: int, + superset_client: SupersetClient, +) -> str: + try: + _, dashboards = superset_client.get_dashboards() + for d in dashboards: + if d.get("id") == dashboard_id: + return d.get("dashboard_title") or d.get("title") or str(dashboard_id) + except Exception: + pass + return str(dashboard_id) +# #endregion _resolve_dashboard_title + +# #endregion MaintenanceDashboardScanner diff --git a/backend/src/services/maintenance/_orchestrators.py b/backend/src/services/maintenance/_orchestrators.py new file mode 100644 index 00000000..c06248cb --- /dev/null +++ b/backend/src/services/maintenance/_orchestrators.py @@ -0,0 +1,338 @@ +# #region MaintenanceOrchestrators [C:4] [TYPE Module] [SEMANTICS maintenance, orchestrator, lifecycle] +# @BRIEF C4 orchestrators for maintenance event lifecycle: start, end, end-all. +# Private helpers extracted to sub-modules. All orchestrators use belief runtime. +# @LAYER Service +# @RELATION DEPENDS_ON -> [MaintenanceModels] +# @RELATION DEPENDS_ON -> [SupersetClient] +# @RELATION DEPENDS_ON -> [MaintenanceDashboardScanner] +# @RELATION DEPENDS_ON -> [MaintenanceBannerRenderer] +# @RELATION DEPENDS_ON -> [MaintenanceChartManager] +# @INVARIANT C4 methods use belief_scope + REASON/REFLECT/EXPLORE markers. +# @INVARIANT Idempotency key: sorted lowercased (tables, start_time, end_time). message NOT in key. + +from datetime import datetime, timezone +from typing import Any + +from sqlalchemy.orm import Session + +from ...core.logger import belief_scope, logger as app_logger +from ...core.superset_client import SupersetClient +from ...models.maintenance import ( + MaintenanceDashboardState, + MaintenanceEvent, + MaintenanceEventStatus, + MaintenanceSettings, +) +from ._chart_manager import _process_dashboards_for_start, _process_states_for_end +from ._dashboard_scanner import find_affected_dashboards + + +# #region build_idempotency_key [C:2] [TYPE Function] +# @BRIEF Build idempotency key from (tables, start_time, end_time). Sorted lowercased tables, ISO timestamps. +# @PRE tables is a list of strings. start_time is a datetime or None. end_time is a datetime or None. +# @POST Returns a tuple of (frozenset(str), str|None, str|None) for DB comparison. +# @RATIONALE message is intentionally excluded from key per spec — different message with same tables/times = same event. +def build_idempotency_key( + tables: list[str], + start_time: datetime | None, + end_time: datetime | None, +) -> tuple[frozenset[str], str | None, str | None]: + sorted_tables = sorted(t.strip().lower() for t in tables if t.strip()) + start_key = start_time.isoformat() if start_time else None + end_key = end_time.isoformat() if end_time else None + return (frozenset(sorted_tables), start_key, end_key) +# #endregion build_idempotency_key + + +# #region start_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, start, orchestration, async] +# @BRIEF C4 orchestrator for starting a maintenance event. Runs inside a TaskManager task. +# Idempotency check with SELECT ... FOR UPDATE. Creates event states, finds dashboards, +# ensures banner charts, builds text, updates charts. Event transitions to ACTIVE or PARTIAL. +# @PRE event_id points to a valid MaintenanceEvent with status=PENDING. +# @POST Event and dashboard states transitioned to ACTIVE/PARTIAL/APPLY_FAILED. +# Banner charts created and updated in Superset. +# @SIDE_EFFECT Modifies Superset dashboards (creates/updates charts, modifies layouts). +# Writes multiple DB rows (dashboard states, banner updates). +# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers. +# @RELATION CALLS -> [find_affected_dashboards] +# @RELATION CALLS -> [_process_dashboards_for_start] +def start_maintenance( + event_id: str, + db_session: Session, + superset_client: SupersetClient, +) -> dict[str, Any]: + with belief_scope("start_maintenance", f"event_id={event_id}"): + app_logger.reason( + "Starting maintenance event", + extra={"event_id": event_id}, + ) + + # Load event + event = db_session.query(MaintenanceEvent).filter( + MaintenanceEvent.id == event_id + ).with_for_update().first() + if not event: + app_logger.explore( + "Event not found", + extra={"event_id": event_id}, + error="EventNotFound", + ) + return {"maintenance_id": event_id, "status": "failed", "error": "Event not found"} + + if event.status != MaintenanceEventStatus.PENDING: + app_logger.reflect( + "Event already processed", + extra={"event_id": event_id, "status": event.status.value}, + ) + return {"maintenance_id": event_id, "status": event.status.value} + + # Transition to APPLYING + event.status = MaintenanceEventStatus.APPLYING + db_session.flush() + + # Load settings + settings = db_session.query(MaintenanceSettings).filter( + MaintenanceSettings.id == "default" + ).first() + environment_id = settings.target_environment_id if settings else event.environment_id + template = settings.banner_template if settings else "" + timezone_str = settings.display_timezone if settings else "UTC" + + # Find affected dashboards + try: + dashboard_ids = find_affected_dashboards( + event.tables, + superset_client, + settings, + ) + except Exception as e: + app_logger.explore( + "Dashboard discovery failed", + extra={"event_id": event_id}, + error=str(e), + ) + event.status = MaintenanceEventStatus.FAILED + db_session.flush() + return { + "maintenance_id": event_id, + "status": "failed", + "error": str(e), + "affected_dashboards": 0, + "dashboards": [], + "failed_dashboards": [], + "unmatched_tables": [], + } + + if not dashboard_ids: + app_logger.reflect( + "No matching dashboards found", + extra={"event_id": event_id}, + ) + event.status = MaintenanceEventStatus.ACTIVE + db_session.flush() + return { + "maintenance_id": event_id, + "status": "no_match", + "affected_dashboards": 0, + "dashboards": [], + "failed_dashboards": [], + "unmatched_tables": [ + t for t in event.tables if t not in dashboard_ids + ], + } + + # Process each dashboard + successful_dashboards, failed_dashboards, _ = _process_dashboards_for_start( + dashboard_ids, + event_id, + environment_id, + template, + timezone_str, + superset_client, + db_session, + ) + + # Determine final event status + if not failed_dashboards: + event.status = MaintenanceEventStatus.ACTIVE + elif successful_dashboards: + event.status = MaintenanceEventStatus.PARTIAL + else: + event.status = MaintenanceEventStatus.FAILED + + db_session.flush() + + result = { + "maintenance_id": event_id, + "status": event.status.value, + "affected_dashboards": len(successful_dashboards), + "dashboards": successful_dashboards, + "failed_dashboards": failed_dashboards, + "unmatched_tables": [], + } + + app_logger.reflect( + "Maintenance start completed", + extra={ + "event_id": event_id, + "status": event.status.value, + "successful": len(successful_dashboards), + "failed": len(failed_dashboards), + }, + ) + return result +# #endregion start_maintenance + + +# #region end_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, end, orchestration, async, removal] +# @BRIEF C4 orchestrator for ending a maintenance event. Runs inside a TaskManager task. +# Event → ENDING. Delegates per-state processing to _process_states_for_end. +# Event → COMPLETED when done. +# @PRE event_id points to a valid active MaintenanceEvent. +# @POST Event transitions to COMPLETED. Dashboard states cleaned up. Charts removed when no other events. +# @SIDE_EFFECT Modifies Superset dashboards (removes charts, updates layouts). Writes DB. +# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers. +# @RELATION CALLS -> [_process_states_for_end] +def end_maintenance( + event_id: str, + db_session: Session, + superset_client: SupersetClient, +) -> dict[str, Any]: + with belief_scope("end_maintenance", f"event_id={event_id}"): + app_logger.reason( + "Ending maintenance event", + extra={"event_id": event_id}, + ) + + # Load event with lock + event = db_session.query(MaintenanceEvent).filter( + MaintenanceEvent.id == event_id + ).with_for_update().first() + if not event: + app_logger.explore( + "Event not found", + extra={"event_id": event_id}, + error="EventNotFound", + ) + return {"maintenance_id": event_id, "status": "failed", "error": "Event not found"} + + # Idempotent: already completed + if event.status == MaintenanceEventStatus.COMPLETED: + app_logger.reflect( + "Event already completed, idempotent", + extra={"event_id": event_id}, + ) + return {"maintenance_id": event_id, "status": "already_completed", "removed_from": 0, "failed_removals": []} + + # Transition to ENDING + event.status = MaintenanceEventStatus.ENDING + db_session.flush() + + # Find all dashboard states for this event + states = db_session.query(MaintenanceDashboardState).filter( + MaintenanceDashboardState.event_id == event_id + ).all() + + # Delegate per-state processing + removed_count, failed_removals = _process_states_for_end( + states, event_id, superset_client, db_session, + ) + + # Transition event to COMPLETED (even if some removals failed) + event.status = MaintenanceEventStatus.COMPLETED + db_session.flush() + + result = { + "maintenance_id": event_id, + "status": "completed" if not failed_removals else "partial", + "removed_from": removed_count, + "failed_removals": failed_removals, + } + + app_logger.reflect( + "Maintenance end completed", + extra={ + "event_id": event_id, + "removed": removed_count, + "failed": len(failed_removals), + }, + ) + return result +# #endregion end_maintenance + + +# #region end_all_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, end-all, orchestration, bulk] +# @BRIEF End ALL active maintenance events. Iterates active events, calls end_maintenance for each. +# @PRE None. +# @POST All events ended. All banners removed or rebuilt (last event removed). +# @SIDE_EFFECT Modifies multiple Superset dashboards. Writes multiple DB rows. +# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers. +# @RELATION CALLS -> [end_maintenance] +def end_all_maintenance( + db_session: Session, + superset_client: SupersetClient, +) -> dict[str, Any]: + with belief_scope("end_all_maintenance"): + app_logger.reason("Ending all active maintenance events") + + active_events = db_session.query(MaintenanceEvent).filter( + MaintenanceEvent.status.in_([ + MaintenanceEventStatus.ACTIVE, + MaintenanceEventStatus.PARTIAL, + MaintenanceEventStatus.APPLYING, + ]) + ).all() + + if not active_events: + app_logger.reflect("No active events to end") + return { + "status": "completed", + "closed_events": 0, + "removed_from": 0, + "failed_removals": [], + } + + total_removed = 0 + all_failed: list[dict[str, Any]] = [] + closed_count = 0 + + for event in active_events: + app_logger.reason( + "Ending event", + extra={"event_id": event.id}, + ) + try: + result = end_maintenance( + event.id, db_session, superset_client + ) + total_removed += result.get("removed_from", 0) + all_failed.extend(result.get("failed_removals", [])) + closed_count += 1 + except Exception as e: + app_logger.explore( + "Failed to end event", + extra={"event_id": event.id}, + error=str(e), + ) + all_failed.append( + {"id": 0, "title": event.id, "error": str(e)} + ) + + app_logger.reflect( + "All events ended", + extra={ + "closed": closed_count, + "removed": total_removed, + "failed": len(all_failed), + }, + ) + + return { + "status": "completed" if not all_failed else "partial", + "closed_events": closed_count, + "removed_from": total_removed, + "failed_removals": all_failed, + } +# #endregion end_all_maintenance + +# #endregion MaintenanceOrchestrators diff --git a/backend/src/services/sql_table_extractor.py b/backend/src/services/sql_table_extractor.py new file mode 100644 index 00000000..6939ac8d --- /dev/null +++ b/backend/src/services/sql_table_extractor.py @@ -0,0 +1,226 @@ +# #region SqlTableExtractorModule [C:2] [TYPE Module] [SEMANTICS sql, jinja, table, extraction, parsing] +# @BRIEF Three-phase SQL+Jinja table name extractor for virtual datasets as per FR-003. +# Phase 1: Detect Jinja spans vs SQL spans +# Phase 2: In Jinja spans, extract "schema.table" from string values +# Phase 3: In SQL spans, regex pattern + sqlparse filter to reject string literal false positives +# @LAYER Service +# @RELATION DEPENDS_ON -> [re, sqlparse] +# @INVARIANT Only exact schema.table matches (case-insensitive); unqualified references are NOT matched. +# @INVARIANT Returns a set[str] of fully-qualified table names (lowercased for case-insensitive matching). + +import re +from typing import Iterable + +import sqlparse +from sqlparse.sql import Identifier, Parenthesis, Token, TokenList +from sqlparse.tokens import Literal, Name, Punctuation, Whitespace + +# ── Phase 1: Jinja span detection ─────────────────────────── + +# Minimal Jinja token detection: {% ... %}, {{ ... }}, {# ... #} +_JINJA_BLOCK_RE = re.compile(r"{%-?\s*.*?\s*-?%}", re.DOTALL) +_JINJA_EXPR_RE = re.compile(r"{{-?\s*.*?\s*-?}}", re.DOTALL) +_JINJA_COMMENT_RE = re.compile(r"{#.*?#}", re.DOTALL) + +# ── Phase 3: schema.table regex (case-insensitive) ─────────── +_SCHEMA_TABLE_RE = re.compile( + r""" + (? list[tuple[str, str]]: + """Split raw SQL+Jinja text into alternating Jinja and SQL spans. + + Phase 1 detects Jinja blocks ({%%}, {{}}, {##}) and returns the + remaining text as SQL spans. + """ + if not raw_sql or not raw_sql.strip(): + return [("sql", raw_sql or "")] + + spans: list[tuple[str, str]] = [] + # Collect all Jinja match positions + jinja_matches: list[tuple[int, int]] = [] + for pattern in (_JINJA_BLOCK_RE, _JINJA_EXPR_RE, _JINJA_COMMENT_RE): + for m in pattern.finditer(raw_sql): + jinja_matches.append((m.start(), m.end())) + + # Merge overlapping Jinja spans + if jinja_matches: + jinja_matches.sort() + merged: list[tuple[int, int]] = [jinja_matches[0]] + for start, end in jinja_matches[1:]: + if start <= merged[-1][1]: + merged[-1] = (merged[-1][0], max(merged[-1][1], end)) + else: + merged.append((start, end)) + + # Build alternating sql/jinja spans + cursor = 0 + for start, end in merged: + if cursor < start: + sql_chunk = raw_sql[cursor:start].strip() + if sql_chunk: + spans.append(("sql", sql_chunk)) + jinja_chunk = raw_sql[start:end].strip() + if jinja_chunk: + spans.append(("jinja", jinja_chunk)) + cursor = end + if cursor < len(raw_sql): + remaining = raw_sql[cursor:].strip() + if remaining: + spans.append(("sql", remaining)) + else: + spans.append(("sql", raw_sql.strip())) + + return spans +# #endregion detect_jinja_spans + + +# #region extract_tables_from_jinja [C:2] [TYPE Function] +# @BRIEF Phase 2: Extract "schema.table" references from Jinja string values. +# Looks for patterns like "raw.sales" inside Jinja text. +# @PRE jinja_text is a string from a Jinja span. +# @POST Returns a set of lowercased schema.table strings. +def extract_tables_from_jinja(jinja_text: str) -> set[str]: + """Extract ``schema.table`` references from within Jinja template blocks. + + Looks for double-quoted or single-quoted string values that match + the ``schema.table`` pattern, e.g. ``"raw.sales"`` or ``'raw.inventory'``. + """ + tables: set[str] = set() + # Match string values: "schema.table" or 'schema.table' + string_pattern = re.compile( + r"""["']([a-zA-Z_][\w]*\.[a-zA-Z_][\w]*)["']""" + ) + for m in string_pattern.finditer(jinja_text): + tables.add(m.group(1).lower()) + return tables +# #endregion extract_tables_from_jinja + + +# #region is_string_literal [C:1] [TYPE Function] +# @BRIEF Check if a sqlparse Token is a string literal (not a schema.table identifier). +# @PRE token is a sqlparse Token. +# @POST Returns True if the token is a string/Single/Literal.String. +def is_string_literal(token: Token) -> bool: + """Return True if token is a string literal type in sqlparse.""" + return token.ttype is Literal.String.Single or token.ttype is Literal.String +# #endregion is_string_literal + + +# #region extract_tables_from_sql_span [C:2] [TYPE Function] +# @BRIEF Phase 3: Extract schema.table references from SQL text using regex + sqlparse filtering. +# Uses regex to find all schema.table candidates, then sqlparse to filter out +# false positives inside string literals. +# @PRE sql_text is a string from a SQL span (non-Jinja). +# @POST Returns a set of lowercased schema.table strings. +def extract_tables_from_sql_span(sql_text: str) -> set[str]: + """Extract ``schema.table`` references from plain SQL text. + + Uses regex to find all ``schema.table`` candidates, then sqlparse + to reject matches that fall inside string literals. + """ + tables: set[str] = set() + raw_matches = _SCHEMA_TABLE_RE.findall(sql_text) + if not raw_matches: + return tables + + # Use sqlparse to identify string literal positions + parsed = sqlparse.parse(sql_text) + string_literal_ranges: list[tuple[int, int]] = [] + + def walk_tokens(tokens: Iterable[Token], base_offset: int = 0) -> None: + offset = base_offset + for token in tokens: + if isinstance(token, TokenList): + walk_tokens(token.flatten(), offset) + else: + ttype = token.ttype + val = token.value + if is_string_literal(token): + string_literal_ranges.append( + (offset, offset + len(val)) + ) + offset += len(val) + + for stmt in parsed: + if stmt is None: + continue + walk_tokens(stmt.flatten(), base_offset=0) + + def is_in_string(pos: int) -> bool: + for s_start, s_end in string_literal_ranges: + if s_start <= pos <= s_end: + return True + return False + + # Re-scan with full match positions to filter + for m in _SCHEMA_TABLE_RE.finditer(sql_text): + if not is_in_string(m.start()): + # Extract schema and table from match groups + schema = m.group(2) or m.group(1) or "" + table = m.group(3) or "" + # Filter out column aliases (single-char schemas like "a.id", "o.id") + if len(schema) < 2 and schema.isalpha() and schema.islower(): + continue + if schema and table: + tables.add(f"{schema.lower()}.{table.lower()}") + + return tables +# #endregion extract_tables_from_sql_span + + +# #region extract_tables_from_sql [C:2] [TYPE Function] +# @BRIEF Three-phase entry point: extract all schema.table references from raw SQL+Jinja text. +# @PRE raw_sql is a string (possibly empty). +# @POST Returns a set of lowercased fully-qualified table names (schema.table format). +# @RELATION CALLS -> [detect_jinja_spans] +# @RELATION CALLS -> [extract_tables_from_jinja] +# @RELATION CALLS -> [extract_tables_from_sql_span] +def extract_tables_from_sql(raw_sql: str) -> set[str]: + """Extract all ``schema.table`` references from raw SQL + Jinja text. + + Three-phase approach per FR-003: + 1. Detect Jinja spans vs SQL spans + 2. In Jinja spans, extract ``schema.table`` from quoted string values + 3. In SQL spans, regex + sqlparse filter to reject string literal false positives + + Returns a set of lowercased ``schema.table`` strings for case-insensitive matching. + + Example: + >>> extract_tables_from_sql("SELECT * FROM raw.sales JOIN raw.inventory ON ...") + {'raw.sales', 'raw.inventory'} + """ + if not raw_sql or not raw_sql.strip(): + return set() + + all_tables: set[str] = set() + spans = detect_jinja_spans(raw_sql) + + for span_type, text in spans: + if span_type == "jinja": + all_tables.update(extract_tables_from_jinja(text)) + else: + all_tables.update(extract_tables_from_sql_span(text)) + + return all_tables +# #endregion extract_tables_from_sql + +# #endregion SqlTableExtractorModule diff --git a/backend/src/services/validation_run_service.py b/backend/src/services/validation_run_service.py index b8495dbb..7fb9a988 100644 --- a/backend/src/services/validation_run_service.py +++ b/backend/src/services/validation_run_service.py @@ -55,7 +55,12 @@ class ValidationRunService: query = self.db.query(ValidationRecord) if task_id: - query = query.filter(ValidationRecord.task_id == task_id) + # Match both spawned task_id (TaskRecord) and policy_id (ValidationPolicy.id) + # because the frontend sends the validation policy UUID, but ValidationRecord.task_id + # stores the spawned task UUID. Fall back to policy_id for the common case. + query = query.filter( + (ValidationRecord.task_id == task_id) | (ValidationRecord.policy_id == task_id) + ) if dashboard_id: query = query.filter(ValidationRecord.dashboard_id == dashboard_id) if environment_id: diff --git a/backend/tests/test_core_scheduler.py b/backend/tests/test_core_scheduler.py index f04d52d8..dc7eb2f8 100644 --- a/backend/tests/test_core_scheduler.py +++ b/backend/tests/test_core_scheduler.py @@ -5,8 +5,10 @@ # @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] -import sys +import asyncio +from datetime import time from pathlib import Path +import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) @@ -172,4 +174,345 @@ def test_remove_nonexistent_translation_job_no_error(): # #endregion test_remove_nonexistent_translation_job_no_error +# #region test_add_validation_job [C:1] [TYPE Function] +def test_add_validation_job(): + """Verify add_validation_job registers an APScheduler job.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + assert sched.get_job("validation_pol-1") is None + + svc.add_validation_job( + policy_id="pol-1", + cron_expression="30 10 * * 0,2,4", # 10:30 Mon, Wed, Fri + app_timezone="Europe/Moscow", + ) + + job = sched.get_job("validation_pol-1") + assert job is not None, "Validation job should be registered after add" + assert job.id == "validation_pol-1" + finally: + _stop_scheduler(sched) +# #endregion test_add_validation_job + + +# #region test_load_schedules_loads_validation_policies [C:1] [TYPE Function] +def test_load_schedules_loads_validation_policies(): + """Verify load_schedules re-registers validation jobs from DB.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + # Add app_timezone to config so cron gets a timezone + cfg.get_config.return_value.settings.app_timezone = "Europe/Moscow" + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + # Pre-register a validation job (to test it survives reload) + svc.add_validation_job( + policy_id="pol-1", + cron_expression="0 10 * * 1,3,5", + ) + assert sched.get_job("validation_pol-1") is not None + + # Mock DB to return an active ValidationPolicy with schedule_days + mock_policy = MagicMock() + mock_policy.id = "pol-1" + mock_policy.schedule_days = [0, 2, 4] # Mon, Wed, Fri + mock_policy.window_start = time(10, 30) + mock_policy.window_end = time(11, 0) + + mock_db = MagicMock() + # First query is for TranslationSchedule (empty), second is ValidationPolicy + mock_db.query.side_effect = [ + MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[])))), + MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[mock_policy])))), + ] + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + svc.load_schedules() + + # Validation job should still exist after reload + job = sched.get_job("validation_pol-1") + assert job is not None, "Validation job should survive load_schedules" + finally: + _stop_scheduler(sched) +# #endregion test_load_schedules_loads_validation_policies + + +# #region test_trigger_validation_creates_tasks [C:1] [TYPE Function] +def test_trigger_validation_creates_tasks(): + """Verify _trigger_validation creates TaskManager tasks for each dashboard.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + svc.loop = asyncio.new_event_loop() + + # Mock the ValidationPolicy DB query + mock_policy = MagicMock() + mock_policy.id = "pol-1" + mock_policy.is_active = True + mock_policy.dashboard_ids = ["dash-1", "dash-2"] + mock_policy.environment_id = "ss-dev" + mock_policy.provider_id = "prov-1" + mock_policy.window_start = time(10, 0) + mock_policy.window_end = time(10, 30) + + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = mock_policy + + # Patch asyncio.run_coroutine_threadsafe to call the function synchronously + # so we can verify the mock was called + captured_calls = [] + + def fake_run_coro(_coro_or_fn, _loop): + captured_calls.append(1) + return MagicMock() + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db), \ + patch("src.core.scheduler.asyncio.run_coroutine_threadsafe", side_effect=fake_run_coro): + svc._trigger_validation("pol-1") + + # Should have submitted 2 coroutines via run_coroutine_threadsafe (one per dashboard) + assert len(captured_calls) == 2, ( + f"Expected 2 task submissions via run_coroutine_threadsafe, got {len(captured_calls)}" + ) + finally: + _stop_scheduler(sched) +# #endregion test_trigger_validation_creates_tasks + + +# #region test_trigger_validation_skips_missing_policy [C:1] [TYPE Function] +def test_trigger_validation_skips_missing_policy(): + """Verify _trigger_validation does not fail when policy is missing.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + svc.loop = asyncio.new_event_loop() + + # Mock DB to return None (policy not found) + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = None + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + # Should not raise + svc._trigger_validation("nonexistent-policy") + + # create_task should not have been called + assert tm.create_task.call_count == 0 + finally: + _stop_scheduler(sched) +# #endregion test_trigger_validation_skips_missing_policy + + +# #region test_trigger_validation_skips_inactive_policy [C:1] [TYPE Function] +def test_trigger_validation_skips_inactive_policy(): + """Verify _trigger_validation skips an inactive policy.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + svc.loop = asyncio.new_event_loop() + + mock_policy = MagicMock() + mock_policy.id = "pol-inactive" + mock_policy.is_active = False + mock_policy.dashboard_ids = ["dash-1"] + + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = mock_policy + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + svc._trigger_validation("pol-inactive") + + # create_task should not have been called for inactive policy + assert tm.create_task.call_count == 0 + finally: + _stop_scheduler(sched) +# #endregion test_trigger_validation_skips_inactive_policy + + +# #region test_trigger_validation_skips_no_dashboards [C:1] [TYPE Function] +def test_trigger_validation_skips_no_dashboards(): + """Verify _trigger_validation skips a policy with no dashboards.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + svc.loop = asyncio.new_event_loop() + + mock_policy = MagicMock() + mock_policy.id = "pol-empty" + mock_policy.is_active = True + mock_policy.dashboard_ids = [] + + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = mock_policy + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + svc._trigger_validation("pol-empty") + + assert tm.create_task.call_count == 0 + finally: + _stop_scheduler(sched) +# #endregion test_trigger_validation_skips_no_dashboards + + +# #region test_remove_validation_job [C:1] [TYPE Function] +def test_remove_validation_job(): + """Verify remove_validation_job removes an existing job.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + svc.add_validation_job("pol-remove", cron_expression="0 10 * * 1") + assert sched.get_job("validation_pol-remove") is not None + + svc.remove_validation_job("pol-remove") + assert sched.get_job("validation_pol-remove") is None + finally: + _stop_scheduler(sched) +# #endregion test_remove_validation_job + + +# #region test_remove_nonexistent_validation_job [C:1] [TYPE Function] +def test_remove_nonexistent_validation_job(): + """Verify remove_validation_job handles non-existent job silently.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + # Should not raise + svc.remove_validation_job("nonexistent-pol") + finally: + _stop_scheduler(sched) +# #endregion test_remove_nonexistent_validation_job + + +# #region test_reload_validation_policy_adds_job [C:1] [TYPE Function] +def test_reload_validation_policy_adds_job(): + """Verify reload_validation_policy registers a job for an active policy with schedule.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + # Mock DB to return an active policy with schedule_days + mock_policy = MagicMock() + mock_policy.id = "pol-reload" + mock_policy.is_active = True + mock_policy.schedule_days = [0, 2, 4] + mock_policy.window_start = time(10, 30) + + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = mock_policy + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + svc.reload_validation_policy("pol-reload") + + job = sched.get_job("validation_pol-reload") + assert job is not None, "Job should be registered after reload" + finally: + _stop_scheduler(sched) +# #endregion test_reload_validation_policy_adds_job + + +# #region test_reload_validation_policy_removes_job_when_policy_gone [C:1] [TYPE Function] +def test_reload_validation_policy_removes_job_when_policy_gone(): + """Verify reload_validation_policy removes job when policy is missing or inactive.""" + from src.core.scheduler import SchedulerService + + sched = _start_scheduler() + try: + cfg = _make_mock_config_manager() + tm = _make_mock_task_manager() + + svc = SchedulerService.__new__(SchedulerService) + svc.task_manager = tm + svc.config_manager = cfg + svc.scheduler = sched + + # Pre-register a job + svc.add_validation_job("pol-gone", cron_expression="0 10 * * 1") + assert sched.get_job("validation_pol-gone") is not None + + # Mock DB to return None (policy not found) + mock_db = MagicMock() + mock_db.query.return_value.filter.return_value.first.return_value = None + + with patch("src.core.scheduler.SessionLocal", return_value=mock_db): + svc.reload_validation_policy("pol-gone") + + # Job should have been removed + assert sched.get_job("validation_pol-gone") is None + finally: + _stop_scheduler(sched) +# #endregion test_reload_validation_policy_removes_job_when_policy_gone # #endregion TestCoreScheduler diff --git a/backend/tests/test_layout_utils.py b/backend/tests/test_layout_utils.py new file mode 100644 index 00000000..97875ac0 --- /dev/null +++ b/backend/tests/test_layout_utils.py @@ -0,0 +1,55 @@ +# #region test_layout_utils [C:3] [TYPE TestModule] [SEMANTICS test, layout, superset, height, estimation] +# @BRIEF Contract tests for layout utility functions — _estimate_markdown_height. +# Verifies the height estimation formula: empty → 19, short text → computed, +# padding accounted for, and long text capped at 200. +# @LAYER Test +# @RELATION BINDS_TO -> [LayoutUtils] +# @TEST_CONTRACT: _estimate_markdown_height(str) -> int in [19, 200] +# @TEST_EDGE: empty_content -> returns minimum height (19) +# @TEST_EDGE: html_only_content -> returns minimum height (19) +# @TEST_EDGE: content_with_padding -> padding:12 correctly increases height +# @TEST_EDGE: very_long_content -> capped at maximum height (200) +import pytest + +from src.core.superset_client._layout_utils import _estimate_markdown_height + + +class TestEstimateMarkdownHeight: + """Tests for _estimate_markdown_height pure function.""" + + # #region test_empty_content [C:2] [TYPE Function] + # @BRIEF Empty string returns minimum height 19. + def test_empty_content(self): + assert _estimate_markdown_height("") == 19 + # #endregion test_empty_content + + # #region test_single_line_text [C:2] [TYPE Function] + # @BRIEF Short text without padding returns expected computed height. + # 200 chars → 200//40+1 = 6 lines → 6*22 = 132px → 40+132 = 172px → 172//8 = 21 + def test_single_line_text(self): + text = "A" * 200 + assert _estimate_markdown_height(text) == 21 + # #endregion test_single_line_text + + # #region test_content_with_padding [C:2] [TYPE Function] + # @BRIEF Content with padding:12 — 24px added to content height. + # 200 chars + padding:12 → 6*22 + 24 = 156 → 40+156 = 196 → 196//8 = 24 + def test_content_with_padding(self): + content = '
' + "A" * 200 + "
" + assert _estimate_markdown_height(content) == 24 + # #endregion test_content_with_padding + + # #region test_very_long_content [C:2] [TYPE Function] + # @BRIEF Very long content (3000 chars) capped at max height 200. + def test_very_long_content(self): + text = "A" * 3000 + assert _estimate_markdown_height(text) == 200 + # #endregion test_very_long_content + + # #region test_html_only_content [C:2] [TYPE Function] + # @BRIEF HTML-only content (no visible text) returns minimum height 19. + def test_html_only_content(self): + content = "

" + assert _estimate_markdown_height(content) == 19 + # #endregion test_html_only_content +# #endregion test_layout_utils diff --git a/backend/tests/test_maintenance_api.py b/backend/tests/test_maintenance_api.py new file mode 100644 index 00000000..d5d056ca --- /dev/null +++ b/backend/tests/test_maintenance_api.py @@ -0,0 +1,466 @@ +# #region test_maintenance_api [C:3] [TYPE TestModule] [SEMANTICS test, maintenance, api, fastapi, pytest] +# @BRIEF Contract tests for Maintenance Banner API endpoints — T016, T025. +# Tests POST /start, POST /{id}/end, POST /end-all, GET /events, GET /dashboard-banners, +# GET /settings, PUT /settings. +# @LAYER Test +# @RELATION BINDS_TO -> [MaintenanceRoutesModule] +# @TEST_CONTRACT: POST /api/maintenance/start -> 202 {task_id, maintenance_id, status} +# @TEST_CONTRACT: POST /api/maintenance/{id}/end -> 202 {task_id, status} +# @TEST_CONTRACT: POST /api/maintenance/end-all -> 202 {task_id, status} +# @TEST_EDGE: missing_tables -> 422 validation error +# @TEST_EDGE: end_time_before_start_time -> 400 validation error +# @TEST_EDGE: non_existent_event_end -> 404 not found +import json +import os +import uuid +from datetime import datetime, timezone, timedelta +from typing import Any +from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock + +import pytest +from fastapi import status + +# Patch GitService at module level to prevent /app/storage/repositories error +# This patches the base module BEFORE any imports can reach it +import sys +from unittest.mock import MagicMock + +_mock_git_svc_cls = MagicMock() +_mock_git_svc_cls.return_value = MagicMock() +sys.modules['src.services.git._base'] = MagicMock(GitService=_mock_git_svc_cls) +sys.modules['src.services.git_service'] = MagicMock(GitService=_mock_git_svc_cls) + + +# ── Fixtures ────────────────────────────────────────────────── + +@pytest.fixture +def client(): + """Create a TestClient with all dependencies mocked.""" + from fastapi.testclient import TestClient + from src.app import app + return TestClient(app) + + +def _mock_auth_overrides(): + """Apply dependency overrides for authentication. + + Creates a mock admin user so that all RBAC checks pass. + The Admin role has full access via has_permission()'s special case. + """ + from src.dependencies import get_current_user + from src.app import app + + # Create admin user with Admin role (full access) + mock_role = MagicMock() + mock_role.name = "Admin" + mock_role.permissions = [] + + mock_user = MagicMock() + mock_user.username = "test-admin" + mock_user.roles = [mock_role] + + async def _mock_get_current_user(): + return mock_user + + app.dependency_overrides[get_current_user] = _mock_get_current_user + + +def _clear_overrides(): + """Clear dependency overrides.""" + from src.app import app + app.dependency_overrides = {} + + +@pytest.fixture(autouse=True) +def auth_mock(): + """Auto-apply auth mocks for all tests.""" + _mock_auth_overrides() + yield + _clear_overrides() + + +@pytest.fixture +def mock_db(): + """Patch get_db dependency to return a clean in-memory session. + + Uses StaticPool so all Session() instances share the same connection, + preventing SQLite threading issues where each :memory: connection + creates a separate database. + Creates all tables on the shared Base.metadata. + """ + from sqlalchemy import create_engine + from sqlalchemy.orm import sessionmaker, Session as SASession + from sqlalchemy.pool import StaticPool + from src.models.mapping import Base + from src.dependencies import get_db + from src.models.maintenance import MaintenanceSettings, DashboardScope + + # StaticPool ensures all sessions share the same in-memory connection + engine = create_engine( + "sqlite:///:memory:", + poolclass=StaticPool, + connect_args={"check_same_thread": False}, + echo=False, + ) + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + # Create default settings + settings = MaintenanceSettings( + id="default", + target_environment_id="test-env", + display_timezone="UTC", + banner_template="Test: {message} ({start_time}-{end_time})", + dashboard_scope=DashboardScope.PUBLISHED_ONLY, + excluded_dashboard_ids=[], + forced_dashboard_ids=[], + ) + session.add(settings) + session.commit() + + def _get_db_override(): + db = Session() + try: + yield db + finally: + db.close() + + from src.app import app + app.dependency_overrides[get_db] = _get_db_override + yield session + app.dependency_overrides.pop(get_db, None) + session.close() + + +@pytest.fixture +def mock_task_manager(): + """Patch get_task_manager to return a mock.""" + from src.dependencies import get_task_manager + + mock_tm = MagicMock() + mock_task = MagicMock() + mock_task.id = "test-task-id-123" + mock_tm.create_task = AsyncMock(return_value=mock_task) + + from src.app import app + app.dependency_overrides[get_task_manager] = lambda: mock_tm + yield mock_tm + app.dependency_overrides.pop(get_task_manager, None) + + +# ── T016: POST /api/maintenance/start ───────────────────────── + +class TestStartEndpoint: + """Contract tests for POST /api/maintenance/start.""" + + # #region test_start_returns_202 [C:2] [TYPE Function] + # @BRIEF Valid request returns 202 with task_id and maintenance_id. + def test_start_returns_202(self, client, mock_db, mock_task_manager): + response = client.post( + "/api/maintenance/start", + json={ + "tables": ["raw.sales"], + "start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(), + "end_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(), + "message": "Test maintenance", + }, + ) + assert response.status_code == 202 + data = response.json() + assert "task_id" in data + assert "maintenance_id" in data + assert data["status"] == "pending" + # #endregion test_start_returns_202 + + # #region test_start_missing_tables [C:2] [TYPE Function] + # @BRIEF Missing tables field returns 422. + def test_start_missing_tables(self, client, mock_db, mock_task_manager): + response = client.post( + "/api/maintenance/start", + json={ + "start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(), + }, + ) + assert response.status_code == 422 + # #endregion test_start_missing_tables + + # #region test_start_end_time_before_start [C:2] [TYPE Function] + # @BRIEF end_time before start_time returns 400. + def test_start_end_time_before_start(self, client, mock_db, mock_task_manager): + response = client.post( + "/api/maintenance/start", + json={ + "tables": ["raw.sales"], + "start_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(), + "end_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(), + }, + ) + assert response.status_code == 400 + # #endregion test_start_end_time_before_start + + # #region test_start_too_many_tables [C:2] [TYPE Function] + # @BRIEF More than 100 tables returns 422 (Pydantic validation). + def test_start_too_many_tables(self, client, mock_db, mock_task_manager): + tables = [f"raw.table{i}" for i in range(101)] + response = client.post( + "/api/maintenance/start", + json={ + "tables": tables, + "start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(), + }, + ) + assert response.status_code == 422 + # #endregion test_start_too_many_tables + + # #region test_start_idempotency [C:2] [TYPE Function] + # @BRIEF Same (tables, start, end) returns already_active. + def test_start_idempotency(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + + payload = { + "tables": ["raw.sales"], + "start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(), + "end_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(), + } + + # First call creates event + response1 = client.post("/api/maintenance/start", json=payload) + assert response1.status_code == 202 + + # Manually set event to ACTIVE so idempotency check finds it + maintenance_id = response1.json()["maintenance_id"] + event = mock_db.query(MaintenanceEvent).filter( + MaintenanceEvent.id == maintenance_id + ).first() + if event: + event.status = MaintenanceEventStatus.ACTIVE + mock_db.commit() + + # Second call with same params — idempotent + response2 = client.post("/api/maintenance/start", json=payload) + assert response2.status_code == 202 + data = response2.json() + # Should have maintenance_id and status + assert data.get("maintenance_id") or data.get("status") + # #endregion test_start_idempotency + + +# ── T025: POST /api/maintenance/{id}/end ────────────────────── + +class TestEndEndpoint: + """Contract tests for POST /api/maintenance/{id}/end.""" + + # #region test_end_returns_202 [C:2] [TYPE Function] + # @BRIEF Valid maintenance_id returns 202. + def test_end_returns_202(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + + event = MaintenanceEvent( + tables=["raw.sales"], + start_time=datetime.now(timezone.utc), + status=MaintenanceEventStatus.ACTIVE, + environment_id="test-env", + ) + mock_db.add(event) + mock_db.commit() + + response = client.post(f"/api/maintenance/{event.id}/end") + assert response.status_code == 202 + data = response.json() + assert "task_id" in data + # #endregion test_end_returns_202 + + # #region test_end_not_found [C:2] [TYPE Function] + # @BRIEF Non-existent maintenance_id returns 404. + def test_end_not_found(self, client, mock_db, mock_task_manager): + response = client.post("/api/maintenance/nonexistent-id/end") + assert response.status_code == 404 + # #endregion test_end_not_found + + +# ── POST /api/maintenance/end-all ───────────────────────────── + +class TestEndAllEndpoint: + """Contract tests for POST /api/maintenance/end-all.""" + + # #region test_end_all_returns_202 [C:2] [TYPE Function] + # @BRIEF end-all returns 202. + def test_end_all_returns_202(self, client, mock_db, mock_task_manager): + response = client.post("/api/maintenance/end-all") + assert response.status_code == 202 + data = response.json() + assert "task_id" in data + assert data["status"] == "pending" + # #endregion test_end_all_returns_202 + + +# ── GET /api/maintenance/events ─────────────────────────────── + +class TestEventsEndpoint: + """Contract tests for GET /api/maintenance/events.""" + + # #region test_list_events [C:2] [TYPE Function] + # @BRIEF Returns active and completed events. + def test_list_events(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + + active = MaintenanceEvent( + tables=["raw.active"], + start_time=datetime.now(timezone.utc), + status=MaintenanceEventStatus.ACTIVE, + environment_id="test-env", + ) + mock_db.add(active) + + completed = MaintenanceEvent( + tables=["raw.done"], + start_time=datetime.now(timezone.utc), + status=MaintenanceEventStatus.COMPLETED, + environment_id="test-env", + ) + mock_db.add(completed) + mock_db.commit() + + response = client.get("/api/maintenance/events") + assert response.status_code == 200 + data = response.json() + assert "active" in data + assert "completed" in data + # #endregion test_list_events + + # #region test_expired_event_auto_ends [C:2] [TYPE Function] + # @BRIEF Event past end_time with ACTIVE status → create_task called with auto-end params. + def test_expired_event_auto_ends(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + from datetime import timedelta + + event = MaintenanceEvent( + tables=["raw.sales"], + start_time=datetime.now(timezone.utc) - timedelta(hours=2), + end_time=datetime.now(timezone.utc) - timedelta(hours=1), + message="Expired maintenance", + status=MaintenanceEventStatus.ACTIVE, + environment_id="test-env", + ) + mock_db.add(event) + mock_db.commit() + + response = client.get("/api/maintenance/events") + assert response.status_code == 200 + + mock_task_manager.create_task.assert_called_once_with( + plugin_id="maintenance_banner_apply", + params={ + "operation": "end", + "event_id": event.id, + "environment_id": "test-env", + "user": "system", + }, + ) + # #endregion test_expired_event_auto_ends + + # #region test_future_end_time_skipped [C:2] [TYPE Function] + # @BRIEF Event with future end_time → no task created, skipped by < now filter. + def test_future_end_time_skipped(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + from datetime import timedelta + + event = MaintenanceEvent( + tables=["raw.sales"], + start_time=datetime.now(timezone.utc) + timedelta(hours=1), + end_time=datetime.now(timezone.utc) + timedelta(hours=3), + message="Future maintenance", + status=MaintenanceEventStatus.ACTIVE, + environment_id="test-env", + ) + mock_db.add(event) + mock_db.commit() + + response = client.get("/api/maintenance/events") + assert response.status_code == 200 + + mock_task_manager.create_task.assert_not_called() + # #endregion test_future_end_time_skipped + + # #region test_no_end_time_skipped [C:2] [TYPE Function] + # @BRIEF Event with end_time=None → no task created, skipped by isnot(None) filter. + def test_no_end_time_skipped(self, client, mock_db, mock_task_manager): + from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus + from datetime import timedelta + + event = MaintenanceEvent( + tables=["raw.sales"], + start_time=datetime.now(timezone.utc) - timedelta(hours=2), + end_time=None, + message="No end time", + status=MaintenanceEventStatus.ACTIVE, + environment_id="test-env", + ) + mock_db.add(event) + mock_db.commit() + + response = client.get("/api/maintenance/events") + assert response.status_code == 200 + + mock_task_manager.create_task.assert_not_called() + # #endregion test_no_end_time_skipped + + +# ── GET /api/maintenance/dashboard-banners ──────────────────── + +class TestDashboardBannersEndpoint: + """Contract tests for GET /api/maintenance/dashboard-banners.""" + + # #region test_list_banners [C:2] [TYPE Function] + # @BRIEF Returns list of active banners. + def test_list_banners(self, client, mock_db, mock_task_manager): + from src.models.maintenance import ( + MaintenanceDashboardBanner, + MaintenanceDashboardBannerStatus, + ) + + banner = MaintenanceDashboardBanner( + environment_id="test-env", + dashboard_id=101, + chart_id=12345, + banner_text="Test", + status=MaintenanceDashboardBannerStatus.ACTIVE, + ) + mock_db.add(banner) + mock_db.commit() + + response = client.get("/api/maintenance/dashboard-banners") + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + # #endregion test_list_banners + + +# ── GET /api/maintenance/settings ───────────────────────────── + +class TestSettingsEndpoint: + """Contract tests for GET/PUT /api/maintenance/settings.""" + + # #region test_get_settings [C:2] [TYPE Function] + # @BRIEF GET returns settings. + def test_get_settings(self, client, mock_db, mock_task_manager): + response = client.get("/api/maintenance/settings") + assert response.status_code == 200 + data = response.json() + assert "target_environment_id" in data + assert data["target_environment_id"] == "test-env" + # #endregion test_get_settings + + # #region test_put_settings [C:2] [TYPE Function] + # @BRIEF PUT updates settings. + def test_put_settings(self, client, mock_db, mock_task_manager): + response = client.put( + "/api/maintenance/settings", + json={"display_timezone": "Europe/Moscow"}, + ) + assert response.status_code == 200 + data = response.json() + assert data["display_timezone"] == "Europe/Moscow" + # #endregion test_put_settings +# #endregion test_maintenance_api diff --git a/backend/tests/test_maintenance_service.py b/backend/tests/test_maintenance_service.py new file mode 100644 index 00000000..4eeeae82 --- /dev/null +++ b/backend/tests/test_maintenance_service.py @@ -0,0 +1,622 @@ +# #region test_maintenance_service [C:3] [TYPE TestModule] [SEMANTICS test, maintenance, service, pytest, integration] +# @BRIEF Integration tests for MaintenanceService — T018, T026, T026a. +# Tests the C3/C4 orchestrators: start_maintenance, end_maintenance, end_all_maintenance, +# and helpers: find_affected_dashboards, ensure_banner_chart, build_banner_text, rebuild_banner. +# @LAYER Test +# @RELATION BINDS_TO -> [MaintenanceServiceModule] +# @TEST_CONTRACT: start_maintenance(str, Session, SupersetClient) -> dict +# @TEST_CONTRACT: end_maintenance(str, Session, SupersetClient) -> dict +# @TEST_CONTRACT: end_all_maintenance(Session, SupersetClient) -> dict +# @TEST_EDGE: event_not_found -> returns failed status with error message +# @TEST_EDGE: no_matching_dashboards -> returns "no_match" status +# @TEST_EDGE: superset_api_failure -> returns partial/failed with error details +import uuid +from datetime import datetime, timezone +from typing import Any, cast +from unittest.mock import MagicMock, patch, PropertyMock + +import pytest + +from src.models.maintenance import ( + DashboardScope, + MaintenanceDashboardBanner, + MaintenanceDashboardBannerStatus, + MaintenanceDashboardState, + MaintenanceDashboardStateStatus, + MaintenanceEvent, + MaintenanceEventStatus, + MaintenanceSettings, +) +from src.services.maintenance import ( + build_banner_text, + build_idempotency_key, + end_all_maintenance, + end_maintenance, + ensure_banner_chart, + find_affected_dashboards, + rebuild_banner, + start_maintenance, +) + + +# ── Fixtures ────────────────────────────────────────────────── + +@pytest.fixture +def mock_superset(): + """Create a mock SupersetClient for testing.""" + client = MagicMock() + # Default: no datasets + client.get_datasets.return_value = (0, []) + client.get_dashboards.return_value = (0, []) + client.get_dataset_detail.return_value = {"linked_dashboards": []} + client.create_markdown_chart.return_value = 12345 + client.get_chart.return_value = {"id": 12345, "result": {"viz_type": "markdown"}} + client.update_banner_on_dashboard.return_value = {"result": "ok"} + client.update_dashboard_layout.return_value = {"result": "ok"} + client.remove_chart_from_layout.return_value = {"result": "ok"} + client.delete_chart.return_value = {"result": "ok"} + return client + + +@pytest.fixture +def db_session(): + """Create an in-memory SQLite session with tables.""" + from sqlalchemy import create_engine + from sqlalchemy.orm import sessionmaker + from src.models.mapping import Base + + engine = create_engine("sqlite:///:memory:", echo=False) + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + # Create default settings + settings = MaintenanceSettings( + id="default", + target_environment_id="test-env", + display_timezone="UTC", + banner_template="Maintenance: {message} ({start_time} - {end_time})", + dashboard_scope=DashboardScope.PUBLISHED_ONLY, + excluded_dashboard_ids=[], + forced_dashboard_ids=[], + ) + session.add(settings) + session.commit() + return session + + +@pytest.fixture +def pending_event(db_session): + """Create a PENDING maintenance event in the DB.""" + event = MaintenanceEvent( + tables=["raw.sales", "raw.inventory"], + start_time=datetime.now(timezone.utc), + end_time=datetime.now(timezone.utc), + message="Test maintenance", + status=MaintenanceEventStatus.PENDING, + environment_id="test-env", + ) + db_session.add(event) + db_session.commit() + return event + + +# ── T017: build_idempotency_key tests ───────────────────────── + +class TestBuildIdempotencyKey: + """Tests for build_idempotency_key helper.""" + + # #region test_basic_key [C:2] [TYPE Function] + # @BRIEF Basic idempotency key with tables and times. + def test_basic_key(self): + tables = ["raw.sales", "RAW.INVENTORY"] + start = datetime(2026, 5, 21, 22, 0, 0, tzinfo=timezone.utc) + end = datetime(2026, 5, 22, 2, 0, 0, tzinfo=timezone.utc) + key = build_idempotency_key(tables, start, end) + assert key[0] == frozenset({"raw.inventory", "raw.sales"}) + assert key[1] == "2026-05-21T22:00:00+00:00" + assert key[2] == "2026-05-22T02:00:00+00:00" + # #endregion test_basic_key + + # #region test_key_without_end_time [C:2] [TYPE Function] + # @BRIEF Idempotency key with None end_time. + def test_key_without_end_time(self): + tables = ["raw.sales"] + start = datetime(2026, 5, 21, 22, 0, 0, tzinfo=timezone.utc) + key = build_idempotency_key(tables, start, None) + assert key[0] == frozenset({"raw.sales"}) + assert key[1] == "2026-05-21T22:00:00+00:00" + assert key[2] is None + # #endregion test_key_without_end_time + + # #region test_key_table_sorting [C:2] [TYPE Function] + # @BRIEF Tables are sorted alphabetically in frozenset. + def test_key_table_sorting(self): + key1 = build_idempotency_key(["z.table", "a.table"], None, None) + key2 = build_idempotency_key(["a.table", "z.table"], None, None) + assert key1 == key2 + # #endregion test_key_table_sorting + + +# ── T019: find_affected_dashboards tests ────────────────────── + +class TestFindAffectedDashboards: + """Tests for find_affected_dashboards.""" + + # #region test_empty_tables [C:2] [TYPE Function] + # @BRIEF Empty tables list returns empty. + def test_empty_tables(self, mock_superset): + result = find_affected_dashboards([], mock_superset) + assert result == [] + # #endregion test_empty_tables + + # #region test_table_based_match [C:2] [TYPE Function] + # @BRIEF Table-based dataset matching. + def test_table_based_match(self, mock_superset): + mock_superset.get_datasets.return_value = (2, [ + {"id": 1, "schema": "raw", "table_name": "sales", "sql": None}, + {"id": 2, "schema": "raw", "table_name": "inventory", "sql": None}, + ]) + mock_superset.get_dataset_detail.side_effect = [ + {"linked_dashboards": [{"id": 101}]}, + {"linked_dashboards": [{"id": 102}]}, + ] + + result = find_affected_dashboards(["raw.sales"], mock_superset) + assert 101 in result + assert 102 not in result + # #endregion test_table_based_match + + # #region test_virtual_dataset_match [C:2] [TYPE Function] + # @BRIEF Virtual SQL dataset matching via SqlTableExtractor. + def test_virtual_dataset_match(self, mock_superset): + mock_superset.get_datasets.return_value = (1, [ + { + "id": 1, + "schema": "raw", + "table_name": "sales_view", + "sql": "SELECT * FROM raw.sales", + "is_sqllab_view": True, + }, + ]) + mock_superset.get_dataset_detail.return_value = { + "linked_dashboards": [{"id": 101}], + } + + result = find_affected_dashboards(["raw.sales"], mock_superset) + assert 101 in result + # #endregion test_virtual_dataset_match + + # #region test_case_insensitive_matching [C:2] [TYPE Function] + # @BRIEF Matching is case-insensitive. + def test_case_insensitive_matching(self, mock_superset): + mock_superset.get_datasets.return_value = (1, [ + {"id": 1, "schema": "RAW", "table_name": "SALES", "sql": None}, + ]) + mock_superset.get_dataset_detail.return_value = { + "linked_dashboards": [{"id": 101}], + } + + result = find_affected_dashboards(["raw.sales"], mock_superset) + assert 101 in result + # #endregion test_case_insensitive_matching + + # #region test_superset_api_failure [C:2] [TYPE Function] + # @BRIEF Superset API failure propagates. + def test_superset_api_failure(self, mock_superset): + mock_superset.get_datasets.side_effect = Exception("Superset API error") + with pytest.raises(Exception, match="Superset API error"): + find_affected_dashboards(["raw.sales"], mock_superset) + # #endregion test_superset_api_failure + + +# ── T019a: ensure_banner_chart tests ────────────────────────── + +class TestEnsureBannerChart: + """Tests for ensure_banner_chart.""" + + # #region test_creates_new_banner [C:2] [TYPE Function] + # @BRIEF No existing banner — creates new chart and banner row. + def test_creates_new_banner(self, mock_superset, db_session): + banner = ensure_banner_chart( + 101, "test-env", mock_superset, db_session + ) + assert banner.dashboard_id == 101 + assert banner.chart_id == 12345 + assert banner.status == MaintenanceDashboardBannerStatus.ACTIVE + mock_superset.create_markdown_chart.assert_called_once_with(101, "*Maintenance banner placeholder*") + mock_superset.update_dashboard_layout.assert_called_once_with(101, 12345) + # #endregion test_creates_new_banner + + # #region test_returns_existing_banner [C:2] [TYPE Function] + # @BRIEF Existing active banner — returns it. + def test_returns_existing_banner(self, mock_superset, db_session): + existing = MaintenanceDashboardBanner( + environment_id="test-env", + dashboard_id=101, + chart_id=999, + banner_text="Existing", + status=MaintenanceDashboardBannerStatus.ACTIVE, + ) + db_session.add(existing) + db_session.commit() + + banner = ensure_banner_chart( + 101, "test-env", mock_superset, db_session + ) + assert banner.id == existing.id + assert banner.chart_id == 999 + mock_superset.create_markdown_chart.assert_not_called() + # #endregion test_returns_existing_banner + + # #region test_chart_creation_failure [C:2] [TYPE Function] + # @BRIEF Chart creation failure propagates. + def test_chart_creation_failure(self, mock_superset, db_session): + mock_superset.create_markdown_chart.side_effect = Exception("Chart error") + with pytest.raises(Exception, match="Chart error"): + ensure_banner_chart(101, "test-env", mock_superset, db_session) + # #endregion test_chart_creation_failure + + +# ── T020: build_banner_text tests ───────────────────────────── + +class TestBuildBannerText: + """Tests for build_banner_text.""" + + # #region test_single_event [C:2] [TYPE Function] + # @BRIEF Single event — direct substitution. + def test_single_event(self): + events = [ + {"start_time": "2026-05-21T22:00:00+00:00", + "end_time": "2026-05-22T02:00:00+00:00", + "message": "Updating tables"} + ] + template = "Banner: {message} ({start_time} - {end_time})" + result = build_banner_text(events, template) + assert "Updating tables" in result + assert "2026-05-21 22:00" in result + assert "2026-05-22 02:00" in result + # #endregion test_single_event + + # #region test_multiple_events [C:2] [TYPE Function] + # @BRIEF Multiple events — combined message. + def test_multiple_events(self): + events = [ + {"start_time": "2026-05-21T22:00:00+00:00", + "end_time": "2026-05-22T02:00:00+00:00", + "message": "Event 1"}, + {"start_time": "2026-05-23T22:00:00+00:00", + "end_time": "2026-05-24T02:00:00+00:00", + "message": "Event 2"}, + ] + template = "Banner: {message} ({start_time} - {end_time})" + result = build_banner_text(events, template) + assert "Event 1" in result + assert "Event 2" in result + # #endregion test_multiple_events + + # #region test_empty_events [C:2] [TYPE Function] + # @BRIEF Empty events list returns empty string. + def test_empty_events(self): + result = build_banner_text([], "Template: {message}") + assert result == "" + # #endregion test_empty_events + + # #region test_missing_variables [C:2] [TYPE Function] + # @BRIEF Missing variables replaced with empty string. + def test_missing_variables(self): + events = [{"start_time": None, "end_time": None, "message": "Hi"}] + template = "Start: {start_time} - End: {end_time} - Msg: {message}" + result = build_banner_text(events, template) + assert "уточняется" in result + assert "Hi" in result + # #endregion test_missing_variables + + # #region test_html_escaping [C:2] [TYPE Function] + # @BRIEF Message is HTML-escaped. + def test_html_escaping(self): + events = [{ + "start_time": "2026-05-21T22:00:00+00:00", + "end_time": "2026-05-22T02:00:00+00:00", + "message": "", + }] + template = "{message}" + result = build_banner_text(events, template) + assert " + +{#if isActive} + + {$t.maintenance?.maintenance_badge || "Maintenance"} + +{/if} + diff --git a/frontend/src/lib/components/MaintenanceEventsTable.svelte b/frontend/src/lib/components/MaintenanceEventsTable.svelte new file mode 100644 index 00000000..d8dffc24 --- /dev/null +++ b/frontend/src/lib/components/MaintenanceEventsTable.svelte @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + +
+ +
+
+

+ {$t.maintenance?.active_events || "Active Events"} +

+ + {#if activeEvents.length > 0} + + {/if} +
+ + {#if isLoading && activeEvents.length === 0} + +
+ + + + + + + + + + + + + + {#each [1, 2, 3] as _, i (i)} + + + + + + + + + + {/each} + +
IDTablesDashboardsStartEndStatusActions
+
+ {:else if activeEvents.length === 0} + +
+

+ {$t.maintenance?.no_active_events || "No active maintenance events"} +

+
+ {:else} + +
+ + + + + + + + + + + + + + {#each activeEvents as event (event.id)} + + + + + + + + + + {/each} + +
+ {$t.maintenance?.event_id || "Event ID"} + + {$t.maintenance?.tables || "Tables"} + + {$t.maintenance?.affected_dashboards || "Dashboards"} + + {$t.maintenance?.start_time || "Start Time"} + + {$t.maintenance?.end_time || "End Time"} + + {$t.maintenance?.status || "Status"} + + {$t.maintenance?.actions || "Actions"} +
+ {event.id?.length > 16 ? event.id.slice(0, 16) + "…" : event.id} + + {(event.tables || []).join(", ") || "-"} + + {event.affected_count ?? "-"} + + {formatTime(event.start_time)} + + {formatTime(event.end_time)} + + + {event.status} + + + +
+
+ {/if} +
+ + + {#if completedEvents.length > 0} +
+ + {$t.maintenance?.completed_events || "Completed Events"} ({completedEvents.length}) + + +
+
+ + + + + + + + + + + + + {#each completedEvents as event (event.id)} + + + + + + + + + {/each} + +
IDTablesDashboardsStartEndStatus
+ {event.id?.length > 16 ? event.id.slice(0, 16) + "…" : event.id} + + {(event.tables || []).join(", ") || "-"} + + {event.affected_count ?? "-"} + + {formatTime(event.start_time)} + + {formatTime(event.end_time)} + + + {event.status} + +
+
+
+
+ {/if} +
+ diff --git a/frontend/src/lib/components/MaintenanceSettingsPanel.svelte b/frontend/src/lib/components/MaintenanceSettingsPanel.svelte new file mode 100644 index 00000000..01039b28 --- /dev/null +++ b/frontend/src/lib/components/MaintenanceSettingsPanel.svelte @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + +
+ + {$t.maintenance?.settings || "Settings"} + + +
+
+ +
+ + + {$t.maintenance?.environment || "Environment"} + + + + +
+
+ + +
+ + {$t.maintenance?.scope || "Dashboard Scope"} + + +
+ + + +
+
+ + +
+
+ + + {$t.maintenance?.excluded_dashboards || "Excluded Dashboards"} + + + + +
+ +
+ + + {$t.maintenance?.forced_dashboards || "Forced Dashboards"} + + + + +
+
+ + +
+ + + + + + +
+ + {$t.maintenance?.banner_templates || "Banner Templates"}: + +
+ + + + +
+
+ + +
+ + + {#if bannerTemplate} +
+ + {$t.maintenance?.banner_preview || "Preview"} + +
+ {@html bannerPreview} +
+
+ {/if} + + +
+ +
+
+
+ diff --git a/frontend/src/lib/components/StartMaintenanceForm.svelte b/frontend/src/lib/components/StartMaintenanceForm.svelte new file mode 100644 index 00000000..e8357251 --- /dev/null +++ b/frontend/src/lib/components/StartMaintenanceForm.svelte @@ -0,0 +1,279 @@ + + + + + + + + + + + + + +
+
+

+ {$t.maintenance?.start_maintenance || "Start Maintenance"} +

+

+ {$t.maintenance?.start_maintenance_description || ""} +

+
+ +
+ +
+ + + {$t.maintenance?.template_label || "Quick Template"} + + +
+ {#each Object.entries(TEMPLATES) as [id, tmpl]} + + {/each} +
+
+ + +
+ + + + + + {#if tableError} +

{tableError}

+ {/if} +
+ + +
+
+ + + + + +
+ +
+ + + + + +
+
+ + +
+ + + + + +
+ + +
+ +
+
+
+ diff --git a/frontend/src/lib/components/health/ScheduleAtAGlance.svelte b/frontend/src/lib/components/health/ScheduleAtAGlance.svelte new file mode 100644 index 00000000..10892c40 --- /dev/null +++ b/frontend/src/lib/components/health/ScheduleAtAGlance.svelte @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +

+ {$t.health?.schedule_title || 'Schedule'} +

+
+ + {#if !loading && !error && scheduledTasks.length > 0} +
+ + + + {$t.health?.schedule_dashboard_count?.replace('{count}', String(totalDashboards)) || `${totalDashboards} dashboards`} + +
+ {/if} +
+ + + {#if loading} +
+
+ {#each Array(7) as _, i (i)} +
+ {/each} +
+
+
+
+
+
+ + + {:else if error} +
+
+ + + + {error} + +
+
+ + + {:else if scheduledTasks.length === 0} +
+
+ + + +
+

+ {$t.health?.schedule_empty || 'No active validation schedules.'} +

+

+ {$t.health?.schedule_empty_desc || 'Create a validation task with a schedule to see it here.'} +

+
+ + + {:else} +
+
+ +
+
+ {#each DAY_SHORT as dayLabel, idx (idx)} + {@const active = isDayActive(idx)} + {@const dayTasks = getTasksForDay(idx)} +
+ + {$t.validation?.[`days_${dayLabel}`] || dayLabel.toUpperCase()} + + {#if active} + {#each dayTasks.slice(0, 2) as task (task.id)} + {@const tc = getTaskColor(task)} + + {/each} + {#if dayTasks.length > 2} + +{dayTasks.length - 2} + {/if} + {/if} +
+ {/each} +
+ + +
+ + + + {#if scheduledTasks.length === 1} + {formatTimeRange(scheduledTasks[0].window_start, scheduledTasks[0].window_end)} + {:else} + {$t.health?.schedule_multi_time || 'Multiple windows'} + {/if} + · + {appTimezone} +
+
+ + +
+
+ {#each scheduledTasks as task (task.id)} + {@const status = getTaskStatus(task.id)} + {@const tc = status ? getStatusStyle(status) : null} + + {/each} +
+ + + {#if nextUpcoming} +
+
+ + + + {$t.health?.schedule_next || 'Next'}: + {nextUpcoming.task.name} + · + + {formatNextDay(nextUpcoming.dayIdx)} {nextUpcoming.timeStr?.slice(0, 5)} {appTimezone} + +
+
+ {/if} +
+
+
+ {/if} +
+ diff --git a/frontend/src/lib/components/layout/sidebarNavigation.js b/frontend/src/lib/components/layout/sidebarNavigation.js index 9db6e295..485b291b 100644 --- a/frontend/src/lib/components/layout/sidebarNavigation.js +++ b/frontend/src/lib/components/layout/sidebarNavigation.js @@ -183,6 +183,18 @@ export function buildSidebarSections(i18nState, user, features = {}) { { label: nav.admin_llm, path: "/admin/settings/llm", requiredPermission: "admin:settings", requiredAction: "READ" }, ], }, + { + id: "maintenance", + label: nav.maintenance || "Maintenance", + icon: "activity", + tone: "from-orange-100 to-orange-200 text-orange-700 ring-orange-200", + path: "/maintenance", + requiredPermission: "maintenance:write", + requiredAction: "READ", + subItems: [ + { label: nav.maintenance || "Maintenance", path: "/maintenance", requiredPermission: "maintenance:write", requiredAction: "READ" }, + ], + }, ], }; diff --git a/frontend/src/lib/components/translate/ScheduleConfig.svelte b/frontend/src/lib/components/translate/ScheduleConfig.svelte index caf0d20d..f78357c4 100644 --- a/frontend/src/lib/components/translate/ScheduleConfig.svelte +++ b/frontend/src/lib/components/translate/ScheduleConfig.svelte @@ -11,6 +11,7 @@ + + + + + + + + + diff --git a/frontend/src/routes/dashboards/+page.svelte b/frontend/src/routes/dashboards/+page.svelte index 2dcaa1bc..0ed65004 100644 --- a/frontend/src/routes/dashboards/+page.svelte +++ b/frontend/src/routes/dashboards/+page.svelte @@ -65,6 +65,7 @@ import MappingTable from "../../components/MappingTable.svelte"; import StartupEnvironmentWizard from "../../components/StartupEnvironmentWizard.svelte"; import SearchableMultiSelect from "$lib/components/ui/SearchableMultiSelect.svelte"; + import DashboardMaintenanceBadge from "$lib/components/DashboardMaintenanceBadge.svelte"; import { environmentContextStore, initializeEnvironmentContext, @@ -1597,7 +1598,7 @@ >
@@ -1606,11 +1607,12 @@
+
{#each Array(5) as _}
@@ -1619,6 +1621,7 @@
+
{/each} @@ -1733,7 +1736,7 @@
@@ -1941,6 +1944,9 @@ {/if}
+
+ {$t.maintenance?.maintenance_badge || "Maint."} +
{$t.dashboard?.actions}
@@ -2086,7 +2092,7 @@ {#each dashboards as dashboard}
@@ -2161,6 +2167,11 @@ {/if}
+ +
+ +
+
diff --git a/frontend/src/routes/dashboards/health/+page.svelte b/frontend/src/routes/dashboards/health/+page.svelte index 7d39d26e..90243d2e 100644 --- a/frontend/src/routes/dashboards/health/+page.svelte +++ b/frontend/src/routes/dashboards/health/+page.svelte @@ -2,14 +2,17 @@ + + +
+ +
+

+ {$t.maintenance?.title || "Maintenance Banners"} +

+ +
+ + {#if pageLoading} + +
+
+
+
+
+
+
+
+
+
+
+ {#each [1, 2, 3] as _, i (i)} +
+ {/each} +
+
+ {:else} + + maintenanceStore.loadEvents()} /> + + + + + + + {/if} +
+ diff --git a/frontend/src/routes/migration/+page.svelte b/frontend/src/routes/migration/+page.svelte index 842221a3..9705724e 100644 --- a/frontend/src/routes/migration/+page.svelte +++ b/frontend/src/routes/migration/+page.svelte @@ -492,7 +492,7 @@ - + diff --git a/frontend/src/routes/reports/llm/[taskId]/+page.svelte b/frontend/src/routes/reports/llm/[taskId]/+page.svelte index 9b2e7694..31bc4b3a 100644 --- a/frontend/src/routes/reports/llm/[taskId]/+page.svelte +++ b/frontend/src/routes/reports/llm/[taskId]/+page.svelte @@ -1,6 +1,6 @@ -/+page.svelte:Component] --> + @@ -22,9 +23,12 @@
- + + + +

{$t.settings?.feature_dataset_review_hint || "Automatic dataset review, clarification workflow, and SQL execution."}

@@ -38,9 +42,12 @@
- + + + +

{$t.settings?.feature_health_monitor_hint || "Dashboard health monitoring and validation report aggregation."}

diff --git a/frontend/src/routes/settings/LlmSettings.svelte b/frontend/src/routes/settings/LlmSettings.svelte index 7de4adb6..0abff43c 100644 --- a/frontend/src/routes/settings/LlmSettings.svelte +++ b/frontend/src/routes/settings/LlmSettings.svelte @@ -11,6 +11,7 @@ import { t } from "$lib/i18n"; import ProviderConfig from "../../components/llm/ProviderConfig.svelte"; import { isDashboardValidationBindingValid } from "./settings-utils.js"; + import HelpTooltip from "$lib/ui/HelpTooltip.svelte"; let { settings = $bindable(), onSave } = $props(); @@ -38,12 +39,15 @@
- + + + +
- + + + +
- + + + +