diff --git a/.axiom/semantic_index/index.json b/.axiom/semantic_index/index.json index 826afcd7..ede5e33f 100644 --- a/.axiom/semantic_index/index.json +++ b/.axiom/semantic_index/index.json @@ -1,9 +1,9 @@ { - "generated_at": "2026-05-21T17:00:02.724155271Z", + "generated_at": "2026-05-25T09:10:32.733122728Z", "root_path": "/home/busya/dev/ss-tools", - "contract_count": 2781, - "edge_count": 1947, - "file_count": 654, + "contract_count": 3037, + "edge_count": 2022, + "file_count": 691, "contracts": [ { "contract_id": "SrcRoot", @@ -277,7 +277,7 @@ "contract_type": "Module", "file_path": "backend/src/api/routes/__init__.py", "start_line": 1, - "end_line": 59, + "end_line": 61, "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 -> [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" + "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 \"admin_api_keys\",\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 \"maintenance\",\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": 42, + "end_line": 44, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -405,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 -> [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" + "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 \"admin_api_keys\",\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 \"maintenance\",\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": 45, - "end_line": 58, + "start_line": 47, + "end_line": 60, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -4519,6 +4519,181 @@ "tier_source": "AutoCalculated", "body": "# #region create_ad_mapping [C:2] [TYPE Function]\n# @RELATION DEPENDS_ON -> [ADGroupMapping:Class]\n# @RELATION DEPENDS_ON -> [get_auth_db:Function]\n# @RELATION DEPENDS_ON -> [has_permission:Function]\n# @BRIEF Creates a new AD Group mapping.\n@router.post(\"/ad-mappings\", response_model=ADGroupMappingSchema)\nasync def create_ad_mapping(\n mapping_in: ADGroupMappingCreate,\n db: Session = Depends(get_auth_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"api.admin.create_ad_mapping\"):\n new_mapping = ADGroupMapping(\n ad_group=mapping_in.ad_group, role_id=mapping_in.role_id\n )\n db.add(new_mapping)\n db.commit()\n db.refresh(new_mapping)\n return new_mapping\n\n\n# #endregion create_ad_mapping\n" }, + { + "contract_id": "AdminApiKeyRoutes", + "contract_type": "Module", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 1, + "end_line": 185, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "INVARIANT": "DELETE /api/admin/api-keys/{id} soft-deletes (active=False), preserves row for audit.", + "LAYER": "API", + "PURPOSE": "Admin API endpoints for API key management — list, generate (one-time reveal), and revoke." + }, + "relations": [ + { + "source_id": "AdminApiKeyRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "APIKeyModel", + "target_ref": "[APIKeyModel]" + }, + { + "source_id": "AdminApiKeyRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "APIKeyUtilities", + "target_ref": "[APIKeyUtilities]" + }, + { + "source_id": "AdminApiKeyRoutes", + "relation_type": "DEPENDS_ON", + "target_id": "has_permission(\"admin:settings\", \"WRITE\")", + "target_ref": "[has_permission(\"admin:settings\", \"WRITE\")]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region AdminApiKeyRoutes [C:3] [TYPE Module] [SEMANTICS fastapi, admin, api_key, crud]\n# @BRIEF Admin API endpoints for API key management — list, generate (one-time reveal), and revoke.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [APIKeyUtilities]\n# @RELATION DEPENDS_ON -> [has_permission(\"admin:settings\", \"WRITE\")]\n# @INVARIANT GET /api/admin/api-keys NEVER returns key_hash or raw_key.\n# @INVARIANT POST /api/admin/api-keys returns raw_key ONCE — never stored, never retrievable again.\n# @INVARIANT DELETE /api/admin/api-keys/{id} soft-deletes (active=False), preserves row for audit.\n\nfrom datetime import datetime\n\nfrom fastapi import APIRouter, Depends, HTTPException, status\nfrom pydantic import BaseModel, Field\nfrom sqlalchemy.orm import Session\n\nfrom ...core.auth.api_key import generate_api_key\nfrom ...core.database import get_db\nfrom ...dependencies import has_permission\nfrom ...models.api_key import APIKey\n\n# #region router [TYPE Variable]\n# @BRIEF APIRouter for admin API key management routes.\nrouter = APIRouter(prefix=\"/api/admin/api-keys\", tags=[\"admin\", \"api-keys\"])\n# #endregion router\n\n\n# ── Pydantic schemas ──────────────────────────────────────────\n\n# #region ApiKeyCreateRequest [C:1] [TYPE Class]\nclass ApiKeyCreateRequest(BaseModel):\n name: str = Field(..., min_length=1, max_length=255)\n environment_id: str | None = None\n permissions: list[str] = Field(..., min_length=1)\n expires_at: datetime | None = None\n# #endregion ApiKeyCreateRequest\n\n\n# #region ApiKeyCreateResponse [C:1] [TYPE Class]\nclass ApiKeyCreateResponse(BaseModel):\n id: str\n raw_key: str\n prefix: str\n name: str\n environment_id: str | None\n permissions: list[str]\n active: bool\n created_at: datetime\n expires_at: datetime | None\n# #endregion ApiKeyCreateResponse\n\n\n# #region ApiKeyListItem [C:1] [TYPE Class]\nclass ApiKeyListItem(BaseModel):\n id: str\n name: str\n prefix: str\n environment_id: str | None\n permissions: list[str]\n active: bool\n created_at: datetime\n expires_at: datetime | None\n last_used_at: datetime | None\n\n model_config = {\"from_attributes\": True}\n# #endregion ApiKeyListItem\n\n\n# #region ApiKeyRevokeResponse [C:1] [TYPE Class]\nclass ApiKeyRevokeResponse(BaseModel):\n id: str\n status: str\n# #endregion ApiKeyRevokeResponse\n\n\n# ── Routes ────────────────────────────────────────────────────\n\n# #region list_api_keys [C:2] [TYPE Function]\n# @BRIEF List all API keys — NEVER returns key_hash or raw_key.\n# @PRE Requires admin:settings WRITE permission.\n# @POST Returns list of ApiKeyListItem without sensitive fields.\n@router.get(\"/\", response_model=list[ApiKeyListItem])\nasync def list_api_keys(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all()\n return [\n ApiKeyListItem(\n id=k.id,\n name=k.name,\n prefix=k.prefix,\n environment_id=k.environment_id,\n permissions=list(k.permissions or []),\n active=k.active,\n created_at=k.created_at,\n expires_at=k.expires_at,\n last_used_at=k.last_used_at,\n )\n for k in keys\n ]\n# #endregion list_api_keys\n\n\n# #region create_api_key [C:3] [TYPE Function]\n# @BRIEF Generate a new API key — returns raw key ONCE, never stored or retrievable again.\n# @PRE Requires admin:settings WRITE permission. name is required, at least one permission.\n# @POST Creates APIKey row with SHA-256 hash. Returns raw key in response.\n# @SIDE_EFFECT Generates cryptographically random key, stores hash in DB.\n# @RELATION DEPENDS_ON -> [generate_api_key]\n@router.post(\"/\", response_model=ApiKeyCreateResponse, status_code=status.HTTP_201_CREATED)\nasync def create_api_key(\n request: ApiKeyCreateRequest,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n # Validate\n if not request.name.strip():\n raise HTTPException(status_code=400, detail=\"Name is required\")\n if not request.permissions:\n raise HTTPException(status_code=400, detail=\"At least one permission is required\")\n\n # Generate key\n raw_key, prefix, key_hash = generate_api_key()\n\n # Store hash only\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=request.name.strip(),\n environment_id=request.environment_id,\n permissions=request.permissions,\n active=True,\n expires_at=request.expires_at,\n )\n db.add(api_key)\n db.commit()\n db.refresh(api_key)\n\n return ApiKeyCreateResponse(\n id=api_key.id,\n raw_key=raw_key,\n prefix=api_key.prefix,\n name=api_key.name,\n environment_id=api_key.environment_id,\n permissions=list(api_key.permissions or []),\n active=api_key.active,\n created_at=api_key.created_at,\n expires_at=api_key.expires_at,\n )\n# #endregion create_api_key\n\n\n# #region revoke_api_key [C:2] [TYPE Function]\n# @BRIEF Revoke an API key by setting active=False. Preserves row for audit.\n# @PRE Requires admin:settings WRITE permission.\n# @POST Sets active=False on the key. Returns 404 if already revoked or not found.\n@router.delete(\"/{key_id}\", response_model=ApiKeyRevokeResponse)\nasync def revoke_api_key(\n key_id: str,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n api_key = db.query(APIKey).filter(APIKey.id == key_id).first()\n if not api_key:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND,\n detail=\"API key not found\",\n )\n if not api_key.active:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND,\n detail=\"API key is already revoked\",\n )\n\n api_key.active = False\n db.commit()\n\n return ApiKeyRevokeResponse(\n id=api_key.id,\n status=\"revoked\",\n )\n# #endregion revoke_api_key\n\n# #endregion AdminApiKeyRoutes\n" + }, + { + "contract_id": "ApiKeyCreateRequest", + "contract_type": "Class", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 30, + "end_line": 36, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ApiKeyCreateRequest [C:1] [TYPE Class]\nclass ApiKeyCreateRequest(BaseModel):\n name: str = Field(..., min_length=1, max_length=255)\n environment_id: str | None = None\n permissions: list[str] = Field(..., min_length=1)\n expires_at: datetime | None = None\n# #endregion ApiKeyCreateRequest\n" + }, + { + "contract_id": "ApiKeyCreateResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 39, + "end_line": 50, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ApiKeyCreateResponse [C:1] [TYPE Class]\nclass ApiKeyCreateResponse(BaseModel):\n id: str\n raw_key: str\n prefix: str\n name: str\n environment_id: str | None\n permissions: list[str]\n active: bool\n created_at: datetime\n expires_at: datetime | None\n# #endregion ApiKeyCreateResponse\n" + }, + { + "contract_id": "ApiKeyListItem", + "contract_type": "Class", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 53, + "end_line": 66, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ApiKeyListItem [C:1] [TYPE Class]\nclass ApiKeyListItem(BaseModel):\n id: str\n name: str\n prefix: str\n environment_id: str | None\n permissions: list[str]\n active: bool\n created_at: datetime\n expires_at: datetime | None\n last_used_at: datetime | None\n\n model_config = {\"from_attributes\": True}\n# #endregion ApiKeyListItem\n" + }, + { + "contract_id": "ApiKeyRevokeResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 69, + "end_line": 73, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ApiKeyRevokeResponse [C:1] [TYPE Class]\nclass ApiKeyRevokeResponse(BaseModel):\n id: str\n status: str\n# #endregion ApiKeyRevokeResponse\n" + }, + { + "contract_id": "list_api_keys", + "contract_type": "Function", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 78, + "end_line": 102, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns list of ApiKeyListItem without sensitive fields.", + "PRE": "Requires admin:settings WRITE permission.", + "PURPOSE": "List all API keys — NEVER returns key_hash or raw_key." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region list_api_keys [C:2] [TYPE Function]\n# @BRIEF List all API keys — NEVER returns key_hash or raw_key.\n# @PRE Requires admin:settings WRITE permission.\n# @POST Returns list of ApiKeyListItem without sensitive fields.\n@router.get(\"/\", response_model=list[ApiKeyListItem])\nasync def list_api_keys(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all()\n return [\n ApiKeyListItem(\n id=k.id,\n name=k.name,\n prefix=k.prefix,\n environment_id=k.environment_id,\n permissions=list(k.permissions or []),\n active=k.active,\n created_at=k.created_at,\n expires_at=k.expires_at,\n last_used_at=k.last_used_at,\n )\n for k in keys\n ]\n# #endregion list_api_keys\n" + }, + { + "contract_id": "create_api_key", + "contract_type": "Function", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 105, + "end_line": 151, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "Creates APIKey row with SHA-256 hash. Returns raw key in response.", + "PRE": "Requires admin:settings WRITE permission. name is required, at least one permission.", + "PURPOSE": "Generate a new API key — returns raw key ONCE, never stored or retrievable again.", + "SIDE_EFFECT": "Generates cryptographically random key, stores hash in DB." + }, + "relations": [ + { + "source_id": "create_api_key", + "relation_type": "DEPENDS_ON", + "target_id": "generate_api_key", + "target_ref": "[generate_api_key]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region create_api_key [C:3] [TYPE Function]\n# @BRIEF Generate a new API key — returns raw key ONCE, never stored or retrievable again.\n# @PRE Requires admin:settings WRITE permission. name is required, at least one permission.\n# @POST Creates APIKey row with SHA-256 hash. Returns raw key in response.\n# @SIDE_EFFECT Generates cryptographically random key, stores hash in DB.\n# @RELATION DEPENDS_ON -> [generate_api_key]\n@router.post(\"/\", response_model=ApiKeyCreateResponse, status_code=status.HTTP_201_CREATED)\nasync def create_api_key(\n request: ApiKeyCreateRequest,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n # Validate\n if not request.name.strip():\n raise HTTPException(status_code=400, detail=\"Name is required\")\n if not request.permissions:\n raise HTTPException(status_code=400, detail=\"At least one permission is required\")\n\n # Generate key\n raw_key, prefix, key_hash = generate_api_key()\n\n # Store hash only\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=request.name.strip(),\n environment_id=request.environment_id,\n permissions=request.permissions,\n active=True,\n expires_at=request.expires_at,\n )\n db.add(api_key)\n db.commit()\n db.refresh(api_key)\n\n return ApiKeyCreateResponse(\n id=api_key.id,\n raw_key=raw_key,\n prefix=api_key.prefix,\n name=api_key.name,\n environment_id=api_key.environment_id,\n permissions=list(api_key.permissions or []),\n active=api_key.active,\n created_at=api_key.created_at,\n expires_at=api_key.expires_at,\n )\n# #endregion create_api_key\n" + }, + { + "contract_id": "revoke_api_key", + "contract_type": "Function", + "file_path": "backend/src/api/routes/admin_api_keys.py", + "start_line": 154, + "end_line": 183, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Sets active=False on the key. Returns 404 if already revoked or not found.", + "PRE": "Requires admin:settings WRITE permission.", + "PURPOSE": "Revoke an API key by setting active=False. Preserves row for audit." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region revoke_api_key [C:2] [TYPE Function]\n# @BRIEF Revoke an API key by setting active=False. Preserves row for audit.\n# @PRE Requires admin:settings WRITE permission.\n# @POST Sets active=False on the key. Returns 404 if already revoked or not found.\n@router.delete(\"/{key_id}\", response_model=ApiKeyRevokeResponse)\nasync def revoke_api_key(\n key_id: str,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n api_key = db.query(APIKey).filter(APIKey.id == key_id).first()\n if not api_key:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND,\n detail=\"API key not found\",\n )\n if not api_key.active:\n raise HTTPException(\n status_code=status.HTTP_404_NOT_FOUND,\n detail=\"API key is already revoked\",\n )\n\n api_key.active = False\n db.commit()\n\n return ApiKeyRevokeResponse(\n id=api_key.id,\n status=\"revoked\",\n )\n# #endregion revoke_api_key\n" + }, { "contract_id": "AssistantAdminRoutes", "contract_type": "Module", @@ -13972,6 +14147,632 @@ "tier_source": "AutoCalculated", "body": "# #region test_provider_config [C:4] [TYPE Function]\n# @BRIEF Test connection with a provided configuration (not yet saved).\n# @PRE: User is authenticated.\n# @POST: Returns success status and message.\n# @RELATION DEPENDS_ON -> [LLMClient]\n# @RELATION DEPENDS_ON -> [LLMProviderConfig]\n@router.post(\"/providers/test\")\nasync def test_provider_config(\n config: LLMProviderConfig, current_user: User = Depends(get_current_active_user)\n):\n \"\"\"\n Test connection with a provided configuration.\n \"\"\"\n from ...plugins.llm_analysis.service import LLMClient\n\n logger.reason(\n f\"Testing config for {config.name}\",\n extra={\"src\": \"llm_routes.test_provider_config\"},\n )\n\n # Check if API key is provided (reject empty, placeholder, or masked keys)\n if is_masked_or_placeholder(config.api_key):\n raise HTTPException(\n status_code=400, detail=\"API key is required for testing connection\"\n )\n\n client = LLMClient(\n provider_type=config.provider_type,\n api_key=config.api_key,\n base_url=config.base_url,\n default_model=config.default_model,\n )\n\n try:\n await client.test_runtime_connection()\n return {\"success\": True, \"message\": \"Connection successful\"}\n except Exception as e:\n return {\"success\": False, \"error\": str(e)}\n\n\n# #endregion test_provider_config\n" }, + { + "contract_id": "MaintenanceRoutesPackage", + "contract_type": "Package", + "file_path": "backend/src/api/routes/maintenance/__init__.py", + "start_line": 1, + "end_line": 10, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "LAYER": "API", + "PURPOSE": "Maintenance Banner API route package." + }, + "relations": [ + { + "source_id": "MaintenanceRoutesPackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceRouter", + "target_ref": "[MaintenanceRouter]" + }, + { + "source_id": "MaintenanceRoutesPackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceSchemasModule", + "target_ref": "[MaintenanceSchemasModule]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceRoutesPackage [C:1] [TYPE Package] [SEMANTICS maintenance, api, package]\n# @BRIEF Maintenance Banner API route package.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [MaintenanceRouter]\n# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule]\n\nfrom ._router import router as maintenance_router\n\n__all__ = [\"maintenance_router\"]\n# #endregion MaintenanceRoutesPackage\n" + }, + { + "contract_id": "MaintenanceRouter", + "contract_type": "Module", + "file_path": "backend/src/api/routes/maintenance/_router.py", + "start_line": 1, + "end_line": 14, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "API", + "PURPOSE": "FastAPI APIRouter for the Maintenance Banner endpoints." + }, + "relations": [ + { + "source_id": "MaintenanceRouter", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceRoutesModule", + "target_ref": "[MaintenanceRoutesModule]" + }, + { + "source_id": "MaintenanceRouter", + "relation_type": "DEPENDS_ON", + "target_id": "AppDependencies", + "target_ref": "[AppDependencies]" + }, + { + "source_id": "MaintenanceRouter", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceSchemasModule", + "target_ref": "[MaintenanceSchemasModule]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceRouter [C:3] [TYPE Module] [SEMANTICS fastapi, router, maintenance, api]\n# @BRIEF FastAPI APIRouter for the Maintenance Banner endpoints.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [MaintenanceRoutesModule]\n# @RELATION DEPENDS_ON -> [AppDependencies]\n# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule]\n\nfrom fastapi import APIRouter\n\nrouter = APIRouter(prefix=\"/api/maintenance\", tags=[\"Maintenance\"])\n\n# Import route handlers to register them with the router\nfrom . import _routes # noqa: F401, E402\n# #endregion MaintenanceRouter\n" + }, + { + "contract_id": "MaintenanceRoutesModule", + "contract_type": "Module", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 1, + "end_line": 592, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "INVARIANT": "RBAC enforced per FR-015 matrix via has_permission() dependency.", + "LAYER": "API", + "PURPOSE": "Route handler stubs for all 7 Maintenance Banner API endpoints with RBAC guards per FR-015." + }, + "relations": [ + { + "source_id": "MaintenanceRoutesModule", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceSchemasModule", + "target_ref": "[MaintenanceSchemasModule]" + }, + { + "source_id": "MaintenanceRoutesModule", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceRouter", + "target_ref": "[MaintenanceRouter]" + }, + { + "source_id": "MaintenanceRoutesModule", + "relation_type": "DEPENDS_ON", + "target_id": "AppDependencies", + "target_ref": "[AppDependencies]" + }, + { + "source_id": "MaintenanceRoutesModule", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceServiceModule", + "target_ref": "[MaintenanceServiceModule]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, routes, maintenance, api]\n# @BRIEF Route handler stubs for all 7 Maintenance Banner API endpoints with RBAC guards per FR-015.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [MaintenanceSchemasModule]\n# @RELATION DEPENDS_ON -> [MaintenanceRouter]\n# @RELATION DEPENDS_ON -> [AppDependencies]\n# @RELATION DEPENDS_ON -> [MaintenanceServiceModule]\n# @INVARIANT All mutation endpoints return 202 {task_id} per spec.\n# @INVARIANT RBAC enforced per FR-015 matrix via has_permission() dependency.\n\nfrom datetime import datetime, timezone\nfrom typing import Any, cast\n\nfrom fastapi import APIRouter, Depends, HTTPException, Request, status\nfrom sqlalchemy.orm import Session\n\nfrom ....core.logger import belief_scope, logger as app_logger\nfrom ....core.task_manager import TaskManager\n\napp_logger = cast(Any, app_logger)\nfrom ....dependencies import (\n check_api_key_environment_scope,\n get_db,\n get_task_manager,\n has_permission,\n require_api_key_or_jwt,\n)\nfrom ....models.api_key import APIKey\nfrom ....models.maintenance import (\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n MaintenanceDashboardState,\n MaintenanceDashboardStateStatus,\n MaintenanceEvent,\n MaintenanceEventStatus,\n MaintenanceSettings,\n)\nfrom ._router import router\nfrom ._schemas import (\n MaintenanceAlreadyActiveResponse,\n MaintenanceDashboardBannerState,\n MaintenanceEndResponse,\n MaintenanceEventItem,\n MaintenanceEventListResponse,\n MaintenanceSettingsResponse,\n MaintenanceSettingsUpdate,\n MaintenanceStartRequest,\n MaintenanceStartResponse,\n)\n\n\n# ── GET /api/maintenance/dashboard-banners ───────────────────\n# FR-015: viewer, operator, admin all have READ access\n\n# #region list_dashboard_banners [C:2] [TYPE Function]\n# @BRIEF Get per-dashboard banner state for the Dashboard Hub indicator.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/dashboard-banners\", response_model=list[MaintenanceDashboardBannerState])\nasync def list_dashboard_banners(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n):\n with belief_scope(\"list_dashboard_banners\"):\n # Query active banners with their linked active/pending states\n active_banners = (\n db.query(MaintenanceDashboardBanner)\n .filter(MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE)\n .all()\n )\n\n result: list[MaintenanceDashboardBannerState] = []\n for banner in active_banners:\n linked_states = (\n db.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.banner_id == banner.id,\n MaintenanceDashboardState.status.in_([\n MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardStateStatus.PENDING_APPLY,\n ]),\n )\n .all()\n )\n\n event_ids: list[str] = []\n start_times: list[str] = []\n end_times: list[str] = []\n\n for state in linked_states:\n event = (\n db.query(MaintenanceEvent)\n .filter(MaintenanceEvent.id == state.event_id)\n .first()\n )\n if event:\n event_ids.append(event.id)\n if event.start_time:\n start_times.append(event.start_time.isoformat())\n if event.end_time:\n end_times.append(event.end_time.isoformat())\n\n result.append(\n MaintenanceDashboardBannerState(\n dashboard_id=banner.dashboard_id,\n active=True,\n events=event_ids,\n start_time=min(start_times) if start_times else None,\n end_time=max(end_times) if end_times else None,\n )\n )\n\n return result\n# #endregion list_dashboard_banners\n\n\n# ── GET /api/maintenance/events ──────────────────────────────\n# FR-015: operator, admin (NOT viewer)\n\n# #region list_events [C:2] [TYPE Function]\n# @BRIEF Get active and completed maintenance event lists with affected dashboard counts.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/events\", response_model=MaintenanceEventListResponse)\nasync def list_events(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"list_events\"):\n # ── Auto-expiry: end events past their end_time ──\n now = datetime.now(timezone.utc)\n expired = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_([\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n MaintenanceEventStatus.ENDING,\n ]),\n MaintenanceEvent.end_time.isnot(None),\n MaintenanceEvent.end_time < now,\n )\n .all()\n )\n for ev in expired:\n app_logger.reason(\n \"Auto-ending expired maintenance event\",\n extra={\"event_id\": ev.id, \"end_time\": ev.end_time.isoformat()},\n )\n # Schedule proper cleanup via task manager (removes banner from dashboard)\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": ev.id,\n \"environment_id\": ev.environment_id,\n \"user\": \"system\",\n },\n )\n app_logger.reflect(\n \"Scheduled cleanup for expired event\",\n extra={\"event_id\": ev.id, \"task_id\": task.id},\n )\n\n # Active events: ACTIVE, PARTIAL (per spec T040)\n active_statuses = [\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n ]\n active_events = (\n db.query(MaintenanceEvent)\n .filter(MaintenanceEvent.status.in_(active_statuses))\n .order_by(MaintenanceEvent.created_at.desc())\n .all()\n )\n\n # Completed events: COMPLETED, FAILED\n completed_events = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_([\n MaintenanceEventStatus.COMPLETED,\n MaintenanceEventStatus.FAILED,\n ])\n )\n .order_by(MaintenanceEvent.created_at.desc())\n .limit(50)\n .all()\n )\n\n def _to_item(event: MaintenanceEvent) -> MaintenanceEventItem:\n affected_count = (\n db.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.event_id == event.id,\n MaintenanceDashboardState.status.in_([\n MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardStateStatus.PENDING_APPLY,\n ]),\n )\n .count()\n )\n return MaintenanceEventItem(\n id=event.id,\n tables=list(event.tables) if event.tables else [],\n start_time=event.start_time.isoformat() if event.start_time else \"\",\n end_time=event.end_time.isoformat() if event.end_time else None,\n message=event.message or None,\n status=event.status.value,\n affected_count=affected_count,\n created_at=event.created_at.isoformat() if event.created_at else \"\",\n )\n\n return MaintenanceEventListResponse(\n active=[_to_item(e) for e in active_events],\n completed=[_to_item(e) for e in completed_events],\n )\n# #endregion list_events\n\n\n# ── POST /api/maintenance/start ──────────────────────────────\n# FR-001: Always returns 202 {task_id} after validation\n# FR-015: operator, admin (NOT viewer)\n\n# #region start_maintenance [C:3] [TYPE Function]\n# @BRIEF Start a maintenance event. Validates input, creates event, dispatches TaskManager task.\n# Always returns 202 with task_id and maintenance_id.\n# Idempotency: same (tables, start_time, end_time) returns already_active (409-like but 200).\n# Tables sorted & lowered for idempotency key. Message NOT in key.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n# @RELATION DEPENDS_ON -> [TaskManager]\n@router.post(\n \"/start\",\n status_code=status.HTTP_202_ACCEPTED,\n responses={\n 202: {\"model\": MaintenanceStartResponse},\n 409: {\"model\": MaintenanceAlreadyActiveResponse},\n },\n)\nasync def start_maintenance(\n request: MaintenanceStartRequest,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:start\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"start_maintenance\"):\n # ── Validation ──\n\n # Validate end_time > start_time\n if request.end_time and request.start_time and request.end_time <= request.start_time:\n raise HTTPException(\n status_code=400,\n detail=\"end_time must be after start_time\",\n )\n\n # Validate times are within reasonable range (future ±1h grace period)\n now = datetime.now(timezone.utc)\n grace_threshold = 3600 # 1 hour in seconds\n if request.start_time:\n diff = (request.start_time - now).total_seconds() if request.start_time.tzinfo else \\\n (request.start_time.replace(tzinfo=timezone.utc) - now).total_seconds()\n if diff < -grace_threshold:\n raise HTTPException(\n status_code=400,\n detail=\"start_time is too far in the past (max 1h grace period)\",\n )\n\n # Validate tables list length\n if len(request.tables) > 100:\n raise HTTPException(\n status_code=400,\n detail=\"Maximum 100 tables allowed\",\n )\n\n # Sanitize message (HTML escape already done in rendering, but check for raw HTML)\n message = request.message\n if message:\n import html as _html\n sanitized = _html.escape(message)\n if sanitized != message:\n # Message contained HTML — accept it, it will be escaped at render time\n pass\n\n # ── Idempotency check ──\n from ....services.maintenance import build_idempotency_key\n\n sorted_tables = sorted(t.strip().lower() for t in request.tables if t.strip())\n idem_tables = frozenset(sorted_tables)\n idem_start = request.start_time.isoformat() if request.start_time else None\n idem_end = request.end_time.isoformat() if request.end_time else None\n\n # Find existing active event with same idempotency key\n active_statuses = [\n MaintenanceEventStatus.PENDING,\n MaintenanceEventStatus.APPLYING,\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n ]\n existing = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_(active_statuses),\n )\n .all()\n )\n for ev in existing:\n ev_tables = frozenset(\n sorted(t.lower() for t in (ev.tables or []) if t)\n )\n ev_start = ev.start_time.isoformat() if ev.start_time else None\n ev_end = ev.end_time.isoformat() if ev.end_time else None\n if ev_tables == idem_tables and ev_start == idem_start and ev_end == idem_end:\n # Same key → return already_active\n app_logger.reflect(\n \"Idempotency hit — event already active\",\n extra={\"existing_id\": ev.id},\n )\n return MaintenanceAlreadyActiveResponse(\n maintenance_id=ev.id,\n status=\"already_active\",\n )\n\n # ── Environment scoping ──\n env_id = request.environment_id\n\n # ── Create event ──\n event = MaintenanceEvent(\n tables=sorted_tables,\n start_time=request.start_time,\n end_time=request.end_time,\n message=message,\n status=MaintenanceEventStatus.PENDING,\n environment_id=env_id,\n )\n db.add(event)\n db.flush()\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"start\",\n \"event_id\": event.id,\n \"environment_id\": env_id,\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n event.task_id = task.id\n db.commit()\n\n app_logger.reflect(\n \"Maintenance start dispatched\",\n extra={\"event_id\": event.id, \"task_id\": task.id},\n )\n\n return MaintenanceStartResponse(\n task_id=task.id,\n maintenance_id=event.id,\n status=\"pending\",\n )\n# #endregion start_maintenance\n\n\n# ── POST /api/maintenance/{maintenance_id}/end ───────────────\n# FR-006: Remove banners for a specific maintenance event\n# FR-015: operator, admin (NOT viewer)\n\n# #region end_maintenance [C:3] [TYPE Function]\n# @BRIEF End a specific maintenance event by ID. Removes banners from affected dashboards.\n# Always returns 202 with task_id. Idempotent: already_completed returns success.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n@router.post(\n \"/{maintenance_id}/end\",\n status_code=status.HTTP_202_ACCEPTED,\n response_model=MaintenanceEndResponse,\n)\nasync def end_maintenance(\n maintenance_id: str,\n request: Request,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:end\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"end_maintenance\", f\"maintenance_id={maintenance_id}\"):\n # Check event exists\n event = db.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == maintenance_id\n ).first()\n\n if not event:\n raise HTTPException(\n status_code=404,\n detail=f\"Maintenance event {maintenance_id} not found\",\n )\n\n # Validate API key environment scope against event's environment\n if _auth.startswith(\"api_key:\"):\n await check_api_key_environment_scope(request, db, event.environment_id or \"\")\n\n # If already completed, return idempotent success\n if event.status == MaintenanceEventStatus.COMPLETED:\n app_logger.reflect(\n \"Event already completed, returning idempotent\",\n extra={\"event_id\": maintenance_id},\n )\n return MaintenanceEndResponse(\n task_id=event.task_id or \"\",\n status=\"already_completed\",\n )\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": maintenance_id,\n \"environment_id\": event.environment_id,\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n\n app_logger.reflect(\n \"Maintenance end dispatched\",\n extra={\"event_id\": maintenance_id, \"task_id\": task.id},\n )\n\n return MaintenanceEndResponse(\n task_id=task.id,\n status=\"pending\",\n )\n# #endregion end_maintenance\n\n\n# ── POST /api/maintenance/end-all ────────────────────────────\n# FR-007: Bulk removal of all active banners\n# FR-015: operator, admin (NOT viewer)\n\n# #region end_all_maintenance [C:3] [TYPE Function]\n# @BRIEF End all active maintenance events. Removes all banners from all dashboards.\n# Always returns 202 with task_id. Supports environment scoping for API keys.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n@router.post(\n \"/end-all\",\n status_code=status.HTTP_202_ACCEPTED,\n response_model=MaintenanceEndResponse,\n)\nasync def end_all_maintenance(\n request: Request,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:end_all\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"end_all_maintenance\"):\n # ── Resolve environment scope ──\n effective_env_id: str | None = None\n try:\n body = await request.json()\n effective_env_id = body.get(\"environment_id\")\n except Exception:\n pass\n\n # ── Enforce API key environment scoping ──\n if _auth.startswith(\"api_key:\"):\n # Auto-scope to the key's environment if not specified in body\n if not effective_env_id:\n raw_key = request.headers.get(\"X-API-Key\")\n if raw_key:\n from ....core.auth.api_key import hash_api_key\n key_hash = hash_api_key(raw_key)\n key_row = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if key_row and key_row.environment_id:\n effective_env_id = key_row.environment_id\n\n await check_api_key_environment_scope(request, db, effective_env_id or \"\")\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end_all\",\n \"environment_id\": effective_env_id or \"\",\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n\n app_logger.reflect(\n \"End-all maintenance dispatched\",\n extra={\"task_id\": task.id, \"environment_id\": effective_env_id},\n )\n\n return MaintenanceEndResponse(\n task_id=task.id,\n status=\"pending\",\n )\n# #endregion end_all_maintenance\n\n\n# ── GET /api/maintenance/settings ────────────────────────────\n# FR-009: Get maintenance settings configuration\n# FR-015: operator, admin (NOT viewer)\n\n# #region get_maintenance_settings [C:2] [TYPE Function]\n# @BRIEF Get current maintenance settings configuration.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/settings\", response_model=MaintenanceSettingsResponse)\nasync def get_maintenance_settings(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n):\n with belief_scope(\"get_maintenance_settings\"):\n settings = db.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n\n if not settings:\n raise HTTPException(\n status_code=404,\n detail=\"Maintenance settings not configured\",\n )\n\n return MaintenanceSettingsResponse(\n target_environment_id=settings.target_environment_id,\n display_timezone=settings.display_timezone,\n banner_template=settings.banner_template,\n dashboard_scope=settings.dashboard_scope.value,\n excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []),\n forced_dashboard_ids=list(settings.forced_dashboard_ids or []),\n updated_at=settings.updated_at.isoformat() if settings.updated_at else None,\n )\n# #endregion get_maintenance_settings\n\n\n# ── PUT /api/maintenance/settings ────────────────────────────\n# FR-009: Update maintenance settings configuration\n# FR-015: admin ONLY (NOT operator, NOT viewer)\n\n# #region update_maintenance_settings [C:2] [TYPE Function]\n# @BRIEF Update maintenance settings. All fields optional for partial update.\n# admin role required per FR-015.\n# @RELATION DEPENDS_ON -> [has_permission(\"admin:settings\", \"WRITE\")]\n@router.put(\"/settings\", response_model=MaintenanceSettingsResponse)\nasync def update_maintenance_settings(\n settings_data: MaintenanceSettingsUpdate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_maintenance_settings\"):\n settings = db.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n\n if not settings:\n # Auto-create with defaults on first save (upsert behavior).\n # Column-level defaults from the model apply for omitted fields.\n settings = MaintenanceSettings(\n id=\"default\",\n target_environment_id=settings_data.target_environment_id or \"\",\n )\n db.add(settings)\n db.flush()\n\n # Apply partial updates\n update_data = settings_data.model_dump(exclude_unset=True)\n\n if \"target_environment_id\" in update_data:\n settings.target_environment_id = update_data[\"target_environment_id\"]\n if \"display_timezone\" in update_data:\n settings.display_timezone = update_data[\"display_timezone\"]\n if \"banner_template\" in update_data:\n settings.banner_template = update_data[\"banner_template\"]\n if \"dashboard_scope\" in update_data:\n from ....models.maintenance import DashboardScope\n settings.dashboard_scope = DashboardScope(update_data[\"dashboard_scope\"])\n if \"excluded_dashboard_ids\" in update_data:\n settings.excluded_dashboard_ids = update_data[\"excluded_dashboard_ids\"]\n if \"forced_dashboard_ids\" in update_data:\n settings.forced_dashboard_ids = update_data[\"forced_dashboard_ids\"]\n\n db.commit()\n db.refresh(settings)\n\n return MaintenanceSettingsResponse(\n target_environment_id=settings.target_environment_id,\n display_timezone=settings.display_timezone,\n banner_template=settings.banner_template,\n dashboard_scope=settings.dashboard_scope.value,\n excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []),\n forced_dashboard_ids=list(settings.forced_dashboard_ids or []),\n updated_at=settings.updated_at.isoformat() if settings.updated_at else None,\n )\n# #endregion update_maintenance_settings\n\n# #endregion MaintenanceRoutesModule\n" + }, + { + "contract_id": "list_dashboard_banners", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 55, + "end_line": 113, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Get per-dashboard banner state for the Dashboard Hub indicator." + }, + "relations": [ + { + "source_id": "list_dashboard_banners", + "relation_type": "DEPENDS_ON", + "target_id": "has_permission(\"maintenance\", \"READ\")", + "target_ref": "[has_permission(\"maintenance\", \"READ\")]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region list_dashboard_banners [C:2] [TYPE Function]\n# @BRIEF Get per-dashboard banner state for the Dashboard Hub indicator.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/dashboard-banners\", response_model=list[MaintenanceDashboardBannerState])\nasync def list_dashboard_banners(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n):\n with belief_scope(\"list_dashboard_banners\"):\n # Query active banners with their linked active/pending states\n active_banners = (\n db.query(MaintenanceDashboardBanner)\n .filter(MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE)\n .all()\n )\n\n result: list[MaintenanceDashboardBannerState] = []\n for banner in active_banners:\n linked_states = (\n db.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.banner_id == banner.id,\n MaintenanceDashboardState.status.in_([\n MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardStateStatus.PENDING_APPLY,\n ]),\n )\n .all()\n )\n\n event_ids: list[str] = []\n start_times: list[str] = []\n end_times: list[str] = []\n\n for state in linked_states:\n event = (\n db.query(MaintenanceEvent)\n .filter(MaintenanceEvent.id == state.event_id)\n .first()\n )\n if event:\n event_ids.append(event.id)\n if event.start_time:\n start_times.append(event.start_time.isoformat())\n if event.end_time:\n end_times.append(event.end_time.isoformat())\n\n result.append(\n MaintenanceDashboardBannerState(\n dashboard_id=banner.dashboard_id,\n active=True,\n events=event_ids,\n start_time=min(start_times) if start_times else None,\n end_time=max(end_times) if end_times else None,\n )\n )\n\n return result\n# #endregion list_dashboard_banners\n" + }, + { + "contract_id": "list_events", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 119, + "end_line": 217, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Get active and completed maintenance event lists with affected dashboard counts." + }, + "relations": [ + { + "source_id": "list_events", + "relation_type": "DEPENDS_ON", + "target_id": "has_permission(\"maintenance\", \"READ\")", + "target_ref": "[has_permission(\"maintenance\", \"READ\")]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region list_events [C:2] [TYPE Function]\n# @BRIEF Get active and completed maintenance event lists with affected dashboard counts.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/events\", response_model=MaintenanceEventListResponse)\nasync def list_events(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"list_events\"):\n # ── Auto-expiry: end events past their end_time ──\n now = datetime.now(timezone.utc)\n expired = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_([\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n MaintenanceEventStatus.ENDING,\n ]),\n MaintenanceEvent.end_time.isnot(None),\n MaintenanceEvent.end_time < now,\n )\n .all()\n )\n for ev in expired:\n app_logger.reason(\n \"Auto-ending expired maintenance event\",\n extra={\"event_id\": ev.id, \"end_time\": ev.end_time.isoformat()},\n )\n # Schedule proper cleanup via task manager (removes banner from dashboard)\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": ev.id,\n \"environment_id\": ev.environment_id,\n \"user\": \"system\",\n },\n )\n app_logger.reflect(\n \"Scheduled cleanup for expired event\",\n extra={\"event_id\": ev.id, \"task_id\": task.id},\n )\n\n # Active events: ACTIVE, PARTIAL (per spec T040)\n active_statuses = [\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n ]\n active_events = (\n db.query(MaintenanceEvent)\n .filter(MaintenanceEvent.status.in_(active_statuses))\n .order_by(MaintenanceEvent.created_at.desc())\n .all()\n )\n\n # Completed events: COMPLETED, FAILED\n completed_events = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_([\n MaintenanceEventStatus.COMPLETED,\n MaintenanceEventStatus.FAILED,\n ])\n )\n .order_by(MaintenanceEvent.created_at.desc())\n .limit(50)\n .all()\n )\n\n def _to_item(event: MaintenanceEvent) -> MaintenanceEventItem:\n affected_count = (\n db.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.event_id == event.id,\n MaintenanceDashboardState.status.in_([\n MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardStateStatus.PENDING_APPLY,\n ]),\n )\n .count()\n )\n return MaintenanceEventItem(\n id=event.id,\n tables=list(event.tables) if event.tables else [],\n start_time=event.start_time.isoformat() if event.start_time else \"\",\n end_time=event.end_time.isoformat() if event.end_time else None,\n message=event.message or None,\n status=event.status.value,\n affected_count=affected_count,\n created_at=event.created_at.isoformat() if event.created_at else \"\",\n )\n\n return MaintenanceEventListResponse(\n active=[_to_item(e) for e in active_events],\n completed=[_to_item(e) for e in completed_events],\n )\n# #endregion list_events\n" + }, + { + "contract_id": "start_maintenance", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 224, + "end_line": 360, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Start a maintenance event. Validates input, creates event, dispatches TaskManager task." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region start_maintenance [C:3] [TYPE Function]\n# @BRIEF Start a maintenance event. Validates input, creates event, dispatches TaskManager task.\n# Always returns 202 with task_id and maintenance_id.\n# Idempotency: same (tables, start_time, end_time) returns already_active (409-like but 200).\n# Tables sorted & lowered for idempotency key. Message NOT in key.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n# @RELATION DEPENDS_ON -> [TaskManager]\n@router.post(\n \"/start\",\n status_code=status.HTTP_202_ACCEPTED,\n responses={\n 202: {\"model\": MaintenanceStartResponse},\n 409: {\"model\": MaintenanceAlreadyActiveResponse},\n },\n)\nasync def start_maintenance(\n request: MaintenanceStartRequest,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:start\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"start_maintenance\"):\n # ── Validation ──\n\n # Validate end_time > start_time\n if request.end_time and request.start_time and request.end_time <= request.start_time:\n raise HTTPException(\n status_code=400,\n detail=\"end_time must be after start_time\",\n )\n\n # Validate times are within reasonable range (future ±1h grace period)\n now = datetime.now(timezone.utc)\n grace_threshold = 3600 # 1 hour in seconds\n if request.start_time:\n diff = (request.start_time - now).total_seconds() if request.start_time.tzinfo else \\\n (request.start_time.replace(tzinfo=timezone.utc) - now).total_seconds()\n if diff < -grace_threshold:\n raise HTTPException(\n status_code=400,\n detail=\"start_time is too far in the past (max 1h grace period)\",\n )\n\n # Validate tables list length\n if len(request.tables) > 100:\n raise HTTPException(\n status_code=400,\n detail=\"Maximum 100 tables allowed\",\n )\n\n # Sanitize message (HTML escape already done in rendering, but check for raw HTML)\n message = request.message\n if message:\n import html as _html\n sanitized = _html.escape(message)\n if sanitized != message:\n # Message contained HTML — accept it, it will be escaped at render time\n pass\n\n # ── Idempotency check ──\n from ....services.maintenance import build_idempotency_key\n\n sorted_tables = sorted(t.strip().lower() for t in request.tables if t.strip())\n idem_tables = frozenset(sorted_tables)\n idem_start = request.start_time.isoformat() if request.start_time else None\n idem_end = request.end_time.isoformat() if request.end_time else None\n\n # Find existing active event with same idempotency key\n active_statuses = [\n MaintenanceEventStatus.PENDING,\n MaintenanceEventStatus.APPLYING,\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n ]\n existing = (\n db.query(MaintenanceEvent)\n .filter(\n MaintenanceEvent.status.in_(active_statuses),\n )\n .all()\n )\n for ev in existing:\n ev_tables = frozenset(\n sorted(t.lower() for t in (ev.tables or []) if t)\n )\n ev_start = ev.start_time.isoformat() if ev.start_time else None\n ev_end = ev.end_time.isoformat() if ev.end_time else None\n if ev_tables == idem_tables and ev_start == idem_start and ev_end == idem_end:\n # Same key → return already_active\n app_logger.reflect(\n \"Idempotency hit — event already active\",\n extra={\"existing_id\": ev.id},\n )\n return MaintenanceAlreadyActiveResponse(\n maintenance_id=ev.id,\n status=\"already_active\",\n )\n\n # ── Environment scoping ──\n env_id = request.environment_id\n\n # ── Create event ──\n event = MaintenanceEvent(\n tables=sorted_tables,\n start_time=request.start_time,\n end_time=request.end_time,\n message=message,\n status=MaintenanceEventStatus.PENDING,\n environment_id=env_id,\n )\n db.add(event)\n db.flush()\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"start\",\n \"event_id\": event.id,\n \"environment_id\": env_id,\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n event.task_id = task.id\n db.commit()\n\n app_logger.reflect(\n \"Maintenance start dispatched\",\n extra={\"event_id\": event.id, \"task_id\": task.id},\n )\n\n return MaintenanceStartResponse(\n task_id=task.id,\n maintenance_id=event.id,\n status=\"pending\",\n )\n# #endregion start_maintenance\n" + }, + { + "contract_id": "end_maintenance", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 367, + "end_line": 430, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "End a specific maintenance event by ID. Removes banners from affected dashboards." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region end_maintenance [C:3] [TYPE Function]\n# @BRIEF End a specific maintenance event by ID. Removes banners from affected dashboards.\n# Always returns 202 with task_id. Idempotent: already_completed returns success.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n@router.post(\n \"/{maintenance_id}/end\",\n status_code=status.HTTP_202_ACCEPTED,\n response_model=MaintenanceEndResponse,\n)\nasync def end_maintenance(\n maintenance_id: str,\n request: Request,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:end\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"end_maintenance\", f\"maintenance_id={maintenance_id}\"):\n # Check event exists\n event = db.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == maintenance_id\n ).first()\n\n if not event:\n raise HTTPException(\n status_code=404,\n detail=f\"Maintenance event {maintenance_id} not found\",\n )\n\n # Validate API key environment scope against event's environment\n if _auth.startswith(\"api_key:\"):\n await check_api_key_environment_scope(request, db, event.environment_id or \"\")\n\n # If already completed, return idempotent success\n if event.status == MaintenanceEventStatus.COMPLETED:\n app_logger.reflect(\n \"Event already completed, returning idempotent\",\n extra={\"event_id\": maintenance_id},\n )\n return MaintenanceEndResponse(\n task_id=event.task_id or \"\",\n status=\"already_completed\",\n )\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": maintenance_id,\n \"environment_id\": event.environment_id,\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n\n app_logger.reflect(\n \"Maintenance end dispatched\",\n extra={\"event_id\": maintenance_id, \"task_id\": task.id},\n )\n\n return MaintenanceEndResponse(\n task_id=task.id,\n status=\"pending\",\n )\n# #endregion end_maintenance\n" + }, + { + "contract_id": "end_all_maintenance", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 437, + "end_line": 494, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "End all active maintenance events. Removes all banners from all dashboards." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region end_all_maintenance [C:3] [TYPE Function]\n# @BRIEF End all active maintenance events. Removes all banners from all dashboards.\n# Always returns 202 with task_id. Supports environment scoping for API keys.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"WRITE\")]\n@router.post(\n \"/end-all\",\n status_code=status.HTTP_202_ACCEPTED,\n response_model=MaintenanceEndResponse,\n)\nasync def end_all_maintenance(\n request: Request,\n db: Session = Depends(get_db),\n _auth=Depends(require_api_key_or_jwt(\"maintenance:end_all\", \"maintenance\", \"WRITE\")),\n task_manager: TaskManager = Depends(get_task_manager),\n):\n with belief_scope(\"end_all_maintenance\"):\n # ── Resolve environment scope ──\n effective_env_id: str | None = None\n try:\n body = await request.json()\n effective_env_id = body.get(\"environment_id\")\n except Exception:\n pass\n\n # ── Enforce API key environment scoping ──\n if _auth.startswith(\"api_key:\"):\n # Auto-scope to the key's environment if not specified in body\n if not effective_env_id:\n raw_key = request.headers.get(\"X-API-Key\")\n if raw_key:\n from ....core.auth.api_key import hash_api_key\n key_hash = hash_api_key(raw_key)\n key_row = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if key_row and key_row.environment_id:\n effective_env_id = key_row.environment_id\n\n await check_api_key_environment_scope(request, db, effective_env_id or \"\")\n\n # ── Dispatch TaskManager task ──\n task = await task_manager.create_task(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end_all\",\n \"environment_id\": effective_env_id or \"\",\n \"user\": _auth.split(\":\", 1)[1] if \":\" in _auth else _auth,\n },\n )\n\n app_logger.reflect(\n \"End-all maintenance dispatched\",\n extra={\"task_id\": task.id, \"environment_id\": effective_env_id},\n )\n\n return MaintenanceEndResponse(\n task_id=task.id,\n status=\"pending\",\n )\n# #endregion end_all_maintenance\n" + }, + { + "contract_id": "get_maintenance_settings", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 501, + "end_line": 529, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Get current maintenance settings configuration." + }, + "relations": [ + { + "source_id": "get_maintenance_settings", + "relation_type": "DEPENDS_ON", + "target_id": "has_permission(\"maintenance\", \"READ\")", + "target_ref": "[has_permission(\"maintenance\", \"READ\")]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region get_maintenance_settings [C:2] [TYPE Function]\n# @BRIEF Get current maintenance settings configuration.\n# @RELATION DEPENDS_ON -> [has_permission(\"maintenance\", \"READ\")]\n@router.get(\"/settings\", response_model=MaintenanceSettingsResponse)\nasync def get_maintenance_settings(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"maintenance\", \"READ\")),\n):\n with belief_scope(\"get_maintenance_settings\"):\n settings = db.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n\n if not settings:\n raise HTTPException(\n status_code=404,\n detail=\"Maintenance settings not configured\",\n )\n\n return MaintenanceSettingsResponse(\n target_environment_id=settings.target_environment_id,\n display_timezone=settings.display_timezone,\n banner_template=settings.banner_template,\n dashboard_scope=settings.dashboard_scope.value,\n excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []),\n forced_dashboard_ids=list(settings.forced_dashboard_ids or []),\n updated_at=settings.updated_at.isoformat() if settings.updated_at else None,\n )\n# #endregion get_maintenance_settings\n" + }, + { + "contract_id": "update_maintenance_settings", + "contract_type": "Function", + "file_path": "backend/src/api/routes/maintenance/_routes.py", + "start_line": 536, + "end_line": 590, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Update maintenance settings. All fields optional for partial update." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region update_maintenance_settings [C:2] [TYPE Function]\n# @BRIEF Update maintenance settings. All fields optional for partial update.\n# admin role required per FR-015.\n# @RELATION DEPENDS_ON -> [has_permission(\"admin:settings\", \"WRITE\")]\n@router.put(\"/settings\", response_model=MaintenanceSettingsResponse)\nasync def update_maintenance_settings(\n settings_data: MaintenanceSettingsUpdate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_maintenance_settings\"):\n settings = db.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n\n if not settings:\n # Auto-create with defaults on first save (upsert behavior).\n # Column-level defaults from the model apply for omitted fields.\n settings = MaintenanceSettings(\n id=\"default\",\n target_environment_id=settings_data.target_environment_id or \"\",\n )\n db.add(settings)\n db.flush()\n\n # Apply partial updates\n update_data = settings_data.model_dump(exclude_unset=True)\n\n if \"target_environment_id\" in update_data:\n settings.target_environment_id = update_data[\"target_environment_id\"]\n if \"display_timezone\" in update_data:\n settings.display_timezone = update_data[\"display_timezone\"]\n if \"banner_template\" in update_data:\n settings.banner_template = update_data[\"banner_template\"]\n if \"dashboard_scope\" in update_data:\n from ....models.maintenance import DashboardScope\n settings.dashboard_scope = DashboardScope(update_data[\"dashboard_scope\"])\n if \"excluded_dashboard_ids\" in update_data:\n settings.excluded_dashboard_ids = update_data[\"excluded_dashboard_ids\"]\n if \"forced_dashboard_ids\" in update_data:\n settings.forced_dashboard_ids = update_data[\"forced_dashboard_ids\"]\n\n db.commit()\n db.refresh(settings)\n\n return MaintenanceSettingsResponse(\n target_environment_id=settings.target_environment_id,\n display_timezone=settings.display_timezone,\n banner_template=settings.banner_template,\n dashboard_scope=settings.dashboard_scope.value,\n excluded_dashboard_ids=list(settings.excluded_dashboard_ids or []),\n forced_dashboard_ids=list(settings.forced_dashboard_ids or []),\n updated_at=settings.updated_at.isoformat() if settings.updated_at else None,\n )\n# #endregion update_maintenance_settings\n" + }, + { + "contract_id": "MaintenanceSchemasModule", + "contract_type": "Module", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 1, + "end_line": 157, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "INVARIANT": "All response schemas use the standard envelope shape: { status, data, error, meta }", + "LAYER": "API", + "PURPOSE": "Pydantic models for Maintenance Banner API: request/response schemas per data-model.md." + }, + "relations": [ + { + "source_id": "MaintenanceSchemasModule", + "relation_type": "DEPENDS_ON", + "target_id": "Pydantic", + "target_ref": "[Pydantic]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceSchemasModule [C:2] [TYPE Module] [SEMANTICS pydantic, schema, maintenance, request, response]\n# @BRIEF Pydantic models for Maintenance Banner API: request/response schemas per data-model.md.\n# @LAYER API\n# @RELATION DEPENDS_ON -> [Pydantic]\n# @INVARIANT All response schemas use the standard envelope shape: { status, data, error, meta }\n\nfrom datetime import datetime\n\nfrom pydantic import BaseModel, Field\n\n\n# ── Request Schemas ──────────────────────────────────────────\n\n# #region MaintenanceStartRequest [C:1] [TYPE Class]\n# @BRIEF POST /api/maintenance/start request body with environment scoping.\nclass MaintenanceStartRequest(BaseModel):\n tables: list[str] = Field(..., min_length=1, max_length=100)\n start_time: datetime\n end_time: datetime | None = None\n message: str | None = Field(None, max_length=500)\n environment_id: str = Field(..., description=\"Target environment for the maintenance operation\")\n# #endregion MaintenanceStartRequest\n\n\n# #region MaintenanceSettingsUpdate [C:1] [TYPE Class]\n# @BRIEF PUT /api/maintenance/settings request body — all fields optional for partial update.\nclass MaintenanceSettingsUpdate(BaseModel):\n target_environment_id: str | None = None\n display_timezone: str | None = None\n banner_template: str | None = None\n dashboard_scope: str | None = None\n excluded_dashboard_ids: list[int] | None = None\n forced_dashboard_ids: list[int] | None = None\n# #endregion MaintenanceSettingsUpdate\n\n\n# ── Response Schemas ─────────────────────────────────────────\n\n# #region MaintenanceStartResponse [C:1] [TYPE Class]\n# @BRIEF Response for /api/maintenance/start — always 202 with task_id.\nclass MaintenanceStartResponse(BaseModel):\n task_id: str\n maintenance_id: str\n status: str # \"pending\"\n# #endregion MaintenanceStartResponse\n\n\n# #region MaintenanceDashboardResult [C:1] [TYPE Class]\n# @BRIEF Describes a single dashboard affected by a maintenance operation.\nclass MaintenanceDashboardResult(BaseModel):\n id: int\n title: str\n chart_id: int | None = None\n# #endregion MaintenanceDashboardResult\n\n\n# #region MaintenanceFailedDashboard [C:1] [TYPE Class]\n# @BRIEF Describes a dashboard that failed during banner apply/removal.\nclass MaintenanceFailedDashboard(BaseModel):\n id: int\n title: str\n error: str\n# #endregion MaintenanceFailedDashboard\n\n\n# #region MaintenanceTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed maintenance start task.\nclass MaintenanceTaskResult(BaseModel):\n maintenance_id: str\n status: str # \"active\" | \"partial\" | \"completed\" | \"no_match\"\n affected_dashboards: int = 0\n dashboards: list[MaintenanceDashboardResult] = []\n failed_dashboards: list[MaintenanceFailedDashboard] = []\n unmatched_tables: list[str] = []\n# #endregion MaintenanceTaskResult\n\n\n# #region MaintenanceEndResponse [C:1] [TYPE Class]\n# @BRIEF Response for /api/maintenance/{id}/end and /api/maintenance/end-all — always 202 with task_id.\nclass MaintenanceEndResponse(BaseModel):\n task_id: str\n status: str # \"pending\"\n# #endregion MaintenanceEndResponse\n\n\n# #region MaintenanceEndTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed end maintenance task.\nclass MaintenanceEndTaskResult(BaseModel):\n maintenance_id: str\n removed_from: int = 0\n failed_removals: list[MaintenanceFailedDashboard] = []\n# #endregion MaintenanceEndTaskResult\n\n\n# #region MaintenanceEndAllTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed end-all maintenance task.\nclass MaintenanceEndAllTaskResult(BaseModel):\n closed_events: int = 0\n removed_from: int = 0\n failed_removals: list[MaintenanceFailedDashboard] = []\n# #endregion MaintenanceEndAllTaskResult\n\n\n# #region MaintenanceSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response for GET /api/maintenance/settings.\nclass MaintenanceSettingsResponse(BaseModel):\n target_environment_id: str\n display_timezone: str\n banner_template: str\n dashboard_scope: str\n excluded_dashboard_ids: list[int]\n forced_dashboard_ids: list[int]\n updated_at: str | None = None\n# #endregion MaintenanceSettingsResponse\n\n\n# #region MaintenanceEventItem [C:1] [TYPE Class]\n# @BRIEF Single maintenance event summary for GET /api/maintenance/events.\nclass MaintenanceEventItem(BaseModel):\n id: str\n tables: list[str]\n start_time: str\n end_time: str | None = None\n message: str | None = None\n status: str\n affected_count: int\n created_at: str\n# #endregion MaintenanceEventItem\n\n\n# #region MaintenanceEventListResponse [C:1] [TYPE Class]\n# @BRIEF Response for GET /api/maintenance/events.\nclass MaintenanceEventListResponse(BaseModel):\n active: list[MaintenanceEventItem]\n completed: list[MaintenanceEventItem]\n# #endregion MaintenanceEventListResponse\n\n\n# #region MaintenanceDashboardBannerState [C:1] [TYPE Class]\n# @BRIEF Per-dashboard banner state for GET /api/maintenance/dashboard-banners.\nclass MaintenanceDashboardBannerState(BaseModel):\n dashboard_id: int\n active: bool\n events: list[str]\n start_time: str | None = None\n end_time: str | None = None\n# #endregion MaintenanceDashboardBannerState\n\n\n# #region MaintenanceAlreadyActiveResponse [C:1] [TYPE Class]\n# @BRIEF Response for duplicate /start call — idempotency hit.\nclass MaintenanceAlreadyActiveResponse(BaseModel):\n maintenance_id: str\n status: str = \"already_active\"\n# #endregion MaintenanceAlreadyActiveResponse\n\n# #endregion MaintenanceSchemasModule\n" + }, + { + "contract_id": "MaintenanceStartRequest", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 14, + "end_line": 22, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "POST /api/maintenance/start request body with environment scoping." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceStartRequest [C:1] [TYPE Class]\n# @BRIEF POST /api/maintenance/start request body with environment scoping.\nclass MaintenanceStartRequest(BaseModel):\n tables: list[str] = Field(..., min_length=1, max_length=100)\n start_time: datetime\n end_time: datetime | None = None\n message: str | None = Field(None, max_length=500)\n environment_id: str = Field(..., description=\"Target environment for the maintenance operation\")\n# #endregion MaintenanceStartRequest\n" + }, + { + "contract_id": "MaintenanceSettingsUpdate", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 25, + "end_line": 34, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "PUT /api/maintenance/settings request body — all fields optional for partial update." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceSettingsUpdate [C:1] [TYPE Class]\n# @BRIEF PUT /api/maintenance/settings request body — all fields optional for partial update.\nclass MaintenanceSettingsUpdate(BaseModel):\n target_environment_id: str | None = None\n display_timezone: str | None = None\n banner_template: str | None = None\n dashboard_scope: str | None = None\n excluded_dashboard_ids: list[int] | None = None\n forced_dashboard_ids: list[int] | None = None\n# #endregion MaintenanceSettingsUpdate\n" + }, + { + "contract_id": "MaintenanceStartResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 39, + "end_line": 45, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Response for /api/maintenance/start — always 202 with task_id." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceStartResponse [C:1] [TYPE Class]\n# @BRIEF Response for /api/maintenance/start — always 202 with task_id.\nclass MaintenanceStartResponse(BaseModel):\n task_id: str\n maintenance_id: str\n status: str # \"pending\"\n# #endregion MaintenanceStartResponse\n" + }, + { + "contract_id": "MaintenanceDashboardResult", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 48, + "end_line": 54, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Describes a single dashboard affected by a maintenance operation." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardResult [C:1] [TYPE Class]\n# @BRIEF Describes a single dashboard affected by a maintenance operation.\nclass MaintenanceDashboardResult(BaseModel):\n id: int\n title: str\n chart_id: int | None = None\n# #endregion MaintenanceDashboardResult\n" + }, + { + "contract_id": "MaintenanceFailedDashboard", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 57, + "end_line": 63, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Describes a dashboard that failed during banner apply/removal." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceFailedDashboard [C:1] [TYPE Class]\n# @BRIEF Describes a dashboard that failed during banner apply/removal.\nclass MaintenanceFailedDashboard(BaseModel):\n id: int\n title: str\n error: str\n# #endregion MaintenanceFailedDashboard\n" + }, + { + "contract_id": "MaintenanceTaskResult", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 66, + "end_line": 75, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Result payload for a completed maintenance start task." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed maintenance start task.\nclass MaintenanceTaskResult(BaseModel):\n maintenance_id: str\n status: str # \"active\" | \"partial\" | \"completed\" | \"no_match\"\n affected_dashboards: int = 0\n dashboards: list[MaintenanceDashboardResult] = []\n failed_dashboards: list[MaintenanceFailedDashboard] = []\n unmatched_tables: list[str] = []\n# #endregion MaintenanceTaskResult\n" + }, + { + "contract_id": "MaintenanceEndResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 78, + "end_line": 83, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Response for /api/maintenance/{id}/end and /api/maintenance/end-all — always 202 with task_id." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEndResponse [C:1] [TYPE Class]\n# @BRIEF Response for /api/maintenance/{id}/end and /api/maintenance/end-all — always 202 with task_id.\nclass MaintenanceEndResponse(BaseModel):\n task_id: str\n status: str # \"pending\"\n# #endregion MaintenanceEndResponse\n" + }, + { + "contract_id": "MaintenanceEndTaskResult", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 86, + "end_line": 92, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Result payload for a completed end maintenance task." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEndTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed end maintenance task.\nclass MaintenanceEndTaskResult(BaseModel):\n maintenance_id: str\n removed_from: int = 0\n failed_removals: list[MaintenanceFailedDashboard] = []\n# #endregion MaintenanceEndTaskResult\n" + }, + { + "contract_id": "MaintenanceEndAllTaskResult", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 95, + "end_line": 101, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Result payload for a completed end-all maintenance task." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEndAllTaskResult [C:1] [TYPE Class]\n# @BRIEF Result payload for a completed end-all maintenance task.\nclass MaintenanceEndAllTaskResult(BaseModel):\n closed_events: int = 0\n removed_from: int = 0\n failed_removals: list[MaintenanceFailedDashboard] = []\n# #endregion MaintenanceEndAllTaskResult\n" + }, + { + "contract_id": "MaintenanceSettingsResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 104, + "end_line": 114, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Response for GET /api/maintenance/settings." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response for GET /api/maintenance/settings.\nclass MaintenanceSettingsResponse(BaseModel):\n target_environment_id: str\n display_timezone: str\n banner_template: str\n dashboard_scope: str\n excluded_dashboard_ids: list[int]\n forced_dashboard_ids: list[int]\n updated_at: str | None = None\n# #endregion MaintenanceSettingsResponse\n" + }, + { + "contract_id": "MaintenanceEventItem", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 117, + "end_line": 128, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Single maintenance event summary for GET /api/maintenance/events." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEventItem [C:1] [TYPE Class]\n# @BRIEF Single maintenance event summary for GET /api/maintenance/events.\nclass MaintenanceEventItem(BaseModel):\n id: str\n tables: list[str]\n start_time: str\n end_time: str | None = None\n message: str | None = None\n status: str\n affected_count: int\n created_at: str\n# #endregion MaintenanceEventItem\n" + }, + { + "contract_id": "MaintenanceEventListResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 131, + "end_line": 136, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Response for GET /api/maintenance/events." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEventListResponse [C:1] [TYPE Class]\n# @BRIEF Response for GET /api/maintenance/events.\nclass MaintenanceEventListResponse(BaseModel):\n active: list[MaintenanceEventItem]\n completed: list[MaintenanceEventItem]\n# #endregion MaintenanceEventListResponse\n" + }, + { + "contract_id": "MaintenanceDashboardBannerState", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 139, + "end_line": 147, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Per-dashboard banner state for GET /api/maintenance/dashboard-banners." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardBannerState [C:1] [TYPE Class]\n# @BRIEF Per-dashboard banner state for GET /api/maintenance/dashboard-banners.\nclass MaintenanceDashboardBannerState(BaseModel):\n dashboard_id: int\n active: bool\n events: list[str]\n start_time: str | None = None\n end_time: str | None = None\n# #endregion MaintenanceDashboardBannerState\n" + }, + { + "contract_id": "MaintenanceAlreadyActiveResponse", + "contract_type": "Class", + "file_path": "backend/src/api/routes/maintenance/_schemas.py", + "start_line": 150, + "end_line": 155, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Response for duplicate /start call — idempotency hit." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceAlreadyActiveResponse [C:1] [TYPE Class]\n# @BRIEF Response for duplicate /start call — idempotency hit.\nclass MaintenanceAlreadyActiveResponse(BaseModel):\n maintenance_id: str\n status: str = \"already_active\"\n# #endregion MaintenanceAlreadyActiveResponse\n" + }, { "contract_id": "MappingsApi", "contract_type": "Module", @@ -14822,7 +15623,7 @@ "contract_type": "Module", "file_path": "backend/src/api/routes/settings.py", "start_line": 1, - "end_line": 649, + "end_line": 661, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -14859,7 +15660,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SettingsRouter [C:5] [TYPE Module] [SEMANTICS fastapi, api, superset, logging-config-response]\n#\n# @BRIEF Provides API endpoints for managing application settings and Superset environments.\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [get_config_manager]\n# @RELATION DEPENDS_ON -> [has_permission]\n#\n# @PRE ConfigManager is initialized and accessible.\n# @POST Settings are read or written via ConfigManager.\n# @SIDE_EFFECT Persists config changes to disk via ConfigManager.\n# @DATA_CONTRACT Input -> ConfigUpdateRequest, Output -> AppConfig, LoggingConfigResponse\n# @INVARIANT: All settings changes must be persisted via ConfigManager.\n# @PUBLIC_API: router\n\n\nfrom fastapi import APIRouter, Depends, HTTPException\nfrom pydantic import BaseModel\nfrom sqlalchemy.orm import Session\n\nfrom ...core.config_manager import ConfigManager\nfrom ...core.config_models import AppConfig, Environment, GlobalSettings, LoggingConfig\nfrom ...core.database import get_db\nfrom ...core.logger import belief_scope, logger\nfrom ...core.superset_client import SupersetClient\nfrom ...dependencies import get_config_manager, has_permission\nfrom ...models.config import AppConfigRecord\nfrom ...models.llm import ValidationPolicy\nfrom ...models.storage import StorageConfig\nfrom ...models.translate import TranslationJob, TranslationSchedule\nfrom ...schemas.settings import (\n TranslationScheduleItem,\n ValidationPolicyCreate,\n ValidationPolicyResponse,\n ValidationPolicyUpdate,\n)\nfrom ...services.llm_prompt_templates import normalize_llm_settings\n\n\n# #region LoggingConfigResponse [C:1] [TYPE Class] [SEMANTICS logging, config, response]\n# @BRIEF Response model for logging configuration with current task log level.\nclass LoggingConfigResponse(BaseModel):\n level: str\n task_log_level: str\n enable_belief_state: bool\n\n\n# #endregion LoggingConfigResponse\n\nrouter = APIRouter()\n\n\n# #region _normalize_superset_env_url [C:1] [TYPE Function]\n# @BRIEF Canonicalize Superset environment URL to base host/path without trailing /api/v1.\n# Auto-prepends https:// if no scheme is present.\n# @PRE: raw_url can be empty.\n# @POST: Returns normalized base URL with scheme.\ndef _normalize_superset_env_url(raw_url: str) -> str:\n normalized = str(raw_url or \"\").strip().rstrip(\"/\")\n if normalized.lower().endswith(\"/api/v1\"):\n normalized = normalized[: -len(\"/api/v1\")]\n normalized = normalized.rstrip(\"/\")\n # Auto-prepend https:// if no scheme is present\n if normalized and not normalized.startswith(\"http://\") and not normalized.startswith(\"https://\"):\n normalized = f\"https://{normalized}\"\n return normalized\n\n\n# #endregion _normalize_superset_env_url\n\n\n# #region _validate_superset_connection_fast [C:2] [TYPE Function]\n# @BRIEF Run lightweight Superset connectivity validation without full pagination scan.\n# @PRE: env contains valid URL and credentials.\n# @POST: Raises on auth/API failures; returns None on success.\ndef _validate_superset_connection_fast(env: Environment) -> None:\n client = SupersetClient(env)\n # 1) Explicit auth check\n client.authenticate()\n # 2) Single lightweight API call to ensure read access\n client.get_dashboards_page(\n query={\n \"page\": 0,\n \"page_size\": 1,\n \"columns\": [\"id\"],\n }\n )\n\n\n# #endregion _validate_superset_connection_fast\n\n\n# #region get_settings [C:2] [TYPE Function]\n# @BRIEF Retrieves all application settings.\n# @PRE: Config manager is available.\n# @POST: Returns masked AppConfig.\n@router.get(\"\", response_model=AppConfig)\nasync def get_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_settings\"):\n logger.reason(\"Fetching all settings\", extra={\"src\": \"get_settings\"})\n config = config_manager.get_config().copy(deep=True)\n config.settings.llm = normalize_llm_settings(config.settings.llm)\n # Mask passwords\n for env in config.environments:\n if env.password:\n env.password = \"********\"\n return config\n\n\n# #endregion get_settings\n\n\n# #region get_features [C:1] [TYPE Function]\n# @BRIEF Public endpoint returning feature flags for frontend sidebar filtering.\n# @RATIONALE: Unauthenticated because sidebar filtering must work for all users, not just admins.\n# @PRE: Config manager is available.\n# @POST: Returns dict with dataset_review and health_monitor booleans.\n@router.get(\"/features\")\nasync def get_features(\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n return config_manager.get_config().settings.features.model_dump()\n\n\n# #endregion get_features\n\n\n# #region update_global_settings [C:2] [TYPE Function]\n# @BRIEF Updates global application settings.\n# @PRE: New settings are provided.\n# @POST: Global settings are updated.\n@router.patch(\"/global\", response_model=GlobalSettings)\nasync def update_global_settings(\n settings: GlobalSettings,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_global_settings\"):\n logger.reason(\"Updating global settings\", extra={\"src\": \"update_global_settings\"})\n\n config_manager.update_global_settings(settings)\n return settings\n\n\n# #endregion update_global_settings\n\n\n# #region get_storage_settings [C:2] [TYPE Function]\n# @BRIEF Retrieves storage-specific settings.\n@router.get(\"/storage\", response_model=StorageConfig)\nasync def get_storage_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_storage_settings\"):\n return config_manager.get_config().settings.storage\n\n\n# #endregion get_storage_settings\n\n\n# #region update_storage_settings [C:2] [TYPE Function]\n# @BRIEF Updates storage-specific settings.\n# @POST: Storage settings are updated and saved.\n@router.put(\"/storage\", response_model=StorageConfig)\nasync def update_storage_settings(\n storage: StorageConfig,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_storage_settings\"):\n is_valid, message = config_manager.validate_path(storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n\n settings = config_manager.get_config().settings\n settings.storage = storage\n config_manager.update_global_settings(settings)\n return config_manager.get_config().settings.storage\n\n\n# #endregion update_storage_settings\n\n\n# #region get_environments [C:2] [TYPE Function]\n# @BRIEF Lists all configured Superset environments.\n# @PRE: Config manager is available.\n# @POST: Returns list of environments.\n@router.get(\"/environments\", response_model=list[Environment])\nasync def get_environments(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_environments\"):\n logger.reason(\"Fetching environments\", extra={\"src\": \"get_environments\"})\n environments = config_manager.get_environments()\n return [\n env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n for env in environments\n ]\n\n\n# #endregion get_environments\n\n\n# #region add_environment [C:2] [TYPE Function]\n# @BRIEF Adds a new Superset environment.\n# @PRE: Environment data is valid and reachable.\n# @POST: Environment is added to config.\n@router.post(\"/environments\", response_model=Environment)\nasync def add_environment(\n env: Environment,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"add_environment\"):\n logger.reason(f\"Adding environment {env.id}\", extra={\"src\": \"add_environment\"})\n env = env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n\n # Validate connection before adding (fast path)\n try:\n _validate_superset_connection_fast(env)\n except Exception as e:\n logger.error(\n f\"[add_environment][Coherence:Failed] Connection validation failed: {e}\"\n )\n raise HTTPException(\n status_code=400, detail=f\"Connection validation failed: {e}\"\n )\n\n config_manager.add_environment(env)\n return env\n\n\n# #endregion add_environment\n\n\n# #region update_environment [C:2] [TYPE Function]\n# @BRIEF Updates an existing Superset environment.\n# @PRE: ID and valid environment data are provided.\n# @POST: Environment is updated in config.\n@router.put(\"/environments/{id}\", response_model=Environment)\nasync def update_environment(\n id: str,\n env: Environment,\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n with belief_scope(\"update_environment\"):\n logger.reason(f\"Updating environment {id}\", extra={\"src\": \"update_environment\"})\n\n env = env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n\n # If password is masked, we need the real one for validation\n env_to_validate = env.copy(deep=True)\n if env_to_validate.password == \"********\":\n old_env = next(\n (e for e in config_manager.get_environments() if e.id == id), None\n )\n if old_env:\n env_to_validate.password = old_env.password\n\n # Validate connection before updating (fast path)\n try:\n _validate_superset_connection_fast(env_to_validate)\n except Exception as e:\n logger.error(\n f\"[update_environment][Coherence:Failed] Connection validation failed: {e}\"\n )\n raise HTTPException(\n status_code=400, detail=f\"Connection validation failed: {e}\"\n )\n\n if config_manager.update_environment(id, env):\n return env\n raise HTTPException(status_code=404, detail=f\"Environment {id} not found\")\n\n\n# #endregion update_environment\n\n\n# #region delete_environment [C:2] [TYPE Function]\n# @BRIEF Deletes a Superset environment.\n# @PRE: ID is provided.\n# @POST: Environment is removed from config.\n@router.delete(\"/environments/{id}\")\nasync def delete_environment(\n id: str, config_manager: ConfigManager = Depends(get_config_manager)\n):\n with belief_scope(\"delete_environment\"):\n logger.reason(f\"Deleting environment {id}\", extra={\"src\": \"delete_environment\"})\n config_manager.delete_environment(id)\n return {\"message\": f\"Environment {id} deleted\"}\n\n\n# #endregion delete_environment\n\n\n# #region test_environment_connection [C:2] [TYPE Function]\n# @BRIEF Tests the connection to a Superset environment.\n# @PRE: ID is provided.\n# @POST: Returns success or error status.\n@router.post(\"/environments/{id}/test\")\nasync def test_environment_connection(\n id: str, config_manager: ConfigManager = Depends(get_config_manager)\n):\n with belief_scope(\"test_environment_connection\"):\n logger.reason(f\"Testing environment {id}\", extra={\"src\": \"test_environment_connection\"})\n\n # Find environment\n env = next((e for e in config_manager.get_environments() if e.id == id), None)\n if not env:\n raise HTTPException(status_code=404, detail=f\"Environment {id} not found\")\n\n try:\n _validate_superset_connection_fast(env)\n\n logger.info(\n f\"[test_environment_connection][Coherence:OK] Connection successful for {id}\"\n )\n return {\"status\": \"success\", \"message\": \"Connection successful\"}\n except Exception as e:\n logger.error(\n f\"[test_environment_connection][Coherence:Failed] Connection failed for {id}: {e}\"\n )\n return {\"status\": \"error\", \"message\": str(e)}\n\n\n# #endregion test_environment_connection\n\n\n# #region get_logging_config [C:2] [TYPE Function]\n# @BRIEF Retrieves current logging configuration.\n# @PRE: Config manager is available.\n# @POST: Returns logging configuration.\n@router.get(\"/logging\", response_model=LoggingConfigResponse)\nasync def get_logging_config(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_logging_config\"):\n logging_config = config_manager.get_config().settings.logging\n return LoggingConfigResponse(\n level=logging_config.level,\n task_log_level=logging_config.task_log_level,\n enable_belief_state=logging_config.enable_belief_state,\n )\n\n\n# #endregion get_logging_config\n\n\n# #region update_logging_config [C:2] [TYPE Function]\n# @BRIEF Updates logging configuration.\n# @PRE: New logging config is provided.\n# @POST: Logging configuration is updated and saved.\n@router.patch(\"/logging\", response_model=LoggingConfigResponse)\nasync def update_logging_config(\n config: LoggingConfig,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_logging_config\"):\n logger.reason(\n f\"Updating logging config: level={config.level}, task_log_level={config.task_log_level}\", extra={\"src\": \"update_logging_config\"}\n )\n\n # Get current settings and update logging config\n settings = config_manager.get_config().settings\n settings.logging = config\n config_manager.update_global_settings(settings)\n\n return LoggingConfigResponse(\n level=config.level,\n task_log_level=config.task_log_level,\n enable_belief_state=config.enable_belief_state,\n )\n\n\n# #endregion update_logging_config\n\n\n# #region ConsolidatedSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response model for consolidated application settings.\nclass ConsolidatedSettingsResponse(BaseModel):\n environments: list[dict]\n connections: list[dict]\n llm: dict\n llm_providers: list[dict]\n logging: dict\n storage: dict\n notifications: dict = {}\n features: dict = {}\n\n\n# #endregion ConsolidatedSettingsResponse\n\n\n# #region get_consolidated_settings [C:4] [TYPE Function]\n# @BRIEF Retrieves all settings categories in a single call.\n# @PRE: Config manager is available and the caller holds admin settings read permission.\n# @POST: Returns consolidated settings, provider metadata, and persisted notification payload in one stable response.\n# @SIDE_EFFECT: Opens one database session to read LLM providers and config-backed notification payload, then closes it.\n# @DATA_CONTRACT: Input[ConfigManager] -> Output[ConsolidatedSettingsResponse]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [has_permission]\n# @RELATION DEPENDS_ON -> [normalize_llm_settings]\n@router.get(\"/consolidated\", response_model=ConsolidatedSettingsResponse)\nasync def get_consolidated_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_consolidated_settings\"):\n logger.reason(\"Fetching consolidated settings payload\")\n\n config = config_manager.get_config()\n\n from ...core.database import SessionLocal\n from ...services.llm_provider import LLMProviderService\n\n db = SessionLocal()\n notifications_payload = {}\n try:\n llm_service = LLMProviderService(db)\n providers = llm_service.get_all_providers()\n llm_providers_list = [\n {\n \"id\": p.id,\n \"provider_type\": p.provider_type,\n \"name\": p.name,\n \"base_url\": p.base_url,\n \"api_key\": \"********\",\n \"default_model\": p.default_model,\n \"is_active\": p.is_active,\n }\n for p in providers\n ]\n\n config_record = (\n db.query(AppConfigRecord).filter(AppConfigRecord.id == \"global\").first()\n )\n if config_record and isinstance(config_record.payload, dict):\n notifications_payload = (\n config_record.payload.get(\"notifications\", {}) or {}\n )\n finally:\n db.close()\n\n normalized_llm = normalize_llm_settings(config.settings.llm)\n\n response_payload = ConsolidatedSettingsResponse(\n environments=[env.dict() for env in config.environments],\n connections=config.settings.connections,\n llm=normalized_llm,\n llm_providers=llm_providers_list,\n logging=config.settings.logging.dict(),\n storage=config.settings.storage.dict(),\n notifications=notifications_payload,\n features=config.settings.features.model_dump(),\n )\n logger.reflect(\n \"Consolidated settings payload assembled\",\n extra={\n \"environment_count\": len(response_payload.environments),\n \"provider_count\": len(response_payload.llm_providers),\n },\n )\n return response_payload\n\n\n# #endregion get_consolidated_settings\n\n\n# #region update_consolidated_settings [C:2] [TYPE Function]\n# @BRIEF Bulk update application settings from the consolidated view.\n# @PRE: User has admin permissions, config is valid.\n# @POST: Settings are updated and saved via ConfigManager.\n@router.patch(\"/consolidated\")\nasync def update_consolidated_settings(\n settings_patch: dict,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_consolidated_settings\"):\n logger.reason(\n \"Applying consolidated settings patch\", extra={\"src\": \"update_consolidated_settings\"}\n )\n\n current_config = config_manager.get_config()\n current_settings = current_config.settings\n\n # Update connections if provided\n if \"connections\" in settings_patch:\n current_settings.connections = settings_patch[\"connections\"]\n\n # Update LLM if provided\n if \"llm\" in settings_patch:\n current_settings.llm = normalize_llm_settings(settings_patch[\"llm\"])\n\n # Update Logging if provided\n if \"logging\" in settings_patch:\n current_settings.logging = LoggingConfig(**settings_patch[\"logging\"])\n\n # Update Storage if provided\n if \"storage\" in settings_patch:\n new_storage = StorageConfig(**settings_patch[\"storage\"])\n is_valid, message = config_manager.validate_path(new_storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n current_settings.storage = new_storage\n\n # Update Features if provided\n if \"features\" in settings_patch:\n from ...core.config_models import FeaturesConfig\n\n current_settings.features = FeaturesConfig(**settings_patch[\"features\"])\n\n if \"notifications\" in settings_patch:\n payload = config_manager.get_payload()\n payload[\"notifications\"] = settings_patch[\"notifications\"]\n config_manager.save_config(payload)\n\n config_manager.update_global_settings(current_settings)\n return {\"status\": \"success\", \"message\": \"Settings updated\"}\n\n\n# #endregion update_consolidated_settings\n\n\n# #region get_validation_policies [C:2] [TYPE Function]\n# @BRIEF Lists all validation policies.\n@router.get(\"/automation/policies\", response_model=list[ValidationPolicyResponse])\nasync def get_validation_policies(\n db: Session = Depends(get_db), _=Depends(has_permission(\"admin:settings\", \"READ\"))\n):\n with belief_scope(\"get_validation_policies\"):\n return db.query(ValidationPolicy).all()\n\n\n# #endregion get_validation_policies\n\n\n# #region create_validation_policy [C:2] [TYPE Function]\n# @BRIEF Creates a new validation policy.\n@router.post(\"/automation/policies\", response_model=ValidationPolicyResponse)\nasync def create_validation_policy(\n policy: ValidationPolicyCreate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"create_validation_policy\"):\n db_policy = ValidationPolicy(**policy.dict())\n db.add(db_policy)\n db.commit()\n db.refresh(db_policy)\n return db_policy\n\n\n# #endregion create_validation_policy\n\n\n# #region update_validation_policy [C:2] [TYPE Function]\n# @BRIEF Updates an existing validation policy.\n@router.patch(\"/automation/policies/{id}\", response_model=ValidationPolicyResponse)\nasync def update_validation_policy(\n id: str,\n policy: ValidationPolicyUpdate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_validation_policy\"):\n db_policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == id).first()\n if not db_policy:\n raise HTTPException(status_code=404, detail=\"Policy not found\")\n\n update_data = policy.dict(exclude_unset=True)\n for key, value in update_data.items():\n setattr(db_policy, key, value)\n\n db.commit()\n db.refresh(db_policy)\n return db_policy\n\n\n# #endregion update_validation_policy\n\n\n# #region delete_validation_policy [C:2] [TYPE Function]\n# @BRIEF Deletes a validation policy.\n@router.delete(\"/automation/policies/{id}\")\nasync def delete_validation_policy(\n id: str,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"delete_validation_policy\"):\n db_policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == id).first()\n if not db_policy:\n raise HTTPException(status_code=404, detail=\"Policy not found\")\n\n db.delete(db_policy)\n db.commit()\n return {\"message\": \"Policy deleted\"}\n\n\n# #endregion delete_validation_policy\n\n\n# #region get_translation_schedules [C:2] [TYPE Function]\n# @BRIEF Lists all translation schedules joined with translation job names.\n@router.get(\"/automation/translation-schedules\", response_model=list[TranslationScheduleItem])\nasync def get_translation_schedules(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_translation_schedules\"):\n results = (\n db.query(\n TranslationSchedule,\n TranslationJob.name.label(\"job_name\"),\n )\n .outerjoin(TranslationJob, TranslationSchedule.job_id == TranslationJob.id)\n .all()\n )\n return [\n TranslationScheduleItem(\n schedule_id=ts.id,\n job_id=ts.job_id,\n job_name=job_name,\n cron_expression=ts.cron_expression,\n timezone=ts.timezone,\n is_active=ts.is_active,\n last_run_at=ts.last_run_at,\n next_run_at=ts.next_run_at,\n created_by=ts.created_by,\n created_at=ts.created_at,\n )\n for ts, job_name in results\n ]\n\n\n# #endregion get_translation_schedules\n\n# #endregion SettingsRouter\n" + "body": "# #region SettingsRouter [C:5] [TYPE Module] [SEMANTICS fastapi, api, superset, logging-config-response]\n#\n# @BRIEF Provides API endpoints for managing application settings and Superset environments.\n# @LAYER: API\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [get_config_manager]\n# @RELATION DEPENDS_ON -> [has_permission]\n#\n# @PRE ConfigManager is initialized and accessible.\n# @POST Settings are read or written via ConfigManager.\n# @SIDE_EFFECT Persists config changes to disk via ConfigManager.\n# @DATA_CONTRACT Input -> ConfigUpdateRequest, Output -> AppConfig, LoggingConfigResponse\n# @INVARIANT: All settings changes must be persisted via ConfigManager.\n# @PUBLIC_API: router\n\n\nfrom fastapi import APIRouter, Depends, HTTPException\nfrom pydantic import BaseModel\nfrom sqlalchemy.orm import Session\n\nfrom ...core.config_manager import ConfigManager\nfrom ...core.config_models import AppConfig, Environment, GlobalSettings, LoggingConfig\nfrom ...core.database import get_db\nfrom ...core.logger import belief_scope, logger\nfrom ...core.superset_client import SupersetClient\nfrom ...dependencies import get_config_manager, has_permission\nfrom ...models.config import AppConfigRecord\nfrom ...models.llm import ValidationPolicy\nfrom ...models.storage import StorageConfig\nfrom ...models.translate import TranslationJob, TranslationSchedule\nfrom ...schemas.settings import (\n TranslationScheduleItem,\n ValidationPolicyCreate,\n ValidationPolicyResponse,\n ValidationPolicyUpdate,\n)\nfrom ...services.llm_prompt_templates import normalize_llm_settings\n\n\n# #region LoggingConfigResponse [C:1] [TYPE Class] [SEMANTICS logging, config, response]\n# @BRIEF Response model for logging configuration with current task log level.\nclass LoggingConfigResponse(BaseModel):\n level: str\n task_log_level: str\n enable_belief_state: bool\n\n\n# #endregion LoggingConfigResponse\n\nrouter = APIRouter()\n\n\n# #region _normalize_superset_env_url [C:1] [TYPE Function]\n# @BRIEF Canonicalize Superset environment URL to base host/path without trailing /api/v1.\n# Auto-prepends https:// if no scheme is present.\n# @PRE: raw_url can be empty.\n# @POST: Returns normalized base URL with scheme.\ndef _normalize_superset_env_url(raw_url: str) -> str:\n normalized = str(raw_url or \"\").strip().rstrip(\"/\")\n if normalized.lower().endswith(\"/api/v1\"):\n normalized = normalized[: -len(\"/api/v1\")]\n normalized = normalized.rstrip(\"/\")\n # Auto-prepend https:// if no scheme is present\n if normalized and not normalized.startswith(\"http://\") and not normalized.startswith(\"https://\"):\n normalized = f\"https://{normalized}\"\n return normalized\n\n\n# #endregion _normalize_superset_env_url\n\n\n# #region _validate_superset_connection_fast [C:2] [TYPE Function]\n# @BRIEF Run lightweight Superset connectivity validation without full pagination scan.\n# @PRE: env contains valid URL and credentials.\n# @POST: Raises on auth/API failures; returns None on success.\ndef _validate_superset_connection_fast(env: Environment) -> None:\n client = SupersetClient(env)\n # 1) Explicit auth check\n client.authenticate()\n # 2) Single lightweight API call to ensure read access\n client.get_dashboards_page(\n query={\n \"page\": 0,\n \"page_size\": 1,\n \"columns\": [\"id\"],\n }\n )\n\n\n# #endregion _validate_superset_connection_fast\n\n\n# #region get_settings [C:2] [TYPE Function]\n# @BRIEF Retrieves all application settings.\n# @PRE: Config manager is available.\n# @POST: Returns masked AppConfig.\n@router.get(\"\", response_model=AppConfig)\nasync def get_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_settings\"):\n logger.reason(\"Fetching all settings\", extra={\"src\": \"get_settings\"})\n config = config_manager.get_config().copy(deep=True)\n config.settings.llm = normalize_llm_settings(config.settings.llm)\n # Mask passwords\n for env in config.environments:\n if env.password:\n env.password = \"********\"\n return config\n\n\n# #endregion get_settings\n\n\n# #region get_features [C:1] [TYPE Function]\n# @BRIEF Public endpoint returning feature flags for frontend sidebar filtering.\n# @RATIONALE: Unauthenticated because sidebar filtering must work for all users, not just admins.\n# @PRE: Config manager is available.\n# @POST: Returns dict with dataset_review and health_monitor booleans.\n@router.get(\"/features\")\nasync def get_features(\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n return config_manager.get_config().settings.features.model_dump()\n\n\n# #endregion get_features\n\n\n# #region update_global_settings [C:2] [TYPE Function]\n# @BRIEF Updates global application settings.\n# @PRE: New settings are provided.\n# @POST: Global settings are updated.\n@router.patch(\"/global\", response_model=GlobalSettings)\nasync def update_global_settings(\n settings: GlobalSettings,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_global_settings\"):\n logger.reason(\"Updating global settings\", extra={\"src\": \"update_global_settings\"})\n\n config_manager.update_global_settings(settings)\n return settings\n\n\n# #endregion update_global_settings\n\n\n# #region get_storage_settings [C:2] [TYPE Function]\n# @BRIEF Retrieves storage-specific settings.\n@router.get(\"/storage\", response_model=StorageConfig)\nasync def get_storage_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_storage_settings\"):\n return config_manager.get_config().settings.storage\n\n\n# #endregion get_storage_settings\n\n\n# #region update_storage_settings [C:2] [TYPE Function]\n# @BRIEF Updates storage-specific settings.\n# @POST: Storage settings are updated and saved.\n@router.put(\"/storage\", response_model=StorageConfig)\nasync def update_storage_settings(\n storage: StorageConfig,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_storage_settings\"):\n is_valid, message = config_manager.validate_path(storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n\n settings = config_manager.get_config().settings\n settings.storage = storage\n config_manager.update_global_settings(settings)\n return config_manager.get_config().settings.storage\n\n\n# #endregion update_storage_settings\n\n\n# #region get_environments [C:2] [TYPE Function]\n# @BRIEF Lists all configured Superset environments.\n# @PRE: Config manager is available.\n# @POST: Returns list of environments.\n@router.get(\"/environments\", response_model=list[Environment])\nasync def get_environments(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_environments\"):\n logger.reason(\"Fetching environments\", extra={\"src\": \"get_environments\"})\n environments = config_manager.get_environments()\n return [\n env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n for env in environments\n ]\n\n\n# #endregion get_environments\n\n\n# #region add_environment [C:2] [TYPE Function]\n# @BRIEF Adds a new Superset environment.\n# @PRE: Environment data is valid and reachable.\n# @POST: Environment is added to config.\n@router.post(\"/environments\", response_model=Environment)\nasync def add_environment(\n env: Environment,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"add_environment\"):\n logger.reason(f\"Adding environment {env.id}\", extra={\"src\": \"add_environment\"})\n env = env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n\n # Validate connection before adding (fast path)\n try:\n _validate_superset_connection_fast(env)\n except Exception as e:\n logger.error(\n f\"[add_environment][Coherence:Failed] Connection validation failed: {e}\"\n )\n raise HTTPException(\n status_code=400, detail=f\"Connection validation failed: {e}\"\n )\n\n config_manager.add_environment(env)\n return env\n\n\n# #endregion add_environment\n\n\n# #region update_environment [C:2] [TYPE Function]\n# @BRIEF Updates an existing Superset environment.\n# @PRE: ID and valid environment data are provided.\n# @POST: Environment is updated in config.\n@router.put(\"/environments/{id}\", response_model=Environment)\nasync def update_environment(\n id: str,\n env: Environment,\n config_manager: ConfigManager = Depends(get_config_manager),\n):\n with belief_scope(\"update_environment\"):\n logger.reason(f\"Updating environment {id}\", extra={\"src\": \"update_environment\"})\n\n env = env.copy(update={\"url\": _normalize_superset_env_url(env.url)})\n\n # If password is masked, we need the real one for validation\n env_to_validate = env.copy(deep=True)\n if env_to_validate.password == \"********\":\n old_env = next(\n (e for e in config_manager.get_environments() if e.id == id), None\n )\n if old_env:\n env_to_validate.password = old_env.password\n\n # Validate connection before updating (fast path)\n try:\n _validate_superset_connection_fast(env_to_validate)\n except Exception as e:\n logger.error(\n f\"[update_environment][Coherence:Failed] Connection validation failed: {e}\"\n )\n raise HTTPException(\n status_code=400, detail=f\"Connection validation failed: {e}\"\n )\n\n if config_manager.update_environment(id, env):\n return env\n raise HTTPException(status_code=404, detail=f\"Environment {id} not found\")\n\n\n# #endregion update_environment\n\n\n# #region delete_environment [C:2] [TYPE Function]\n# @BRIEF Deletes a Superset environment.\n# @PRE: ID is provided.\n# @POST: Environment is removed from config.\n@router.delete(\"/environments/{id}\")\nasync def delete_environment(\n id: str, config_manager: ConfigManager = Depends(get_config_manager)\n):\n with belief_scope(\"delete_environment\"):\n logger.reason(f\"Deleting environment {id}\", extra={\"src\": \"delete_environment\"})\n config_manager.delete_environment(id)\n return {\"message\": f\"Environment {id} deleted\"}\n\n\n# #endregion delete_environment\n\n\n# #region test_environment_connection [C:2] [TYPE Function]\n# @BRIEF Tests the connection to a Superset environment.\n# @PRE: ID is provided.\n# @POST: Returns success or error status.\n@router.post(\"/environments/{id}/test\")\nasync def test_environment_connection(\n id: str, config_manager: ConfigManager = Depends(get_config_manager)\n):\n with belief_scope(\"test_environment_connection\"):\n logger.reason(f\"Testing environment {id}\", extra={\"src\": \"test_environment_connection\"})\n\n # Find environment\n env = next((e for e in config_manager.get_environments() if e.id == id), None)\n if not env:\n raise HTTPException(status_code=404, detail=f\"Environment {id} not found\")\n\n try:\n _validate_superset_connection_fast(env)\n\n logger.info(\n f\"[test_environment_connection][Coherence:OK] Connection successful for {id}\"\n )\n return {\"status\": \"success\", \"message\": \"Connection successful\"}\n except Exception as e:\n logger.error(\n f\"[test_environment_connection][Coherence:Failed] Connection failed for {id}: {e}\"\n )\n return {\"status\": \"error\", \"message\": str(e)}\n\n\n# #endregion test_environment_connection\n\n\n# #region get_logging_config [C:2] [TYPE Function]\n# @BRIEF Retrieves current logging configuration.\n# @PRE: Config manager is available.\n# @POST: Returns logging configuration.\n@router.get(\"/logging\", response_model=LoggingConfigResponse)\nasync def get_logging_config(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_logging_config\"):\n logging_config = config_manager.get_config().settings.logging\n return LoggingConfigResponse(\n level=logging_config.level,\n task_log_level=logging_config.task_log_level,\n enable_belief_state=logging_config.enable_belief_state,\n )\n\n\n# #endregion get_logging_config\n\n\n# #region update_logging_config [C:2] [TYPE Function]\n# @BRIEF Updates logging configuration.\n# @PRE: New logging config is provided.\n# @POST: Logging configuration is updated and saved.\n@router.patch(\"/logging\", response_model=LoggingConfigResponse)\nasync def update_logging_config(\n config: LoggingConfig,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_logging_config\"):\n logger.reason(\n f\"Updating logging config: level={config.level}, task_log_level={config.task_log_level}\", extra={\"src\": \"update_logging_config\"}\n )\n\n # Get current settings and update logging config\n settings = config_manager.get_config().settings\n settings.logging = config\n config_manager.update_global_settings(settings)\n\n return LoggingConfigResponse(\n level=config.level,\n task_log_level=config.task_log_level,\n enable_belief_state=config.enable_belief_state,\n )\n\n\n# #endregion update_logging_config\n\n\n# #region ConsolidatedSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response model for consolidated application settings.\nclass ConsolidatedSettingsResponse(BaseModel):\n environments: list[dict]\n connections: list[dict]\n llm: dict\n llm_providers: list[dict]\n logging: dict\n storage: dict\n notifications: dict = {}\n features: dict = {}\n app_timezone: str = \"Europe/Moscow\"\n\n\n# #endregion ConsolidatedSettingsResponse\n\n\n# #region get_consolidated_settings [C:4] [TYPE Function]\n# @BRIEF Retrieves all settings categories in a single call.\n# @PRE: Config manager is available and the caller holds admin settings read permission.\n# @POST: Returns consolidated settings, provider metadata, and persisted notification payload in one stable response.\n# @SIDE_EFFECT: Opens one database session to read LLM providers and config-backed notification payload, then closes it.\n# @DATA_CONTRACT: Input[ConfigManager] -> Output[ConsolidatedSettingsResponse]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [has_permission]\n# @RELATION DEPENDS_ON -> [normalize_llm_settings]\n@router.get(\"/consolidated\", response_model=ConsolidatedSettingsResponse)\nasync def get_consolidated_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_consolidated_settings\"):\n logger.reason(\"Fetching consolidated settings payload\")\n\n config = config_manager.get_config()\n\n from ...core.database import SessionLocal\n from ...services.llm_provider import LLMProviderService\n\n db = SessionLocal()\n notifications_payload = {}\n try:\n llm_service = LLMProviderService(db)\n providers = llm_service.get_all_providers()\n llm_providers_list = [\n {\n \"id\": p.id,\n \"provider_type\": p.provider_type,\n \"name\": p.name,\n \"base_url\": p.base_url,\n \"api_key\": \"********\",\n \"default_model\": p.default_model,\n \"is_active\": p.is_active,\n \"is_multimodal\": bool(p.is_multimodal) if p.is_multimodal is not None else False,\n }\n for p in providers\n ]\n\n config_record = (\n db.query(AppConfigRecord).filter(AppConfigRecord.id == \"global\").first()\n )\n if config_record and isinstance(config_record.payload, dict):\n notifications_payload = (\n config_record.payload.get(\"notifications\", {}) or {}\n )\n finally:\n db.close()\n\n normalized_llm = normalize_llm_settings(config.settings.llm)\n\n response_payload = ConsolidatedSettingsResponse(\n environments=[env.dict() for env in config.environments],\n connections=config.settings.connections,\n llm=normalized_llm,\n llm_providers=llm_providers_list,\n logging=config.settings.logging.dict(),\n storage=config.settings.storage.dict(),\n notifications=notifications_payload,\n features=config.settings.features.model_dump(),\n app_timezone=config.settings.app_timezone,\n )\n logger.reflect(\n \"Consolidated settings payload assembled\",\n extra={\n \"environment_count\": len(response_payload.environments),\n \"provider_count\": len(response_payload.llm_providers),\n },\n )\n return response_payload\n\n\n# #endregion get_consolidated_settings\n\n\n# #region update_consolidated_settings [C:2] [TYPE Function]\n# @BRIEF Bulk update application settings from the consolidated view.\n# @PRE: User has admin permissions, config is valid.\n# @POST: Settings are updated and saved via ConfigManager.\n@router.patch(\"/consolidated\")\nasync def update_consolidated_settings(\n settings_patch: dict,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_consolidated_settings\"):\n logger.reason(\n \"Applying consolidated settings patch\", extra={\"src\": \"update_consolidated_settings\"}\n )\n\n current_config = config_manager.get_config()\n current_settings = current_config.settings\n\n # Update connections if provided\n if \"connections\" in settings_patch:\n current_settings.connections = settings_patch[\"connections\"]\n\n # Update LLM if provided\n if \"llm\" in settings_patch:\n current_settings.llm = normalize_llm_settings(settings_patch[\"llm\"])\n\n # Update Logging if provided\n if \"logging\" in settings_patch:\n current_settings.logging = LoggingConfig(**settings_patch[\"logging\"])\n\n # Update Storage if provided\n if \"storage\" in settings_patch:\n new_storage = StorageConfig(**settings_patch[\"storage\"])\n is_valid, message = config_manager.validate_path(new_storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n current_settings.storage = new_storage\n\n # Update Features if provided\n if \"features\" in settings_patch:\n from ...core.config_models import FeaturesConfig\n\n current_settings.features = FeaturesConfig(**settings_patch[\"features\"])\n\n if \"notifications\" in settings_patch:\n payload = config_manager.get_payload()\n payload[\"notifications\"] = settings_patch[\"notifications\"]\n config_manager.save_config(payload)\n\n # Update app_timezone if provided\n if \"app_timezone\" in settings_patch:\n new_tz = settings_patch[\"app_timezone\"]\n from ...core.timezone import validate_timezone, invalidate_timezone_cache\n if not validate_timezone(new_tz):\n raise HTTPException(status_code=422, detail=f\"Invalid IANA timezone: {new_tz}\")\n current_settings.app_timezone = new_tz\n invalidate_timezone_cache()\n\n config_manager.update_global_settings(current_settings)\n return {\"status\": \"success\", \"message\": \"Settings updated\"}\n\n\n# #endregion update_consolidated_settings\n\n\n# #region get_validation_policies [C:2] [TYPE Function]\n# @BRIEF Lists all validation policies.\n@router.get(\"/automation/policies\", response_model=list[ValidationPolicyResponse])\nasync def get_validation_policies(\n db: Session = Depends(get_db), _=Depends(has_permission(\"admin:settings\", \"READ\"))\n):\n with belief_scope(\"get_validation_policies\"):\n return db.query(ValidationPolicy).all()\n\n\n# #endregion get_validation_policies\n\n\n# #region create_validation_policy [C:2] [TYPE Function]\n# @BRIEF Creates a new validation policy.\n@router.post(\"/automation/policies\", response_model=ValidationPolicyResponse)\nasync def create_validation_policy(\n policy: ValidationPolicyCreate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"create_validation_policy\"):\n db_policy = ValidationPolicy(**policy.dict())\n db.add(db_policy)\n db.commit()\n db.refresh(db_policy)\n return db_policy\n\n\n# #endregion create_validation_policy\n\n\n# #region update_validation_policy [C:2] [TYPE Function]\n# @BRIEF Updates an existing validation policy.\n@router.patch(\"/automation/policies/{id}\", response_model=ValidationPolicyResponse)\nasync def update_validation_policy(\n id: str,\n policy: ValidationPolicyUpdate,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_validation_policy\"):\n db_policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == id).first()\n if not db_policy:\n raise HTTPException(status_code=404, detail=\"Policy not found\")\n\n update_data = policy.dict(exclude_unset=True)\n for key, value in update_data.items():\n setattr(db_policy, key, value)\n\n db.commit()\n db.refresh(db_policy)\n return db_policy\n\n\n# #endregion update_validation_policy\n\n\n# #region delete_validation_policy [C:2] [TYPE Function]\n# @BRIEF Deletes a validation policy.\n@router.delete(\"/automation/policies/{id}\")\nasync def delete_validation_policy(\n id: str,\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"delete_validation_policy\"):\n db_policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == id).first()\n if not db_policy:\n raise HTTPException(status_code=404, detail=\"Policy not found\")\n\n db.delete(db_policy)\n db.commit()\n return {\"message\": \"Policy deleted\"}\n\n\n# #endregion delete_validation_policy\n\n\n# #region get_translation_schedules [C:2] [TYPE Function]\n# @BRIEF Lists all translation schedules joined with translation job names.\n@router.get(\"/automation/translation-schedules\", response_model=list[TranslationScheduleItem])\nasync def get_translation_schedules(\n db: Session = Depends(get_db),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_translation_schedules\"):\n results = (\n db.query(\n TranslationSchedule,\n TranslationJob.name.label(\"job_name\"),\n )\n .outerjoin(TranslationJob, TranslationSchedule.job_id == TranslationJob.id)\n .all()\n )\n return [\n TranslationScheduleItem(\n schedule_id=ts.id,\n job_id=ts.job_id,\n job_name=job_name,\n cron_expression=ts.cron_expression,\n timezone=ts.timezone,\n is_active=ts.is_active,\n last_run_at=ts.last_run_at,\n next_run_at=ts.next_run_at,\n created_by=ts.created_by,\n created_at=ts.created_at,\n )\n for ts, job_name in results\n ]\n\n\n# #endregion get_translation_schedules\n\n# #endregion SettingsRouter\n" }, { "contract_id": "LoggingConfigResponse", @@ -15042,7 +15843,7 @@ "contract_type": "Class", "file_path": "backend/src/api/routes/settings.py", "start_line": 385, - "end_line": 398, + "end_line": 399, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -15053,14 +15854,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ConsolidatedSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response model for consolidated application settings.\nclass ConsolidatedSettingsResponse(BaseModel):\n environments: list[dict]\n connections: list[dict]\n llm: dict\n llm_providers: list[dict]\n logging: dict\n storage: dict\n notifications: dict = {}\n features: dict = {}\n\n\n# #endregion ConsolidatedSettingsResponse\n" + "body": "# #region ConsolidatedSettingsResponse [C:1] [TYPE Class]\n# @BRIEF Response model for consolidated application settings.\nclass ConsolidatedSettingsResponse(BaseModel):\n environments: list[dict]\n connections: list[dict]\n llm: dict\n llm_providers: list[dict]\n logging: dict\n storage: dict\n notifications: dict = {}\n features: dict = {}\n app_timezone: str = \"Europe/Moscow\"\n\n\n# #endregion ConsolidatedSettingsResponse\n" }, { "contract_id": "get_consolidated_settings", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 401, - "end_line": 476, + "start_line": 402, + "end_line": 479, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -15112,14 +15913,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region get_consolidated_settings [C:4] [TYPE Function]\n# @BRIEF Retrieves all settings categories in a single call.\n# @PRE: Config manager is available and the caller holds admin settings read permission.\n# @POST: Returns consolidated settings, provider metadata, and persisted notification payload in one stable response.\n# @SIDE_EFFECT: Opens one database session to read LLM providers and config-backed notification payload, then closes it.\n# @DATA_CONTRACT: Input[ConfigManager] -> Output[ConsolidatedSettingsResponse]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [has_permission]\n# @RELATION DEPENDS_ON -> [normalize_llm_settings]\n@router.get(\"/consolidated\", response_model=ConsolidatedSettingsResponse)\nasync def get_consolidated_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_consolidated_settings\"):\n logger.reason(\"Fetching consolidated settings payload\")\n\n config = config_manager.get_config()\n\n from ...core.database import SessionLocal\n from ...services.llm_provider import LLMProviderService\n\n db = SessionLocal()\n notifications_payload = {}\n try:\n llm_service = LLMProviderService(db)\n providers = llm_service.get_all_providers()\n llm_providers_list = [\n {\n \"id\": p.id,\n \"provider_type\": p.provider_type,\n \"name\": p.name,\n \"base_url\": p.base_url,\n \"api_key\": \"********\",\n \"default_model\": p.default_model,\n \"is_active\": p.is_active,\n }\n for p in providers\n ]\n\n config_record = (\n db.query(AppConfigRecord).filter(AppConfigRecord.id == \"global\").first()\n )\n if config_record and isinstance(config_record.payload, dict):\n notifications_payload = (\n config_record.payload.get(\"notifications\", {}) or {}\n )\n finally:\n db.close()\n\n normalized_llm = normalize_llm_settings(config.settings.llm)\n\n response_payload = ConsolidatedSettingsResponse(\n environments=[env.dict() for env in config.environments],\n connections=config.settings.connections,\n llm=normalized_llm,\n llm_providers=llm_providers_list,\n logging=config.settings.logging.dict(),\n storage=config.settings.storage.dict(),\n notifications=notifications_payload,\n features=config.settings.features.model_dump(),\n )\n logger.reflect(\n \"Consolidated settings payload assembled\",\n extra={\n \"environment_count\": len(response_payload.environments),\n \"provider_count\": len(response_payload.llm_providers),\n },\n )\n return response_payload\n\n\n# #endregion get_consolidated_settings\n" + "body": "# #region get_consolidated_settings [C:4] [TYPE Function]\n# @BRIEF Retrieves all settings categories in a single call.\n# @PRE: Config manager is available and the caller holds admin settings read permission.\n# @POST: Returns consolidated settings, provider metadata, and persisted notification payload in one stable response.\n# @SIDE_EFFECT: Opens one database session to read LLM providers and config-backed notification payload, then closes it.\n# @DATA_CONTRACT: Input[ConfigManager] -> Output[ConsolidatedSettingsResponse]\n# @RELATION DEPENDS_ON -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [LLMProviderService]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [has_permission]\n# @RELATION DEPENDS_ON -> [normalize_llm_settings]\n@router.get(\"/consolidated\", response_model=ConsolidatedSettingsResponse)\nasync def get_consolidated_settings(\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"READ\")),\n):\n with belief_scope(\"get_consolidated_settings\"):\n logger.reason(\"Fetching consolidated settings payload\")\n\n config = config_manager.get_config()\n\n from ...core.database import SessionLocal\n from ...services.llm_provider import LLMProviderService\n\n db = SessionLocal()\n notifications_payload = {}\n try:\n llm_service = LLMProviderService(db)\n providers = llm_service.get_all_providers()\n llm_providers_list = [\n {\n \"id\": p.id,\n \"provider_type\": p.provider_type,\n \"name\": p.name,\n \"base_url\": p.base_url,\n \"api_key\": \"********\",\n \"default_model\": p.default_model,\n \"is_active\": p.is_active,\n \"is_multimodal\": bool(p.is_multimodal) if p.is_multimodal is not None else False,\n }\n for p in providers\n ]\n\n config_record = (\n db.query(AppConfigRecord).filter(AppConfigRecord.id == \"global\").first()\n )\n if config_record and isinstance(config_record.payload, dict):\n notifications_payload = (\n config_record.payload.get(\"notifications\", {}) or {}\n )\n finally:\n db.close()\n\n normalized_llm = normalize_llm_settings(config.settings.llm)\n\n response_payload = ConsolidatedSettingsResponse(\n environments=[env.dict() for env in config.environments],\n connections=config.settings.connections,\n llm=normalized_llm,\n llm_providers=llm_providers_list,\n logging=config.settings.logging.dict(),\n storage=config.settings.storage.dict(),\n notifications=notifications_payload,\n features=config.settings.features.model_dump(),\n app_timezone=config.settings.app_timezone,\n )\n logger.reflect(\n \"Consolidated settings payload assembled\",\n extra={\n \"environment_count\": len(response_payload.environments),\n \"provider_count\": len(response_payload.llm_providers),\n },\n )\n return response_payload\n\n\n# #endregion get_consolidated_settings\n" }, { "contract_id": "update_consolidated_settings", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 479, - "end_line": 532, + "start_line": 482, + "end_line": 544, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -15132,14 +15933,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region update_consolidated_settings [C:2] [TYPE Function]\n# @BRIEF Bulk update application settings from the consolidated view.\n# @PRE: User has admin permissions, config is valid.\n# @POST: Settings are updated and saved via ConfigManager.\n@router.patch(\"/consolidated\")\nasync def update_consolidated_settings(\n settings_patch: dict,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_consolidated_settings\"):\n logger.reason(\n \"Applying consolidated settings patch\", extra={\"src\": \"update_consolidated_settings\"}\n )\n\n current_config = config_manager.get_config()\n current_settings = current_config.settings\n\n # Update connections if provided\n if \"connections\" in settings_patch:\n current_settings.connections = settings_patch[\"connections\"]\n\n # Update LLM if provided\n if \"llm\" in settings_patch:\n current_settings.llm = normalize_llm_settings(settings_patch[\"llm\"])\n\n # Update Logging if provided\n if \"logging\" in settings_patch:\n current_settings.logging = LoggingConfig(**settings_patch[\"logging\"])\n\n # Update Storage if provided\n if \"storage\" in settings_patch:\n new_storage = StorageConfig(**settings_patch[\"storage\"])\n is_valid, message = config_manager.validate_path(new_storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n current_settings.storage = new_storage\n\n # Update Features if provided\n if \"features\" in settings_patch:\n from ...core.config_models import FeaturesConfig\n\n current_settings.features = FeaturesConfig(**settings_patch[\"features\"])\n\n if \"notifications\" in settings_patch:\n payload = config_manager.get_payload()\n payload[\"notifications\"] = settings_patch[\"notifications\"]\n config_manager.save_config(payload)\n\n config_manager.update_global_settings(current_settings)\n return {\"status\": \"success\", \"message\": \"Settings updated\"}\n\n\n# #endregion update_consolidated_settings\n" + "body": "# #region update_consolidated_settings [C:2] [TYPE Function]\n# @BRIEF Bulk update application settings from the consolidated view.\n# @PRE: User has admin permissions, config is valid.\n# @POST: Settings are updated and saved via ConfigManager.\n@router.patch(\"/consolidated\")\nasync def update_consolidated_settings(\n settings_patch: dict,\n config_manager: ConfigManager = Depends(get_config_manager),\n _=Depends(has_permission(\"admin:settings\", \"WRITE\")),\n):\n with belief_scope(\"update_consolidated_settings\"):\n logger.reason(\n \"Applying consolidated settings patch\", extra={\"src\": \"update_consolidated_settings\"}\n )\n\n current_config = config_manager.get_config()\n current_settings = current_config.settings\n\n # Update connections if provided\n if \"connections\" in settings_patch:\n current_settings.connections = settings_patch[\"connections\"]\n\n # Update LLM if provided\n if \"llm\" in settings_patch:\n current_settings.llm = normalize_llm_settings(settings_patch[\"llm\"])\n\n # Update Logging if provided\n if \"logging\" in settings_patch:\n current_settings.logging = LoggingConfig(**settings_patch[\"logging\"])\n\n # Update Storage if provided\n if \"storage\" in settings_patch:\n new_storage = StorageConfig(**settings_patch[\"storage\"])\n is_valid, message = config_manager.validate_path(new_storage.root_path)\n if not is_valid:\n raise HTTPException(status_code=400, detail=message)\n current_settings.storage = new_storage\n\n # Update Features if provided\n if \"features\" in settings_patch:\n from ...core.config_models import FeaturesConfig\n\n current_settings.features = FeaturesConfig(**settings_patch[\"features\"])\n\n if \"notifications\" in settings_patch:\n payload = config_manager.get_payload()\n payload[\"notifications\"] = settings_patch[\"notifications\"]\n config_manager.save_config(payload)\n\n # Update app_timezone if provided\n if \"app_timezone\" in settings_patch:\n new_tz = settings_patch[\"app_timezone\"]\n from ...core.timezone import validate_timezone, invalidate_timezone_cache\n if not validate_timezone(new_tz):\n raise HTTPException(status_code=422, detail=f\"Invalid IANA timezone: {new_tz}\")\n current_settings.app_timezone = new_tz\n invalidate_timezone_cache()\n\n config_manager.update_global_settings(current_settings)\n return {\"status\": \"success\", \"message\": \"Settings updated\"}\n\n\n# #endregion update_consolidated_settings\n" }, { "contract_id": "get_validation_policies", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 535, - "end_line": 545, + "start_line": 547, + "end_line": 557, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -15156,8 +15957,8 @@ "contract_id": "create_validation_policy", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 548, - "end_line": 564, + "start_line": 560, + "end_line": 576, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -15174,8 +15975,8 @@ "contract_id": "update_validation_policy", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 567, - "end_line": 590, + "start_line": 579, + "end_line": 602, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -15192,8 +15993,8 @@ "contract_id": "delete_validation_policy", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 593, - "end_line": 611, + "start_line": 605, + "end_line": 623, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -15210,8 +16011,8 @@ "contract_id": "get_translation_schedules", "contract_type": "Function", "file_path": "backend/src/api/routes/settings.py", - "start_line": 614, - "end_line": 647, + "start_line": 626, + "end_line": 659, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -16767,7 +17568,7 @@ "contract_type": "Module", "file_path": "backend/src/api/routes/validation.py", "start_line": 1, - "end_line": 270, + "end_line": 280, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -16798,14 +17599,14 @@ "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" + "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.scheduler import SchedulerService\nfrom ...core.task_manager import TaskManager\nfrom ...dependencies import get_config_manager, get_current_user, get_scheduler_service, 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 scheduler: SchedulerService = Depends(get_scheduler_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 result = service.create_task(payload)\n scheduler.reload_validation_policy(result.id)\n return result\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 for this specific task via task_id\n recent = run_service.list_runs(\n task_id=task_id,\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 scheduler: SchedulerService = Depends(get_scheduler_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 result = service.update_task(task_id, payload)\n scheduler.reload_validation_policy(result.id)\n return result\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 scheduler: SchedulerService = Depends(get_scheduler_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 scheduler.remove_validation_job(task_id)\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, + "start_line": 37, + "end_line": 44, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -16821,8 +17622,8 @@ "contract_id": "_get_run_service", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 46, - "end_line": 51, + "start_line": 47, + "end_line": 52, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -16838,8 +17639,8 @@ "contract_id": "list_tasks", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 59, - "end_line": 79, + "start_line": 60, + "end_line": 80, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16857,8 +17658,8 @@ "contract_id": "update_task", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 133, - "end_line": 150, + "start_line": 138, + "end_line": 158, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16870,14 +17671,14 @@ "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" + "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 scheduler: SchedulerService = Depends(get_scheduler_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 result = service.update_task(task_id, payload)\n scheduler.reload_validation_policy(result.id)\n return result\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, + "start_line": 161, + "end_line": 180, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16889,14 +17690,14 @@ "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" + "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 scheduler: SchedulerService = Depends(get_scheduler_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 scheduler.remove_validation_job(task_id)\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, + "start_line": 188, + "end_line": 206, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16914,8 +17715,8 @@ "contract_id": "list_runs", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 204, - "end_line": 231, + "start_line": 214, + "end_line": 241, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16933,8 +17734,8 @@ "contract_id": "get_run_detail", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 234, - "end_line": 250, + "start_line": 244, + "end_line": 260, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -16952,8 +17753,8 @@ "contract_id": "delete_run", "contract_type": "Function", "file_path": "backend/src/api/routes/validation.py", - "start_line": 253, - "end_line": 267, + "start_line": 263, + "end_line": 277, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17576,7 +18377,7 @@ "contract_type": "Module", "file_path": "backend/src/app.py", "start_line": 1, - "end_line": 465, + "end_line": 470, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -17601,14 +18402,14 @@ "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 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" + "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 admin_api_keys,\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 maintenance,\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# @RELATION DEPENDS_ON -> [MaintenanceRouter]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(admin_api_keys.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\"])\napp.include_router(maintenance.maintenance_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 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", "contract_type": "Global", "file_path": "backend/src/app.py", - "start_line": 58, - "end_line": 67, + "start_line": 60, + "end_line": 69, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17701,8 +18502,8 @@ "contract_id": "ensure_initial_admin_user", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 68, - "end_line": 115, + "start_line": 70, + "end_line": 117, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17726,8 +18527,8 @@ "contract_id": "startup_event", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 116, - "end_line": 131, + "start_line": 118, + "end_line": 133, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17753,8 +18554,8 @@ "contract_id": "shutdown_event", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 132, - "end_line": 144, + "start_line": 134, + "end_line": 146, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17780,8 +18581,8 @@ "contract_id": "app_middleware", "contract_type": "Block", "file_path": "backend/src/app.py", - "start_line": 145, - "end_line": 164, + "start_line": 147, + "end_line": 166, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -17798,8 +18599,8 @@ "contract_id": "network_error_handler", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 165, - "end_line": 177, + "start_line": 167, + "end_line": 179, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -17818,8 +18619,8 @@ "contract_id": "log_requests", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 178, - "end_line": 203, + "start_line": 180, + "end_line": 205, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17845,8 +18646,8 @@ "contract_id": "API_Routes", "contract_type": "Block", "file_path": "backend/src/app.py", - "start_line": 209, - "end_line": 245, + "start_line": 211, + "end_line": 250, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -17919,19 +18720,25 @@ "relation_type": "DEPENDS_ON", "target_id": "ValidationRoutes", "target_ref": "[ValidationRoutes]" + }, + { + "source_id": "API_Routes", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceRouter", + "target_ref": "[MaintenanceRouter]" } ], "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 -> [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" + "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# @RELATION DEPENDS_ON -> [MaintenanceRouter]\n# Include API routes\napp.include_router(auth.router)\napp.include_router(admin.router)\napp.include_router(admin_api_keys.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\"])\napp.include_router(maintenance.maintenance_router)\n# #endregion API_Routes\n" }, { "contract_id": "api.include_routers", "contract_type": "Action", "file_path": "backend/src/app.py", - "start_line": 246, - "end_line": 249, + "start_line": 251, + "end_line": 254, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -18025,8 +18832,8 @@ "contract_id": "websocket_endpoint", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 250, - "end_line": 393, + "start_line": 255, + "end_line": 398, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -18084,8 +18891,8 @@ "contract_id": "dataset_websocket_endpoint", "contract_type": "Function", "file_path": "backend/src/app.py", - "start_line": 394, - "end_line": 420, + "start_line": 399, + "end_line": 425, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -18112,8 +18919,8 @@ "contract_id": "StaticFiles", "contract_type": "Mount", "file_path": "backend/src/app.py", - "start_line": 421, - "end_line": 464, + "start_line": 426, + "end_line": 469, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -19742,6 +20549,99 @@ "tier_source": "AutoCalculated", "body": "# #region test_provision_adfs_user_existing [TYPE Function]\n# @BRIEF Verifies JIT provisioning reuses existing ADFS user and refreshes role assignments.\n# @RELATION BINDS_TO -> test_auth\ndef test_provision_adfs_user_existing(auth_service, auth_repo):\n \"\"\"@POST: provision_adfs_user updates roles for existing user.\"\"\"\n # Create existing user\n existing = User(\n username=\"existingadfs@domain.com\",\n email=\"existingadfs@domain.com\",\n auth_source=\"ADFS\",\n is_active=True,\n )\n auth_repo.db.add(existing)\n auth_repo.db.commit()\n user_info = {\n \"upn\": \"existingadfs@domain.com\",\n \"email\": \"existingadfs@domain.com\",\n \"groups\": [],\n }\n user = auth_service.provision_adfs_user(user_info)\n assert user is not None\n assert user.username == \"existingadfs@domain.com\"\n assert len(user.roles) == 0 # No matching group mappings\n# #endregion test_auth\n# #endregion test_provision_adfs_user_existing\n" }, + { + "contract_id": "APIKeyUtilities", + "contract_type": "Module", + "file_path": "backend/src/core/auth/api_key.py", + "start_line": 1, + "end_line": 53, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "INVARIANT": "hash_api_key() produces SHA-256 hex digest for lookup and storage.", + "LAYER": "Core", + "PURPOSE": "API key generation and hashing utilities for service-to-service authentication." + }, + "relations": [ + { + "source_id": "APIKeyUtilities", + "relation_type": "DEPENDS_ON", + "target_id": "hashlib", + "target_ref": "[hashlib]" + }, + { + "source_id": "APIKeyUtilities", + "relation_type": "DEPENDS_ON", + "target_id": "secrets", + "target_ref": "[secrets]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region APIKeyUtilities [C:2] [TYPE Module] [SEMANTICS auth, api_key, crypto, generation]\n# @BRIEF API key generation and hashing utilities for service-to-service authentication.\n# @LAYER Core\n# @RELATION DEPENDS_ON -> [hashlib]\n# @RELATION DEPENDS_ON -> [secrets]\n# @INVARIANT generate_api_key() always returns (raw_key, prefix, key_hash) where prefix is \"ssk_\" + 7 chars.\n# @INVARIANT hash_api_key() produces SHA-256 hex digest for lookup and storage.\n\nimport hashlib\nimport secrets\n\n\n# #region generate_api_key [C:2] [TYPE Function]\n# @BRIEF Generate a new API key in ssk_ format with SHA-256 hash.\n# @POST Returns (raw_key, prefix, key_hash) — raw_key shown ONCE to caller, never stored.\n# @SIDE_EFFECT Uses secrets.token_urlsafe(32) for cryptographic randomness.\n# @RELATION DEPENDS_ON -> [secrets.token_urlsafe]\n# @RELATION DEPENDS_ON -> [hashlib.sha256]\ndef generate_api_key() -> tuple[str, str, str]:\n \"\"\"Generate a new API key.\n\n Returns:\n tuple[str, str, str]: (raw_key, prefix, key_hash)\n - raw_key: Full key string starting with \"ssk_\", shown once\n - prefix: First 11 characters (\"ssk_\" + 7 chars), stored for identification\n - key_hash: SHA-256 hex digest, stored in database\n \"\"\"\n raw = f\"ssk_{secrets.token_urlsafe(32)}\" # 32 bytes -> 43 base64 chars\n prefix = raw[:11] # \"ssk_\" + 7 chars\n key_hash = hashlib.sha256(raw.encode()).hexdigest()\n return raw, prefix, key_hash\n\n\n# #endregion generate_api_key\n\n# #region hash_api_key [C:1] [TYPE Function]\n# @BRIEF Hash an API key string to SHA-256 hex digest for lookup.\n# @PRE raw_key is a non-empty string.\n# @POST Returns 64-character hex digest.\n# @RELATION DEPENDS_ON -> [hashlib.sha256]\ndef hash_api_key(raw_key: str) -> str:\n \"\"\"Hash an API key using SHA-256.\n\n Args:\n raw_key: The full API key string (e.g. ssk_...)\n\n Returns:\n str: 64-character hex digest\n \"\"\"\n return hashlib.sha256(raw_key.encode()).hexdigest()\n\n# #endregion hash_api_key\n# #endregion APIKeyUtilities\n" + }, + { + "contract_id": "generate_api_key", + "contract_type": "Function", + "file_path": "backend/src/core/auth/api_key.py", + "start_line": 13, + "end_line": 34, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns (raw_key, prefix, key_hash) — raw_key shown ONCE to caller, never stored.", + "PURPOSE": "Generate a new API key in ssk_ format with SHA-256 hash.", + "SIDE_EFFECT": "Uses secrets.token_urlsafe(32) for cryptographic randomness." + }, + "relations": [ + { + "source_id": "generate_api_key", + "relation_type": "DEPENDS_ON", + "target_id": "secrets.token_urlsafe", + "target_ref": "[secrets.token_urlsafe]" + }, + { + "source_id": "generate_api_key", + "relation_type": "DEPENDS_ON", + "target_id": "hashlib.sha256", + "target_ref": "[hashlib.sha256]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region generate_api_key [C:2] [TYPE Function]\n# @BRIEF Generate a new API key in ssk_ format with SHA-256 hash.\n# @POST Returns (raw_key, prefix, key_hash) — raw_key shown ONCE to caller, never stored.\n# @SIDE_EFFECT Uses secrets.token_urlsafe(32) for cryptographic randomness.\n# @RELATION DEPENDS_ON -> [secrets.token_urlsafe]\n# @RELATION DEPENDS_ON -> [hashlib.sha256]\ndef generate_api_key() -> tuple[str, str, str]:\n \"\"\"Generate a new API key.\n\n Returns:\n tuple[str, str, str]: (raw_key, prefix, key_hash)\n - raw_key: Full key string starting with \"ssk_\", shown once\n - prefix: First 11 characters (\"ssk_\" + 7 chars), stored for identification\n - key_hash: SHA-256 hex digest, stored in database\n \"\"\"\n raw = f\"ssk_{secrets.token_urlsafe(32)}\" # 32 bytes -> 43 base64 chars\n prefix = raw[:11] # \"ssk_\" + 7 chars\n key_hash = hashlib.sha256(raw.encode()).hexdigest()\n return raw, prefix, key_hash\n\n\n# #endregion generate_api_key\n" + }, + { + "contract_id": "hash_api_key", + "contract_type": "Function", + "file_path": "backend/src/core/auth/api_key.py", + "start_line": 36, + "end_line": 52, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns 64-character hex digest.", + "PRE": "raw_key is a non-empty string.", + "PURPOSE": "Hash an API key string to SHA-256 hex digest for lookup." + }, + "relations": [ + { + "source_id": "hash_api_key", + "relation_type": "DEPENDS_ON", + "target_id": "hashlib.sha256", + "target_ref": "[hashlib.sha256]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region hash_api_key [C:1] [TYPE Function]\n# @BRIEF Hash an API key string to SHA-256 hex digest for lookup.\n# @PRE raw_key is a non-empty string.\n# @POST Returns 64-character hex digest.\n# @RELATION DEPENDS_ON -> [hashlib.sha256]\ndef hash_api_key(raw_key: str) -> str:\n \"\"\"Hash an API key using SHA-256.\n\n Args:\n raw_key: The full API key string (e.g. ssk_...)\n\n Returns:\n str: 64-character hex digest\n \"\"\"\n return hashlib.sha256(raw_key.encode()).hexdigest()\n\n# #endregion hash_api_key\n" + }, { "contract_id": "AuthConfigModule", "contract_type": "Module", @@ -20543,7 +21443,7 @@ "contract_type": "Module", "file_path": "backend/src/core/config_manager.py", "start_line": 1, - "end_line": 541, + "end_line": 549, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -20591,14 +21491,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ConfigManager [C:5] [TYPE Module] [SEMANTICS sqlalchemy, validate, migration, config-manager]\n#\n# @BRIEF Manages application configuration persistence in DB with one-time migration from legacy JSON.\n# @LAYER: Domain\n# @PRE: Database schema for AppConfigRecord must be initialized.\n# @POST: Configuration is loaded into memory and logger is configured.\n# @SIDE_EFFECT: Performs DB I/O and may update global logging level.\n# @DATA_CONTRACT: Input[json, record] -> Model[AppConfig]\n# @INVARIANT: Configuration must always be representable by AppConfig and persisted under global record id.\n# @RELATION DEPENDS_ON -> [AppConfig]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION CALLS -> [logger]\n# @RELATION CALLS -> [configure_logger]\n#\nimport json\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ..models.config import AppConfigRecord\nfrom ..models.mapping import Environment as EnvironmentRecord\nfrom .config_models import AppConfig, Environment, GlobalSettings\nfrom .database import SessionLocal\nfrom .logger import belief_scope, configure_logger, logger\n\n\n# #region ConfigManager [C:5] [TYPE Class]\n# @BRIEF Handles application configuration load, validation, mutation, and persistence lifecycle.\n# @PRE: Database is accessible and AppConfigRecord schema is loaded.\n# @POST: Configuration state is synchronized between memory and database.\n# @SIDE_EFFECT: Performs DB I/O, OS path validation, and logger reconfiguration.\nclass ConfigManager:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initialize manager state from persisted or migrated configuration.\n # @PRE: config_path is a non-empty string path.\n # @POST: self.config is initialized as AppConfig and logger is configured.\n # @SIDE_EFFECT: Reads config sources and updates logging configuration.\n # @DATA_CONTRACT: Input(str config_path) -> Output(None; self.config: AppConfig)\n def __init__(self, config_path: str = \"config.json\"):\n with belief_scope(\"ConfigManager.__init__\"):\n if not isinstance(config_path, str) or not config_path:\n logger.explore(\n \"Invalid config_path provided\", extra={\"path\": config_path}\n )\n raise ValueError(\"config_path must be a non-empty string\")\n logger.reason(f\"Initializing ConfigManager with legacy path: {config_path}\")\n self.config_path = Path(config_path)\n self.raw_payload: dict[str, Any] = {}\n self.config: AppConfig = self._load_config()\n configure_logger(self.config.settings.logging)\n if not isinstance(self.config, AppConfig):\n logger.explore(\n \"Config loading resulted in invalid type\",\n extra={\"type\": type(self.config)},\n )\n raise TypeError(\"self.config must be an instance of AppConfig\")\n logger.reflect(\"ConfigManager initialization complete\")\n # #endregion __init__\n # #region _apply_features_from_env [TYPE Function]\n # @PURPOSE: Read FEATURES__* env vars and apply them to a GlobalSettings features config.\n # @SIDE_EFFECT: Reads os.environ; mutates settings.features in-place.\n # @RATIONALE: Env vars seed the initial defaults. After first bootstrap, DB is source of truth.\n @staticmethod\n def _apply_features_from_env(settings: GlobalSettings) -> None:\n with belief_scope(\"ConfigManager._apply_features_from_env\"):\n dataset_review_env = os.getenv(\"FEATURES__DATASET_REVIEW\")\n if dataset_review_env is not None:\n parsed = dataset_review_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.dataset_review = parsed\n logger.reason(\n \"Applied FEATURES__DATASET_REVIEW from env\",\n extra={\"value\": parsed, \"raw\": dataset_review_env},\n )\n health_monitor_env = os.getenv(\"FEATURES__HEALTH_MONITOR\")\n if health_monitor_env is not None:\n parsed = health_monitor_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.health_monitor = parsed\n logger.reason(\n \"Applied FEATURES__HEALTH_MONITOR from env\",\n extra={\"value\": parsed, \"raw\": health_monitor_env},\n )\n # #endregion _apply_features_from_env\n # #region _default_config [TYPE Function]\n # @PURPOSE: Build default application configuration fallback.\n def _default_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager._default_config\"):\n logger.reason(\"Building default AppConfig fallback\")\n config = AppConfig(environments=[], settings=GlobalSettings())\n self._apply_features_from_env(config.settings)\n return config\n # #endregion _default_config\n # #region _sync_raw_payload_from_config [TYPE Function]\n # @PURPOSE: Merge typed AppConfig state into raw payload while preserving unsupported legacy sections.\n def _sync_raw_payload_from_config(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager._sync_raw_payload_from_config\"):\n typed_payload = self.config.model_dump()\n merged_payload = dict(self.raw_payload or {})\n merged_payload[\"environments\"] = typed_payload.get(\"environments\", [])\n merged_payload[\"settings\"] = typed_payload.get(\"settings\", {})\n self.raw_payload = merged_payload\n logger.reason(\n \"Synchronized raw payload from typed config\",\n extra={\n \"environments_count\": len(\n merged_payload.get(\"environments\", []) or []\n ),\n \"has_settings\": \"settings\" in merged_payload,\n \"extra_sections\": sorted(\n key\n for key in merged_payload\n if key not in {\"environments\", \"settings\"}\n ),\n },\n )\n return merged_payload\n # #endregion _sync_raw_payload_from_config\n # #region _load_from_legacy_file [TYPE Function]\n # @PURPOSE: Load legacy JSON configuration for migration fallback path.\n def _load_from_legacy_file(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager._load_from_legacy_file\"):\n if not self.config_path.exists():\n logger.reason(\n \"Legacy config file not found; using default payload\",\n extra={\"path\": str(self.config_path)},\n )\n return {}\n logger.reason(\n \"Loading legacy config file\", extra={\"path\": str(self.config_path)}\n )\n with self.config_path.open(\"r\", encoding=\"utf-8\") as fh:\n payload = json.load(fh)\n if not isinstance(payload, dict):\n logger.explore(\n \"Legacy config payload is not a JSON object\",\n extra={\n \"path\": str(self.config_path),\n \"type\": type(payload).__name__,\n },\n )\n raise ValueError(\"Legacy config payload must be a JSON object\")\n logger.reason(\n \"Legacy config file loaded successfully\",\n extra={\"path\": str(self.config_path), \"keys\": sorted(payload.keys())},\n )\n return payload\n # #endregion _load_from_legacy_file\n # #region _get_record [TYPE Function]\n # @PURPOSE: Resolve global configuration record from DB.\n def _get_record(self, session: Session) -> AppConfigRecord | None:\n with belief_scope(\"ConfigManager._get_record\"):\n record = (\n session.query(AppConfigRecord)\n .filter(AppConfigRecord.id == \"global\")\n .first()\n )\n logger.reason(\n \"Resolved app config record\", extra={\"exists\": record is not None}\n )\n return record\n # #endregion _get_record\n # #region _load_config [TYPE Function]\n # @PURPOSE: Load configuration from DB or perform one-time migration from legacy JSON.\n def _load_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager._load_config\"):\n session = SessionLocal()\n try:\n record = self._get_record(session)\n if record and isinstance(record.payload, dict):\n logger.reason(\n \"Loading configuration from database\",\n extra={\"record_id\": record.id},\n )\n self.raw_payload = dict(record.payload)\n config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self._sync_environment_records(session, config)\n session.commit()\n logger.reason(\n \"Database configuration validated successfully\",\n extra={\n \"environments_count\": len(config.environments),\n \"payload_keys\": sorted(self.raw_payload.keys()),\n },\n )\n return config\n logger.reason(\n \"Database configuration record missing; attempting legacy file migration\",\n extra={\"legacy_path\": str(self.config_path)},\n )\n legacy_payload = self._load_from_legacy_file()\n if legacy_payload:\n self.raw_payload = dict(legacy_payload)\n config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self._apply_features_from_env(config.settings)\n logger.reason(\n \"Legacy payload validated; persisting migrated configuration to database\",\n extra={\n \"environments_count\": len(config.environments),\n \"payload_keys\": sorted(self.raw_payload.keys()),\n },\n )\n self._save_config_to_db(config, session=session)\n return config\n logger.reason(\n \"No persisted config found; falling back to default configuration\"\n )\n config = self._default_config()\n self.raw_payload = config.model_dump()\n self._save_config_to_db(config, session=session)\n return config\n except (json.JSONDecodeError, TypeError, ValueError) as exc:\n logger.explore(\n \"Recoverable config load failure; falling back to default configuration\",\n extra={\"error\": str(exc), \"legacy_path\": str(self.config_path)},\n )\n config = self._default_config()\n self.raw_payload = config.model_dump()\n return config\n except Exception as exc:\n logger.explore(\n \"Critical config load failure; re-raising persistence or validation error\",\n extra={\"error\": str(exc)},\n )\n raise\n finally:\n session.close()\n # #endregion _load_config\n # #region _sync_environment_records [TYPE Function]\n # @PURPOSE: Mirror configured environments into the relational environments table used by FK-backed domain models.\n def _sync_environment_records(self, session: Session, config: AppConfig) -> None:\n with belief_scope(\"ConfigManager._sync_environment_records\"):\n configured_envs = list(config.environments or [])\n persisted_records = session.query(EnvironmentRecord).all()\n persisted_by_id = {\n str(record.id or \"\").strip(): record for record in persisted_records\n }\n for environment in configured_envs:\n normalized_id = str(environment.id or \"\").strip()\n if not normalized_id:\n continue\n display_name = (\n str(environment.name or normalized_id).strip() or normalized_id\n )\n normalized_url = str(environment.url or \"\").strip()\n credentials_id = (\n str(environment.username or \"\").strip() or normalized_id\n )\n record = persisted_by_id.get(normalized_id)\n if record is None:\n logger.reason(\n \"Creating relational environment record from typed config\",\n extra={\n \"environment_id\": normalized_id,\n \"environment_name\": display_name,\n },\n )\n session.add(\n EnvironmentRecord(\n id=normalized_id,\n name=display_name,\n url=normalized_url,\n credentials_id=credentials_id,\n )\n )\n continue\n record.name = display_name\n record.url = normalized_url\n record.credentials_id = credentials_id\n # #endregion _sync_environment_records\n # #region _delete_stale_environment_records [TYPE Function]\n # @PURPOSE: Remove persisted environment records that are no longer in the configured environments.\n # @PRE: _sync_environment_records must already have run so the query returns a current view.\n # @POST: Stale Environment rows are deleted via the session (caller must commit).\n # @SIDE_EFFECT: Only safe to call during explicit save (_save_config_to_db), NOT during _load_config,\n # because FK-dependent rows (task_records, database_mappings, etc.) may reference deleted rows.\n def _delete_stale_environment_records(\n self, session: Session, config: AppConfig\n ) -> None:\n with belief_scope(\"ConfigManager._delete_stale_environment_records\"):\n persisted_records = session.query(EnvironmentRecord).all()\n configured_ids = {\n str(env.id or \"\").strip()\n for env in (config.environments or [])\n if str(env.id or \"\").strip()\n }\n for record in persisted_records:\n record_id = str(record.id or \"\").strip()\n if record_id and record_id not in configured_ids:\n logger.reason(\n \"Deleting stale environment record\",\n extra={\"environment_id\": record_id},\n )\n session.delete(record)\n # #endregion _delete_stale_environment_records\n # #region _save_config_to_db [TYPE Function]\n # @PURPOSE: Persist provided AppConfig into the global DB configuration record.\n def _save_config_to_db(\n self, config: AppConfig, session: Session | None = None\n ) -> None:\n with belief_scope(\"ConfigManager._save_config_to_db\"):\n owns_session = session is None\n db = session or SessionLocal()\n try:\n self.config = config\n payload = self._sync_raw_payload_from_config()\n record = self._get_record(db)\n if record is None:\n logger.reason(\"Creating new global app config record\")\n record = AppConfigRecord(id=\"global\", payload=payload)\n db.add(record)\n else:\n logger.reason(\n \"Updating existing global app config record\",\n extra={\"record_id\": record.id},\n )\n record.payload = payload\n self._sync_environment_records(db, config)\n self._delete_stale_environment_records(db, config)\n db.commit()\n logger.reason(\n \"Configuration persisted to database\",\n extra={\n \"environments_count\": len(\n payload.get(\"environments\", []) or []\n ),\n \"payload_keys\": sorted(payload.keys()),\n },\n )\n except Exception:\n db.rollback()\n logger.explore(\"Database save failed; transaction rolled back\")\n raise\n finally:\n if owns_session:\n db.close()\n # #endregion _save_config_to_db\n # #region save [TYPE Function]\n # @PURPOSE: Persist current in-memory configuration state.\n def save(self) -> None:\n with belief_scope(\"ConfigManager.save\"):\n logger.reason(\"Persisting current in-memory configuration\")\n self._save_config_to_db(self.config)\n # #endregion save\n # #region get_config [TYPE Function]\n # @PURPOSE: Return current in-memory configuration snapshot.\n def get_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager.get_config\"):\n return self.config\n # #endregion get_config\n # #region get_payload [TYPE Function]\n # @PURPOSE: Return full persisted payload including sections outside typed AppConfig schema.\n def get_payload(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager.get_payload\"):\n return self._sync_raw_payload_from_config()\n # #endregion get_payload\n # #region save_config [TYPE Function]\n # @PURPOSE: Persist configuration provided either as typed AppConfig or raw payload dict.\n def save_config(self, config: Any) -> AppConfig:\n with belief_scope(\"ConfigManager.save_config\"):\n if isinstance(config, AppConfig):\n logger.reason(\"Saving typed AppConfig payload\")\n self.config = config\n self.raw_payload = config.model_dump()\n self._save_config_to_db(config)\n return self.config\n if isinstance(config, dict):\n logger.reason(\n \"Saving raw config payload\",\n extra={\"keys\": sorted(config.keys())},\n )\n self.raw_payload = dict(config)\n typed_config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self.config = typed_config\n self._save_config_to_db(typed_config)\n return self.config\n logger.explore(\n \"Unsupported config type supplied to save_config\",\n extra={\"type\": type(config).__name__},\n )\n raise TypeError(\"config must be AppConfig or dict\")\n # #endregion save_config\n # #region update_global_settings [TYPE Function]\n # @PURPOSE: Replace global settings and persist the resulting configuration.\n def update_global_settings(self, settings: GlobalSettings) -> AppConfig:\n with belief_scope(\"ConfigManager.update_global_settings\"):\n logger.reason(\"Updating global settings\")\n self.config.settings = settings\n self.save()\n return self.config\n # #endregion update_global_settings\n # #region validate_path [TYPE Function]\n # @PURPOSE: Validate that path exists and is writable, creating it when absent.\n def validate_path(self, path: str) -> tuple[bool, str]:\n with belief_scope(\"ConfigManager.validate_path\", f\"path={path}\"):\n try:\n target = Path(path).expanduser()\n target.mkdir(parents=True, exist_ok=True)\n if not target.exists():\n return False, f\"Path does not exist: {target}\"\n if not target.is_dir():\n return False, f\"Path is not a directory: {target}\"\n test_file = target / \".write_test\"\n with test_file.open(\"w\", encoding=\"utf-8\") as fh:\n fh.write(\"ok\")\n test_file.unlink(missing_ok=True)\n logger.reason(\"Path validation succeeded\", extra={\"path\": str(target)})\n return True, \"OK\"\n except Exception as exc:\n logger.explore(\n \"Path validation failed\", extra={\"path\": path, \"error\": str(exc)}\n )\n return False, str(exc)\n # #endregion validate_path\n # #region get_environments [TYPE Function]\n # @PURPOSE: Return all configured environments.\n def get_environments(self) -> list[Environment]:\n with belief_scope(\"ConfigManager.get_environments\"):\n return list(self.config.environments)\n # #endregion get_environments\n # #region has_environments [TYPE Function]\n # @PURPOSE: Check whether at least one environment exists in configuration.\n def has_environments(self) -> bool:\n with belief_scope(\"ConfigManager.has_environments\"):\n return len(self.config.environments) > 0\n # #endregion has_environments\n # #region get_environment [TYPE Function]\n # @PURPOSE: Resolve a configured environment by identifier.\n def get_environment(self, env_id: str) -> Environment | None:\n with belief_scope(\"ConfigManager.get_environment\", f\"env_id={env_id}\"):\n normalized = str(env_id or \"\").strip()\n if not normalized:\n return None\n for env in self.config.environments:\n if env.id == normalized or env.name == normalized:\n return env\n return None\n # #endregion get_environment\n # #region add_environment [TYPE Function]\n # @PURPOSE: Upsert environment by id into configuration and persist.\n def add_environment(self, env: Environment) -> AppConfig:\n with belief_scope(\"ConfigManager.add_environment\", f\"env_id={env.id}\"):\n existing_index = next(\n (\n i\n for i, item in enumerate(self.config.environments)\n if item.id == env.id\n ),\n None,\n )\n if env.is_default:\n for item in self.config.environments:\n item.is_default = False\n if existing_index is None:\n logger.reason(\"Appending new environment\", extra={\"env_id\": env.id})\n self.config.environments.append(env)\n else:\n logger.reason(\n \"Replacing existing environment during add\",\n extra={\"env_id\": env.id},\n )\n self.config.environments[existing_index] = env\n if len(self.config.environments) == 1 and not any(\n item.is_default for item in self.config.environments\n ):\n self.config.environments[0].is_default = True\n self.save()\n return self.config\n # #endregion add_environment\n # #region update_environment [TYPE Function]\n # @PURPOSE: Update existing environment by id and preserve masked password placeholder behavior.\n def update_environment(self, env_id: str, env: Environment) -> bool:\n with belief_scope(\"ConfigManager.update_environment\", f\"env_id={env_id}\"):\n for index, existing in enumerate(self.config.environments):\n if existing.id != env_id:\n continue\n update_data = env.model_dump()\n if update_data.get(\"password\") == \"********\":\n update_data[\"password\"] = existing.password\n updated = Environment.model_validate(update_data)\n if updated.is_default:\n for item in self.config.environments:\n item.is_default = False\n elif existing.is_default and not updated.is_default:\n updated.is_default = True\n self.config.environments[index] = updated\n logger.reason(\"Environment updated\", extra={\"env_id\": env_id})\n self.save()\n return True\n logger.explore(\n \"Environment update skipped; env not found\", extra={\"env_id\": env_id}\n )\n return False\n # #endregion update_environment\n # #region delete_environment [TYPE Function]\n # @PURPOSE: Delete environment by id and persist when deletion occurs.\n def delete_environment(self, env_id: str) -> bool:\n with belief_scope(\"ConfigManager.delete_environment\", f\"env_id={env_id}\"):\n before = len(self.config.environments)\n removed = [env for env in self.config.environments if env.id == env_id]\n self.config.environments = [\n env for env in self.config.environments if env.id != env_id\n ]\n if len(self.config.environments) == before:\n logger.explore(\n \"Environment delete skipped; env not found\",\n extra={\"env_id\": env_id},\n )\n return False\n if removed and removed[0].is_default and self.config.environments:\n self.config.environments[0].is_default = True\n if self.config.settings.default_environment_id == env_id:\n replacement = next(\n (env.id for env in self.config.environments if env.is_default), None\n )\n self.config.settings.default_environment_id = replacement\n logger.reason(\n \"Environment deleted\",\n extra={\"env_id\": env_id, \"remaining\": len(self.config.environments)},\n )\n self.save()\n return True\n # #endregion delete_environment\n# #endregion ConfigManager\n# #endregion ConfigManager\n" + "body": "# #region ConfigManager [C:5] [TYPE Module] [SEMANTICS sqlalchemy, validate, migration, config-manager]\n#\n# @BRIEF Manages application configuration persistence in DB with one-time migration from legacy JSON.\n# @LAYER: Domain\n# @PRE: Database schema for AppConfigRecord must be initialized.\n# @POST: Configuration is loaded into memory and logger is configured.\n# @SIDE_EFFECT: Performs DB I/O and may update global logging level.\n# @DATA_CONTRACT: Input[json, record] -> Model[AppConfig]\n# @INVARIANT: Configuration must always be representable by AppConfig and persisted under global record id.\n# @RELATION DEPENDS_ON -> [AppConfig]\n# @RELATION DEPENDS_ON -> [SessionLocal]\n# @RELATION DEPENDS_ON -> [AppConfigRecord]\n# @RELATION CALLS -> [logger]\n# @RELATION CALLS -> [configure_logger]\n#\nimport json\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ..models.config import AppConfigRecord\nfrom ..models.mapping import Environment as EnvironmentRecord\nfrom .config_models import AppConfig, Environment, GlobalSettings\nfrom .database import SessionLocal\nfrom .logger import belief_scope, configure_logger, logger\n\n\n# #region ConfigManager [C:5] [TYPE Class]\n# @BRIEF Handles application configuration load, validation, mutation, and persistence lifecycle.\n# @PRE: Database is accessible and AppConfigRecord schema is loaded.\n# @POST: Configuration state is synchronized between memory and database.\n# @SIDE_EFFECT: Performs DB I/O, OS path validation, and logger reconfiguration.\nclass ConfigManager:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initialize manager state from persisted or migrated configuration.\n # @PRE: config_path is a non-empty string path.\n # @POST: self.config is initialized as AppConfig and logger is configured.\n # @SIDE_EFFECT: Reads config sources and updates logging configuration.\n # @DATA_CONTRACT: Input(str config_path) -> Output(None; self.config: AppConfig)\n def __init__(self, config_path: str = \"config.json\"):\n with belief_scope(\"ConfigManager.__init__\"):\n if not isinstance(config_path, str) or not config_path:\n logger.explore(\n \"Invalid config_path provided\", extra={\"path\": config_path}\n )\n raise ValueError(\"config_path must be a non-empty string\")\n logger.reason(f\"Initializing ConfigManager with legacy path: {config_path}\")\n self.config_path = Path(config_path)\n self.raw_payload: dict[str, Any] = {}\n self.config: AppConfig = self._load_config()\n configure_logger(self.config.settings.logging)\n if not isinstance(self.config, AppConfig):\n logger.explore(\n \"Config loading resulted in invalid type\",\n extra={\"type\": type(self.config)},\n )\n raise TypeError(\"self.config must be an instance of AppConfig\")\n logger.reflect(\"ConfigManager initialization complete\")\n # #endregion __init__\n # #region _apply_features_from_env [TYPE Function]\n # @PURPOSE: Read FEATURES__* env vars and apply them to a GlobalSettings features config.\n # @SIDE_EFFECT: Reads os.environ; mutates settings.features in-place.\n # @RATIONALE: Env vars seed the initial defaults. After first bootstrap, DB is source of truth.\n @staticmethod\n def _apply_features_from_env(settings: GlobalSettings) -> None:\n with belief_scope(\"ConfigManager._apply_features_from_env\"):\n dataset_review_env = os.getenv(\"FEATURES__DATASET_REVIEW\")\n if dataset_review_env is not None:\n parsed = dataset_review_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.dataset_review = parsed\n logger.reason(\n \"Applied FEATURES__DATASET_REVIEW from env\",\n extra={\"value\": parsed, \"raw\": dataset_review_env},\n )\n health_monitor_env = os.getenv(\"FEATURES__HEALTH_MONITOR\")\n if health_monitor_env is not None:\n parsed = health_monitor_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.health_monitor = parsed\n logger.reason(\n \"Applied FEATURES__HEALTH_MONITOR from env\",\n extra={\"value\": parsed, \"raw\": health_monitor_env},\n )\n\n app_timezone_env = os.getenv(\"APP_TIMEZONE\")\n if app_timezone_env is not None:\n settings.app_timezone = app_timezone_env.strip()\n logger.reason(\n \"Applied APP_TIMEZONE from env\",\n extra={\"value\": settings.app_timezone},\n )\n # #endregion _apply_features_from_env\n # #region _default_config [TYPE Function]\n # @PURPOSE: Build default application configuration fallback.\n def _default_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager._default_config\"):\n logger.reason(\"Building default AppConfig fallback\")\n config = AppConfig(environments=[], settings=GlobalSettings())\n self._apply_features_from_env(config.settings)\n return config\n # #endregion _default_config\n # #region _sync_raw_payload_from_config [TYPE Function]\n # @PURPOSE: Merge typed AppConfig state into raw payload while preserving unsupported legacy sections.\n def _sync_raw_payload_from_config(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager._sync_raw_payload_from_config\"):\n typed_payload = self.config.model_dump()\n merged_payload = dict(self.raw_payload or {})\n merged_payload[\"environments\"] = typed_payload.get(\"environments\", [])\n merged_payload[\"settings\"] = typed_payload.get(\"settings\", {})\n self.raw_payload = merged_payload\n logger.reason(\n \"Synchronized raw payload from typed config\",\n extra={\n \"environments_count\": len(\n merged_payload.get(\"environments\", []) or []\n ),\n \"has_settings\": \"settings\" in merged_payload,\n \"extra_sections\": sorted(\n key\n for key in merged_payload\n if key not in {\"environments\", \"settings\"}\n ),\n },\n )\n return merged_payload\n # #endregion _sync_raw_payload_from_config\n # #region _load_from_legacy_file [TYPE Function]\n # @PURPOSE: Load legacy JSON configuration for migration fallback path.\n def _load_from_legacy_file(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager._load_from_legacy_file\"):\n if not self.config_path.exists():\n logger.reason(\n \"Legacy config file not found; using default payload\",\n extra={\"path\": str(self.config_path)},\n )\n return {}\n logger.reason(\n \"Loading legacy config file\", extra={\"path\": str(self.config_path)}\n )\n with self.config_path.open(\"r\", encoding=\"utf-8\") as fh:\n payload = json.load(fh)\n if not isinstance(payload, dict):\n logger.explore(\n \"Legacy config payload is not a JSON object\",\n extra={\n \"path\": str(self.config_path),\n \"type\": type(payload).__name__,\n },\n )\n raise ValueError(\"Legacy config payload must be a JSON object\")\n logger.reason(\n \"Legacy config file loaded successfully\",\n extra={\"path\": str(self.config_path), \"keys\": sorted(payload.keys())},\n )\n return payload\n # #endregion _load_from_legacy_file\n # #region _get_record [TYPE Function]\n # @PURPOSE: Resolve global configuration record from DB.\n def _get_record(self, session: Session) -> AppConfigRecord | None:\n with belief_scope(\"ConfigManager._get_record\"):\n record = (\n session.query(AppConfigRecord)\n .filter(AppConfigRecord.id == \"global\")\n .first()\n )\n logger.reason(\n \"Resolved app config record\", extra={\"exists\": record is not None}\n )\n return record\n # #endregion _get_record\n # #region _load_config [TYPE Function]\n # @PURPOSE: Load configuration from DB or perform one-time migration from legacy JSON.\n def _load_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager._load_config\"):\n session = SessionLocal()\n try:\n record = self._get_record(session)\n if record and isinstance(record.payload, dict):\n logger.reason(\n \"Loading configuration from database\",\n extra={\"record_id\": record.id},\n )\n self.raw_payload = dict(record.payload)\n config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self._sync_environment_records(session, config)\n session.commit()\n logger.reason(\n \"Database configuration validated successfully\",\n extra={\n \"environments_count\": len(config.environments),\n \"payload_keys\": sorted(self.raw_payload.keys()),\n },\n )\n return config\n logger.reason(\n \"Database configuration record missing; attempting legacy file migration\",\n extra={\"legacy_path\": str(self.config_path)},\n )\n legacy_payload = self._load_from_legacy_file()\n if legacy_payload:\n self.raw_payload = dict(legacy_payload)\n config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self._apply_features_from_env(config.settings)\n logger.reason(\n \"Legacy payload validated; persisting migrated configuration to database\",\n extra={\n \"environments_count\": len(config.environments),\n \"payload_keys\": sorted(self.raw_payload.keys()),\n },\n )\n self._save_config_to_db(config, session=session)\n return config\n logger.reason(\n \"No persisted config found; falling back to default configuration\"\n )\n config = self._default_config()\n self.raw_payload = config.model_dump()\n self._save_config_to_db(config, session=session)\n return config\n except (json.JSONDecodeError, TypeError, ValueError) as exc:\n logger.explore(\n \"Recoverable config load failure; falling back to default configuration\",\n extra={\"error\": str(exc), \"legacy_path\": str(self.config_path)},\n )\n config = self._default_config()\n self.raw_payload = config.model_dump()\n return config\n except Exception as exc:\n logger.explore(\n \"Critical config load failure; re-raising persistence or validation error\",\n extra={\"error\": str(exc)},\n )\n raise\n finally:\n session.close()\n # #endregion _load_config\n # #region _sync_environment_records [TYPE Function]\n # @PURPOSE: Mirror configured environments into the relational environments table used by FK-backed domain models.\n def _sync_environment_records(self, session: Session, config: AppConfig) -> None:\n with belief_scope(\"ConfigManager._sync_environment_records\"):\n configured_envs = list(config.environments or [])\n persisted_records = session.query(EnvironmentRecord).all()\n persisted_by_id = {\n str(record.id or \"\").strip(): record for record in persisted_records\n }\n for environment in configured_envs:\n normalized_id = str(environment.id or \"\").strip()\n if not normalized_id:\n continue\n display_name = (\n str(environment.name or normalized_id).strip() or normalized_id\n )\n normalized_url = str(environment.url or \"\").strip()\n credentials_id = (\n str(environment.username or \"\").strip() or normalized_id\n )\n record = persisted_by_id.get(normalized_id)\n if record is None:\n logger.reason(\n \"Creating relational environment record from typed config\",\n extra={\n \"environment_id\": normalized_id,\n \"environment_name\": display_name,\n },\n )\n session.add(\n EnvironmentRecord(\n id=normalized_id,\n name=display_name,\n url=normalized_url,\n credentials_id=credentials_id,\n )\n )\n continue\n record.name = display_name\n record.url = normalized_url\n record.credentials_id = credentials_id\n # #endregion _sync_environment_records\n # #region _delete_stale_environment_records [TYPE Function]\n # @PURPOSE: Remove persisted environment records that are no longer in the configured environments.\n # @PRE: _sync_environment_records must already have run so the query returns a current view.\n # @POST: Stale Environment rows are deleted via the session (caller must commit).\n # @SIDE_EFFECT: Only safe to call during explicit save (_save_config_to_db), NOT during _load_config,\n # because FK-dependent rows (task_records, database_mappings, etc.) may reference deleted rows.\n def _delete_stale_environment_records(\n self, session: Session, config: AppConfig\n ) -> None:\n with belief_scope(\"ConfigManager._delete_stale_environment_records\"):\n persisted_records = session.query(EnvironmentRecord).all()\n configured_ids = {\n str(env.id or \"\").strip()\n for env in (config.environments or [])\n if str(env.id or \"\").strip()\n }\n for record in persisted_records:\n record_id = str(record.id or \"\").strip()\n if record_id and record_id not in configured_ids:\n logger.reason(\n \"Deleting stale environment record\",\n extra={\"environment_id\": record_id},\n )\n session.delete(record)\n # #endregion _delete_stale_environment_records\n # #region _save_config_to_db [TYPE Function]\n # @PURPOSE: Persist provided AppConfig into the global DB configuration record.\n def _save_config_to_db(\n self, config: AppConfig, session: Session | None = None\n ) -> None:\n with belief_scope(\"ConfigManager._save_config_to_db\"):\n owns_session = session is None\n db = session or SessionLocal()\n try:\n self.config = config\n payload = self._sync_raw_payload_from_config()\n record = self._get_record(db)\n if record is None:\n logger.reason(\"Creating new global app config record\")\n record = AppConfigRecord(id=\"global\", payload=payload)\n db.add(record)\n else:\n logger.reason(\n \"Updating existing global app config record\",\n extra={\"record_id\": record.id},\n )\n record.payload = payload\n self._sync_environment_records(db, config)\n self._delete_stale_environment_records(db, config)\n db.commit()\n logger.reason(\n \"Configuration persisted to database\",\n extra={\n \"environments_count\": len(\n payload.get(\"environments\", []) or []\n ),\n \"payload_keys\": sorted(payload.keys()),\n },\n )\n except Exception:\n db.rollback()\n logger.explore(\"Database save failed; transaction rolled back\")\n raise\n finally:\n if owns_session:\n db.close()\n # #endregion _save_config_to_db\n # #region save [TYPE Function]\n # @PURPOSE: Persist current in-memory configuration state.\n def save(self) -> None:\n with belief_scope(\"ConfigManager.save\"):\n logger.reason(\"Persisting current in-memory configuration\")\n self._save_config_to_db(self.config)\n # #endregion save\n # #region get_config [TYPE Function]\n # @PURPOSE: Return current in-memory configuration snapshot.\n def get_config(self) -> AppConfig:\n with belief_scope(\"ConfigManager.get_config\"):\n return self.config\n # #endregion get_config\n # #region get_payload [TYPE Function]\n # @PURPOSE: Return full persisted payload including sections outside typed AppConfig schema.\n def get_payload(self) -> dict[str, Any]:\n with belief_scope(\"ConfigManager.get_payload\"):\n return self._sync_raw_payload_from_config()\n # #endregion get_payload\n # #region save_config [TYPE Function]\n # @PURPOSE: Persist configuration provided either as typed AppConfig or raw payload dict.\n def save_config(self, config: Any) -> AppConfig:\n with belief_scope(\"ConfigManager.save_config\"):\n if isinstance(config, AppConfig):\n logger.reason(\"Saving typed AppConfig payload\")\n self.config = config\n self.raw_payload = config.model_dump()\n self._save_config_to_db(config)\n return self.config\n if isinstance(config, dict):\n logger.reason(\n \"Saving raw config payload\",\n extra={\"keys\": sorted(config.keys())},\n )\n self.raw_payload = dict(config)\n typed_config = AppConfig.model_validate(\n {\n \"environments\": self.raw_payload.get(\"environments\", []),\n \"settings\": self.raw_payload.get(\"settings\", {}),\n }\n )\n self.config = typed_config\n self._save_config_to_db(typed_config)\n return self.config\n logger.explore(\n \"Unsupported config type supplied to save_config\",\n extra={\"type\": type(config).__name__},\n )\n raise TypeError(\"config must be AppConfig or dict\")\n # #endregion save_config\n # #region update_global_settings [TYPE Function]\n # @PURPOSE: Replace global settings and persist the resulting configuration.\n def update_global_settings(self, settings: GlobalSettings) -> AppConfig:\n with belief_scope(\"ConfigManager.update_global_settings\"):\n logger.reason(\"Updating global settings\")\n self.config.settings = settings\n self.save()\n return self.config\n # #endregion update_global_settings\n # #region validate_path [TYPE Function]\n # @PURPOSE: Validate that path exists and is writable, creating it when absent.\n def validate_path(self, path: str) -> tuple[bool, str]:\n with belief_scope(\"ConfigManager.validate_path\", f\"path={path}\"):\n try:\n target = Path(path).expanduser()\n target.mkdir(parents=True, exist_ok=True)\n if not target.exists():\n return False, f\"Path does not exist: {target}\"\n if not target.is_dir():\n return False, f\"Path is not a directory: {target}\"\n test_file = target / \".write_test\"\n with test_file.open(\"w\", encoding=\"utf-8\") as fh:\n fh.write(\"ok\")\n test_file.unlink(missing_ok=True)\n logger.reason(\"Path validation succeeded\", extra={\"path\": str(target)})\n return True, \"OK\"\n except Exception as exc:\n logger.explore(\n \"Path validation failed\", extra={\"path\": path, \"error\": str(exc)}\n )\n return False, str(exc)\n # #endregion validate_path\n # #region get_environments [TYPE Function]\n # @PURPOSE: Return all configured environments.\n def get_environments(self) -> list[Environment]:\n with belief_scope(\"ConfigManager.get_environments\"):\n return list(self.config.environments)\n # #endregion get_environments\n # #region has_environments [TYPE Function]\n # @PURPOSE: Check whether at least one environment exists in configuration.\n def has_environments(self) -> bool:\n with belief_scope(\"ConfigManager.has_environments\"):\n return len(self.config.environments) > 0\n # #endregion has_environments\n # #region get_environment [TYPE Function]\n # @PURPOSE: Resolve a configured environment by identifier.\n def get_environment(self, env_id: str) -> Environment | None:\n with belief_scope(\"ConfigManager.get_environment\", f\"env_id={env_id}\"):\n normalized = str(env_id or \"\").strip()\n if not normalized:\n return None\n for env in self.config.environments:\n if env.id == normalized or env.name == normalized:\n return env\n return None\n # #endregion get_environment\n # #region add_environment [TYPE Function]\n # @PURPOSE: Upsert environment by id into configuration and persist.\n def add_environment(self, env: Environment) -> AppConfig:\n with belief_scope(\"ConfigManager.add_environment\", f\"env_id={env.id}\"):\n existing_index = next(\n (\n i\n for i, item in enumerate(self.config.environments)\n if item.id == env.id\n ),\n None,\n )\n if env.is_default:\n for item in self.config.environments:\n item.is_default = False\n if existing_index is None:\n logger.reason(\"Appending new environment\", extra={\"env_id\": env.id})\n self.config.environments.append(env)\n else:\n logger.reason(\n \"Replacing existing environment during add\",\n extra={\"env_id\": env.id},\n )\n self.config.environments[existing_index] = env\n if len(self.config.environments) == 1 and not any(\n item.is_default for item in self.config.environments\n ):\n self.config.environments[0].is_default = True\n self.save()\n return self.config\n # #endregion add_environment\n # #region update_environment [TYPE Function]\n # @PURPOSE: Update existing environment by id and preserve masked password placeholder behavior.\n def update_environment(self, env_id: str, env: Environment) -> bool:\n with belief_scope(\"ConfigManager.update_environment\", f\"env_id={env_id}\"):\n for index, existing in enumerate(self.config.environments):\n if existing.id != env_id:\n continue\n update_data = env.model_dump()\n if update_data.get(\"password\") == \"********\":\n update_data[\"password\"] = existing.password\n updated = Environment.model_validate(update_data)\n if updated.is_default:\n for item in self.config.environments:\n item.is_default = False\n elif existing.is_default and not updated.is_default:\n updated.is_default = True\n self.config.environments[index] = updated\n logger.reason(\"Environment updated\", extra={\"env_id\": env_id})\n self.save()\n return True\n logger.explore(\n \"Environment update skipped; env not found\", extra={\"env_id\": env_id}\n )\n return False\n # #endregion update_environment\n # #region delete_environment [TYPE Function]\n # @PURPOSE: Delete environment by id and persist when deletion occurs.\n def delete_environment(self, env_id: str) -> bool:\n with belief_scope(\"ConfigManager.delete_environment\", f\"env_id={env_id}\"):\n before = len(self.config.environments)\n removed = [env for env in self.config.environments if env.id == env_id]\n self.config.environments = [\n env for env in self.config.environments if env.id != env_id\n ]\n if len(self.config.environments) == before:\n logger.explore(\n \"Environment delete skipped; env not found\",\n extra={\"env_id\": env_id},\n )\n return False\n if removed and removed[0].is_default and self.config.environments:\n self.config.environments[0].is_default = True\n if self.config.settings.default_environment_id == env_id:\n replacement = next(\n (env.id for env in self.config.environments if env.is_default), None\n )\n self.config.settings.default_environment_id = replacement\n logger.reason(\n \"Environment deleted\",\n extra={\"env_id\": env_id, \"remaining\": len(self.config.environments)},\n )\n self.save()\n return True\n # #endregion delete_environment\n# #endregion ConfigManager\n# #endregion ConfigManager\n" }, { "contract_id": "_apply_features_from_env", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", "start_line": 62, - "end_line": 85, + "end_line": 93, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20610,14 +21510,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region _apply_features_from_env [TYPE Function]\n # @PURPOSE: Read FEATURES__* env vars and apply them to a GlobalSettings features config.\n # @SIDE_EFFECT: Reads os.environ; mutates settings.features in-place.\n # @RATIONALE: Env vars seed the initial defaults. After first bootstrap, DB is source of truth.\n @staticmethod\n def _apply_features_from_env(settings: GlobalSettings) -> None:\n with belief_scope(\"ConfigManager._apply_features_from_env\"):\n dataset_review_env = os.getenv(\"FEATURES__DATASET_REVIEW\")\n if dataset_review_env is not None:\n parsed = dataset_review_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.dataset_review = parsed\n logger.reason(\n \"Applied FEATURES__DATASET_REVIEW from env\",\n extra={\"value\": parsed, \"raw\": dataset_review_env},\n )\n health_monitor_env = os.getenv(\"FEATURES__HEALTH_MONITOR\")\n if health_monitor_env is not None:\n parsed = health_monitor_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.health_monitor = parsed\n logger.reason(\n \"Applied FEATURES__HEALTH_MONITOR from env\",\n extra={\"value\": parsed, \"raw\": health_monitor_env},\n )\n # #endregion _apply_features_from_env\n" + "body": " # #region _apply_features_from_env [TYPE Function]\n # @PURPOSE: Read FEATURES__* env vars and apply them to a GlobalSettings features config.\n # @SIDE_EFFECT: Reads os.environ; mutates settings.features in-place.\n # @RATIONALE: Env vars seed the initial defaults. After first bootstrap, DB is source of truth.\n @staticmethod\n def _apply_features_from_env(settings: GlobalSettings) -> None:\n with belief_scope(\"ConfigManager._apply_features_from_env\"):\n dataset_review_env = os.getenv(\"FEATURES__DATASET_REVIEW\")\n if dataset_review_env is not None:\n parsed = dataset_review_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.dataset_review = parsed\n logger.reason(\n \"Applied FEATURES__DATASET_REVIEW from env\",\n extra={\"value\": parsed, \"raw\": dataset_review_env},\n )\n health_monitor_env = os.getenv(\"FEATURES__HEALTH_MONITOR\")\n if health_monitor_env is not None:\n parsed = health_monitor_env.strip().lower() in (\"true\", \"1\", \"yes\")\n settings.features.health_monitor = parsed\n logger.reason(\n \"Applied FEATURES__HEALTH_MONITOR from env\",\n extra={\"value\": parsed, \"raw\": health_monitor_env},\n )\n\n app_timezone_env = os.getenv(\"APP_TIMEZONE\")\n if app_timezone_env is not None:\n settings.app_timezone = app_timezone_env.strip()\n logger.reason(\n \"Applied APP_TIMEZONE from env\",\n extra={\"value\": settings.app_timezone},\n )\n # #endregion _apply_features_from_env\n" }, { "contract_id": "_default_config", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 86, - "end_line": 94, + "start_line": 94, + "end_line": 102, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20633,8 +21533,8 @@ "contract_id": "_sync_raw_payload_from_config", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 95, - "end_line": 119, + "start_line": 103, + "end_line": 127, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20650,8 +21550,8 @@ "contract_id": "_load_from_legacy_file", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 120, - "end_line": 149, + "start_line": 128, + "end_line": 157, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20667,8 +21567,8 @@ "contract_id": "_get_record", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 150, - "end_line": 163, + "start_line": 158, + "end_line": 171, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20684,8 +21584,8 @@ "contract_id": "_load_config", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 164, - "end_line": 239, + "start_line": 172, + "end_line": 247, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20701,8 +21601,8 @@ "contract_id": "_sync_environment_records", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 240, - "end_line": 281, + "start_line": 248, + "end_line": 289, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20718,8 +21618,8 @@ "contract_id": "_delete_stale_environment_records", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 282, - "end_line": 306, + "start_line": 290, + "end_line": 314, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20738,8 +21638,8 @@ "contract_id": "_save_config_to_db", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 307, - "end_line": 348, + "start_line": 315, + "end_line": 356, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20755,8 +21655,8 @@ "contract_id": "save", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 349, - "end_line": 355, + "start_line": 357, + "end_line": 363, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20772,8 +21672,8 @@ "contract_id": "get_config", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 356, - "end_line": 361, + "start_line": 364, + "end_line": 369, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20789,8 +21689,8 @@ "contract_id": "get_payload", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 362, - "end_line": 367, + "start_line": 370, + "end_line": 375, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20806,8 +21706,8 @@ "contract_id": "save_config", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 368, - "end_line": 398, + "start_line": 376, + "end_line": 406, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20823,8 +21723,8 @@ "contract_id": "update_global_settings", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 399, - "end_line": 407, + "start_line": 407, + "end_line": 415, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20840,8 +21740,8 @@ "contract_id": "validate_path", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 408, - "end_line": 430, + "start_line": 416, + "end_line": 438, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20857,8 +21757,8 @@ "contract_id": "get_environments", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 431, - "end_line": 436, + "start_line": 439, + "end_line": 444, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20874,8 +21774,8 @@ "contract_id": "has_environments", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 437, - "end_line": 442, + "start_line": 445, + "end_line": 450, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20891,8 +21791,8 @@ "contract_id": "get_environment", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 443, - "end_line": 454, + "start_line": 451, + "end_line": 462, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20908,8 +21808,8 @@ "contract_id": "add_environment", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 455, - "end_line": 485, + "start_line": 463, + "end_line": 493, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20925,8 +21825,8 @@ "contract_id": "update_environment", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 486, - "end_line": 510, + "start_line": 494, + "end_line": 518, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20942,8 +21842,8 @@ "contract_id": "delete_environment", "contract_type": "Function", "file_path": "backend/src/core/config_manager.py", - "start_line": 511, - "end_line": 539, + "start_line": 519, + "end_line": 547, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -20960,7 +21860,7 @@ "contract_type": "Module", "file_path": "backend/src/core/config_models.py", "start_line": 1, - "end_line": 130, + "end_line": 143, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -20985,7 +21885,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ConfigModels [C:3] [TYPE Module] [SEMANTICS pydantic, model, schedule]\n# @BRIEF Defines the data models for application configuration using Pydantic.\n# @LAYER: Core\n# @RELATION IMPLEMENTS -> [CoreContracts]\n# @RELATION IMPLEMENTS -> [ConnectionContracts]\n\n\nfrom pydantic import BaseModel, Field\n\nfrom ..models.storage import StorageConfig\nfrom ..services.llm_prompt_templates import (\n DEFAULT_LLM_ASSISTANT_SETTINGS,\n DEFAULT_LLM_PROMPTS,\n DEFAULT_LLM_PROVIDER_BINDINGS,\n)\n\n\n# #region Schedule [TYPE DataClass]\n# @BRIEF Represents a backup schedule configuration.\nclass Schedule(BaseModel):\n enabled: bool = False\n cron_expression: str = \"0 0 * * *\" # Default: daily at midnight\n\n\n# #endregion Schedule\n\n\n# #region Environment [TYPE DataClass]\n# @BRIEF Represents a Superset environment configuration.\nclass Environment(BaseModel):\n id: str\n name: str\n url: str\n username: str\n password: str # Will be masked in UI\n stage: str = Field(default=\"DEV\", pattern=\"^(DEV|PREPROD|PROD)$\")\n verify_ssl: bool = True\n timeout: int = 30\n is_default: bool = False\n is_production: bool = False\n backup_schedule: Schedule = Field(default_factory=Schedule)\n\n\n# #endregion Environment\n\n\n# #region LoggingConfig [TYPE DataClass]\n# @BRIEF Defines the configuration for the application's logging system.\nclass LoggingConfig(BaseModel):\n level: str = \"INFO\"\n task_log_level: str = (\n \"INFO\" # Minimum level for task-specific logs (DEBUG, INFO, WARNING, ERROR)\n )\n file_path: str | None = None\n max_bytes: int = 10 * 1024 * 1024\n backup_count: int = 5\n enable_belief_state: bool = True\n\n\n# #endregion LoggingConfig\n\n\n# #region CleanReleaseConfig [TYPE DataClass]\n# @BRIEF Configuration for clean release compliance subsystem.\nclass CleanReleaseConfig(BaseModel):\n active_policy_id: str | None = None\n active_registry_id: str | None = None\n\n\n# #endregion CleanReleaseConfig\n\n\n# #region FeaturesConfig [C:1] [TYPE DataClass]\n# @BRIEF Top-level feature flags that toggle entire project features on/off.\n# @RATIONALE: Features are read from environment variables on bootstrap and persisted in DB.\n# DB is source of truth after initial bootstrap; env vars only seed defaults.\nclass FeaturesConfig(BaseModel):\n dataset_review: bool = True\n health_monitor: bool = True\n\n\n# #endregion FeaturesConfig\n\n\n# #region GlobalSettings [TYPE DataClass]\n# @BRIEF Represents global application settings.\nclass GlobalSettings(BaseModel):\n storage: StorageConfig = Field(default_factory=StorageConfig)\n clean_release: CleanReleaseConfig = Field(default_factory=CleanReleaseConfig)\n default_environment_id: str | None = None\n logging: LoggingConfig = Field(default_factory=LoggingConfig)\n features: FeaturesConfig = Field(default_factory=FeaturesConfig)\n connections: list[dict] = []\n llm: dict = Field(\n default_factory=lambda: {\n \"providers\": [],\n \"default_provider\": \"\",\n \"prompts\": dict(DEFAULT_LLM_PROMPTS),\n \"provider_bindings\": dict(DEFAULT_LLM_PROVIDER_BINDINGS),\n **dict(DEFAULT_LLM_ASSISTANT_SETTINGS),\n }\n )\n\n # Task retention settings\n task_retention_days: int = 30\n task_retention_limit: int = 100\n pagination_limit: int = 10\n\n # Migration sync settings\n migration_sync_cron: str = \"0 2 * * *\"\n\n # Dataset Review Feature Flags\n ff_dataset_auto_review: bool = True\n ff_dataset_clarification: bool = True\n ff_dataset_execution: bool = True\n\n\n# #endregion GlobalSettings\n\n\n# #region AppConfig [TYPE DataClass]\n# @BRIEF The root configuration model containing all application settings.\nclass AppConfig(BaseModel):\n environments: list[Environment] = []\n settings: GlobalSettings\n\n\n# #endregion AppConfig\n\n# #endregion ConfigModels\n" + "body": "# #region ConfigModels [C:3] [TYPE Module] [SEMANTICS pydantic, model, schedule]\n# @BRIEF Defines the data models for application configuration using Pydantic.\n# @LAYER: Core\n# @RELATION IMPLEMENTS -> [CoreContracts]\n# @RELATION IMPLEMENTS -> [ConnectionContracts]\n\n\nfrom pydantic import BaseModel, Field, field_validator\n\nfrom ..models.storage import StorageConfig\nfrom ..services.llm_prompt_templates import (\n DEFAULT_LLM_ASSISTANT_SETTINGS,\n DEFAULT_LLM_PROMPTS,\n DEFAULT_LLM_PROVIDER_BINDINGS,\n)\n\n\n# #region Schedule [TYPE DataClass]\n# @BRIEF Represents a backup schedule configuration.\nclass Schedule(BaseModel):\n enabled: bool = False\n cron_expression: str = \"0 0 * * *\" # Default: daily at midnight\n\n\n# #endregion Schedule\n\n\n# #region Environment [TYPE DataClass]\n# @BRIEF Represents a Superset environment configuration.\nclass Environment(BaseModel):\n id: str\n name: str\n url: str\n username: str\n password: str # Will be masked in UI\n stage: str = Field(default=\"DEV\", pattern=\"^(DEV|PREPROD|PROD)$\")\n verify_ssl: bool = True\n timeout: int = 30\n is_default: bool = False\n is_production: bool = False\n backup_schedule: Schedule = Field(default_factory=Schedule)\n\n\n# #endregion Environment\n\n\n# #region LoggingConfig [TYPE DataClass]\n# @BRIEF Defines the configuration for the application's logging system.\nclass LoggingConfig(BaseModel):\n level: str = \"INFO\"\n task_log_level: str = (\n \"INFO\" # Minimum level for task-specific logs (DEBUG, INFO, WARNING, ERROR)\n )\n file_path: str | None = None\n max_bytes: int = 10 * 1024 * 1024\n backup_count: int = 5\n enable_belief_state: bool = True\n\n\n# #endregion LoggingConfig\n\n\n# #region CleanReleaseConfig [TYPE DataClass]\n# @BRIEF Configuration for clean release compliance subsystem.\nclass CleanReleaseConfig(BaseModel):\n active_policy_id: str | None = None\n active_registry_id: str | None = None\n\n\n# #endregion CleanReleaseConfig\n\n\n# #region FeaturesConfig [C:1] [TYPE DataClass]\n# @BRIEF Top-level feature flags that toggle entire project features on/off.\n# @RATIONALE: Features are read from environment variables on bootstrap and persisted in DB.\n# DB is source of truth after initial bootstrap; env vars only seed defaults.\nclass FeaturesConfig(BaseModel):\n dataset_review: bool = True\n health_monitor: bool = True\n\n\n# #endregion FeaturesConfig\n\n\n# #region GlobalSettings [TYPE DataClass]\n# @BRIEF Represents global application settings.\nclass GlobalSettings(BaseModel):\n storage: StorageConfig = Field(default_factory=StorageConfig)\n clean_release: CleanReleaseConfig = Field(default_factory=CleanReleaseConfig)\n default_environment_id: str | None = None\n logging: LoggingConfig = Field(default_factory=LoggingConfig)\n features: FeaturesConfig = Field(default_factory=FeaturesConfig)\n connections: list[dict] = []\n llm: dict = Field(\n default_factory=lambda: {\n \"providers\": [],\n \"default_provider\": \"\",\n \"prompts\": dict(DEFAULT_LLM_PROMPTS),\n \"provider_bindings\": dict(DEFAULT_LLM_PROVIDER_BINDINGS),\n **dict(DEFAULT_LLM_ASSISTANT_SETTINGS),\n }\n )\n\n # Application timezone\n app_timezone: str = \"Europe/Moscow\"\n\n @field_validator(\"app_timezone\")\n @classmethod\n def validate_app_timezone(cls, v: str) -> str:\n from zoneinfo import ZoneInfo\n try:\n ZoneInfo(v)\n except (KeyError, TypeError):\n raise ValueError(f\"Invalid IANA timezone: {v}\") from None\n return v\n\n # Task retention settings\n task_retention_days: int = 30\n task_retention_limit: int = 100\n pagination_limit: int = 10\n\n # Migration sync settings\n migration_sync_cron: str = \"0 2 * * *\"\n\n # Dataset Review Feature Flags\n ff_dataset_auto_review: bool = True\n ff_dataset_clarification: bool = True\n ff_dataset_execution: bool = True\n\n\n# #endregion GlobalSettings\n\n\n# #region AppConfig [TYPE DataClass]\n# @BRIEF The root configuration model containing all application settings.\nclass AppConfig(BaseModel):\n environments: list[Environment] = []\n settings: GlobalSettings\n\n\n# #endregion AppConfig\n\n# #endregion ConfigModels\n" }, { "contract_id": "Schedule", @@ -21272,7 +22172,7 @@ "contract_type": "DataClass", "file_path": "backend/src/core/config_models.py", "start_line": 85, - "end_line": 118, + "end_line": 131, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21310,14 +22210,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region GlobalSettings [TYPE DataClass]\n# @BRIEF Represents global application settings.\nclass GlobalSettings(BaseModel):\n storage: StorageConfig = Field(default_factory=StorageConfig)\n clean_release: CleanReleaseConfig = Field(default_factory=CleanReleaseConfig)\n default_environment_id: str | None = None\n logging: LoggingConfig = Field(default_factory=LoggingConfig)\n features: FeaturesConfig = Field(default_factory=FeaturesConfig)\n connections: list[dict] = []\n llm: dict = Field(\n default_factory=lambda: {\n \"providers\": [],\n \"default_provider\": \"\",\n \"prompts\": dict(DEFAULT_LLM_PROMPTS),\n \"provider_bindings\": dict(DEFAULT_LLM_PROVIDER_BINDINGS),\n **dict(DEFAULT_LLM_ASSISTANT_SETTINGS),\n }\n )\n\n # Task retention settings\n task_retention_days: int = 30\n task_retention_limit: int = 100\n pagination_limit: int = 10\n\n # Migration sync settings\n migration_sync_cron: str = \"0 2 * * *\"\n\n # Dataset Review Feature Flags\n ff_dataset_auto_review: bool = True\n ff_dataset_clarification: bool = True\n ff_dataset_execution: bool = True\n\n\n# #endregion GlobalSettings\n" + "body": "# #region GlobalSettings [TYPE DataClass]\n# @BRIEF Represents global application settings.\nclass GlobalSettings(BaseModel):\n storage: StorageConfig = Field(default_factory=StorageConfig)\n clean_release: CleanReleaseConfig = Field(default_factory=CleanReleaseConfig)\n default_environment_id: str | None = None\n logging: LoggingConfig = Field(default_factory=LoggingConfig)\n features: FeaturesConfig = Field(default_factory=FeaturesConfig)\n connections: list[dict] = []\n llm: dict = Field(\n default_factory=lambda: {\n \"providers\": [],\n \"default_provider\": \"\",\n \"prompts\": dict(DEFAULT_LLM_PROMPTS),\n \"provider_bindings\": dict(DEFAULT_LLM_PROVIDER_BINDINGS),\n **dict(DEFAULT_LLM_ASSISTANT_SETTINGS),\n }\n )\n\n # Application timezone\n app_timezone: str = \"Europe/Moscow\"\n\n @field_validator(\"app_timezone\")\n @classmethod\n def validate_app_timezone(cls, v: str) -> str:\n from zoneinfo import ZoneInfo\n try:\n ZoneInfo(v)\n except (KeyError, TypeError):\n raise ValueError(f\"Invalid IANA timezone: {v}\") from None\n return v\n\n # Task retention settings\n task_retention_days: int = 30\n task_retention_limit: int = 100\n pagination_limit: int = 10\n\n # Migration sync settings\n migration_sync_cron: str = \"0 2 * * *\"\n\n # Dataset Review Feature Flags\n ff_dataset_auto_review: bool = True\n ff_dataset_clarification: bool = True\n ff_dataset_execution: bool = True\n\n\n# #endregion GlobalSettings\n" }, { "contract_id": "AppConfig", "contract_type": "DataClass", "file_path": "backend/src/core/config_models.py", - "start_line": 121, - "end_line": 128, + "start_line": 134, + "end_line": 141, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21718,7 +22618,7 @@ "contract_type": "Module", "file_path": "backend/src/core/database.py", "start_line": 1, - "end_line": 740, + "end_line": 742, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -21744,14 +22644,14 @@ "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#\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" + "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 api_key as _api_key_models, # noqa: F401\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 maintenance as _maintenance_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": 31, - "end_line": 34, + "start_line": 33, + "end_line": 36, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21822,8 +22722,8 @@ "contract_id": "DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 36, - "end_line": 52, + "start_line": 38, + "end_line": 54, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21922,8 +22822,8 @@ "contract_id": "TASKS_DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 54, - "end_line": 58, + "start_line": 56, + "end_line": 60, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -21994,8 +22894,8 @@ "contract_id": "AUTH_DATABASE_URL", "contract_type": "Constant", "file_path": "backend/src/core/database.py", - "start_line": 60, - "end_line": 63, + "start_line": 62, + "end_line": 65, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22066,8 +22966,8 @@ "contract_id": "engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 66, - "end_line": 77, + "start_line": 68, + "end_line": 79, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22163,8 +23063,8 @@ "contract_id": "tasks_engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 79, - "end_line": 82, + "start_line": 81, + "end_line": 84, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22235,8 +23135,8 @@ "contract_id": "auth_engine", "contract_type": "Variable", "file_path": "backend/src/core/database.py", - "start_line": 84, - "end_line": 87, + "start_line": 86, + "end_line": 89, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22307,8 +23207,8 @@ "contract_id": "SessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 89, - "end_line": 93, + "start_line": 91, + "end_line": 95, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22326,8 +23226,8 @@ "contract_id": "TasksSessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 95, - "end_line": 99, + "start_line": 97, + "end_line": 101, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22345,8 +23245,8 @@ "contract_id": "AuthSessionLocal", "contract_type": "Class", "file_path": "backend/src/core/database.py", - "start_line": 101, - "end_line": 105, + "start_line": 103, + "end_line": 107, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -22364,8 +23264,8 @@ "contract_id": "_ensure_user_dashboard_preferences_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 108, - "end_line": 174, + "start_line": 110, + "end_line": 176, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22391,8 +23291,8 @@ "contract_id": "_ensure_user_dashboard_preferences_health_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 177, - "end_line": 220, + "start_line": 179, + "end_line": 222, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22416,8 +23316,8 @@ "contract_id": "_ensure_llm_validation_results_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 223, - "end_line": 262, + "start_line": 225, + "end_line": 264, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22441,8 +23341,8 @@ "contract_id": "_ensure_git_server_configs_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 265, - "end_line": 302, + "start_line": 267, + "end_line": 304, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22468,8 +23368,8 @@ "contract_id": "_ensure_auth_users_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 305, - "end_line": 364, + "start_line": 307, + "end_line": 366, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22495,8 +23395,8 @@ "contract_id": "_ensure_filter_source_enum_values", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 367, - "end_line": 435, + "start_line": 369, + "end_line": 437, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22522,8 +23422,8 @@ "contract_id": "_ensure_dataset_review_session_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 438, - "end_line": 568, + "start_line": 440, + "end_line": 570, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -22556,8 +23456,8 @@ "contract_id": "_ensure_translation_schedules_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 571, - "end_line": 609, + "start_line": 573, + "end_line": 611, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22583,8 +23483,8 @@ "contract_id": "_ensure_dictionary_entries_columns", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 612, - "end_line": 658, + "start_line": 614, + "end_line": 660, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22608,8 +23508,8 @@ "contract_id": "init_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 661, - "end_line": 686, + "start_line": 663, + "end_line": 688, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22648,8 +23548,8 @@ "contract_id": "get_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 689, - "end_line": 703, + "start_line": 691, + "end_line": 705, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22675,8 +23575,8 @@ "contract_id": "get_tasks_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 706, - "end_line": 720, + "start_line": 708, + "end_line": 722, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22702,8 +23602,8 @@ "contract_id": "get_auth_db", "contract_type": "Function", "file_path": "backend/src/core/database.py", - "start_line": 723, - "end_line": 738, + "start_line": 725, + "end_line": 740, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -22802,7 +23702,7 @@ "contract_type": "Module", "file_path": "backend/src/core/logger.py", "start_line": 1, - "end_line": 312, + "end_line": 321, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -22860,7 +23760,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region LoggerModule [C:5] [TYPE Module] [SEMANTICS pydantic, logging, json, formatter, structured]\n# @BRIEF Application logging system with CotJsonFormatter producing molecular CoT JSON output.\n# @LAYER Core\n# @RELATION USED_BY -> [All application modules]\n# @RELATION DEPENDS_ON -> [CotLoggerModule]\n# @RELATION DEPENDS_ON -> [WebSocketLogHandler]\n# @PRE Python 3.7+ with cot_logger ContextVars available.\n# @POST All log output is single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.\n# @SIDE_EFFECT Configures global logger handlers and formatters; seeds global _enable_belief_state and _task_log_level; writes JSON to console/files.\n# @RATIONALE Replaced BeliefFormatter text-based [Entry]/[Exit]/[Action] logging with CotJsonFormatter JSON output. Old format was not machine-parseable and mixed presentation with intent. CotJsonFormatter produces structured JSON consistent with cot_logger.py MarkerLogger protocol.\n# @REJECTED Keeping both formatters side-by-side was rejected (two inconsistent output formats would confuse log consumers).\n# @DATA_CONTRACT All log records conform to molecular CoT JSON schema: {ts, level, trace_id, src, marker, intent, span_id?, payload?, error?}\n# @INVARIANT CotJsonFormatter.format() always returns valid single-line JSON string.\nfrom contextlib import contextmanager\nfrom datetime import UTC, datetime\nimport json\nimport logging\nfrom logging.handlers import RotatingFileHandler\nimport threading\nimport types\nfrom typing import Any\n\nfrom pydantic import BaseModel, Field\n\nfrom .cot_logger import _span_id, _trace_id, log as cot_log\nfrom .ws_log_handler import WebSocketLogHandler\n\n# Thread-local storage for belief state\n_belief_state = threading.local()\n\n# Global flag for belief state logging\n_enable_belief_state = True\n\n# Global task log level filter\n_task_log_level = \"INFO\"\n\n\n# #region CotJsonFormatter [C:3] [TYPE Class] [SEMANTICS logging,formatter,json,cot,protocol]\n# @BRIEF JSON formatter implementing the molecular CoT logging protocol. Outputs single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.\n# @RELATION IMPLEMENTS -> [CotJsonFormat]\nclass CotJsonFormatter(logging.Formatter):\n \"\"\"JSON formatter implementing the molecular CoT logging protocol.\n\n Reads structured data from the LogRecord's extra attributes (marker, intent, payload,\n error, src) set via the ``extra`` kwarg. Falls back to plain message wrapping when no\n structured extra is present.\n\n Output format (single-line JSON)::\n\n {\n \"ts\": \"2026-05-12T10:30:00.123\",\n \"level\": \"INFO\",\n \"trace_id\": \"uuid-or-no-trace\",\n \"src\": \"module.name\",\n \"marker\": \"REASON|REFLECT|EXPLORE\",\n \"intent\": \"human-readable intent\",\n \"span_id\": \"optional-span\",\n \"payload\": { ... }, # optional\n \"error\": \"...\" # optional\n }\n \"\"\"\n\n # #region CotJsonFormatter.format [C:2] [TYPE Function] [SEMANTICS format,json,record]\n # @BRIEF Format a LogRecord into a single-line CoT JSON string with molecular CoT protocol fields.\n # @INVARIANT Output is always valid single-line JSON.\n def format(self, record):\n # Try to extract structured data from extra kwargs on the record\n marker = getattr(record, 'marker', None)\n intent = getattr(record, 'intent', None)\n payload = getattr(record, 'payload', None)\n error = getattr(record, 'error', None)\n src = getattr(record, 'src', None) or record.name\n\n # Default marker for plain messages\n if not marker:\n marker = \"REASON\"\n if not intent:\n intent = record.getMessage()\n\n log_obj = {\n \"ts\": datetime.now(UTC).isoformat(timespec=\"milliseconds\"),\n \"level\": record.levelname,\n \"trace_id\": _trace_id.get() or \"no-trace\",\n \"src\": src,\n \"marker\": marker,\n \"intent\": intent,\n }\n\n span_id = _span_id.get()\n if span_id:\n log_obj[\"span_id\"] = span_id\n if payload:\n log_obj[\"payload\"] = payload\n if error:\n log_obj[\"error\"] = error\n\n return json.dumps(log_obj, ensure_ascii=False, default=str)\n # #endregion CotJsonFormatter.format\n# #endregion CotJsonFormatter\n\n\n# #region BeliefFormatter [C:2] [TYPE Class] [SEMANTICS logging,formatter,legacy,text]\n# @BRIEF Legacy formatter that adds belief state prefixes to log messages. Deprecated in favor of CotJsonFormatter.\n# @RATIONALE Kept for backward compatibility; may be used by external consumers of this module.\nclass BeliefFormatter(logging.Formatter):\n \"\"\"Legacy formatter that adds belief state prefixes to log messages. Deprecated in favor of CotJsonFormatter.\"\"\"\n def format(self, record):\n anchor_id = getattr(_belief_state, 'anchor_id', None)\n if anchor_id:\n msg = str(record.msg)\n markers = (\"[EXPLORE]\", \"[REASON]\", \"[REFLECT]\")\n\n if msg.startswith(f\"[{anchor_id}]\"):\n pass\n elif any(msg.startswith(m) for m in markers):\n record.msg = f\"[{anchor_id}]{msg}\"\n else:\n record.msg = f\"[{anchor_id}][REASON] {msg}\"\n\n return super().format(record)\n# #endregion BeliefFormatter\n\n\n# #region LogEntry [C:1] [TYPE Class] [SEMANTICS log,entry,record,pydantic]\n# @BRIEF A Pydantic model representing a single, structured log entry.\nclass LogEntry(BaseModel):\n timestamp: datetime = Field(default_factory=datetime.utcnow)\n level: str\n message: str\n context: dict[str, Any] | None = None\n# #endregion LogEntry\n\n\n# #region belief_scope [C:3] [TYPE Function] [SEMANTICS logging,context,belief_state,cot]\n# @BRIEF Context manager for Molecular CoT structured logging. Uses cot_logger.log() for JSON output.\n# @PRE anchor_id must be provided.\n# @POST Thread-local belief state is updated; REASON/REFLECT/EXPLORE markers emitted via structured JSON logger.\n@contextmanager\ndef belief_scope(anchor_id: str, message: str = \"\"):\n old_anchor = getattr(_belief_state, 'anchor_id', None)\n _belief_state.anchor_id = anchor_id\n\n try:\n # Log entry as REASON (gated by _enable_belief_state)\n if _enable_belief_state:\n intent_msg = message or f\"Entering {anchor_id}\"\n cot_log(anchor_id, \"REASON\", intent_msg, level=\"DEBUG\")\n yield\n # Log success as REFLECT (always logged)\n cot_log(anchor_id, \"REFLECT\", \"Coherence OK\", level=\"DEBUG\")\n except Exception as e:\n # Log exception as EXPLORE (always logged)\n cot_log(anchor_id, \"EXPLORE\", \"Assumption violated\", error=str(e), level=\"WARNING\")\n raise\n finally:\n _belief_state.anchor_id = old_anchor\n# #endregion belief_scope\n\n\n# #region configure_logger [C:4] [TYPE Function] [SEMANTICS logging,configuration,initialization,cot]\n# @BRIEF Configures the main logger and the CoT logger with CotJsonFormatter, file handlers, and global flags.\n# @RELATION CALLS -> [CotJsonFormatter]\n# @RELATION CALLS -> [CotLoggerModule]\n# @PRE config is a valid LoggingConfig instance.\n# @POST Logger levels, handlers, formatters, belief state flag, and task log level are updated.\n# @SIDE_EFFECT Mutates global _enable_belief_state, _task_log_level; adds/removes handlers on both logger and cot_logger; creates file directories.\ndef configure_logger(config):\n global _enable_belief_state, _task_log_level\n _enable_belief_state = config.enable_belief_state\n _task_log_level = config.task_log_level.upper()\n\n # Set logger level\n level = getattr(logging, config.level.upper(), logging.INFO)\n logger.setLevel(level)\n\n # Remove existing file handlers\n handlers_to_remove = [h for h in logger.handlers if isinstance(h, RotatingFileHandler)]\n for h in handlers_to_remove:\n logger.removeHandler(h)\n h.close()\n\n # Add file handler if file_path is set\n if config.file_path:\n from pathlib import Path\n log_file = Path(config.file_path)\n log_file.parent.mkdir(parents=True, exist_ok=True)\n\n file_handler = RotatingFileHandler(\n config.file_path,\n maxBytes=config.max_bytes,\n backupCount=config.backup_count\n )\n file_handler.setFormatter(CotJsonFormatter())\n logger.addHandler(file_handler)\n\n # Update existing handlers' formatters to CotJsonFormatter\n for handler in logger.handlers:\n if not isinstance(handler, RotatingFileHandler):\n handler.setFormatter(CotJsonFormatter())\n\n # Configure the 'cot' logger for consistent JSON output\n from .cot_logger import cot_logger\n cot_logger.setLevel(level)\n if not cot_logger.handlers:\n cot_handler = logging.StreamHandler()\n cot_handler.setFormatter(CotJsonFormatter())\n cot_logger.addHandler(cot_handler)\n# #endregion configure_logger\n\n\n# #region get_task_log_level [C:1] [TYPE Function] [SEMANTICS logging,configuration,getter]\n# @BRIEF Returns the current task log level filter.\ndef get_task_log_level() -> str:\n return _task_log_level\n# #endregion get_task_log_level\n\n\n# #region should_log_task_level [C:1] [TYPE Function] [SEMANTICS logging,filter,level]\n# @BRIEF Checks if a log level should be recorded based on task_log_level setting.\ndef should_log_task_level(level: str) -> bool:\n level_order = {\"DEBUG\": 0, \"INFO\": 1, \"WARNING\": 2, \"ERROR\": 3}\n current_level = _task_log_level.upper()\n check_level = level.upper()\n\n current_order = level_order.get(current_level, 1)\n check_order = level_order.get(check_level, 1)\n\n return check_order >= current_order\n# #endregion should_log_task_level\n\n\n# #region Logger [C:2] [TYPE Global] [SEMANTICS logger,global,instance]\n# @BRIEF The global application logger instance configured with CotJsonFormatter, console handler, and WebSocketLogHandler.\nlogger = logging.getLogger(\"superset_tools_app\")\n\n# #region believed [C:2] [TYPE Function] [SEMANTICS decorator,belief,scope]\n# @BRIEF A decorator that wraps a function in a belief scope.\ndef believed(anchor_id: str):\n def decorator(func):\n def wrapper(*args, **kwargs):\n with belief_scope(anchor_id):\n return func(*args, **kwargs)\n return wrapper\n return decorator\n# #endregion believed\nlogger.setLevel(logging.INFO)\n\n# Create CotJsonFormatter\n_formatter = CotJsonFormatter()\n\n# Add console handler\nconsole_handler = logging.StreamHandler()\nconsole_handler.setFormatter(_formatter)\nlogger.addHandler(console_handler)\n\n# Add WebSocket log handler\nwebsocket_log_handler = WebSocketLogHandler()\nwebsocket_log_handler.setFormatter(_formatter)\nlogger.addHandler(websocket_log_handler)\n\n# Example usage:\n# logger.info(\"Application started\", extra={\"context_key\": \"context_value\"})\n# logger.error(\"An error occurred\", exc_info=True)\n\n\n# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'EXPLORE', 'intent': msg}\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n\n\n# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REASON', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n\n\n# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REFLECT', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n\nlogger.explore = types.MethodType(explore, logger)\nlogger.reason = types.MethodType(reason, logger)\nlogger.reflect = types.MethodType(reflect, logger)\n\n# #endregion Logger\n# #endregion LoggerModule\n" + "body": "# #region LoggerModule [C:5] [TYPE Module] [SEMANTICS pydantic, logging, json, formatter, structured]\n# @BRIEF Application logging system with CotJsonFormatter producing molecular CoT JSON output.\n# @LAYER Core\n# @RELATION USED_BY -> [All application modules]\n# @RELATION DEPENDS_ON -> [CotLoggerModule]\n# @RELATION DEPENDS_ON -> [WebSocketLogHandler]\n# @PRE Python 3.7+ with cot_logger ContextVars available.\n# @POST All log output is single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.\n# @SIDE_EFFECT Configures global logger handlers and formatters; seeds global _enable_belief_state and _task_log_level; writes JSON to console/files.\n# @RATIONALE Replaced BeliefFormatter text-based [Entry]/[Exit]/[Action] logging with CotJsonFormatter JSON output. Old format was not machine-parseable and mixed presentation with intent. CotJsonFormatter produces structured JSON consistent with cot_logger.py MarkerLogger protocol.\n# @REJECTED Keeping both formatters side-by-side was rejected (two inconsistent output formats would confuse log consumers).\n# @DATA_CONTRACT All log records conform to molecular CoT JSON schema: {ts, level, trace_id, src, marker, intent, span_id?, payload?, error?}\n# @INVARIANT CotJsonFormatter.format() always returns valid single-line JSON string.\nfrom contextlib import contextmanager\nfrom datetime import UTC, datetime\nimport json\nimport logging\nfrom logging.handlers import RotatingFileHandler\nimport threading\nimport types\nfrom typing import Any\n\nfrom pydantic import BaseModel, Field\n\nfrom .cot_logger import _span_id, _trace_id, log as cot_log\nfrom .ws_log_handler import WebSocketLogHandler\n\n# Thread-local storage for belief state\n_belief_state = threading.local()\n\n# Global flag for belief state logging\n_enable_belief_state = True\n\n# Global task log level filter\n_task_log_level = \"INFO\"\n\n\n# #region CotJsonFormatter [C:3] [TYPE Class] [SEMANTICS logging,formatter,json,cot,protocol]\n# @BRIEF JSON formatter implementing the molecular CoT logging protocol. Outputs single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.\n# @RELATION IMPLEMENTS -> [CotJsonFormat]\nclass CotJsonFormatter(logging.Formatter):\n \"\"\"JSON formatter implementing the molecular CoT logging protocol.\n\n Reads structured data from the LogRecord's extra attributes (marker, intent, payload,\n error, src) set via the ``extra`` kwarg. Falls back to plain message wrapping when no\n structured extra is present.\n\n Output format (single-line JSON)::\n\n {\n \"ts\": \"2026-05-12T10:30:00.123\",\n \"level\": \"INFO\",\n \"trace_id\": \"uuid-or-no-trace\",\n \"src\": \"module.name\",\n \"marker\": \"REASON|REFLECT|EXPLORE\",\n \"intent\": \"human-readable intent\",\n \"span_id\": \"optional-span\",\n \"payload\": { ... }, # optional\n \"error\": \"...\" # optional\n }\n \"\"\"\n\n # #region CotJsonFormatter.format [C:2] [TYPE Function] [SEMANTICS format,json,record]\n # @BRIEF Format a LogRecord into a single-line CoT JSON string with molecular CoT protocol fields.\n # @INVARIANT Output is always valid single-line JSON.\n def format(self, record):\n # Try to extract structured data from extra kwargs on the record\n marker = getattr(record, 'marker', None)\n intent = getattr(record, 'intent', None)\n payload = getattr(record, 'payload', None)\n error = getattr(record, 'error', None)\n src = getattr(record, 'src', None) or record.name\n\n # Default marker for plain messages\n if not marker:\n marker = \"REASON\"\n if not intent:\n intent = record.getMessage()\n\n log_obj = {\n \"ts\": datetime.now(UTC).isoformat(timespec=\"milliseconds\"),\n \"level\": record.levelname,\n \"trace_id\": _trace_id.get() or \"no-trace\",\n \"src\": src,\n \"marker\": marker,\n \"intent\": intent,\n }\n\n span_id = _span_id.get()\n if span_id:\n log_obj[\"span_id\"] = span_id\n if payload:\n log_obj[\"payload\"] = payload\n if error:\n log_obj[\"error\"] = error\n\n return json.dumps(log_obj, ensure_ascii=False, default=str)\n # #endregion CotJsonFormatter.format\n# #endregion CotJsonFormatter\n\n\n# #region BeliefFormatter [C:2] [TYPE Class] [SEMANTICS logging,formatter,legacy,text]\n# @BRIEF Legacy formatter that adds belief state prefixes to log messages. Deprecated in favor of CotJsonFormatter.\n# @RATIONALE Kept for backward compatibility; may be used by external consumers of this module.\nclass BeliefFormatter(logging.Formatter):\n \"\"\"Legacy formatter that adds belief state prefixes to log messages. Deprecated in favor of CotJsonFormatter.\"\"\"\n def format(self, record):\n anchor_id = getattr(_belief_state, 'anchor_id', None)\n if anchor_id:\n msg = str(record.msg)\n markers = (\"[EXPLORE]\", \"[REASON]\", \"[REFLECT]\")\n\n if msg.startswith(f\"[{anchor_id}]\"):\n pass\n elif any(msg.startswith(m) for m in markers):\n record.msg = f\"[{anchor_id}]{msg}\"\n else:\n record.msg = f\"[{anchor_id}][REASON] {msg}\"\n\n return super().format(record)\n# #endregion BeliefFormatter\n\n\n# #region LogEntry [C:1] [TYPE Class] [SEMANTICS log,entry,record,pydantic]\n# @BRIEF A Pydantic model representing a single, structured log entry.\nclass LogEntry(BaseModel):\n timestamp: datetime = Field(default_factory=datetime.utcnow)\n level: str\n message: str\n context: dict[str, Any] | None = None\n# #endregion LogEntry\n\n\n# #region belief_scope [C:3] [TYPE Function] [SEMANTICS logging,context,belief_state,cot]\n# @BRIEF Context manager for Molecular CoT structured logging. Uses cot_logger.log() for JSON output.\n# @PRE anchor_id must be provided.\n# @POST Thread-local belief state is updated; REASON/REFLECT/EXPLORE markers emitted via structured JSON logger.\n@contextmanager\ndef belief_scope(anchor_id: str, message: str = \"\"):\n old_anchor = getattr(_belief_state, 'anchor_id', None)\n _belief_state.anchor_id = anchor_id\n\n try:\n # Log entry as REASON (gated by _enable_belief_state)\n if _enable_belief_state:\n intent_msg = message or f\"Entering {anchor_id}\"\n cot_log(anchor_id, \"REASON\", intent_msg, level=\"DEBUG\")\n yield\n # Log success as REFLECT (always logged)\n cot_log(anchor_id, \"REFLECT\", \"Coherence OK\", level=\"DEBUG\")\n except Exception as e:\n # Log exception as EXPLORE (always logged)\n cot_log(anchor_id, \"EXPLORE\", \"Assumption violated\", error=str(e), level=\"WARNING\")\n raise\n finally:\n _belief_state.anchor_id = old_anchor\n# #endregion belief_scope\n\n\n# #region configure_logger [C:4] [TYPE Function] [SEMANTICS logging,configuration,initialization,cot]\n# @BRIEF Configures the main logger and the CoT logger with CotJsonFormatter, file handlers, and global flags.\n# @RELATION CALLS -> [CotJsonFormatter]\n# @RELATION CALLS -> [CotLoggerModule]\n# @PRE config is a valid LoggingConfig instance.\n# @POST Logger levels, handlers, formatters, belief state flag, and task log level are updated.\n# @SIDE_EFFECT Mutates global _enable_belief_state, _task_log_level; adds/removes handlers on both logger and cot_logger; creates file directories.\ndef configure_logger(config):\n global _enable_belief_state, _task_log_level\n _enable_belief_state = config.enable_belief_state\n _task_log_level = config.task_log_level.upper()\n\n # Set logger level\n level = getattr(logging, config.level.upper(), logging.INFO)\n logger.setLevel(level)\n\n # Remove existing file handlers\n handlers_to_remove = [h for h in logger.handlers if isinstance(h, RotatingFileHandler)]\n for h in handlers_to_remove:\n logger.removeHandler(h)\n h.close()\n\n # Add file handler if file_path is set\n if config.file_path:\n from pathlib import Path\n log_file = Path(config.file_path)\n log_file.parent.mkdir(parents=True, exist_ok=True)\n\n file_handler = RotatingFileHandler(\n config.file_path,\n maxBytes=config.max_bytes,\n backupCount=config.backup_count\n )\n file_handler.setFormatter(CotJsonFormatter())\n logger.addHandler(file_handler)\n\n # Update existing handlers' formatters to CotJsonFormatter\n for handler in logger.handlers:\n if not isinstance(handler, RotatingFileHandler):\n handler.setFormatter(CotJsonFormatter())\n\n # Configure the 'cot' logger for consistent JSON output\n from .cot_logger import cot_logger\n cot_logger.setLevel(level)\n if not cot_logger.handlers:\n cot_handler = logging.StreamHandler()\n cot_handler.setFormatter(CotJsonFormatter())\n cot_logger.addHandler(cot_handler)\n# #endregion configure_logger\n\n\n# #region get_task_log_level [C:1] [TYPE Function] [SEMANTICS logging,configuration,getter]\n# @BRIEF Returns the current task log level filter.\ndef get_task_log_level() -> str:\n return _task_log_level\n# #endregion get_task_log_level\n\n\n# #region should_log_task_level [C:1] [TYPE Function] [SEMANTICS logging,filter,level]\n# @BRIEF Checks if a log level should be recorded based on task_log_level setting.\ndef should_log_task_level(level: str) -> bool:\n level_order = {\"DEBUG\": 0, \"INFO\": 1, \"WARNING\": 2, \"ERROR\": 3}\n current_level = _task_log_level.upper()\n check_level = level.upper()\n\n current_order = level_order.get(current_level, 1)\n check_order = level_order.get(check_level, 1)\n\n return check_order >= current_order\n# #endregion should_log_task_level\n\n\n# #region Logger [C:2] [TYPE Global] [SEMANTICS logger,global,instance]\n# @BRIEF The global application logger instance configured with CotJsonFormatter, console handler, and WebSocketLogHandler.\nlogger = logging.getLogger(\"superset_tools_app\")\n\n# #region believed [C:2] [TYPE Function] [SEMANTICS decorator,belief,scope]\n# @BRIEF A decorator that wraps a function in a belief scope.\ndef believed(anchor_id: str):\n def decorator(func):\n def wrapper(*args, **kwargs):\n with belief_scope(anchor_id):\n return func(*args, **kwargs)\n return wrapper\n return decorator\n# #endregion believed\nlogger.setLevel(logging.INFO)\n\n# Create CotJsonFormatter\n_formatter = CotJsonFormatter()\n\n# Add console handler\nconsole_handler = logging.StreamHandler()\nconsole_handler.setFormatter(_formatter)\nlogger.addHandler(console_handler)\n\n# Add WebSocket log handler\nwebsocket_log_handler = WebSocketLogHandler()\nwebsocket_log_handler.setFormatter(_formatter)\nlogger.addHandler(websocket_log_handler)\n\n# Example usage:\n# logger.info(\"Application started\", extra={\"context_key\": \"context_value\"})\n# logger.error(\"An error occurred\", exc_info=True)\n\n\n# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'EXPLORE', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n\n\n# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REASON', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n\n\n# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REFLECT', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n\nlogger.explore = types.MethodType(explore, logger)\nlogger.reason = types.MethodType(reason, logger)\nlogger.reflect = types.MethodType(reflect, logger)\n\n# #endregion Logger\n# #endregion LoggerModule\n" }, { "contract_id": "CotJsonFormatter", @@ -23038,7 +23938,7 @@ "contract_type": "Global", "file_path": "backend/src/core/logger.py", "start_line": 232, - "end_line": 311, + "end_line": 320, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -23103,7 +24003,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region Logger [C:2] [TYPE Global] [SEMANTICS logger,global,instance]\n# @BRIEF The global application logger instance configured with CotJsonFormatter, console handler, and WebSocketLogHandler.\nlogger = logging.getLogger(\"superset_tools_app\")\n\n# #region believed [C:2] [TYPE Function] [SEMANTICS decorator,belief,scope]\n# @BRIEF A decorator that wraps a function in a belief scope.\ndef believed(anchor_id: str):\n def decorator(func):\n def wrapper(*args, **kwargs):\n with belief_scope(anchor_id):\n return func(*args, **kwargs)\n return wrapper\n return decorator\n# #endregion believed\nlogger.setLevel(logging.INFO)\n\n# Create CotJsonFormatter\n_formatter = CotJsonFormatter()\n\n# Add console handler\nconsole_handler = logging.StreamHandler()\nconsole_handler.setFormatter(_formatter)\nlogger.addHandler(console_handler)\n\n# Add WebSocket log handler\nwebsocket_log_handler = WebSocketLogHandler()\nwebsocket_log_handler.setFormatter(_formatter)\nlogger.addHandler(websocket_log_handler)\n\n# Example usage:\n# logger.info(\"Application started\", extra={\"context_key\": \"context_value\"})\n# logger.error(\"An error occurred\", exc_info=True)\n\n\n# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'EXPLORE', 'intent': msg}\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n\n\n# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REASON', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n\n\n# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REFLECT', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n\nlogger.explore = types.MethodType(explore, logger)\nlogger.reason = types.MethodType(reason, logger)\nlogger.reflect = types.MethodType(reflect, logger)\n\n# #endregion Logger\n" + "body": "# #region Logger [C:2] [TYPE Global] [SEMANTICS logger,global,instance]\n# @BRIEF The global application logger instance configured with CotJsonFormatter, console handler, and WebSocketLogHandler.\nlogger = logging.getLogger(\"superset_tools_app\")\n\n# #region believed [C:2] [TYPE Function] [SEMANTICS decorator,belief,scope]\n# @BRIEF A decorator that wraps a function in a belief scope.\ndef believed(anchor_id: str):\n def decorator(func):\n def wrapper(*args, **kwargs):\n with belief_scope(anchor_id):\n return func(*args, **kwargs)\n return wrapper\n return decorator\n# #endregion believed\nlogger.setLevel(logging.INFO)\n\n# Create CotJsonFormatter\n_formatter = CotJsonFormatter()\n\n# Add console handler\nconsole_handler = logging.StreamHandler()\nconsole_handler.setFormatter(_formatter)\nlogger.addHandler(console_handler)\n\n# Add WebSocket log handler\nwebsocket_log_handler = WebSocketLogHandler()\nwebsocket_log_handler.setFormatter(_formatter)\nlogger.addHandler(websocket_log_handler)\n\n# Example usage:\n# logger.info(\"Application started\", extra={\"context_key\": \"context_value\"})\n# logger.error(\"An error occurred\", exc_info=True)\n\n\n# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'EXPLORE', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n\n\n# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REASON', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n\n\n# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REFLECT', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n\nlogger.explore = types.MethodType(explore, logger)\nlogger.reason = types.MethodType(reason, logger)\nlogger.reflect = types.MethodType(reflect, logger)\n\n# #endregion Logger\n" }, { "contract_id": "believed", @@ -23128,7 +24028,7 @@ "contract_type": "Function", "file_path": "backend/src/core/logger.py", "start_line": 266, - "end_line": 277, + "end_line": 280, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -23139,14 +24039,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'EXPLORE', 'intent': msg}\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n" + "body": "# #region explore [C:2] [TYPE Function] [SEMANTICS log,explore,marker,warning]\n# @BRIEF Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.\ndef explore(self, msg, *args, **kwargs):\n \"\"\"Log an EXPLORE marker — searching, alternatives, violated assumptions.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'EXPLORE', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.warning(msg, *args, extra=extra, **kwargs)\n# #endregion explore\n" }, { "contract_id": "reason", "contract_type": "Function", "file_path": "backend/src/core/logger.py", - "start_line": 280, - "end_line": 291, + "start_line": 283, + "end_line": 297, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -23157,14 +24057,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REASON', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n" + "body": "# #region reason [C:2] [TYPE Function] [SEMANTICS log,reason,marker,debug]\n# @BRIEF Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reason(self, msg, *args, **kwargs):\n \"\"\"Log a REASON marker — strict deduction, core logic.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REASON', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reason\n" }, { "contract_id": "reflect", "contract_type": "Function", "file_path": "backend/src/core/logger.py", - "start_line": 294, - "end_line": 305, + "start_line": 300, + "end_line": 314, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -23175,7 +24075,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n extra = {'marker': 'REFLECT', 'intent': msg}\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n" + "body": "# #region reflect [C:2] [TYPE Function] [SEMANTICS log,reflect,marker,debug]\n# @BRIEF Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.\ndef reflect(self, msg, *args, **kwargs):\n \"\"\"Log a REFLECT marker — self-check, structural validation.\n\n Passes structured ``extra`` data so CotJsonFormatter produces proper JSON.\n \"\"\"\n user_extra = kwargs.pop('extra', {})\n error_val = kwargs.pop('error', None)\n extra = {'marker': 'REFLECT', 'intent': msg}\n if error_val is not None:\n extra['error'] = error_val\n extra.update(user_extra)\n self.debug(msg, *args, extra=extra, **kwargs)\n# #endregion reflect\n" }, { "contract_id": "test_belief_scope_logs_reason_reflect_at_debug", @@ -25539,7 +26439,7 @@ "contract_type": "Module", "file_path": "backend/src/core/scheduler.py", "start_line": 1, - "end_line": 253, + "end_line": 435, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -25558,14 +26458,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SchedulerModule [C:3] [TYPE Module] [SEMANTICS scheduler, schedule, scheduler-service]\n# @BRIEF Manages scheduled tasks using APScheduler.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> TaskManager\nimport asyncio\nfrom datetime import date, datetime, time, timedelta\n\nfrom apscheduler.schedulers.background import BackgroundScheduler\nfrom apscheduler.triggers.cron import CronTrigger\n\nfrom .config_manager import ConfigManager\nfrom .cot_logger import seed_trace_id\nfrom .database import SessionLocal\nfrom .logger import belief_scope, logger\n\n\n# #region SchedulerService [C:3] [TYPE Class] [SEMANTICS scheduler, service, apscheduler]\n# @BRIEF Provides a service to manage scheduled backup tasks.\n# @RELATION DEPENDS_ON -> [ThrottledSchedulerConfigurator]\nclass SchedulerService:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the scheduler service with task and config managers.\n # @PRE: task_manager and config_manager must be provided.\n # @POST: Scheduler instance is created but not started.\n def __init__(self, task_manager, config_manager: ConfigManager):\n with belief_scope(\"SchedulerService.__init__\"):\n self.task_manager = task_manager\n self.config_manager = config_manager\n self.scheduler = BackgroundScheduler()\n self.loop = asyncio.get_event_loop()\n # #endregion __init__\n # #region start [TYPE Function]\n # @PURPOSE: Starts the background scheduler and loads initial schedules.\n # @PRE: Scheduler should be initialized.\n # @POST: Scheduler is running and schedules are loaded.\n def start(self):\n with belief_scope(\"SchedulerService.start\"):\n if not self.scheduler.running:\n self.scheduler.start()\n logger.info(\"Scheduler started.\")\n self.load_schedules()\n # #endregion start\n # #region stop [TYPE Function]\n # @PURPOSE: Stops the background scheduler.\n # @PRE: Scheduler should be running.\n # @POST: Scheduler is shut down.\n def stop(self):\n with belief_scope(\"SchedulerService.stop\"):\n if self.scheduler.running:\n self.scheduler.shutdown()\n logger.info(\"Scheduler stopped.\")\n # #endregion stop\n # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n # #region add_backup_job [TYPE Function]\n # @PURPOSE: Adds a scheduled backup job for an environment.\n # @PRE: env_id and cron_expression must be valid strings.\n # @POST: A new job is added to the scheduler or replaced if it already exists.\n # @PARAM: env_id (str) - The ID of the environment.\n # @PARAM: cron_expression (str) - The cron expression for the schedule.\n def add_backup_job(self, env_id: str, cron_expression: str):\n with belief_scope(\n \"SchedulerService.add_backup_job\",\n f\"env_id={env_id}, cron={cron_expression}\",\n ):\n job_id = f\"backup_{env_id}\"\n try:\n self.scheduler.add_job(\n self._trigger_backup,\n CronTrigger.from_crontab(cron_expression),\n id=job_id,\n args=[env_id],\n replace_existing=True,\n )\n logger.info(\n f\"Scheduled backup job added for environment {env_id}: {cron_expression}\"\n )\n except Exception as e:\n logger.error(f\"Failed to add backup job for environment {env_id}: {e}\")\n # #endregion add_backup_job\n # #region add_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,cron,apscheduler]\n # @BRIEF Register a translation schedule with APScheduler.\n # @PRE schedule_id, job_id, and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls execute_scheduled_translation on trigger.\n # @RELATION DEPENDS_ON -> [execute_scheduled_translation]\n # @RELATION DEPENDS_ON -> [SessionLocal]\n def add_translation_job(self, schedule_id: str, job_id: str, cron_expression: str, timezone: str = \"UTC\", execution_mode: str = \"full\"):\n with belief_scope(\n \"SchedulerService.add_translation_job\",\n f\"schedule_id={schedule_id}, job_id={job_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n from ..plugins.translate.scheduler import execute_scheduled_translation\n\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n tz = ZoneInfo(timezone)\n self.scheduler.add_job(\n execute_scheduled_translation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[schedule_id, job_id, SessionLocal, self.config_manager, execution_mode],\n replace_existing=True,\n )\n logger.reason(\n f\"Translation schedule registered: {job_id_aps} ({cron_expression})\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register translation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_translation_job\n # #region remove_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,remove,apscheduler]\n # @BRIEF Remove a translation schedule from APScheduler.\n # @PRE schedule_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_translation_job(self, schedule_id: str):\n with belief_scope(\n \"SchedulerService.remove_translation_job\",\n f\"schedule_id={schedule_id}\",\n ):\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Translation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Translation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_translation_job\n # #region _trigger_backup [TYPE Function]\n # @PURPOSE: Triggered by the scheduler to start a backup task.\n # @PRE: env_id must be a valid environment ID.\n # @POST: A new backup task is created in the task manager if not already running.\n # @PARAM: env_id (str) - The ID of the environment.\n def _trigger_backup(self, env_id: str):\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_backup\", f\"env_id={env_id}\"):\n logger.info(f\"Triggering scheduled backup for environment {env_id}\")\n # Check if a backup is already running for this environment\n active_tasks = self.task_manager.get_tasks(limit=100)\n for task in active_tasks:\n if (\n task.plugin_id == \"superset-backup\"\n and task.status in [\"PENDING\", \"RUNNING\"]\n and task.params.get(\"environment_id\") == env_id\n ):\n logger.warning(\n f\"Backup already running for environment {env_id}. Skipping scheduled run.\"\n )\n return\n # Run the backup task\n # We need to run this in the event loop since create_task is async\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n \"superset-backup\", {\"environment_id\": env_id}\n ),\n self.loop,\n )\n # #endregion _trigger_backup\n# #endregion SchedulerService\n# #region ThrottledSchedulerConfigurator [C:5] [TYPE Class] [SEMANTICS scheduler, throttling, distribution]\n# @BRIEF Distributes validation tasks evenly within an execution window.\n# @PRE: Validation policies provide a finite dashboard list and a valid execution window.\n# @POST: Produces deterministic per-dashboard run timestamps within the configured window.\n# @RELATION DEPENDS_ON -> SchedulerModule\n# @INVARIANT: Returned schedule size always matches number of dashboard IDs.\n# @SIDE_EFFECT: Emits warning logs for degenerate or near-zero scheduling windows.\n# @DATA_CONTRACT: Input[window_start, window_end, dashboard_ids, current_date] -> Output[List[datetime]]\nclass ThrottledSchedulerConfigurator:\n # #region calculate_schedule [TYPE Function]\n # @PURPOSE: Calculates execution times for N tasks within a window.\n # @PRE: window_start, window_end (time), dashboard_ids (List), current_date (date).\n # @POST: Returns List[datetime] of scheduled times.\n # @INVARIANT: Tasks are distributed with near-even spacing.\n @staticmethod\n def calculate_schedule(\n window_start: time, window_end: time, dashboard_ids: list, current_date: date\n ) -> list:\n with belief_scope(\"ThrottledSchedulerConfigurator.calculate_schedule\"):\n n = len(dashboard_ids)\n if n == 0:\n return []\n start_dt = datetime.combine(current_date, window_start)\n end_dt = datetime.combine(current_date, window_end)\n # Handle window crossing midnight\n if end_dt < start_dt:\n end_dt += timedelta(days=1)\n total_seconds = (end_dt - start_dt).total_seconds()\n # Minimum interval of 1 second to avoid division by zero or negative\n if total_seconds <= 0:\n logger.warning(\n f\"[calculate_schedule] Window size is zero or negative. Falling back to start time for all {n} tasks.\"\n )\n return [start_dt] * n\n # If window is too small for even distribution (e.g. 10 tasks in 5 seconds),\n # we still distribute them but they might be very close.\n # The requirement says \"near-even spacing\".\n if n == 1:\n return [start_dt]\n interval = total_seconds / (n - 1) if n > 1 else 0\n # If interval is too small (e.g. < 1s), we might want a fallback,\n # but the spec says \"handle too-small windows with explicit fallback/warning\".\n if interval < 1:\n logger.warning(\n f\"[calculate_schedule] Window too small for {n} tasks (interval {interval:.2f}s). Tasks will be highly concentrated.\"\n )\n scheduled_times = []\n for i in range(n):\n scheduled_times.append(start_dt + timedelta(seconds=i * interval))\n return scheduled_times\n # #endregion calculate_schedule\n# #endregion ThrottledSchedulerConfigurator\n# #endregion SchedulerModule\n" + "body": "# #region SchedulerModule [C:3] [TYPE Module] [SEMANTICS scheduler, schedule, scheduler-service]\n# @BRIEF Manages scheduled tasks using APScheduler.\n# @LAYER: Core\n# @RELATION DEPENDS_ON -> TaskManager\nimport asyncio\nfrom datetime import date, datetime, time, timedelta\n\nfrom apscheduler.schedulers.background import BackgroundScheduler\nfrom apscheduler.triggers.cron import CronTrigger\n\nfrom .config_manager import ConfigManager\nfrom .cot_logger import seed_trace_id\nfrom .database import SessionLocal\nfrom .logger import belief_scope, logger\n\n\n# #region SchedulerService [C:3] [TYPE Class] [SEMANTICS scheduler, service, apscheduler]\n# @BRIEF Provides a service to manage scheduled backup tasks.\n# @RELATION DEPENDS_ON -> [ThrottledSchedulerConfigurator]\nclass SchedulerService:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the scheduler service with task and config managers.\n # @PRE: task_manager and config_manager must be provided.\n # @POST: Scheduler instance is created but not started.\n def __init__(self, task_manager, config_manager: ConfigManager):\n with belief_scope(\"SchedulerService.__init__\"):\n self.task_manager = task_manager\n self.config_manager = config_manager\n self.scheduler = BackgroundScheduler()\n self.loop = asyncio.get_event_loop()\n # #endregion __init__\n # #region start [TYPE Function]\n # @PURPOSE: Starts the background scheduler and loads initial schedules.\n # @PRE: Scheduler should be initialized.\n # @POST: Scheduler is running and schedules are loaded.\n def start(self):\n with belief_scope(\"SchedulerService.start\"):\n if not self.scheduler.running:\n self.scheduler.start()\n logger.info(\"Scheduler started.\")\n self.load_schedules()\n # #endregion start\n # #region stop [TYPE Function]\n # @PURPOSE: Stops the background scheduler.\n # @PRE: Scheduler should be running.\n # @POST: Scheduler is shut down.\n def stop(self):\n with belief_scope(\"SchedulerService.stop\"):\n if self.scheduler.running:\n self.scheduler.shutdown()\n logger.info(\"Scheduler stopped.\")\n # #endregion stop\n # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # Re-register active validation policies with schedules\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n active_policies = (\n db.query(ValidationPolicy)\n .filter(\n ValidationPolicy.is_active.is_(True),\n ValidationPolicy.schedule_days.isnot(None),\n )\n .all()\n )\n for policy in active_policies:\n schedule_days = policy.schedule_days or []\n if not schedule_days:\n continue\n ws = policy.window_start\n if ws is None:\n continue\n # Build cron: minute hour * * day-of-week\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(\n policy_id=policy.id,\n cron_expression=cron,\n app_timezone=config.settings.app_timezone,\n )\n if active_policies:\n logger.reason(f\"Loaded {len(active_policies)} active validation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load validation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n # #region add_backup_job [TYPE Function]\n # @PURPOSE: Adds a scheduled backup job for an environment.\n # @PRE: env_id and cron_expression must be valid strings.\n # @POST: A new job is added to the scheduler or replaced if it already exists.\n # @PARAM: env_id (str) - The ID of the environment.\n # @PARAM: cron_expression (str) - The cron expression for the schedule.\n def add_backup_job(self, env_id: str, cron_expression: str):\n with belief_scope(\n \"SchedulerService.add_backup_job\",\n f\"env_id={env_id}, cron={cron_expression}\",\n ):\n job_id = f\"backup_{env_id}\"\n try:\n self.scheduler.add_job(\n self._trigger_backup,\n CronTrigger.from_crontab(cron_expression),\n id=job_id,\n args=[env_id],\n replace_existing=True,\n )\n logger.info(\n f\"Scheduled backup job added for environment {env_id}: {cron_expression}\"\n )\n except Exception as e:\n logger.error(f\"Failed to add backup job for environment {env_id}: {e}\")\n # #endregion add_backup_job\n # #region add_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,cron,apscheduler]\n # @BRIEF Register a translation schedule with APScheduler.\n # @PRE schedule_id, job_id, and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls execute_scheduled_translation on trigger.\n # @RELATION DEPENDS_ON -> [execute_scheduled_translation]\n # @RELATION DEPENDS_ON -> [SessionLocal]\n def add_translation_job(self, schedule_id: str, job_id: str, cron_expression: str, timezone: str = \"UTC\", execution_mode: str = \"full\"):\n with belief_scope(\n \"SchedulerService.add_translation_job\",\n f\"schedule_id={schedule_id}, job_id={job_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n from ..plugins.translate.scheduler import execute_scheduled_translation\n\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n tz = ZoneInfo(timezone)\n self.scheduler.add_job(\n execute_scheduled_translation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[schedule_id, job_id, SessionLocal, self.config_manager, execution_mode],\n replace_existing=True,\n )\n logger.reason(\n f\"Translation schedule registered: {job_id_aps} ({cron_expression})\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register translation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_translation_job\n # #region remove_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,remove,apscheduler]\n # @BRIEF Remove a translation schedule from APScheduler.\n # @PRE schedule_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_translation_job(self, schedule_id: str):\n with belief_scope(\n \"SchedulerService.remove_translation_job\",\n f\"schedule_id={schedule_id}\",\n ):\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Translation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Translation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_translation_job\n # #region _trigger_backup [TYPE Function]\n # @PURPOSE: Triggered by the scheduler to start a backup task.\n # @PRE: env_id must be a valid environment ID.\n # @POST: A new backup task is created in the task manager if not already running.\n # @PARAM: env_id (str) - The ID of the environment.\n def _trigger_backup(self, env_id: str):\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_backup\", f\"env_id={env_id}\"):\n logger.info(f\"Triggering scheduled backup for environment {env_id}\")\n # Check if a backup is already running for this environment\n active_tasks = self.task_manager.get_tasks(limit=100)\n for task in active_tasks:\n if (\n task.plugin_id == \"superset-backup\"\n and task.status in [\"PENDING\", \"RUNNING\"]\n and task.params.get(\"environment_id\") == env_id\n ):\n logger.warning(\n f\"Backup already running for environment {env_id}. Skipping scheduled run.\"\n )\n return\n # Run the backup task\n # We need to run this in the event loop since create_task is async\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n \"superset-backup\", {\"environment_id\": env_id}\n ),\n self.loop,\n )\n # #endregion _trigger_backup\n # #region add_validation_job [C:3] [TYPE Function] [SEMANTICS scheduler,validation,cron,apscheduler]\n # @BRIEF Register a validation policy schedule with APScheduler.\n # @PRE policy_id and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls _trigger_validation on trigger.\n # @RELATION DEPENDS_ON -> [_trigger_validation]\n def add_validation_job(self, policy_id: str, cron_expression: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.add_validation_job\",\n f\"policy_id={policy_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n job_id_aps = f\"validation_{policy_id}\"\n try:\n tz = ZoneInfo(app_timezone)\n self.scheduler.add_job(\n self._trigger_validation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[policy_id],\n replace_existing=True,\n )\n logger.reason(\n f\"Validation schedule registered: {job_id_aps} ({cron_expression}) [{app_timezone}]\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register validation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_validation_job\n # #region remove_validation_job [C:2] [TYPE Function] [SEMANTICS scheduler,validation,remove,apscheduler]\n # @BRIEF Remove a validation policy schedule from APScheduler.\n # @PRE policy_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_validation_job(self, policy_id: str) -> None:\n with belief_scope(\n \"SchedulerService.remove_validation_job\",\n f\"policy_id={policy_id}\",\n ):\n job_id_aps = f\"validation_{policy_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Validation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Validation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_validation_job\n # #region reload_validation_policy [C:2] [TYPE Function] [SEMANTICS scheduler,validation,reload,apscheduler]\n # @BRIEF Reload a single validation policy schedule — calls remove then add.\n # @PRE policy_id is a valid ValidationPolicy id with schedule data in DB.\n # @POST Old job is removed; new job is registered if policy is active and has schedule_days.\n # @SIDE_EFFECT Mutates APScheduler state; queries ValidationPolicy from DB.\n def reload_validation_policy(self, policy_id: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.reload_validation_policy\",\n f\"policy_id={policy_id}\",\n ):\n self.remove_validation_job(policy_id)\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.reason(f\"Policy {policy_id} not found; schedule removed\")\n return\n if not policy.is_active:\n logger.reason(f\"Policy {policy_id} is inactive; schedule removed\")\n return\n schedule_days = policy.schedule_days or []\n if not schedule_days or policy.window_start is None:\n logger.reason(f\"Policy {policy_id} has no schedule; nothing to register\")\n return\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n ws = policy.window_start\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(policy_id, cron, app_timezone=app_timezone)\n finally:\n db.close()\n except Exception as e:\n logger.explore(\n f\"Failed to reload validation policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n # #endregion reload_validation_policy\n # #region _trigger_validation [C:3] [TYPE Function] [SEMANTICS scheduler,validation,trigger]\n # @BRIEF APScheduler job handler — triggers validation runs for a policy.\n # @PRE policy_id is a valid ValidationPolicy id with dashboard_ids.\n # @POST A validation task is spawned via TaskManager for each dashboard in the policy.\n # @SIDE_EFFECT Creates TaskRecord entries for validation runs; logs progress.\n def _trigger_validation(self, policy_id: str) -> None:\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_validation\", f\"policy_id={policy_id}\"):\n logger.reason(f\"Triggering scheduled validation for policy {policy_id}\")\n db = SessionLocal()\n try:\n from ..models.llm import ValidationPolicy\n\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.explore(f\"Validation policy not found: {policy_id}\")\n return\n if not policy.is_active:\n logger.reason(f\"Validation policy {policy_id} is no longer active; skipping\")\n return\n dashboard_ids = list(policy.dashboard_ids or [])\n if not dashboard_ids:\n logger.explore(f\"Validation policy {policy_id} has no dashboards; skipping\")\n return\n\n ws = policy.window_start\n we = policy.window_end\n today = date.today()\n scheduled_times = ThrottledSchedulerConfigurator.calculate_schedule(\n window_start=ws,\n window_end=we or time(ws.hour, ws.minute + 30),\n dashboard_ids=dashboard_ids,\n current_date=today,\n )\n\n for idx, dash_id in enumerate(dashboard_ids):\n sched_time = scheduled_times[idx] if idx < len(scheduled_times) else scheduled_times[-1]\n params: dict = {\n \"dashboard_id\": dash_id,\n \"environment_id\": policy.environment_id,\n \"provider_id\": policy.provider_id or \"\",\n \"policy_id\": policy_id,\n }\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n plugin_id=\"llm_dashboard_validation\", params=params\n ),\n self.loop,\n )\n logger.reason(\n f\"Scheduled validation for dashboard {dash_id} at {sched_time.isoformat()}\"\n )\n except Exception as e:\n logger.explore(\n f\"Error triggering validation for policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n finally:\n db.close()\n # #endregion _trigger_validation\n# #endregion SchedulerService\n# #region ThrottledSchedulerConfigurator [C:5] [TYPE Class] [SEMANTICS scheduler, throttling, distribution]\n# @BRIEF Distributes validation tasks evenly within an execution window.\n# @PRE: Validation policies provide a finite dashboard list and a valid execution window.\n# @POST: Produces deterministic per-dashboard run timestamps within the configured window.\n# @RELATION DEPENDS_ON -> SchedulerModule\n# @INVARIANT: Returned schedule size always matches number of dashboard IDs.\n# @SIDE_EFFECT: Emits warning logs for degenerate or near-zero scheduling windows.\n# @DATA_CONTRACT: Input[window_start, window_end, dashboard_ids, current_date] -> Output[List[datetime]]\nclass ThrottledSchedulerConfigurator:\n # #region calculate_schedule [TYPE Function]\n # @PURPOSE: Calculates execution times for N tasks within a window.\n # @PRE: window_start, window_end (time), dashboard_ids (List), current_date (date).\n # @POST: Returns List[datetime] of scheduled times.\n # @INVARIANT: Tasks are distributed with near-even spacing.\n @staticmethod\n def calculate_schedule(\n window_start: time, window_end: time, dashboard_ids: list, current_date: date\n ) -> list:\n with belief_scope(\"ThrottledSchedulerConfigurator.calculate_schedule\"):\n n = len(dashboard_ids)\n if n == 0:\n return []\n start_dt = datetime.combine(current_date, window_start)\n end_dt = datetime.combine(current_date, window_end)\n # Handle window crossing midnight\n if end_dt < start_dt:\n end_dt += timedelta(days=1)\n total_seconds = (end_dt - start_dt).total_seconds()\n # Minimum interval of 1 second to avoid division by zero or negative\n if total_seconds <= 0:\n logger.warning(\n f\"[calculate_schedule] Window size is zero or negative. Falling back to start time for all {n} tasks.\"\n )\n return [start_dt] * n\n # If window is too small for even distribution (e.g. 10 tasks in 5 seconds),\n # we still distribute them but they might be very close.\n # The requirement says \"near-even spacing\".\n if n == 1:\n return [start_dt]\n interval = total_seconds / (n - 1) if n > 1 else 0\n # If interval is too small (e.g. < 1s), we might want a fallback,\n # but the spec says \"handle too-small windows with explicit fallback/warning\".\n if interval < 1:\n logger.warning(\n f\"[calculate_schedule] Window too small for {n} tasks (interval {interval:.2f}s). Tasks will be highly concentrated.\"\n )\n scheduled_times = []\n for i in range(n):\n scheduled_times.append(start_dt + timedelta(seconds=i * interval))\n return scheduled_times\n # #endregion calculate_schedule\n# #endregion ThrottledSchedulerConfigurator\n# #endregion SchedulerModule\n" }, { "contract_id": "SchedulerService", "contract_type": "Class", "file_path": "backend/src/core/scheduler.py", "start_line": 17, - "end_line": 200, + "end_line": 382, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -25583,7 +26483,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SchedulerService [C:3] [TYPE Class] [SEMANTICS scheduler, service, apscheduler]\n# @BRIEF Provides a service to manage scheduled backup tasks.\n# @RELATION DEPENDS_ON -> [ThrottledSchedulerConfigurator]\nclass SchedulerService:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the scheduler service with task and config managers.\n # @PRE: task_manager and config_manager must be provided.\n # @POST: Scheduler instance is created but not started.\n def __init__(self, task_manager, config_manager: ConfigManager):\n with belief_scope(\"SchedulerService.__init__\"):\n self.task_manager = task_manager\n self.config_manager = config_manager\n self.scheduler = BackgroundScheduler()\n self.loop = asyncio.get_event_loop()\n # #endregion __init__\n # #region start [TYPE Function]\n # @PURPOSE: Starts the background scheduler and loads initial schedules.\n # @PRE: Scheduler should be initialized.\n # @POST: Scheduler is running and schedules are loaded.\n def start(self):\n with belief_scope(\"SchedulerService.start\"):\n if not self.scheduler.running:\n self.scheduler.start()\n logger.info(\"Scheduler started.\")\n self.load_schedules()\n # #endregion start\n # #region stop [TYPE Function]\n # @PURPOSE: Stops the background scheduler.\n # @PRE: Scheduler should be running.\n # @POST: Scheduler is shut down.\n def stop(self):\n with belief_scope(\"SchedulerService.stop\"):\n if self.scheduler.running:\n self.scheduler.shutdown()\n logger.info(\"Scheduler stopped.\")\n # #endregion stop\n # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n # #region add_backup_job [TYPE Function]\n # @PURPOSE: Adds a scheduled backup job for an environment.\n # @PRE: env_id and cron_expression must be valid strings.\n # @POST: A new job is added to the scheduler or replaced if it already exists.\n # @PARAM: env_id (str) - The ID of the environment.\n # @PARAM: cron_expression (str) - The cron expression for the schedule.\n def add_backup_job(self, env_id: str, cron_expression: str):\n with belief_scope(\n \"SchedulerService.add_backup_job\",\n f\"env_id={env_id}, cron={cron_expression}\",\n ):\n job_id = f\"backup_{env_id}\"\n try:\n self.scheduler.add_job(\n self._trigger_backup,\n CronTrigger.from_crontab(cron_expression),\n id=job_id,\n args=[env_id],\n replace_existing=True,\n )\n logger.info(\n f\"Scheduled backup job added for environment {env_id}: {cron_expression}\"\n )\n except Exception as e:\n logger.error(f\"Failed to add backup job for environment {env_id}: {e}\")\n # #endregion add_backup_job\n # #region add_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,cron,apscheduler]\n # @BRIEF Register a translation schedule with APScheduler.\n # @PRE schedule_id, job_id, and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls execute_scheduled_translation on trigger.\n # @RELATION DEPENDS_ON -> [execute_scheduled_translation]\n # @RELATION DEPENDS_ON -> [SessionLocal]\n def add_translation_job(self, schedule_id: str, job_id: str, cron_expression: str, timezone: str = \"UTC\", execution_mode: str = \"full\"):\n with belief_scope(\n \"SchedulerService.add_translation_job\",\n f\"schedule_id={schedule_id}, job_id={job_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n from ..plugins.translate.scheduler import execute_scheduled_translation\n\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n tz = ZoneInfo(timezone)\n self.scheduler.add_job(\n execute_scheduled_translation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[schedule_id, job_id, SessionLocal, self.config_manager, execution_mode],\n replace_existing=True,\n )\n logger.reason(\n f\"Translation schedule registered: {job_id_aps} ({cron_expression})\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register translation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_translation_job\n # #region remove_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,remove,apscheduler]\n # @BRIEF Remove a translation schedule from APScheduler.\n # @PRE schedule_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_translation_job(self, schedule_id: str):\n with belief_scope(\n \"SchedulerService.remove_translation_job\",\n f\"schedule_id={schedule_id}\",\n ):\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Translation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Translation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_translation_job\n # #region _trigger_backup [TYPE Function]\n # @PURPOSE: Triggered by the scheduler to start a backup task.\n # @PRE: env_id must be a valid environment ID.\n # @POST: A new backup task is created in the task manager if not already running.\n # @PARAM: env_id (str) - The ID of the environment.\n def _trigger_backup(self, env_id: str):\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_backup\", f\"env_id={env_id}\"):\n logger.info(f\"Triggering scheduled backup for environment {env_id}\")\n # Check if a backup is already running for this environment\n active_tasks = self.task_manager.get_tasks(limit=100)\n for task in active_tasks:\n if (\n task.plugin_id == \"superset-backup\"\n and task.status in [\"PENDING\", \"RUNNING\"]\n and task.params.get(\"environment_id\") == env_id\n ):\n logger.warning(\n f\"Backup already running for environment {env_id}. Skipping scheduled run.\"\n )\n return\n # Run the backup task\n # We need to run this in the event loop since create_task is async\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n \"superset-backup\", {\"environment_id\": env_id}\n ),\n self.loop,\n )\n # #endregion _trigger_backup\n# #endregion SchedulerService\n" + "body": "# #region SchedulerService [C:3] [TYPE Class] [SEMANTICS scheduler, service, apscheduler]\n# @BRIEF Provides a service to manage scheduled backup tasks.\n# @RELATION DEPENDS_ON -> [ThrottledSchedulerConfigurator]\nclass SchedulerService:\n # #region __init__ [TYPE Function]\n # @PURPOSE: Initializes the scheduler service with task and config managers.\n # @PRE: task_manager and config_manager must be provided.\n # @POST: Scheduler instance is created but not started.\n def __init__(self, task_manager, config_manager: ConfigManager):\n with belief_scope(\"SchedulerService.__init__\"):\n self.task_manager = task_manager\n self.config_manager = config_manager\n self.scheduler = BackgroundScheduler()\n self.loop = asyncio.get_event_loop()\n # #endregion __init__\n # #region start [TYPE Function]\n # @PURPOSE: Starts the background scheduler and loads initial schedules.\n # @PRE: Scheduler should be initialized.\n # @POST: Scheduler is running and schedules are loaded.\n def start(self):\n with belief_scope(\"SchedulerService.start\"):\n if not self.scheduler.running:\n self.scheduler.start()\n logger.info(\"Scheduler started.\")\n self.load_schedules()\n # #endregion start\n # #region stop [TYPE Function]\n # @PURPOSE: Stops the background scheduler.\n # @PRE: Scheduler should be running.\n # @POST: Scheduler is shut down.\n def stop(self):\n with belief_scope(\"SchedulerService.stop\"):\n if self.scheduler.running:\n self.scheduler.shutdown()\n logger.info(\"Scheduler stopped.\")\n # #endregion stop\n # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # Re-register active validation policies with schedules\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n active_policies = (\n db.query(ValidationPolicy)\n .filter(\n ValidationPolicy.is_active.is_(True),\n ValidationPolicy.schedule_days.isnot(None),\n )\n .all()\n )\n for policy in active_policies:\n schedule_days = policy.schedule_days or []\n if not schedule_days:\n continue\n ws = policy.window_start\n if ws is None:\n continue\n # Build cron: minute hour * * day-of-week\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(\n policy_id=policy.id,\n cron_expression=cron,\n app_timezone=config.settings.app_timezone,\n )\n if active_policies:\n logger.reason(f\"Loaded {len(active_policies)} active validation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load validation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n # #region add_backup_job [TYPE Function]\n # @PURPOSE: Adds a scheduled backup job for an environment.\n # @PRE: env_id and cron_expression must be valid strings.\n # @POST: A new job is added to the scheduler or replaced if it already exists.\n # @PARAM: env_id (str) - The ID of the environment.\n # @PARAM: cron_expression (str) - The cron expression for the schedule.\n def add_backup_job(self, env_id: str, cron_expression: str):\n with belief_scope(\n \"SchedulerService.add_backup_job\",\n f\"env_id={env_id}, cron={cron_expression}\",\n ):\n job_id = f\"backup_{env_id}\"\n try:\n self.scheduler.add_job(\n self._trigger_backup,\n CronTrigger.from_crontab(cron_expression),\n id=job_id,\n args=[env_id],\n replace_existing=True,\n )\n logger.info(\n f\"Scheduled backup job added for environment {env_id}: {cron_expression}\"\n )\n except Exception as e:\n logger.error(f\"Failed to add backup job for environment {env_id}: {e}\")\n # #endregion add_backup_job\n # #region add_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,cron,apscheduler]\n # @BRIEF Register a translation schedule with APScheduler.\n # @PRE schedule_id, job_id, and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls execute_scheduled_translation on trigger.\n # @RELATION DEPENDS_ON -> [execute_scheduled_translation]\n # @RELATION DEPENDS_ON -> [SessionLocal]\n def add_translation_job(self, schedule_id: str, job_id: str, cron_expression: str, timezone: str = \"UTC\", execution_mode: str = \"full\"):\n with belief_scope(\n \"SchedulerService.add_translation_job\",\n f\"schedule_id={schedule_id}, job_id={job_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n from ..plugins.translate.scheduler import execute_scheduled_translation\n\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n tz = ZoneInfo(timezone)\n self.scheduler.add_job(\n execute_scheduled_translation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[schedule_id, job_id, SessionLocal, self.config_manager, execution_mode],\n replace_existing=True,\n )\n logger.reason(\n f\"Translation schedule registered: {job_id_aps} ({cron_expression})\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register translation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_translation_job\n # #region remove_translation_job [C:4] [TYPE Function] [SEMANTICS scheduler,translation,remove,apscheduler]\n # @BRIEF Remove a translation schedule from APScheduler.\n # @PRE schedule_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_translation_job(self, schedule_id: str):\n with belief_scope(\n \"SchedulerService.remove_translation_job\",\n f\"schedule_id={schedule_id}\",\n ):\n job_id_aps = f\"translate_{schedule_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Translation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Translation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_translation_job\n # #region _trigger_backup [TYPE Function]\n # @PURPOSE: Triggered by the scheduler to start a backup task.\n # @PRE: env_id must be a valid environment ID.\n # @POST: A new backup task is created in the task manager if not already running.\n # @PARAM: env_id (str) - The ID of the environment.\n def _trigger_backup(self, env_id: str):\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_backup\", f\"env_id={env_id}\"):\n logger.info(f\"Triggering scheduled backup for environment {env_id}\")\n # Check if a backup is already running for this environment\n active_tasks = self.task_manager.get_tasks(limit=100)\n for task in active_tasks:\n if (\n task.plugin_id == \"superset-backup\"\n and task.status in [\"PENDING\", \"RUNNING\"]\n and task.params.get(\"environment_id\") == env_id\n ):\n logger.warning(\n f\"Backup already running for environment {env_id}. Skipping scheduled run.\"\n )\n return\n # Run the backup task\n # We need to run this in the event loop since create_task is async\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n \"superset-backup\", {\"environment_id\": env_id}\n ),\n self.loop,\n )\n # #endregion _trigger_backup\n # #region add_validation_job [C:3] [TYPE Function] [SEMANTICS scheduler,validation,cron,apscheduler]\n # @BRIEF Register a validation policy schedule with APScheduler.\n # @PRE policy_id and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls _trigger_validation on trigger.\n # @RELATION DEPENDS_ON -> [_trigger_validation]\n def add_validation_job(self, policy_id: str, cron_expression: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.add_validation_job\",\n f\"policy_id={policy_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n job_id_aps = f\"validation_{policy_id}\"\n try:\n tz = ZoneInfo(app_timezone)\n self.scheduler.add_job(\n self._trigger_validation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[policy_id],\n replace_existing=True,\n )\n logger.reason(\n f\"Validation schedule registered: {job_id_aps} ({cron_expression}) [{app_timezone}]\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register validation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_validation_job\n # #region remove_validation_job [C:2] [TYPE Function] [SEMANTICS scheduler,validation,remove,apscheduler]\n # @BRIEF Remove a validation policy schedule from APScheduler.\n # @PRE policy_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_validation_job(self, policy_id: str) -> None:\n with belief_scope(\n \"SchedulerService.remove_validation_job\",\n f\"policy_id={policy_id}\",\n ):\n job_id_aps = f\"validation_{policy_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Validation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Validation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_validation_job\n # #region reload_validation_policy [C:2] [TYPE Function] [SEMANTICS scheduler,validation,reload,apscheduler]\n # @BRIEF Reload a single validation policy schedule — calls remove then add.\n # @PRE policy_id is a valid ValidationPolicy id with schedule data in DB.\n # @POST Old job is removed; new job is registered if policy is active and has schedule_days.\n # @SIDE_EFFECT Mutates APScheduler state; queries ValidationPolicy from DB.\n def reload_validation_policy(self, policy_id: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.reload_validation_policy\",\n f\"policy_id={policy_id}\",\n ):\n self.remove_validation_job(policy_id)\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.reason(f\"Policy {policy_id} not found; schedule removed\")\n return\n if not policy.is_active:\n logger.reason(f\"Policy {policy_id} is inactive; schedule removed\")\n return\n schedule_days = policy.schedule_days or []\n if not schedule_days or policy.window_start is None:\n logger.reason(f\"Policy {policy_id} has no schedule; nothing to register\")\n return\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n ws = policy.window_start\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(policy_id, cron, app_timezone=app_timezone)\n finally:\n db.close()\n except Exception as e:\n logger.explore(\n f\"Failed to reload validation policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n # #endregion reload_validation_policy\n # #region _trigger_validation [C:3] [TYPE Function] [SEMANTICS scheduler,validation,trigger]\n # @BRIEF APScheduler job handler — triggers validation runs for a policy.\n # @PRE policy_id is a valid ValidationPolicy id with dashboard_ids.\n # @POST A validation task is spawned via TaskManager for each dashboard in the policy.\n # @SIDE_EFFECT Creates TaskRecord entries for validation runs; logs progress.\n def _trigger_validation(self, policy_id: str) -> None:\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_validation\", f\"policy_id={policy_id}\"):\n logger.reason(f\"Triggering scheduled validation for policy {policy_id}\")\n db = SessionLocal()\n try:\n from ..models.llm import ValidationPolicy\n\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.explore(f\"Validation policy not found: {policy_id}\")\n return\n if not policy.is_active:\n logger.reason(f\"Validation policy {policy_id} is no longer active; skipping\")\n return\n dashboard_ids = list(policy.dashboard_ids or [])\n if not dashboard_ids:\n logger.explore(f\"Validation policy {policy_id} has no dashboards; skipping\")\n return\n\n ws = policy.window_start\n we = policy.window_end\n today = date.today()\n scheduled_times = ThrottledSchedulerConfigurator.calculate_schedule(\n window_start=ws,\n window_end=we or time(ws.hour, ws.minute + 30),\n dashboard_ids=dashboard_ids,\n current_date=today,\n )\n\n for idx, dash_id in enumerate(dashboard_ids):\n sched_time = scheduled_times[idx] if idx < len(scheduled_times) else scheduled_times[-1]\n params: dict = {\n \"dashboard_id\": dash_id,\n \"environment_id\": policy.environment_id,\n \"provider_id\": policy.provider_id or \"\",\n \"policy_id\": policy_id,\n }\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n plugin_id=\"llm_dashboard_validation\", params=params\n ),\n self.loop,\n )\n logger.reason(\n f\"Scheduled validation for dashboard {dash_id} at {sched_time.isoformat()}\"\n )\n except Exception as e:\n logger.explore(\n f\"Error triggering validation for policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n finally:\n db.close()\n # #endregion _trigger_validation\n# #endregion SchedulerService\n" }, { "contract_id": "start", @@ -25628,7 +26528,7 @@ "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", "start_line": 53, - "end_line": 91, + "end_line": 126, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -25642,14 +26542,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n" + "body": " # #region load_schedules [C:4] [TYPE Function] [SEMANTICS scheduler,backup,translation,apscheduler]\n # @BRIEF Load backup and active translation schedules from config and DB, re-registering all jobs.\n # @PRE config_manager must have valid configuration; database is accessible.\n # @POST All enabled backup jobs and active translation schedules are re-registered in APScheduler.\n # @SIDE_EFFECT Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.\n def load_schedules(self):\n with belief_scope(\"SchedulerService.load_schedules\"):\n # Clear existing jobs\n self.scheduler.remove_all_jobs()\n config = self.config_manager.get_config()\n for env in config.environments:\n if env.backup_schedule and env.backup_schedule.enabled:\n self.add_backup_job(env.id, env.backup_schedule.cron_expression)\n # Re-register active translation schedules from the database\n try:\n from ..models.translate import TranslationSchedule\n db = SessionLocal()\n try:\n active_schedules = (\n db.query(TranslationSchedule)\n .filter(TranslationSchedule.is_active == True)\n .all()\n )\n for sched in active_schedules:\n self.add_translation_job(\n schedule_id=sched.id,\n job_id=sched.job_id,\n cron_expression=sched.cron_expression,\n timezone=sched.timezone,\n execution_mode=getattr(sched, 'execution_mode', 'full'),\n )\n if active_schedules:\n logger.reason(f\"Loaded {len(active_schedules)} active translation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load translation schedules on startup\",\n extra={\"error\": str(e)})\n # Re-register active validation policies with schedules\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n active_policies = (\n db.query(ValidationPolicy)\n .filter(\n ValidationPolicy.is_active.is_(True),\n ValidationPolicy.schedule_days.isnot(None),\n )\n .all()\n )\n for policy in active_policies:\n schedule_days = policy.schedule_days or []\n if not schedule_days:\n continue\n ws = policy.window_start\n if ws is None:\n continue\n # Build cron: minute hour * * day-of-week\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(\n policy_id=policy.id,\n cron_expression=cron,\n app_timezone=config.settings.app_timezone,\n )\n if active_policies:\n logger.reason(f\"Loaded {len(active_policies)} active validation schedule(s)\")\n finally:\n db.close()\n except Exception as e:\n logger.explore(\"Failed to load validation schedules on startup\",\n extra={\"error\": str(e)})\n # #endregion load_schedules\n" }, { "contract_id": "add_backup_job", "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", - "start_line": 92, - "end_line": 117, + "start_line": 127, + "end_line": 152, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -25675,8 +26575,8 @@ "contract_id": "add_translation_job", "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", - "start_line": 118, - "end_line": 152, + "start_line": 153, + "end_line": 187, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -25709,8 +26609,8 @@ "contract_id": "remove_translation_job", "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", - "start_line": 153, - "end_line": 169, + "start_line": 188, + "end_line": 204, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -25730,8 +26630,8 @@ "contract_id": "_trigger_backup", "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", - "start_line": 170, - "end_line": 199, + "start_line": 205, + "end_line": 234, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -25753,12 +26653,103 @@ "tier_source": "AutoCalculated", "body": " # #region _trigger_backup [TYPE Function]\n # @PURPOSE: Triggered by the scheduler to start a backup task.\n # @PRE: env_id must be a valid environment ID.\n # @POST: A new backup task is created in the task manager if not already running.\n # @PARAM: env_id (str) - The ID of the environment.\n def _trigger_backup(self, env_id: str):\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_backup\", f\"env_id={env_id}\"):\n logger.info(f\"Triggering scheduled backup for environment {env_id}\")\n # Check if a backup is already running for this environment\n active_tasks = self.task_manager.get_tasks(limit=100)\n for task in active_tasks:\n if (\n task.plugin_id == \"superset-backup\"\n and task.status in [\"PENDING\", \"RUNNING\"]\n and task.params.get(\"environment_id\") == env_id\n ):\n logger.warning(\n f\"Backup already running for environment {env_id}. Skipping scheduled run.\"\n )\n return\n # Run the backup task\n # We need to run this in the event loop since create_task is async\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n \"superset-backup\", {\"environment_id\": env_id}\n ),\n self.loop,\n )\n # #endregion _trigger_backup\n" }, + { + "contract_id": "add_validation_job", + "contract_type": "Function", + "file_path": "backend/src/core/scheduler.py", + "start_line": 235, + "end_line": 266, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "A new APScheduler job is registered or replaced if it already exists.", + "PRE": "policy_id and cron_expression are valid strings.", + "PURPOSE": "Register a validation policy schedule with APScheduler.", + "SIDE_EFFECT": "Mutates APScheduler state; calls _trigger_validation on trigger." + }, + "relations": [ + { + "source_id": "add_validation_job", + "relation_type": "DEPENDS_ON", + "target_id": "_trigger_validation", + "target_ref": "[_trigger_validation]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region add_validation_job [C:3] [TYPE Function] [SEMANTICS scheduler,validation,cron,apscheduler]\n # @BRIEF Register a validation policy schedule with APScheduler.\n # @PRE policy_id and cron_expression are valid strings.\n # @POST A new APScheduler job is registered or replaced if it already exists.\n # @SIDE_EFFECT Mutates APScheduler state; calls _trigger_validation on trigger.\n # @RELATION DEPENDS_ON -> [_trigger_validation]\n def add_validation_job(self, policy_id: str, cron_expression: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.add_validation_job\",\n f\"policy_id={policy_id}, cron={cron_expression}\",\n ):\n from zoneinfo import ZoneInfo\n\n job_id_aps = f\"validation_{policy_id}\"\n try:\n tz = ZoneInfo(app_timezone)\n self.scheduler.add_job(\n self._trigger_validation,\n CronTrigger.from_crontab(cron_expression, timezone=tz),\n id=job_id_aps,\n args=[policy_id],\n replace_existing=True,\n )\n logger.reason(\n f\"Validation schedule registered: {job_id_aps} ({cron_expression}) [{app_timezone}]\"\n )\n except Exception as e:\n logger.explore(\n f\"Failed to register validation schedule: {job_id_aps}\",\n extra={\"error\": str(e)},\n )\n # #endregion add_validation_job\n" + }, + { + "contract_id": "remove_validation_job", + "contract_type": "Function", + "file_path": "backend/src/core/scheduler.py", + "start_line": 267, + "end_line": 283, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "The APScheduler job is removed if it exists; silently ignored otherwise.", + "PRE": "policy_id is a valid string.", + "PURPOSE": "Remove a validation policy schedule from APScheduler.", + "SIDE_EFFECT": "Mutates APScheduler state." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region remove_validation_job [C:2] [TYPE Function] [SEMANTICS scheduler,validation,remove,apscheduler]\n # @BRIEF Remove a validation policy schedule from APScheduler.\n # @PRE policy_id is a valid string.\n # @POST The APScheduler job is removed if it exists; silently ignored otherwise.\n # @SIDE_EFFECT Mutates APScheduler state.\n def remove_validation_job(self, policy_id: str) -> None:\n with belief_scope(\n \"SchedulerService.remove_validation_job\",\n f\"policy_id={policy_id}\",\n ):\n job_id_aps = f\"validation_{policy_id}\"\n try:\n self.scheduler.remove_job(job_id_aps)\n logger.info(f\"Validation schedule removed: {job_id_aps}\")\n except Exception:\n logger.reason(f\"Validation schedule not found (already removed): {job_id_aps}\")\n # #endregion remove_validation_job\n" + }, + { + "contract_id": "reload_validation_policy", + "contract_type": "Function", + "file_path": "backend/src/core/scheduler.py", + "start_line": 284, + "end_line": 321, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Old job is removed; new job is registered if policy is active and has schedule_days.", + "PRE": "policy_id is a valid ValidationPolicy id with schedule data in DB.", + "PURPOSE": "Reload a single validation policy schedule — calls remove then add.", + "SIDE_EFFECT": "Mutates APScheduler state; queries ValidationPolicy from DB." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region reload_validation_policy [C:2] [TYPE Function] [SEMANTICS scheduler,validation,reload,apscheduler]\n # @BRIEF Reload a single validation policy schedule — calls remove then add.\n # @PRE policy_id is a valid ValidationPolicy id with schedule data in DB.\n # @POST Old job is removed; new job is registered if policy is active and has schedule_days.\n # @SIDE_EFFECT Mutates APScheduler state; queries ValidationPolicy from DB.\n def reload_validation_policy(self, policy_id: str, app_timezone: str = \"Europe/Moscow\") -> None:\n with belief_scope(\n \"SchedulerService.reload_validation_policy\",\n f\"policy_id={policy_id}\",\n ):\n self.remove_validation_job(policy_id)\n try:\n from ..models.llm import ValidationPolicy\n db = SessionLocal()\n try:\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.reason(f\"Policy {policy_id} not found; schedule removed\")\n return\n if not policy.is_active:\n logger.reason(f\"Policy {policy_id} is inactive; schedule removed\")\n return\n schedule_days = policy.schedule_days or []\n if not schedule_days or policy.window_start is None:\n logger.reason(f\"Policy {policy_id} has no schedule; nothing to register\")\n return\n dow = \",\".join(str(d) for d in sorted(schedule_days))\n ws = policy.window_start\n cron = f\"{ws.minute} {ws.hour} * * {dow}\"\n self.add_validation_job(policy_id, cron, app_timezone=app_timezone)\n finally:\n db.close()\n except Exception as e:\n logger.explore(\n f\"Failed to reload validation policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n # #endregion reload_validation_policy\n" + }, + { + "contract_id": "_trigger_validation", + "contract_type": "Function", + "file_path": "backend/src/core/scheduler.py", + "start_line": 322, + "end_line": 381, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "A validation task is spawned via TaskManager for each dashboard in the policy.", + "PRE": "policy_id is a valid ValidationPolicy id with dashboard_ids.", + "PURPOSE": "APScheduler job handler — triggers validation runs for a policy.", + "SIDE_EFFECT": "Creates TaskRecord entries for validation runs; logs progress." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _trigger_validation [C:3] [TYPE Function] [SEMANTICS scheduler,validation,trigger]\n # @BRIEF APScheduler job handler — triggers validation runs for a policy.\n # @PRE policy_id is a valid ValidationPolicy id with dashboard_ids.\n # @POST A validation task is spawned via TaskManager for each dashboard in the policy.\n # @SIDE_EFFECT Creates TaskRecord entries for validation runs; logs progress.\n def _trigger_validation(self, policy_id: str) -> None:\n seed_trace_id()\n with belief_scope(\"SchedulerService._trigger_validation\", f\"policy_id={policy_id}\"):\n logger.reason(f\"Triggering scheduled validation for policy {policy_id}\")\n db = SessionLocal()\n try:\n from ..models.llm import ValidationPolicy\n\n policy = db.query(ValidationPolicy).filter(ValidationPolicy.id == policy_id).first()\n if not policy:\n logger.explore(f\"Validation policy not found: {policy_id}\")\n return\n if not policy.is_active:\n logger.reason(f\"Validation policy {policy_id} is no longer active; skipping\")\n return\n dashboard_ids = list(policy.dashboard_ids or [])\n if not dashboard_ids:\n logger.explore(f\"Validation policy {policy_id} has no dashboards; skipping\")\n return\n\n ws = policy.window_start\n we = policy.window_end\n today = date.today()\n scheduled_times = ThrottledSchedulerConfigurator.calculate_schedule(\n window_start=ws,\n window_end=we or time(ws.hour, ws.minute + 30),\n dashboard_ids=dashboard_ids,\n current_date=today,\n )\n\n for idx, dash_id in enumerate(dashboard_ids):\n sched_time = scheduled_times[idx] if idx < len(scheduled_times) else scheduled_times[-1]\n params: dict = {\n \"dashboard_id\": dash_id,\n \"environment_id\": policy.environment_id,\n \"provider_id\": policy.provider_id or \"\",\n \"policy_id\": policy_id,\n }\n asyncio.run_coroutine_threadsafe(\n self.task_manager.create_task(\n plugin_id=\"llm_dashboard_validation\", params=params\n ),\n self.loop,\n )\n logger.reason(\n f\"Scheduled validation for dashboard {dash_id} at {sched_time.isoformat()}\"\n )\n except Exception as e:\n logger.explore(\n f\"Error triggering validation for policy {policy_id}\",\n extra={\"error\": str(e)},\n )\n finally:\n db.close()\n # #endregion _trigger_validation\n" + }, { "contract_id": "ThrottledSchedulerConfigurator", "contract_type": "Class", "file_path": "backend/src/core/scheduler.py", - "start_line": 201, - "end_line": 252, + "start_line": 383, + "end_line": 434, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -25787,8 +26778,8 @@ "contract_id": "calculate_schedule", "contract_type": "Function", "file_path": "backend/src/core/scheduler.py", - "start_line": 210, - "end_line": 251, + "start_line": 392, + "end_line": 433, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -25808,7 +26799,7 @@ "contract_type": "Module", "file_path": "backend/src/core/superset_client/__init__.py", "start_line": 1, - "end_line": 72, + "end_line": 75, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -25854,14 +26845,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SupersetClientModule [C:5] [TYPE Module] [SEMANTICS superset, package, superset-client]\n# @LAYER: Service\n# @BRIEF Предоставляет высокоуровневый клиент для взаимодействия с Superset REST API, инкапсулируя логику запросов, обработку ошибок и пагинацию.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION DEPENDS_ON -> [get_filename_from_headers]\n# @RELATION DEPENDS_ON -> [SupersetDatasetsPreviewFiltersMixin]\n#\n# @INVARIANT: All network operations must use the internal APIClient instance.\n# @PUBLIC_API: SupersetClient\n#\n# @RATIONALE: Decomposed from monolithic superset_client.py (2145 lines) into\n# domain-scoped mixins to satisfy INV_7 (module < 400 lines). The composed class\n# preserves the original public API surface — all consumers continue to import\n# `from src.core.superset_client import SupersetClient` without changes.\n# @REJECTED: Keeping a single 2145-line file — violates fractal limit INV_7.\n# @PRE: Superset instance URL and credentials configured\n# @POST: SupersetClient class exported\n# @SIDE_EFFECT: Establishes HTTP connection pool to Superset\n# @DATA_CONTRACT: SupersetConfig -> SupersetClient\n\nfrom ._base import SupersetClientBase\nfrom ._charts import SupersetChartsMixin\nfrom ._dashboards_crud import SupersetDashboardsCrudMixin\nfrom ._dashboards_filters import SupersetDashboardsFiltersMixin\nfrom ._dashboards_list import SupersetDashboardsListMixin\nfrom ._databases import SupersetDatabasesMixin\nfrom ._datasets import SupersetDatasetsMixin\nfrom ._datasets_preview import SupersetDatasetsPreviewMixin\nfrom ._datasets_preview_filters import SupersetDatasetsPreviewFiltersMixin\nfrom ._user_projection import SupersetUserProjectionMixin\n\n\n# #region SupersetClient [C:3] [TYPE Class]\n# @BRIEF Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION INHERITS -> [SupersetClientBase]\n# @RELATION INHERITS -> [SupersetUserProjectionMixin]\n# @RELATION INHERITS -> [SupersetDashboardsListMixin]\n# @RELATION INHERITS -> [SupersetDashboardsFiltersMixin]\n# @RELATION INHERITS -> [SupersetDashboardsCrudMixin]\n# @RELATION INHERITS -> [SupersetChartsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewFiltersMixin]\n# @RELATION INHERITS -> [SupersetDatabasesMixin]\nclass SupersetClient(\n SupersetDatabasesMixin,\n SupersetDatasetsPreviewFiltersMixin,\n SupersetDatasetsPreviewMixin,\n SupersetDatasetsMixin,\n SupersetChartsMixin,\n SupersetDashboardsCrudMixin,\n SupersetDashboardsFiltersMixin,\n SupersetDashboardsListMixin,\n SupersetUserProjectionMixin,\n SupersetClientBase,\n):\n \"\"\"Composed Superset REST API client.\n\n MRO order ensures domain mixins resolve before base class.\n All consumers continue to use: from src.core.superset_client import SupersetClient\n \"\"\"\n pass\n\n\n# #endregion SupersetClient\n\n# #endregion SupersetClientModule\n" + "body": "# #region SupersetClientModule [C:5] [TYPE Module] [SEMANTICS superset, package, superset-client]\n# @LAYER: Service\n# @BRIEF Предоставляет высокоуровневый клиент для взаимодействия с Superset REST API, инкапсулируя логику запросов, обработку ошибок и пагинацию.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION DEPENDS_ON -> [get_filename_from_headers]\n# @RELATION DEPENDS_ON -> [SupersetDatasetsPreviewFiltersMixin]\n#\n# @INVARIANT: All network operations must use the internal APIClient instance.\n# @PUBLIC_API: SupersetClient\n#\n# @RATIONALE: Decomposed from monolithic superset_client.py (2145 lines) into\n# domain-scoped mixins to satisfy INV_7 (module < 400 lines). The composed class\n# preserves the original public API surface — all consumers continue to import\n# `from src.core.superset_client import SupersetClient` without changes.\n# @REJECTED: Keeping a single 2145-line file — violates fractal limit INV_7.\n# @PRE: Superset instance URL and credentials configured\n# @POST: SupersetClient class exported\n# @SIDE_EFFECT: Establishes HTTP connection pool to Superset\n# @DATA_CONTRACT: SupersetConfig -> SupersetClient\n\nfrom ._base import SupersetClientBase\nfrom ._charts import SupersetChartsMixin\nfrom ._dashboards_crud import SupersetDashboardsCrudMixin\nfrom ._dashboards_filters import SupersetDashboardsFiltersMixin\nfrom ._dashboards_list import SupersetDashboardsListMixin\nfrom ._dashboards_write import SupersetDashboardsWriteMixin\nfrom ._databases import SupersetDatabasesMixin\nfrom ._datasets import SupersetDatasetsMixin\nfrom ._datasets_preview import SupersetDatasetsPreviewMixin\nfrom ._datasets_preview_filters import SupersetDatasetsPreviewFiltersMixin\nfrom ._user_projection import SupersetUserProjectionMixin\n\n\n# #region SupersetClient [C:3] [TYPE Class]\n# @BRIEF Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION INHERITS -> [SupersetClientBase]\n# @RELATION INHERITS -> [SupersetUserProjectionMixin]\n# @RELATION INHERITS -> [SupersetDashboardsListMixin]\n# @RELATION INHERITS -> [SupersetDashboardsFiltersMixin]\n# @RELATION INHERITS -> [SupersetDashboardsCrudMixin]\n# @RELATION INHERITS -> [SupersetChartsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewFiltersMixin]\n# @RELATION INHERITS -> [SupersetDatabasesMixin]\n# @RELATION INHERITS -> [SupersetDashboardsWriteMixin]\nclass SupersetClient(\n SupersetDatabasesMixin,\n SupersetDatasetsPreviewFiltersMixin,\n SupersetDatasetsPreviewMixin,\n SupersetDatasetsMixin,\n SupersetChartsMixin,\n SupersetDashboardsCrudMixin,\n SupersetDashboardsFiltersMixin,\n SupersetDashboardsListMixin,\n SupersetDashboardsWriteMixin,\n SupersetUserProjectionMixin,\n SupersetClientBase,\n):\n \"\"\"Composed Superset REST API client.\n\n MRO order ensures domain mixins resolve before base class.\n All consumers continue to use: from src.core.superset_client import SupersetClient\n \"\"\"\n pass\n\n\n# #endregion SupersetClient\n\n# #endregion SupersetClientModule\n" }, { "contract_id": "SupersetClient", "contract_type": "Class", "file_path": "backend/src/core/superset_client/__init__.py", - "start_line": 35, - "end_line": 70, + "start_line": 36, + "end_line": 73, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -25946,12 +26937,18 @@ "relation_type": "INHERITS", "target_id": "SupersetDatabasesMixin", "target_ref": "[SupersetDatabasesMixin]" + }, + { + "source_id": "SupersetClient", + "relation_type": "INHERITS", + "target_id": "SupersetDashboardsWriteMixin", + "target_ref": "[SupersetDashboardsWriteMixin]" } ], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SupersetClient [C:3] [TYPE Class]\n# @BRIEF Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION INHERITS -> [SupersetClientBase]\n# @RELATION INHERITS -> [SupersetUserProjectionMixin]\n# @RELATION INHERITS -> [SupersetDashboardsListMixin]\n# @RELATION INHERITS -> [SupersetDashboardsFiltersMixin]\n# @RELATION INHERITS -> [SupersetDashboardsCrudMixin]\n# @RELATION INHERITS -> [SupersetChartsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewFiltersMixin]\n# @RELATION INHERITS -> [SupersetDatabasesMixin]\nclass SupersetClient(\n SupersetDatabasesMixin,\n SupersetDatasetsPreviewFiltersMixin,\n SupersetDatasetsPreviewMixin,\n SupersetDatasetsMixin,\n SupersetChartsMixin,\n SupersetDashboardsCrudMixin,\n SupersetDashboardsFiltersMixin,\n SupersetDashboardsListMixin,\n SupersetUserProjectionMixin,\n SupersetClientBase,\n):\n \"\"\"Composed Superset REST API client.\n\n MRO order ensures domain mixins resolve before base class.\n All consumers continue to use: from src.core.superset_client import SupersetClient\n \"\"\"\n pass\n\n\n# #endregion SupersetClient\n" + "body": "# #region SupersetClient [C:3] [TYPE Class]\n# @BRIEF Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.\n# @RELATION DEPENDS_ON -> [ConfigModels]\n# @RELATION DEPENDS_ON -> [APIClient]\n# @RELATION DEPENDS_ON -> [SupersetAPIError]\n# @RELATION INHERITS -> [SupersetClientBase]\n# @RELATION INHERITS -> [SupersetUserProjectionMixin]\n# @RELATION INHERITS -> [SupersetDashboardsListMixin]\n# @RELATION INHERITS -> [SupersetDashboardsFiltersMixin]\n# @RELATION INHERITS -> [SupersetDashboardsCrudMixin]\n# @RELATION INHERITS -> [SupersetChartsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewMixin]\n# @RELATION INHERITS -> [SupersetDatasetsPreviewFiltersMixin]\n# @RELATION INHERITS -> [SupersetDatabasesMixin]\n# @RELATION INHERITS -> [SupersetDashboardsWriteMixin]\nclass SupersetClient(\n SupersetDatabasesMixin,\n SupersetDatasetsPreviewFiltersMixin,\n SupersetDatasetsPreviewMixin,\n SupersetDatasetsMixin,\n SupersetChartsMixin,\n SupersetDashboardsCrudMixin,\n SupersetDashboardsFiltersMixin,\n SupersetDashboardsListMixin,\n SupersetDashboardsWriteMixin,\n SupersetUserProjectionMixin,\n SupersetClientBase,\n):\n \"\"\"Composed Superset REST API client.\n\n MRO order ensures domain mixins resolve before base class.\n All consumers continue to use: from src.core.superset_client import SupersetClient\n \"\"\"\n pass\n\n\n# #endregion SupersetClient\n" }, { "contract_id": "SupersetClientBase", @@ -26230,6 +27227,237 @@ "tier_source": "AutoCalculated", "body": "# #region SupersetDashboardsListMixin [C:3] [TYPE Module] [SEMANTICS superset, dashboard, list, search, filter]\n# @LAYER: Infra\n# @BRIEF Dashboard listing mixin for SupersetClient — paginated list, summary projection.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetUserProjectionMixin]\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 SupersetDashboardsListMixin [C:3] [TYPE Class]\n# @BRIEF Mixin providing dashboard listing and summary projection operations.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetUserProjectionMixin]\nclass SupersetDashboardsListMixin:\n # #region SupersetClientGetDashboards [TYPE Function] [C:3]\n # @PURPOSE: Получает полный список дашбордов, автоматически обрабатывая пагинацию.\n # @RELATION: CALLS -> [SupersetClientFetchAllPages]\n def get_dashboards(self, query: dict | None = None) -> tuple[int, list[dict]]:\n with belief_scope(\"get_dashboards\"):\n app_logger.info(\"[get_dashboards][Enter] Fetching dashboards.\")\n validated_query = self._validate_query_params(query or {})\n if \"columns\" not in validated_query:\n validated_query[\"columns\"] = [\n \"slug\", \"id\", \"url\", \"changed_on_utc\", \"dashboard_title\",\n \"published\", \"created_by\", \"changed_by\", \"changed_by_name\", \"owners\",\n ]\n paginated_data = self._fetch_all_pages(\n endpoint=\"/dashboard/\",\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} dashboards.\", extra={\"src\": \"get_dashboards\"})\n return total_count, paginated_data\n # #endregion SupersetClientGetDashboards\n # #region SupersetClientGetDashboardsPage [TYPE Function] [C:3]\n # @PURPOSE: Fetches a single dashboards page from Superset without iterating all pages.\n # @RELATION: CALLS -> [APIClient]\n def get_dashboards_page(\n self, query: dict | None = None\n ) -> tuple[int, list[dict]]:\n with belief_scope(\"get_dashboards_page\"):\n validated_query = self._validate_query_params(query or {})\n if \"columns\" not in validated_query:\n validated_query[\"columns\"] = [\n \"slug\", \"id\", \"url\", \"changed_on_utc\", \"dashboard_title\",\n \"published\", \"created_by\", \"changed_by\", \"changed_by_name\", \"owners\",\n ]\n response_json = cast(\n dict[str, Any],\n self.network.request(\n method=\"GET\",\n endpoint=\"/dashboard/\",\n params={\"q\": json.dumps(validated_query)},\n ),\n )\n result = response_json.get(\"result\", [])\n total_count = response_json.get(\"count\", len(result))\n return total_count, result\n # #endregion SupersetClientGetDashboardsPage\n # #region SupersetClientGetDashboardsSummary [TYPE Function] [C:3]\n # @PURPOSE: Fetches dashboard metadata optimized for the grid.\n # @RELATION: CALLS -> [SupersetClientGetDashboards]\n def get_dashboards_summary(self, require_slug: bool = False) -> list[dict]:\n with belief_scope(\"SupersetClient.get_dashboards_summary\"):\n query: dict[str, Any] = {}\n if require_slug:\n query[\"filters\"] = [{\"col\": \"slug\", \"opr\": \"neq\", \"value\": \"\"}]\n _, dashboards = self.get_dashboards(query=query)\n result = []\n max_debug_samples = 12\n for index, dash in enumerate(dashboards):\n raw_owners = dash.get(\"owners\")\n raw_created_by = dash.get(\"created_by\")\n raw_changed_by = dash.get(\"changed_by\")\n raw_changed_by_name = dash.get(\"changed_by_name\")\n owners = self._extract_owner_labels(raw_owners)\n if not owners:\n owners = self._extract_owner_labels([raw_created_by, raw_changed_by])\n projected_created_by = self._extract_user_display(None, raw_created_by)\n projected_modified_by = self._extract_user_display(\n raw_changed_by_name, raw_changed_by,\n )\n raw_owner_usernames: list[str] = []\n if isinstance(raw_owners, list):\n for owner_payload in raw_owners:\n if isinstance(owner_payload, dict):\n owner_username = self._sanitize_user_text(\n owner_payload.get(\"username\")\n )\n if owner_username:\n raw_owner_usernames.append(owner_username)\n result.append({\n \"id\": dash.get(\"id\"),\n \"slug\": dash.get(\"slug\"),\n \"title\": dash.get(\"dashboard_title\"),\n \"url\": dash.get(\"url\"),\n \"last_modified\": dash.get(\"changed_on_utc\"),\n \"status\": \"published\" if dash.get(\"published\") else \"draft\",\n \"created_by\": projected_created_by,\n \"modified_by\": projected_modified_by,\n \"owners\": owners,\n })\n if index < max_debug_samples:\n app_logger.reflect(\n \"Dashboard actor projection sample\",\n extra={\"src\": \"get_dashboards_summary\", \"payload\": {\"env\": getattr(self.env, 'id', None), \"dashboard_id\": dash.get('id'), \"raw_owners\": raw_owners, \"raw_owner_usernames\": raw_owner_usernames, \"raw_created_by\": raw_created_by, \"raw_changed_by\": raw_changed_by, \"raw_changed_by_name\": raw_changed_by_name, \"projected_owners\": owners, \"projected_created_by\": projected_created_by, \"projected_modified_by\": projected_modified_by}},\n )\n app_logger.reflect(\n \"Dashboard actor projection summary\",\n extra={\"src\": \"get_dashboards_summary\", \"payload\": {\"env\": getattr(self.env, 'id', None), \"dashboards\": len(result), \"sampled\": min(len(result), max_debug_samples)}},\n )\n return result\n # #endregion SupersetClientGetDashboardsSummary\n # #region SupersetClientGetDashboardsSummaryPage [TYPE Function] [C:3]\n # @PURPOSE: Fetches one page of dashboard metadata optimized for the grid.\n # @RELATION: CALLS -> [SupersetClientGetDashboardsPage]\n def get_dashboards_summary_page(\n self,\n page: int,\n page_size: int,\n search: str | None = None,\n require_slug: bool = False,\n ) -> tuple[int, list[dict]]:\n with belief_scope(\"SupersetClient.get_dashboards_summary_page\"):\n query: dict[str, Any] = {\n \"page\": max(page - 1, 0),\n \"page_size\": page_size,\n }\n filters: list[dict[str, Any]] = []\n if require_slug:\n filters.append({\"col\": \"slug\", \"opr\": \"neq\", \"value\": \"\"})\n normalized_search = (search or \"\").strip()\n if normalized_search:\n filters.append({\n \"col\": \"dashboard_title\", \"opr\": \"ct\", \"value\": normalized_search,\n })\n if filters:\n query[\"filters\"] = filters\n total_count, dashboards = self.get_dashboards_page(query=query)\n result = []\n for dash in dashboards:\n owners = self._extract_owner_labels(dash.get(\"owners\"))\n if not owners:\n owners = self._extract_owner_labels(\n [dash.get(\"created_by\"), dash.get(\"changed_by\")],\n )\n result.append({\n \"id\": dash.get(\"id\"),\n \"slug\": dash.get(\"slug\"),\n \"title\": dash.get(\"dashboard_title\"),\n \"url\": dash.get(\"url\"),\n \"last_modified\": dash.get(\"changed_on_utc\"),\n \"status\": \"published\" if dash.get(\"published\") else \"draft\",\n \"created_by\": self._extract_user_display(\n None, dash.get(\"created_by\"),\n ),\n \"modified_by\": self._extract_user_display(\n dash.get(\"changed_by_name\"), dash.get(\"changed_by\"),\n ),\n \"owners\": owners,\n })\n return total_count, result\n # #endregion SupersetClientGetDashboardsSummaryPage\n# #endregion SupersetDashboardsListMixin\n# #endregion SupersetDashboardsListMixin\n" }, + { + "contract_id": "SupersetDashboardsWriteMixin", + "contract_type": "Module", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 1, + "end_line": 291, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "DATA_CONTRACT": "Input: dashboard_id / chart_id / markdown_text → Output: API response dict or chart_id int", + "INVARIANT": "All network operations use self.network.request()", + "LAYER": "Infra", + "PURPOSE": "Dashboard write mixin for SupersetClient — markdown chart CRUD and layout manipulation for maintenance banners.", + "RATIONALE": "Extracted from monolithic superset_client to satisfy INV_7.", + "SIDE_EFFECT": "Creates, updates, deletes markdown charts & modifies dashboard layout via Superset API." + }, + "relations": [ + { + "source_id": "SupersetDashboardsWriteMixin", + "relation_type": "DEPENDS_ON", + "target_id": "SupersetClientBase", + "target_ref": "[SupersetClientBase]" + }, + { + "source_id": "SupersetDashboardsWriteMixin", + "relation_type": "DEPENDS_ON", + "target_id": "SupersetChartsMixin", + "target_ref": "[SupersetChartsMixin]" + }, + { + "source_id": "SupersetDashboardsWriteMixin", + "relation_type": "DEPENDS_ON", + "target_id": "LayoutUtils", + "target_ref": "[LayoutUtils]" + } + ], + "schema_warnings": [ + { + "code": "invalid_enum_value", + "tag": "LAYER", + "message": "@LAYER value 'Infra' is not in allowed enum", + "detail": { + "allowed": [ + "Core", + "Domain", + "API", + "UI", + "Service", + "Infrastructure", + "Plugin", + "Tests" + ], + "value": "Infra" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region SupersetDashboardsWriteMixin [C:4] [TYPE Module] [SEMANTICS superset, dashboard, chart, write, maintenance, banner]\n# @BRIEF Dashboard write mixin for SupersetClient — markdown chart CRUD and layout manipulation for maintenance banners.\n# @LAYER Infra\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetChartsMixin]\n# @RELATION DEPENDS_ON -> [LayoutUtils]\n# @SIDE_EFFECT Creates, updates, deletes markdown charts & modifies dashboard layout via Superset API.\n# @DATA_CONTRACT Input: dashboard_id / chart_id / markdown_text → Output: API response dict or chart_id int\n# @INVARIANT All network operations use self.network.request()\n# @RATIONALE Extracted from monolithic superset_client to satisfy INV_7.\n# Uses belief_scope with REASON/REFLECT/EXPLORE markers for all C4 operations per Std.Semantics.Python.\n\nimport json\nfrom typing import Any, cast\n\nfrom ..logger import belief_scope, logger as app_logger\nfrom ._layout_utils import (\n insert_banner_markdown_at_top,\n parse_position_json,\n remove_banner_from_position,\n update_banner_markdown_content,\n)\n\napp_logger = cast(Any, app_logger)\n\n\n# #region SupersetDashboardsWriteMixin [C:4] [TYPE Class]\n# @BRIEF Mixin providing markdown chart CRUD and dashboard layout manipulation for maintenance banners.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetChartsMixin]\nclass SupersetDashboardsWriteMixin:\n \"\"\"Mixin for creating/updating/deleting markdown charts and manipulating dashboard layouts.\"\"\"\n\n # #region create_markdown_chart [C:3] [TYPE Function]\n # @BRIEF Create a markdown chart and return the new chart ID.\n # @PRE dashboard_id exists in Superset. markdown_text not empty.\n # @POST Returns chart_id (int). Chart is NOT yet placed in dashboard layout.\n # @SIDE_EFFECT Creates a new chart resource in Superset.\n # @RELATION CALLS -> [self.network.request]\n def create_markdown_chart(self, dashboard_id: int, markdown_text: str) -> int:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.create_markdown_chart\",\n f\"dashboard_id={dashboard_id}\",\n ):\n app_logger.reason(\n \"Creating markdown chart\",\n extra={\"dashboard_id\": dashboard_id, \"len\": len(markdown_text)},\n )\n datasource_id = self._resolve_markdown_datasource(dashboard_id)\n payload = {\n \"dashboards\": [dashboard_id],\n \"datasource_id\": datasource_id,\n \"datasource_type\": \"table\",\n \"slice_name\": \"Maintenance Banner\",\n \"viz_type\": \"markdown\",\n \"params\": json.dumps({\n \"markdown\": markdown_text,\n \"viz_type\": \"markdown\",\n }),\n }\n try:\n response = cast(dict, self.network.request(\n method=\"POST\", endpoint=\"/chart/\", json=payload\n ))\n chart_id = int(response.get(\"id\") or response.get(\"result\", {}).get(\"id\", 0))\n app_logger.reflect(\"Chart created\", extra={\"chart_id\": chart_id})\n return chart_id\n except Exception as e:\n app_logger.explore(\"Create chart failed\", extra={\"dashboard_id\": dashboard_id}, error=str(e))\n raise\n # #endregion create_markdown_chart\n\n # #region update_markdown_chart [C:3] [TYPE Function]\n # @BRIEF Update the markdown text of an existing markdown chart.\n # @PRE chart_id exists and is a markdown chart.\n # @POST Chart markdown content updated.\n # @SIDE_EFFECT Modifies a chart resource in Superset.\n def update_markdown_chart(self, chart_id: int, markdown_text: str) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_markdown_chart\",\n f\"chart_id={chart_id}\",\n ):\n app_logger.reason(\"Updating markdown chart\", extra={\"chart_id\": chart_id, \"len\": len(markdown_text)})\n payload = {\"params\": json.dumps({\"markdown\": markdown_text, \"viz_type\": \"markdown\"})}\n try:\n response = cast(dict, self.network.request(method=\"PUT\", endpoint=f\"/chart/{chart_id}\", json=payload))\n app_logger.reflect(\"Chart updated\", extra={\"chart_id\": chart_id})\n return response\n except Exception as e:\n app_logger.explore(\"Update chart failed\", extra={\"chart_id\": chart_id}, error=str(e))\n raise\n # #endregion update_markdown_chart\n\n # #region update_dashboard_layout [C:4] [TYPE Function]\n # @BRIEF Insert a native MARKDOWN element at (0,0) with full width (12 cols),\n # shift existing charts down. Uses native MARKDOWN for reliable rendering.\n # @PRE dashboard_id exists in Superset. chart_id is used for tracking/DB.\n # @POST MARKDOWN element placed at top; existing items shifted down.\n # @SIDE_EFFECT Modifies dashboard layout JSON.\n def update_dashboard_layout(self, dashboard_id: int, chart_id: int) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_dashboard_layout\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Updating layout with native MARKDOWN\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n\n # Use native MARKDOWN element inside a ROW, connected to GRID_ID\n placeholder = \"*Maintenance banner*\"\n insert_banner_markdown_at_top(position_json, chart_id, placeholder)\n\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Layout updated with native MARKDOWN\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Layout update failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion update_dashboard_layout\n\n # #region remove_chart_from_layout [C:3] [TYPE Function]\n # @BRIEF Remove banner markdown element from dashboard layout without deleting the chart.\n # @PRE dashboard_id exists. chart_id exists in layout as MARKDOWN-banner-{chart_id}.\n # @POST MARKDOWN element removed from position_json; items shifted up.\n # @SIDE_EFFECT Modifies dashboard layout JSON.\n def remove_chart_from_layout(self, dashboard_id: int, chart_id: int) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.remove_chart_from_layout\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Removing banner from layout\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n # Remove new MARKDOWN+ROW pair (old CHART-{id} format no longer created)\n remove_banner_from_position(position_json, chart_id)\n\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Banner removed from layout\",\n extra={\"dashboard_id\": dashboard_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Remove from layout failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion remove_chart_from_layout\n\n # #region delete_chart [C:3] [TYPE Function]\n # @BRIEF Delete a chart from Superset by ID.\n # @PRE chart_id exists.\n # @POST Chart permanently deleted from Superset.\n # @SIDE_EFFECT Destroys chart resource.\n def delete_chart(self, chart_id: int) -> dict:\n with belief_scope(\"SupersetDashboardsWriteMixin.delete_chart\", f\"chart_id={chart_id}\"):\n app_logger.reason(\"Deleting chart\", extra={\"chart_id\": chart_id})\n try:\n response = cast(dict, self.network.request(method=\"DELETE\", endpoint=f\"/chart/{chart_id}\"))\n app_logger.reflect(\"Chart deleted\", extra={\"chart_id\": chart_id})\n return response\n except Exception as e:\n app_logger.explore(\"Delete chart failed\", extra={\"chart_id\": chart_id}, error=str(e))\n raise\n # #endregion delete_chart\n\n # #region update_banner_on_dashboard [C:3] [TYPE Function]\n # @BRIEF Update the content of a native MARKDOWN banner element on a dashboard.\n # @PRE dashboard_id exists. chart_id used for key lookup.\n # @POST MARKDOWN element content updated on dashboard.\n # @SIDE_EFFECT Modifies dashboard layout JSON in Superset.\n def update_banner_on_dashboard(\n self, dashboard_id: int, chart_id: int, content: str\n ) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_banner_on_dashboard\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Updating banner content on dashboard\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id, \"len\": len(content)},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n markdown_key = f\"MARKDOWN-banner-{chart_id}\"\n update_banner_markdown_content(position_json, markdown_key, content)\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Banner content updated on dashboard\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Update banner content failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion update_banner_on_dashboard\n\n\n # #region get_dashboard_layout [C:3] [TYPE Function]\n # @BRIEF Fetch the position_json layout of a dashboard.\n # @PRE dashboard_id exists.\n # @POST Returns the dashboard layout dict.\n def get_dashboard_layout(self, dashboard_id: int) -> dict:\n with belief_scope(\"SupersetDashboardsWriteMixin.get_dashboard_layout\", f\"dashboard_id={dashboard_id}\"):\n app_logger.reason(\"Fetching layout\", extra={\"dashboard_id\": dashboard_id})\n try:\n dashboard = cast(dict, self.network.request(method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"))\n result = dashboard.get(\"result\", dashboard)\n layout = parse_position_json(result.get(\"position_json\", \"{}\"))\n app_logger.reflect(\"Layout fetched\", extra={\"dashboard_id\": dashboard_id, \"items\": len(layout)})\n return layout\n except Exception as e:\n app_logger.explore(\"Fetch layout failed\", extra={\"dashboard_id\": dashboard_id}, error=str(e))\n raise\n # #endregion get_dashboard_layout\n\n # #region _resolve_markdown_datasource [C:2] [TYPE Function]\n # @BRIEF Find a valid datasource_id for markdown chart creation.\n # @PRE dashboard_id exists.\n # @POST Returns an integer datasource_id.\n def _resolve_markdown_datasource(self, dashboard_id: int) -> int:\n with belief_scope(\"_resolve_markdown_datasource\", f\"dashboard_id={dashboard_id}\"):\n try:\n datasets_response = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}/datasets\"\n ))\n datasets = datasets_response.get(\"result\", [])\n if datasets:\n ds_id = datasets[0].get(\"id\")\n if ds_id:\n return int(ds_id)\n except Exception:\n app_logger.explore(\"Dashboard datasets fetch failed, falling back\",\n extra={\"dashboard_id\": dashboard_id}, error=\"Dashboard datasets endpoint failed\")\n try:\n all_ds = cast(dict, self.network.request(\n method=\"GET\", endpoint=\"/dataset/\",\n params={\"q\": json.dumps({\"columns\": [\"id\"], \"page_size\": 1, \"page\": 0})},\n ))\n ds_list = all_ds.get(\"result\", [])\n if ds_list:\n ds_id = ds_list[0].get(\"id\")\n if ds_id:\n return int(ds_id)\n except Exception:\n app_logger.explore(\"No datasets available\", extra={}, error=\"Global dataset list failed\")\n raise RuntimeError(\"Cannot create markdown chart: no datasets available in Superset.\")\n # #endregion _resolve_markdown_datasource\n\n# #endregion SupersetDashboardsWriteMixin\n# #endregion SupersetDashboardsWriteMixin\n" + }, + { + "contract_id": "create_markdown_chart", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 34, + "end_line": 71, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "Returns chart_id (int). Chart is NOT yet placed in dashboard layout.", + "PRE": "dashboard_id exists in Superset. markdown_text not empty.", + "PURPOSE": "Create a markdown chart and return the new chart ID.", + "SIDE_EFFECT": "Creates a new chart resource in Superset." + }, + "relations": [ + { + "source_id": "create_markdown_chart", + "relation_type": "CALLS", + "target_id": "self.network.request", + "target_ref": "[self.network.request]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region create_markdown_chart [C:3] [TYPE Function]\n # @BRIEF Create a markdown chart and return the new chart ID.\n # @PRE dashboard_id exists in Superset. markdown_text not empty.\n # @POST Returns chart_id (int). Chart is NOT yet placed in dashboard layout.\n # @SIDE_EFFECT Creates a new chart resource in Superset.\n # @RELATION CALLS -> [self.network.request]\n def create_markdown_chart(self, dashboard_id: int, markdown_text: str) -> int:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.create_markdown_chart\",\n f\"dashboard_id={dashboard_id}\",\n ):\n app_logger.reason(\n \"Creating markdown chart\",\n extra={\"dashboard_id\": dashboard_id, \"len\": len(markdown_text)},\n )\n datasource_id = self._resolve_markdown_datasource(dashboard_id)\n payload = {\n \"dashboards\": [dashboard_id],\n \"datasource_id\": datasource_id,\n \"datasource_type\": \"table\",\n \"slice_name\": \"Maintenance Banner\",\n \"viz_type\": \"markdown\",\n \"params\": json.dumps({\n \"markdown\": markdown_text,\n \"viz_type\": \"markdown\",\n }),\n }\n try:\n response = cast(dict, self.network.request(\n method=\"POST\", endpoint=\"/chart/\", json=payload\n ))\n chart_id = int(response.get(\"id\") or response.get(\"result\", {}).get(\"id\", 0))\n app_logger.reflect(\"Chart created\", extra={\"chart_id\": chart_id})\n return chart_id\n except Exception as e:\n app_logger.explore(\"Create chart failed\", extra={\"dashboard_id\": dashboard_id}, error=str(e))\n raise\n # #endregion create_markdown_chart\n" + }, + { + "contract_id": "update_markdown_chart", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 73, + "end_line": 92, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "Chart markdown content updated.", + "PRE": "chart_id exists and is a markdown chart.", + "PURPOSE": "Update the markdown text of an existing markdown chart.", + "SIDE_EFFECT": "Modifies a chart resource in Superset." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region update_markdown_chart [C:3] [TYPE Function]\n # @BRIEF Update the markdown text of an existing markdown chart.\n # @PRE chart_id exists and is a markdown chart.\n # @POST Chart markdown content updated.\n # @SIDE_EFFECT Modifies a chart resource in Superset.\n def update_markdown_chart(self, chart_id: int, markdown_text: str) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_markdown_chart\",\n f\"chart_id={chart_id}\",\n ):\n app_logger.reason(\"Updating markdown chart\", extra={\"chart_id\": chart_id, \"len\": len(markdown_text)})\n payload = {\"params\": json.dumps({\"markdown\": markdown_text, \"viz_type\": \"markdown\"})}\n try:\n response = cast(dict, self.network.request(method=\"PUT\", endpoint=f\"/chart/{chart_id}\", json=payload))\n app_logger.reflect(\"Chart updated\", extra={\"chart_id\": chart_id})\n return response\n except Exception as e:\n app_logger.explore(\"Update chart failed\", extra={\"chart_id\": chart_id}, error=str(e))\n raise\n # #endregion update_markdown_chart\n" + }, + { + "contract_id": "update_dashboard_layout", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 94, + "end_line": 136, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "Insert a native MARKDOWN element at (0,0) with full width (12 cols)," + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region update_dashboard_layout [C:4] [TYPE Function]\n # @BRIEF Insert a native MARKDOWN element at (0,0) with full width (12 cols),\n # shift existing charts down. Uses native MARKDOWN for reliable rendering.\n # @PRE dashboard_id exists in Superset. chart_id is used for tracking/DB.\n # @POST MARKDOWN element placed at top; existing items shifted down.\n # @SIDE_EFFECT Modifies dashboard layout JSON.\n def update_dashboard_layout(self, dashboard_id: int, chart_id: int) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_dashboard_layout\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Updating layout with native MARKDOWN\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n\n # Use native MARKDOWN element inside a ROW, connected to GRID_ID\n placeholder = \"*Maintenance banner*\"\n insert_banner_markdown_at_top(position_json, chart_id, placeholder)\n\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Layout updated with native MARKDOWN\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Layout update failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion update_dashboard_layout\n" + }, + { + "contract_id": "remove_chart_from_layout", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 138, + "end_line": 177, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "MARKDOWN element removed from position_json; items shifted up.", + "PRE": "dashboard_id exists. chart_id exists in layout as MARKDOWN-banner-{chart_id}.", + "PURPOSE": "Remove banner markdown element from dashboard layout without deleting the chart.", + "SIDE_EFFECT": "Modifies dashboard layout JSON." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region remove_chart_from_layout [C:3] [TYPE Function]\n # @BRIEF Remove banner markdown element from dashboard layout without deleting the chart.\n # @PRE dashboard_id exists. chart_id exists in layout as MARKDOWN-banner-{chart_id}.\n # @POST MARKDOWN element removed from position_json; items shifted up.\n # @SIDE_EFFECT Modifies dashboard layout JSON.\n def remove_chart_from_layout(self, dashboard_id: int, chart_id: int) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.remove_chart_from_layout\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Removing banner from layout\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n # Remove new MARKDOWN+ROW pair (old CHART-{id} format no longer created)\n remove_banner_from_position(position_json, chart_id)\n\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Banner removed from layout\",\n extra={\"dashboard_id\": dashboard_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Remove from layout failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion remove_chart_from_layout\n" + }, + { + "contract_id": "delete_chart", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 179, + "end_line": 194, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "Chart permanently deleted from Superset.", + "PRE": "chart_id exists.", + "PURPOSE": "Delete a chart from Superset by ID.", + "SIDE_EFFECT": "Destroys chart resource." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region delete_chart [C:3] [TYPE Function]\n # @BRIEF Delete a chart from Superset by ID.\n # @PRE chart_id exists.\n # @POST Chart permanently deleted from Superset.\n # @SIDE_EFFECT Destroys chart resource.\n def delete_chart(self, chart_id: int) -> dict:\n with belief_scope(\"SupersetDashboardsWriteMixin.delete_chart\", f\"chart_id={chart_id}\"):\n app_logger.reason(\"Deleting chart\", extra={\"chart_id\": chart_id})\n try:\n response = cast(dict, self.network.request(method=\"DELETE\", endpoint=f\"/chart/{chart_id}\"))\n app_logger.reflect(\"Chart deleted\", extra={\"chart_id\": chart_id})\n return response\n except Exception as e:\n app_logger.explore(\"Delete chart failed\", extra={\"chart_id\": chart_id}, error=str(e))\n raise\n # #endregion delete_chart\n" + }, + { + "contract_id": "update_banner_on_dashboard", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 196, + "end_line": 236, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "MARKDOWN element content updated on dashboard.", + "PRE": "dashboard_id exists. chart_id used for key lookup.", + "PURPOSE": "Update the content of a native MARKDOWN banner element on a dashboard.", + "SIDE_EFFECT": "Modifies dashboard layout JSON in Superset." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region update_banner_on_dashboard [C:3] [TYPE Function]\n # @BRIEF Update the content of a native MARKDOWN banner element on a dashboard.\n # @PRE dashboard_id exists. chart_id used for key lookup.\n # @POST MARKDOWN element content updated on dashboard.\n # @SIDE_EFFECT Modifies dashboard layout JSON in Superset.\n def update_banner_on_dashboard(\n self, dashboard_id: int, chart_id: int, content: str\n ) -> dict:\n with belief_scope(\n \"SupersetDashboardsWriteMixin.update_banner_on_dashboard\",\n f\"dashboard_id={dashboard_id}, chart_id={chart_id}\",\n ):\n app_logger.reason(\n \"Updating banner content on dashboard\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id, \"len\": len(content)},\n )\n try:\n dashboard = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"\n ))\n result = dashboard.get(\"result\", dashboard)\n position_json = parse_position_json(result.get(\"position_json\", \"{}\"))\n markdown_key = f\"MARKDOWN-banner-{chart_id}\"\n update_banner_markdown_content(position_json, markdown_key, content)\n response = cast(dict, self.network.request(\n method=\"PUT\", endpoint=f\"/dashboard/{dashboard_id}\",\n json={\"position_json\": json.dumps(position_json)},\n ))\n app_logger.reflect(\n \"Banner content updated on dashboard\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n )\n return response\n except Exception as e:\n app_logger.explore(\n \"Update banner content failed\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n # #endregion update_banner_on_dashboard\n" + }, + { + "contract_id": "get_dashboard_layout", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 239, + "end_line": 255, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "Returns the dashboard layout dict.", + "PRE": "dashboard_id exists.", + "PURPOSE": "Fetch the position_json layout of a dashboard." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region get_dashboard_layout [C:3] [TYPE Function]\n # @BRIEF Fetch the position_json layout of a dashboard.\n # @PRE dashboard_id exists.\n # @POST Returns the dashboard layout dict.\n def get_dashboard_layout(self, dashboard_id: int) -> dict:\n with belief_scope(\"SupersetDashboardsWriteMixin.get_dashboard_layout\", f\"dashboard_id={dashboard_id}\"):\n app_logger.reason(\"Fetching layout\", extra={\"dashboard_id\": dashboard_id})\n try:\n dashboard = cast(dict, self.network.request(method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}\"))\n result = dashboard.get(\"result\", dashboard)\n layout = parse_position_json(result.get(\"position_json\", \"{}\"))\n app_logger.reflect(\"Layout fetched\", extra={\"dashboard_id\": dashboard_id, \"items\": len(layout)})\n return layout\n except Exception as e:\n app_logger.explore(\"Fetch layout failed\", extra={\"dashboard_id\": dashboard_id}, error=str(e))\n raise\n # #endregion get_dashboard_layout\n" + }, + { + "contract_id": "_resolve_markdown_datasource", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_dashboards_write.py", + "start_line": 257, + "end_line": 288, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns an integer datasource_id.", + "PRE": "dashboard_id exists.", + "PURPOSE": "Find a valid datasource_id for markdown chart creation." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region _resolve_markdown_datasource [C:2] [TYPE Function]\n # @BRIEF Find a valid datasource_id for markdown chart creation.\n # @PRE dashboard_id exists.\n # @POST Returns an integer datasource_id.\n def _resolve_markdown_datasource(self, dashboard_id: int) -> int:\n with belief_scope(\"_resolve_markdown_datasource\", f\"dashboard_id={dashboard_id}\"):\n try:\n datasets_response = cast(dict, self.network.request(\n method=\"GET\", endpoint=f\"/dashboard/{dashboard_id}/datasets\"\n ))\n datasets = datasets_response.get(\"result\", [])\n if datasets:\n ds_id = datasets[0].get(\"id\")\n if ds_id:\n return int(ds_id)\n except Exception:\n app_logger.explore(\"Dashboard datasets fetch failed, falling back\",\n extra={\"dashboard_id\": dashboard_id}, error=\"Dashboard datasets endpoint failed\")\n try:\n all_ds = cast(dict, self.network.request(\n method=\"GET\", endpoint=\"/dataset/\",\n params={\"q\": json.dumps({\"columns\": [\"id\"], \"page_size\": 1, \"page\": 0})},\n ))\n ds_list = all_ds.get(\"result\", [])\n if ds_list:\n ds_id = ds_list[0].get(\"id\")\n if ds_id:\n return int(ds_id)\n except Exception:\n app_logger.explore(\"No datasets available\", extra={}, error=\"Global dataset list failed\")\n raise RuntimeError(\"Cannot create markdown chart: no datasets available in Superset.\")\n # #endregion _resolve_markdown_datasource\n" + }, { "contract_id": "SupersetDatabasesMixin", "contract_type": "Module", @@ -26280,7 +27508,7 @@ "contract_type": "Module", "file_path": "backend/src/core/superset_client/_datasets.py", "start_line": 1, - "end_line": 205, + "end_line": 241, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -26318,7 +27546,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 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" + "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 SupersetClientGetDatasetLinkedDashboardCount [TYPE Function] [C:2]\n # @PURPOSE: Fetch the number of dashboards linked to a dataset via related_objects endpoint.\n # @RELATION: CALLS -> [APIClient]\n # @RATIONALE Added to fix linked_count=0 in StatsBar. Reuses the same /dataset/{id}/related_objects call\n # that get_dataset_detail() was already making, but as a lightweight count-only call.\n # @REJECTED Enriching get_datasets_summary() with more columns rejected — Superset list endpoint\n # doesn't include linked_dashboard_count (it's a computed field from related_objects).\n def get_dataset_linked_dashboard_count(self, dataset_id: int) -> int:\n with belief_scope(\"get_dataset_linked_dashboard_count\", f\"id={dataset_id}\"):\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 return len(dashboards_data)\n return 0\n except Exception as e:\n app_logger.warning(\n f\"[get_dataset_linked_dashboard_count][Warning] Failed to fetch related dashboards for dataset {dataset_id}: {e}\"\n )\n return 0\n # #endregion SupersetClientGetDatasetLinkedDashboardCount\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 # related_objects returns {\"count\": N, \"result\": [...]} — extract the array\n dashboards_list = (\n dashboards_data.get(\"result\", [])\n if isinstance(dashboards_data, dict)\n else dashboards_data\n )\n for dash in dashboards_list:\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", @@ -26422,6 +27650,170 @@ "tier_source": "AutoCalculated", "body": "# #region SupersetDatasetsPreviewFiltersMixin [C:3] [TYPE Module] [SEMANTICS superset, dataset, preview, filter, advanced]\n# @LAYER: Infra\n# @BRIEF Filter normalization and SQL extraction helpers for dataset preview compilation.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetDatasetsPreviewMixin]\nfrom copy import deepcopy\nfrom typing import Any\n\nfrom ..logger import belief_scope, logger as app_logger\nfrom ..utils.network import SupersetAPIError\n\n\n# #region SupersetDatasetsPreviewFiltersMixin [C:3] [TYPE Class]\n# @BRIEF Mixin providing filter normalization and compiled-SQL extraction for dataset preview operations.\n# @RELATION DEPENDS_ON -> [SupersetClientBase]\n# @RELATION DEPENDS_ON -> [SupersetDatasetsPreviewMixin]\nclass SupersetDatasetsPreviewFiltersMixin:\n # #region SupersetClientNormalizeEffectiveFiltersForQueryContext [TYPE Function] [C:3]\n # @PURPOSE: Convert execution mappings into Superset chart-data filter objects.\n def _normalize_effective_filters_for_query_context(\n self,\n effective_filters: list[dict[str, Any]],\n ) -> dict[str, Any]:\n with belief_scope(\n \"SupersetClient._normalize_effective_filters_for_query_context\"\n ):\n normalized_filters: list[dict[str, Any]] = []\n merged_extra_form_data: dict[str, Any] = {}\n diagnostics: list[dict[str, Any]] = []\n for item in effective_filters:\n if not isinstance(item, dict):\n continue\n display_name = str(\n item.get(\"display_name\")\n or item.get(\"filter_name\")\n or item.get(\"variable_name\")\n or \"unresolved_filter\"\n ).strip()\n value = item.get(\"effective_value\")\n normalized_payload = item.get(\"normalized_filter_payload\")\n preserved_clauses: list[dict[str, Any]] = []\n preserved_extra_form_data: dict[str, Any] = {}\n used_preserved_clauses = False\n if isinstance(normalized_payload, dict):\n raw_clauses = normalized_payload.get(\"filter_clauses\")\n if isinstance(raw_clauses, list):\n preserved_clauses = [\n deepcopy(clause)\n for clause in raw_clauses\n if isinstance(clause, dict)\n ]\n raw_extra_form_data = normalized_payload.get(\"extra_form_data\")\n if isinstance(raw_extra_form_data, dict):\n preserved_extra_form_data = deepcopy(raw_extra_form_data)\n if isinstance(preserved_extra_form_data, dict):\n for key, extra_value in preserved_extra_form_data.items():\n if key == \"filters\":\n continue\n merged_extra_form_data[key] = deepcopy(extra_value)\n outgoing_clauses: list[dict[str, Any]] = []\n if preserved_clauses:\n for clause in preserved_clauses:\n clause_copy = deepcopy(clause)\n if \"val\" not in clause_copy and value is not None:\n clause_copy[\"val\"] = deepcopy(value)\n outgoing_clauses.append(clause_copy)\n used_preserved_clauses = True\n elif preserved_extra_form_data:\n outgoing_clauses = []\n else:\n column = str(\n item.get(\"variable_name\") or item.get(\"filter_name\") or \"\"\n ).strip()\n if column and value is not None:\n operator = \"IN\" if isinstance(value, list) else \"==\"\n outgoing_clauses.append(\n {\"col\": column, \"op\": operator, \"val\": value}\n )\n normalized_filters.extend(outgoing_clauses)\n diagnostics.append(\n {\n \"filter_name\": display_name,\n \"value_origin\": (\n normalized_payload.get(\"value_origin\")\n if isinstance(normalized_payload, dict)\n else None\n ),\n \"used_preserved_clauses\": used_preserved_clauses,\n \"outgoing_clauses\": deepcopy(outgoing_clauses),\n }\n )\n app_logger.reason(\n \"Normalized effective preview filter for Superset query context\",\n extra={\n \"filter_name\": display_name,\n \"used_preserved_clauses\": used_preserved_clauses,\n \"outgoing_clauses\": outgoing_clauses,\n \"value_origin\": (\n normalized_payload.get(\"value_origin\")\n if isinstance(normalized_payload, dict)\n else \"heuristic_reconstruction\"\n ),\n },\n )\n return {\n \"filters\": normalized_filters,\n \"extra_form_data\": merged_extra_form_data,\n \"diagnostics\": diagnostics,\n }\n # #endregion SupersetClientNormalizeEffectiveFiltersForQueryContext\n # #region SupersetClientExtractCompiledSqlFromPreviewResponse [TYPE Function] [C:3]\n # @PURPOSE: Normalize compiled SQL from either chart-data or legacy form_data preview responses.\n def _extract_compiled_sql_from_preview_response(\n self, response: Any\n ) -> dict[str, Any]:\n with belief_scope(\"SupersetClient._extract_compiled_sql_from_preview_response\"):\n if not isinstance(response, dict):\n raise SupersetAPIError(\n \"Superset preview response was not a JSON object\"\n )\n response_diagnostics: list[dict[str, Any]] = []\n result_payload = response.get(\"result\")\n if isinstance(result_payload, list):\n for index, item in enumerate(result_payload):\n if not isinstance(item, dict):\n continue\n compiled_sql = str(\n item.get(\"query\")\n or item.get(\"sql\")\n or item.get(\"compiled_sql\")\n or \"\"\n ).strip()\n response_diagnostics.append(\n {\n \"index\": index,\n \"status\": item.get(\"status\"),\n \"applied_filters\": item.get(\"applied_filters\"),\n \"rejected_filters\": item.get(\"rejected_filters\"),\n \"has_query\": bool(compiled_sql),\n \"source\": \"result_list\",\n }\n )\n if compiled_sql:\n return {\n \"compiled_sql\": compiled_sql,\n \"raw_response\": response,\n \"response_diagnostics\": response_diagnostics,\n }\n top_level_candidates: list[tuple[str, Any]] = [\n (\"query\", response.get(\"query\")),\n (\"sql\", response.get(\"sql\")),\n (\"compiled_sql\", response.get(\"compiled_sql\")),\n ]\n if isinstance(result_payload, dict):\n top_level_candidates.extend(\n [\n (\"result.query\", result_payload.get(\"query\")),\n (\"result.sql\", result_payload.get(\"sql\")),\n (\"result.compiled_sql\", result_payload.get(\"compiled_sql\")),\n ]\n )\n for source, candidate in top_level_candidates:\n compiled_sql = str(candidate or \"\").strip()\n response_diagnostics.append(\n {\"source\": source, \"has_query\": bool(compiled_sql)}\n )\n if compiled_sql:\n return {\n \"compiled_sql\": compiled_sql,\n \"raw_response\": response,\n \"response_diagnostics\": response_diagnostics,\n }\n raise SupersetAPIError(\n \"Superset preview response did not expose compiled SQL \"\n f\"(diagnostics={response_diagnostics!r})\"\n )\n # #endregion SupersetClientExtractCompiledSqlFromPreviewResponse\n# #endregion SupersetDatasetsPreviewFiltersMixin\n# #endregion SupersetDatasetsPreviewFiltersMixin\n" }, + { + "contract_id": "LayoutUtils", + "contract_type": "Module", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 1, + "end_line": 197, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "LAYER": "Infra", + "PURPOSE": "Utility functions for manipulating Superset dashboard position_json layout.", + "RATIONALE": "Extracted from SupersetDashboardsWriteMixin to stay under INV_7 400 LOC." + }, + "relations": [ + { + "source_id": "LayoutUtils", + "relation_type": "DEPENDS_ON", + "target_id": "json", + "target_ref": "[json]" + }, + { + "source_id": "LayoutUtils", + "relation_type": "DEPENDS_ON", + "target_id": "SupersetDashboardsWriteMixin", + "target_ref": "[SupersetDashboardsWriteMixin]" + } + ], + "schema_warnings": [ + { + "code": "invalid_enum_value", + "tag": "LAYER", + "message": "@LAYER value 'Infra' is not in allowed enum", + "detail": { + "allowed": [ + "Core", + "Domain", + "API", + "UI", + "Service", + "Infrastructure", + "Plugin", + "Tests" + ], + "value": "Infra" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region LayoutUtils [C:2] [TYPE Module] [SEMANTICS superset, dashboard, layout, position, json]\n# @BRIEF Utility functions for manipulating Superset dashboard position_json layout.\n# @LAYER Infra\n# @RELATION DEPENDS_ON -> [json]\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\n# @RATIONALE Extracted from SupersetDashboardsWriteMixin to stay under INV_7 400 LOC.\n\nimport json\nimport re\nfrom typing import Any\n\n\n# #region parse_position_json [C:1] [TYPE Function]\n# @BRIEF Parse position_json from a dashboard API response (may be string or dict).\n# @PRE raw_position is a string, dict, or None.\n# @POST Returns a dict.\ndef parse_position_json(raw_position: Any) -> dict:\n if isinstance(raw_position, str):\n return json.loads(raw_position) if raw_position.strip() else {}\n if isinstance(raw_position, dict):\n return raw_position\n return {}\n# #endregion parse_position_json\n\n\n# #region _estimate_markdown_height [C:1] [TYPE Function]\n# @BRIEF Estimate grid height for a MARKDOWN element based on HTML content.\n# Counts block-level tags and newlines to estimate visual line count,\n# then converts to Superset grid units (1 unit ≈ 2 text lines + padding).\n# @PRE content is a string of HTML/Markdown.\n# @POST Returns int between 19 and 200 inclusive.\ndef _estimate_markdown_height(content: str) -> int:\n \"\"\"Estimate MARKDOWN element height (position JSON units).\n\n Model: total = CSS min-height(40px) + content pixel height.\n Content height = text_lines × line-height(22px) + container padding.\n 1 position JSON unit ≈ 8 rendered pixels.\n\n Reference: user's banner (5 text lines, padding:12) → height=21 → ~168px.\n \"\"\"\n if not content:\n return 19\n\n # Detect container padding (e.g. padding:12 → 24px vertical)\n pad_match = re.search(r'padding\\s*:\\s*(\\d+)', content)\n container_padding = int(pad_match.group(1)) * 2 if pad_match else 0\n\n # Strip HTML to get plain text\n plain_text = re.sub(r'<[^>]+>', '', content)\n plain_text = re.sub(r'\\s+', ' ', plain_text).strip()\n\n if not plain_text:\n return 19\n\n # Text lines (wrapping at ~40 chars/line at 12col width)\n text_lines = len(plain_text) // 40 + 1\n\n # Content height (px): line-height(~22px) × lines + container padding\n content_px = text_lines * 22 + container_padding\n\n # Total: CSS min-height(40px) + content\n total_px = 40 + content_px\n\n # Convert to position JSON units (÷8)\n height = max(19, total_px // 8)\n return min(200, height)\n# #endregion _estimate_markdown_height\n\n\n# #region _generate_banner_id [C:1] [TYPE Function]\n# @BRIEF Generate a deterministic row and markdown key for a banner chart.\ndef _generate_banner_id(chart_id: int) -> tuple[str, str]:\n row_key = f\"ROW-banner-{chart_id}\"\n md_key = f\"MARKDOWN-banner-{chart_id}\"\n return row_key, md_key\n# #endregion _generate_banner_id\n\n\n# #region insert_banner_markdown_at_top [C:2] [TYPE Function]\n# @BRIEF Insert a ROW + native MARKDOWN pair at the top of the dashboard grid.\n# Creates a ROW entry connected to GRID_ID, and a MARKDOWN child inside it.\n# Shifts all existing grid ROWs down by 2 rows.\n# @PRE position_json is a mutable dict. content is the HTML/markdown string.\n# chart_id is the database chart_id for key generation.\n# @POST position_json is mutated; ROW + MARKDOWN inserted at top of GRID.\ndef insert_banner_markdown_at_top(\n position_json: dict, chart_id: int, content: str\n) -> dict:\n row_key, md_key = _generate_banner_id(chart_id)\n\n # Shift existing ROW y-positions down\n for key, value in list(position_json.items()):\n if isinstance(value, dict):\n meta = value.get(\"meta\", {})\n if isinstance(meta, dict):\n cur_y = meta.get(\"y\", 0)\n if isinstance(cur_y, (int, float)):\n meta[\"y\"] = cur_y + 2\n\n # Add MARKDOWN entry with adaptive height\n height = _estimate_markdown_height(content)\n position_json[md_key] = {\n \"type\": \"MARKDOWN\",\n \"id\": md_key,\n \"children\": [],\n \"parents\": [\"ROOT_ID\", \"GRID_ID\", row_key],\n \"meta\": {\n \"code\": content,\n \"width\": 12,\n \"height\": height,\n \"y\": 0,\n },\n }\n\n # Add ROW entry connected to GRID_ID\n position_json[row_key] = {\n \"type\": \"ROW\",\n \"id\": row_key,\n \"children\": [md_key],\n \"parents\": [\"ROOT_ID\", \"GRID_ID\"],\n \"meta\": {\n \"background\": \"BACKGROUND_TRANSPARENT\",\n \"y\": 0,\n },\n }\n\n # Insert ROW at beginning of GRID_ID children\n grid = position_json.get(\"GRID_ID\")\n if grid and isinstance(grid, dict):\n grid_children = grid.get(\"children\", [])\n if isinstance(grid_children, list):\n if row_key in grid_children:\n grid_children.remove(row_key)\n grid_children.insert(0, row_key)\n\n return position_json\n# #endregion insert_banner_markdown_at_top\n\n\n# #region update_banner_markdown_content [C:1] [TYPE Function]\n# @BRIEF Update the code content and adaptive height of an existing banner markdown element.\n# @PRE position_json has markdown_key. content is the new HTML/markdown string.\n# @POST position_json is mutated; markdown content and height updated.\ndef update_banner_markdown_content(\n position_json: dict, markdown_key: str, content: str\n) -> dict:\n if markdown_key in position_json:\n meta = position_json[markdown_key].get(\"meta\", {})\n if isinstance(meta, dict):\n meta[\"code\"] = content\n meta[\"height\"] = _estimate_markdown_height(content)\n return position_json\n# #endregion update_banner_markdown_content\n\n\n# #region remove_banner_from_position [C:2] [TYPE Function]\n# @BRIEF Remove the banner ROW + MARKDOWN pair from the position dict and GRID children.\n# Shifts remaining items up by 2 if the banner was at y=0.\n# @PRE position_json is a mutable dict. chart_id identifies the banner.\n# @POST position_json is mutated; ROW and MARKDOWN entries removed.\ndef remove_banner_from_position(position_json: dict, chart_id: int) -> dict:\n row_key, md_key = _generate_banner_id(chart_id)\n\n removed_y = None\n # Remove MARKDOWN entry\n if md_key in position_json:\n markdown_data = position_json[md_key]\n if isinstance(markdown_data, dict):\n meta = markdown_data.get(\"meta\", {})\n if isinstance(meta, dict):\n removed_y = meta.get(\"y\", 0)\n del position_json[md_key]\n\n # Remove ROW entry\n if row_key in position_json:\n del position_json[row_key]\n\n # Remove ROW from GRID_ID children\n grid = position_json.get(\"GRID_ID\")\n if grid and isinstance(grid, dict):\n grid_children = grid.get(\"children\", [])\n if isinstance(grid_children, list) and row_key in grid_children:\n grid_children.remove(row_key)\n\n # Shift remaining items up\n if removed_y is not None and removed_y == 0:\n for key, value in position_json.items():\n if isinstance(value, dict):\n meta = value.get(\"meta\", {})\n if isinstance(meta, dict):\n cur_y = meta.get(\"y\", 0)\n if isinstance(cur_y, (int, float)) and cur_y > 0:\n meta[\"y\"] = cur_y - 2\n return position_json\n# #endregion remove_banner_from_position\n\n# #endregion LayoutUtils\n" + }, + { + "contract_id": "parse_position_json", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 13, + "end_line": 23, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns a dict.", + "PRE": "raw_position is a string, dict, or None.", + "PURPOSE": "Parse position_json from a dashboard API response (may be string or dict)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region parse_position_json [C:1] [TYPE Function]\n# @BRIEF Parse position_json from a dashboard API response (may be string or dict).\n# @PRE raw_position is a string, dict, or None.\n# @POST Returns a dict.\ndef parse_position_json(raw_position: Any) -> dict:\n if isinstance(raw_position, str):\n return json.loads(raw_position) if raw_position.strip() else {}\n if isinstance(raw_position, dict):\n return raw_position\n return {}\n# #endregion parse_position_json\n" + }, + { + "contract_id": "_estimate_markdown_height", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 26, + "end_line": 67, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Estimate grid height for a MARKDOWN element based on HTML content." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _estimate_markdown_height [C:1] [TYPE Function]\n# @BRIEF Estimate grid height for a MARKDOWN element based on HTML content.\n# Counts block-level tags and newlines to estimate visual line count,\n# then converts to Superset grid units (1 unit ≈ 2 text lines + padding).\n# @PRE content is a string of HTML/Markdown.\n# @POST Returns int between 19 and 200 inclusive.\ndef _estimate_markdown_height(content: str) -> int:\n \"\"\"Estimate MARKDOWN element height (position JSON units).\n\n Model: total = CSS min-height(40px) + content pixel height.\n Content height = text_lines × line-height(22px) + container padding.\n 1 position JSON unit ≈ 8 rendered pixels.\n\n Reference: user's banner (5 text lines, padding:12) → height=21 → ~168px.\n \"\"\"\n if not content:\n return 19\n\n # Detect container padding (e.g. padding:12 → 24px vertical)\n pad_match = re.search(r'padding\\s*:\\s*(\\d+)', content)\n container_padding = int(pad_match.group(1)) * 2 if pad_match else 0\n\n # Strip HTML to get plain text\n plain_text = re.sub(r'<[^>]+>', '', content)\n plain_text = re.sub(r'\\s+', ' ', plain_text).strip()\n\n if not plain_text:\n return 19\n\n # Text lines (wrapping at ~40 chars/line at 12col width)\n text_lines = len(plain_text) // 40 + 1\n\n # Content height (px): line-height(~22px) × lines + container padding\n content_px = text_lines * 22 + container_padding\n\n # Total: CSS min-height(40px) + content\n total_px = 40 + content_px\n\n # Convert to position JSON units (÷8)\n height = max(19, total_px // 8)\n return min(200, height)\n# #endregion _estimate_markdown_height\n" + }, + { + "contract_id": "_generate_banner_id", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 70, + "end_line": 76, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Generate a deterministic row and markdown key for a banner chart." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _generate_banner_id [C:1] [TYPE Function]\n# @BRIEF Generate a deterministic row and markdown key for a banner chart.\ndef _generate_banner_id(chart_id: int) -> tuple[str, str]:\n row_key = f\"ROW-banner-{chart_id}\"\n md_key = f\"MARKDOWN-banner-{chart_id}\"\n return row_key, md_key\n# #endregion _generate_banner_id\n" + }, + { + "contract_id": "insert_banner_markdown_at_top", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 79, + "end_line": 137, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Insert a ROW + native MARKDOWN pair at the top of the dashboard grid." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region insert_banner_markdown_at_top [C:2] [TYPE Function]\n# @BRIEF Insert a ROW + native MARKDOWN pair at the top of the dashboard grid.\n# Creates a ROW entry connected to GRID_ID, and a MARKDOWN child inside it.\n# Shifts all existing grid ROWs down by 2 rows.\n# @PRE position_json is a mutable dict. content is the HTML/markdown string.\n# chart_id is the database chart_id for key generation.\n# @POST position_json is mutated; ROW + MARKDOWN inserted at top of GRID.\ndef insert_banner_markdown_at_top(\n position_json: dict, chart_id: int, content: str\n) -> dict:\n row_key, md_key = _generate_banner_id(chart_id)\n\n # Shift existing ROW y-positions down\n for key, value in list(position_json.items()):\n if isinstance(value, dict):\n meta = value.get(\"meta\", {})\n if isinstance(meta, dict):\n cur_y = meta.get(\"y\", 0)\n if isinstance(cur_y, (int, float)):\n meta[\"y\"] = cur_y + 2\n\n # Add MARKDOWN entry with adaptive height\n height = _estimate_markdown_height(content)\n position_json[md_key] = {\n \"type\": \"MARKDOWN\",\n \"id\": md_key,\n \"children\": [],\n \"parents\": [\"ROOT_ID\", \"GRID_ID\", row_key],\n \"meta\": {\n \"code\": content,\n \"width\": 12,\n \"height\": height,\n \"y\": 0,\n },\n }\n\n # Add ROW entry connected to GRID_ID\n position_json[row_key] = {\n \"type\": \"ROW\",\n \"id\": row_key,\n \"children\": [md_key],\n \"parents\": [\"ROOT_ID\", \"GRID_ID\"],\n \"meta\": {\n \"background\": \"BACKGROUND_TRANSPARENT\",\n \"y\": 0,\n },\n }\n\n # Insert ROW at beginning of GRID_ID children\n grid = position_json.get(\"GRID_ID\")\n if grid and isinstance(grid, dict):\n grid_children = grid.get(\"children\", [])\n if isinstance(grid_children, list):\n if row_key in grid_children:\n grid_children.remove(row_key)\n grid_children.insert(0, row_key)\n\n return position_json\n# #endregion insert_banner_markdown_at_top\n" + }, + { + "contract_id": "update_banner_markdown_content", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 140, + "end_line": 153, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "position_json is mutated; markdown content and height updated.", + "PRE": "position_json has markdown_key. content is the new HTML/markdown string.", + "PURPOSE": "Update the code content and adaptive height of an existing banner markdown element." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region update_banner_markdown_content [C:1] [TYPE Function]\n# @BRIEF Update the code content and adaptive height of an existing banner markdown element.\n# @PRE position_json has markdown_key. content is the new HTML/markdown string.\n# @POST position_json is mutated; markdown content and height updated.\ndef update_banner_markdown_content(\n position_json: dict, markdown_key: str, content: str\n) -> dict:\n if markdown_key in position_json:\n meta = position_json[markdown_key].get(\"meta\", {})\n if isinstance(meta, dict):\n meta[\"code\"] = content\n meta[\"height\"] = _estimate_markdown_height(content)\n return position_json\n# #endregion update_banner_markdown_content\n" + }, + { + "contract_id": "remove_banner_from_position", + "contract_type": "Function", + "file_path": "backend/src/core/superset_client/_layout_utils.py", + "start_line": 156, + "end_line": 195, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Remove the banner ROW + MARKDOWN pair from the position dict and GRID children." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region remove_banner_from_position [C:2] [TYPE Function]\n# @BRIEF Remove the banner ROW + MARKDOWN pair from the position dict and GRID children.\n# Shifts remaining items up by 2 if the banner was at y=0.\n# @PRE position_json is a mutable dict. chart_id identifies the banner.\n# @POST position_json is mutated; ROW and MARKDOWN entries removed.\ndef remove_banner_from_position(position_json: dict, chart_id: int) -> dict:\n row_key, md_key = _generate_banner_id(chart_id)\n\n removed_y = None\n # Remove MARKDOWN entry\n if md_key in position_json:\n markdown_data = position_json[md_key]\n if isinstance(markdown_data, dict):\n meta = markdown_data.get(\"meta\", {})\n if isinstance(meta, dict):\n removed_y = meta.get(\"y\", 0)\n del position_json[md_key]\n\n # Remove ROW entry\n if row_key in position_json:\n del position_json[row_key]\n\n # Remove ROW from GRID_ID children\n grid = position_json.get(\"GRID_ID\")\n if grid and isinstance(grid, dict):\n grid_children = grid.get(\"children\", [])\n if isinstance(grid_children, list) and row_key in grid_children:\n grid_children.remove(row_key)\n\n # Shift remaining items up\n if removed_y is not None and removed_y == 0:\n for key, value in position_json.items():\n if isinstance(value, dict):\n meta = value.get(\"meta\", {})\n if isinstance(meta, dict):\n cur_y = meta.get(\"y\", 0)\n if isinstance(cur_y, (int, float)) and cur_y > 0:\n meta[\"y\"] = cur_y - 2\n return position_json\n# #endregion remove_banner_from_position\n" + }, { "contract_id": "SupersetUserProjection", "contract_type": "Module", @@ -28894,6 +30286,162 @@ "tier_source": "AutoCalculated", "body": " # #region progress [TYPE Function]\n # @PURPOSE: Log a progress update with percentage.\n # @PRE: percent is between 0 and 100.\n # @POST: Log entry with progress metadata added.\n # @PARAM: message (str) - Progress message.\n # @PARAM: percent (float) - Progress percentage (0-100).\n # @PARAM: source (Optional[str]) - Override source.\n def progress(\n self, message: str, percent: float, source: str | None = None\n ) -> None:\n \"\"\"Log a progress update with percentage.\"\"\"\n metadata = {\"progress\": min(100, max(0, percent))}\n self._log(\"INFO\", message, source, metadata)\n # #endregion progress\n" }, + { + "contract_id": "AppTimezone", + "contract_type": "Module", + "file_path": "backend/src/core/timezone.py", + "start_line": 1, + "end_line": 91, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Application-level timezone utilities. Reads APP_TIMEZONE from env (default Europe/Moscow)" + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region AppTimezone [C:3] [TYPE Module] [SEMANTICS core,timezone,utilities,datetime]\n# @BRIEF Application-level timezone utilities. Reads APP_TIMEZONE from env (default Europe/Moscow)\n# and provides helpers for converting UTC datetimes to the configured timezone.\n# @RELATION CALLED_BY -> [ConfigManager]\n# @RELATION DEPENDS_ON -> [GlobalSettings.app_timezone]\n# @RATIONALE Centralised timezone resolution avoids scattering ZoneInfo() calls across the codebase.\n# All API responses should emit localised timestamps; internal storage remains UTC.\n# @REJECTED Storing non-UTC in the database rejected — UTC is the canonical best practice for\n# persistence; timezone conversion is a presentation-layer concern.\nfrom datetime import datetime\nimport os\nfrom zoneinfo import ZoneInfo\n\n\n# #region _get_default_tz_name [C:1] [TYPE Function]\n# @BRIEF Read APP_TIMEZONE from env, fall back to Europe/Moscow.\n# @PRE: Environment is loaded (dotenv or os.environ).\n# @POST: Returns a valid IANA timezone string.\ndef _get_default_tz_name() -> str:\n return os.getenv(\"APP_TIMEZONE\", \"Europe/Moscow\")\n# #endregion _get_default_tz_name\n\n\n# #region get_app_timezone [C:1] [TYPE Function]\n# @BRIEF Return cached ZoneInfo for the configured application timezone.\n# @SIDE_EFFECT: Reads os.environ on first call; result is cached.\n# @POST: Returns a ZoneInfo instance matching APP_TIMEZONE env var.\n_APP_TZ_CACHE: ZoneInfo | None = None\n\ndef get_app_timezone() -> ZoneInfo:\n global _APP_TZ_CACHE\n if _APP_TZ_CACHE is None:\n _APP_TZ_CACHE = ZoneInfo(_get_default_tz_name())\n return _APP_TZ_CACHE\n# #endregion get_app_timezone\n\n\n# #region invalidate_timezone_cache [C:1] [TYPE Function]\n# @BRIEF Reset the cached ZoneInfo so the next get_app_timezone() call re-reads from env/DB.\n# @POST: _APP_TZ_CACHE is set to None; subsequent get_app_timezone() will re-resolve.\n# @RATIONALE: Called after PATCH /settings/consolidated updates app_timezone.\ndef invalidate_timezone_cache() -> None:\n global _APP_TZ_CACHE\n _APP_TZ_CACHE = None\n# #endregion invalidate_timezone_cache\n\n\n# #region validate_timezone [C:1] [TYPE Function]\n# @BRIEF Validate that a timezone string is a known IANA timezone.\n# @PRE: tz_name is a string.\n# @POST: Returns True if ZoneInfo accepts the name, False otherwise.\ndef validate_timezone(tz_name: str) -> bool:\n try:\n ZoneInfo(tz_name)\n return True\n except (KeyError, TypeError):\n return False\n# #endregion validate_timezone\n\n\n# #region localize [C:1] [TYPE Function]\n# @BRIEF Convert a timezone-aware or naive UTC datetime to the configured app timezone.\n# @PRE: If dt is timezone-naive, it is assumed to be UTC.\n# @POST: Returns a datetime with the app timezone attached (astimezone).\ndef localize(dt: datetime | None) -> datetime | None:\n if dt is None:\n return None\n if dt.tzinfo is None:\n dt = dt.replace(tzinfo=ZoneInfo(\"UTC\"))\n return dt.astimezone(get_app_timezone())\n# #endregion localize\n\n\n# #region now [C:1] [TYPE Function]\n# @BRIEF Get current time in the configured application timezone.\n# @POST: Returns timezone-aware datetime in the app timezone.\ndef now() -> datetime:\n return datetime.now(get_app_timezone())\n# #endregion now\n\n\n# #region format_timezone_offset [C:1] [TYPE Function]\n# @BRIEF Return the UTC offset string for the configured timezone (e.g. \"+03:00\").\n# @POST: Returns string like \"+03:00\" or \"+00:00\".\ndef format_timezone_offset() -> str:\n offset = now().strftime(\"%z\")\n if offset:\n return f\"{offset[:3]}:{offset[3:]}\"\n return \"+00:00\"\n# #endregion format_timezone_offset\n# #endregion AppTimezone\n" + }, + { + "contract_id": "_get_default_tz_name", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 15, + "end_line": 21, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns a valid IANA timezone string.", + "PRE": "Environment is loaded (dotenv or os.environ).", + "PURPOSE": "Read APP_TIMEZONE from env, fall back to Europe/Moscow." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _get_default_tz_name [C:1] [TYPE Function]\n# @BRIEF Read APP_TIMEZONE from env, fall back to Europe/Moscow.\n# @PRE: Environment is loaded (dotenv or os.environ).\n# @POST: Returns a valid IANA timezone string.\ndef _get_default_tz_name() -> str:\n return os.getenv(\"APP_TIMEZONE\", \"Europe/Moscow\")\n# #endregion _get_default_tz_name\n" + }, + { + "contract_id": "get_app_timezone", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 24, + "end_line": 35, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns a ZoneInfo instance matching APP_TIMEZONE env var.", + "PURPOSE": "Return cached ZoneInfo for the configured application timezone.", + "SIDE_EFFECT": "Reads os.environ on first call; result is cached." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region get_app_timezone [C:1] [TYPE Function]\n# @BRIEF Return cached ZoneInfo for the configured application timezone.\n# @SIDE_EFFECT: Reads os.environ on first call; result is cached.\n# @POST: Returns a ZoneInfo instance matching APP_TIMEZONE env var.\n_APP_TZ_CACHE: ZoneInfo | None = None\n\ndef get_app_timezone() -> ZoneInfo:\n global _APP_TZ_CACHE\n if _APP_TZ_CACHE is None:\n _APP_TZ_CACHE = ZoneInfo(_get_default_tz_name())\n return _APP_TZ_CACHE\n# #endregion get_app_timezone\n" + }, + { + "contract_id": "invalidate_timezone_cache", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 38, + "end_line": 45, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "_APP_TZ_CACHE is set to None; subsequent get_app_timezone() will re-resolve.", + "PURPOSE": "Reset the cached ZoneInfo so the next get_app_timezone() call re-reads from env/DB.", + "RATIONALE": "Called after PATCH /settings/consolidated updates app_timezone." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region invalidate_timezone_cache [C:1] [TYPE Function]\n# @BRIEF Reset the cached ZoneInfo so the next get_app_timezone() call re-reads from env/DB.\n# @POST: _APP_TZ_CACHE is set to None; subsequent get_app_timezone() will re-resolve.\n# @RATIONALE: Called after PATCH /settings/consolidated updates app_timezone.\ndef invalidate_timezone_cache() -> None:\n global _APP_TZ_CACHE\n _APP_TZ_CACHE = None\n# #endregion invalidate_timezone_cache\n" + }, + { + "contract_id": "validate_timezone", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 48, + "end_line": 58, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns True if ZoneInfo accepts the name, False otherwise.", + "PRE": "tz_name is a string.", + "PURPOSE": "Validate that a timezone string is a known IANA timezone." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region validate_timezone [C:1] [TYPE Function]\n# @BRIEF Validate that a timezone string is a known IANA timezone.\n# @PRE: tz_name is a string.\n# @POST: Returns True if ZoneInfo accepts the name, False otherwise.\ndef validate_timezone(tz_name: str) -> bool:\n try:\n ZoneInfo(tz_name)\n return True\n except (KeyError, TypeError):\n return False\n# #endregion validate_timezone\n" + }, + { + "contract_id": "localize", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 61, + "end_line": 71, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns a datetime with the app timezone attached (astimezone).", + "PRE": "If dt is timezone-naive, it is assumed to be UTC.", + "PURPOSE": "Convert a timezone-aware or naive UTC datetime to the configured app timezone." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region localize [C:1] [TYPE Function]\n# @BRIEF Convert a timezone-aware or naive UTC datetime to the configured app timezone.\n# @PRE: If dt is timezone-naive, it is assumed to be UTC.\n# @POST: Returns a datetime with the app timezone attached (astimezone).\ndef localize(dt: datetime | None) -> datetime | None:\n if dt is None:\n return None\n if dt.tzinfo is None:\n dt = dt.replace(tzinfo=ZoneInfo(\"UTC\"))\n return dt.astimezone(get_app_timezone())\n# #endregion localize\n" + }, + { + "contract_id": "now", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 74, + "end_line": 79, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns timezone-aware datetime in the app timezone.", + "PURPOSE": "Get current time in the configured application timezone." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region now [C:1] [TYPE Function]\n# @BRIEF Get current time in the configured application timezone.\n# @POST: Returns timezone-aware datetime in the app timezone.\ndef now() -> datetime:\n return datetime.now(get_app_timezone())\n# #endregion now\n" + }, + { + "contract_id": "format_timezone_offset", + "contract_type": "Function", + "file_path": "backend/src/core/timezone.py", + "start_line": 82, + "end_line": 90, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns string like \"+03:00\" or \"+00:00\".", + "PURPOSE": "Return the UTC offset string for the configured timezone (e.g. \"+03:00\")." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region format_timezone_offset [C:1] [TYPE Function]\n# @BRIEF Return the UTC offset string for the configured timezone (e.g. \"+03:00\").\n# @POST: Returns string like \"+03:00\" or \"+00:00\".\ndef format_timezone_offset() -> str:\n offset = now().strftime(\"%z\")\n if offset:\n return f\"{offset[:3]}:{offset[3:]}\"\n return \"+00:00\"\n# #endregion format_timezone_offset\n" + }, { "contract_id": "CoreUtils", "contract_type": "Package", @@ -31170,11 +32718,11 @@ "contract_type": "Module", "file_path": "backend/src/dependencies.py", "start_line": 1, - "end_line": 276, + "end_line": 566, "tier": "TIER_2", - "complexity": 3, + "complexity": 4, "metadata": { - "COMPLEXITY": 3, + "COMPLEXITY": 4, "LAYER": "Core", "PURPOSE": "Manages creation and provision of shared application dependencies, such as PluginLoader and TaskManager, to avoid circular imports." }, @@ -31230,27 +32778,33 @@ { "source_id": "AppDependencies", "relation_type": "CALLS", - "target_id": "info", - "target_ref": "[info]" + "target_id": "APIKeyPrincipal", + "target_ref": "[APIKeyPrincipal]" }, { "source_id": "AppDependencies", "relation_type": "CALLS", - "target_id": "init_db", - "target_ref": "[init_db]" + "target_id": "get_api_key_principal", + "target_ref": "[get_api_key_principal]" + }, + { + "source_id": "AppDependencies", + "relation_type": "CALLS", + "target_id": "info", + "target_ref": "[info]" } ], "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region AppDependencies [C:3] [TYPE Module] [SEMANTICS fastapi, schedule]\n# @BRIEF Manages creation and provision of shared application dependencies, such as PluginLoader and TaskManager, to avoid circular imports.\n# @LAYER: Core\n# @RELATION Used by main app and API routers to get access to shared instances.\n# @RELATION CALLS -> [CleanReleaseRepository]\n# @RELATION CALLS -> [ConfigManager]\n# @RELATION CALLS -> [PluginLoader]\n# @RELATION CALLS -> [SchedulerService]\n# @RELATION CALLS -> [TaskManager]\n# @RELATION CALLS -> [get_all_plugin_configs]\n# @RELATION CALLS -> [get_db]\n# @RELATION CALLS -> [info]\n# @RELATION CALLS -> [init_db]\n\nfrom pathlib import Path\n\nfrom fastapi import Depends, HTTPException, status\nfrom fastapi.security import OAuth2PasswordBearer\nfrom jose import JWTError\n\nfrom .core.auth.jwt import decode_token\nfrom .core.auth.repository import AuthRepository\nfrom .core.config_manager import ConfigManager\nfrom .core.database import get_auth_db, get_db, init_db\nfrom .core.logger import logger\nfrom .core.plugin_loader import PluginLoader\nfrom .core.scheduler import SchedulerService\nfrom .core.task_manager import TaskManager\nfrom .models.auth import User\nfrom .services.clean_release.facade import CleanReleaseFacade\nfrom .services.clean_release.repositories import (\n ApprovalRepository,\n ArtifactRepository,\n AuditRepository,\n CandidateRepository,\n ComplianceRepository,\n ManifestRepository,\n PolicyRepository,\n PublicationRepository,\n ReportRepository,\n)\nfrom .services.clean_release.repository import CleanReleaseRepository\nfrom .services.mapping_service import MappingService\nfrom .services.resource_service import ResourceService\n\n# Initialize singletons lazily to avoid import-time DB side effects during test collection.\n# Use absolute path relative to this file to ensure plugins are found regardless of CWD\nproject_root = Path(__file__).parent.parent.parent\nconfig_path = project_root / \"config.json\"\n\nconfig_manager: ConfigManager | None = None\nplugin_loader: PluginLoader | None = None\ntask_manager: TaskManager | None = None\nscheduler_service: SchedulerService | None = None\nresource_service: ResourceService | None = None\n\n\n# #region get_config_manager [C:1] [TYPE Function]\n# @BRIEF Dependency injector for ConfigManager.\n# @PRE: Global config_manager must be initialized.\n# @POST: Returns shared ConfigManager instance.\ndef get_config_manager() -> ConfigManager:\n \"\"\"Dependency injector for ConfigManager.\"\"\"\n global config_manager\n if config_manager is None:\n init_db()\n config_manager = ConfigManager(config_path=str(config_path))\n return config_manager\n\n\n# #endregion get_config_manager\n\nplugin_dir = Path(__file__).parent / \"plugins\"\n\n# Clean Release Redesign Singletons\n# Note: These use get_db() which is a generator, so we need a way to provide a session.\n# For singletons in dependencies.py, we might need a different approach or\n# initialize them inside the dependency functions.\n\n\n# #region get_plugin_loader [C:1] [TYPE Function]\n# @BRIEF Dependency injector for PluginLoader.\n# @PRE: Global plugin_loader must be initialized.\n# @POST: Returns shared PluginLoader instance.\ndef get_plugin_loader() -> PluginLoader:\n \"\"\"Dependency injector for PluginLoader.\"\"\"\n global plugin_loader\n if plugin_loader is None:\n plugin_loader = PluginLoader(plugin_dir=str(plugin_dir))\n logger.info(f\"PluginLoader initialized with directory: {plugin_dir}\")\n logger.info(\n f\"Available plugins: {[config.name for config in plugin_loader.get_all_plugin_configs()]}\"\n )\n return plugin_loader\n\n\n# #endregion get_plugin_loader\n\n\n# #region get_task_manager [C:1] [TYPE Function]\n# @BRIEF Dependency injector for TaskManager.\n# @PRE: Global task_manager must be initialized.\n# @POST: Returns shared TaskManager instance.\ndef get_task_manager() -> TaskManager:\n \"\"\"Dependency injector for TaskManager.\"\"\"\n global task_manager\n if task_manager is None:\n task_manager = TaskManager(get_plugin_loader())\n logger.info(\"TaskManager initialized\")\n return task_manager\n\n\n# #endregion get_task_manager\n\n\n# #region get_scheduler_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for SchedulerService.\n# @PRE: Global scheduler_service must be initialized.\n# @POST: Returns shared SchedulerService instance.\ndef get_scheduler_service() -> SchedulerService:\n \"\"\"Dependency injector for SchedulerService.\"\"\"\n global scheduler_service\n if scheduler_service is None:\n scheduler_service = SchedulerService(get_task_manager(), get_config_manager())\n logger.info(\"SchedulerService initialized\")\n return scheduler_service\n\n\n# #endregion get_scheduler_service\n\n\n# #region get_resource_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for ResourceService.\n# @PRE: Global resource_service must be initialized.\n# @POST: Returns shared ResourceService instance.\ndef get_resource_service() -> ResourceService:\n \"\"\"Dependency injector for ResourceService.\"\"\"\n global resource_service\n if resource_service is None:\n resource_service = ResourceService()\n logger.info(\"ResourceService initialized\")\n return resource_service\n\n\n# #endregion get_resource_service\n\n\n# #region get_mapping_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for MappingService.\n# @PRE: Global config_manager must be initialized.\n# @POST: Returns new MappingService instance.\ndef get_mapping_service() -> MappingService:\n \"\"\"Dependency injector for MappingService.\"\"\"\n return MappingService(get_config_manager())\n\n\n# #endregion get_mapping_service\n\n\n_clean_release_repository = CleanReleaseRepository()\n\n\n# #region get_clean_release_repository [C:1] [TYPE Function]\n# @BRIEF Legacy compatibility shim for CleanReleaseRepository.\n# @POST: Returns a shared CleanReleaseRepository instance.\ndef get_clean_release_repository() -> CleanReleaseRepository:\n \"\"\"Legacy compatibility shim for CleanReleaseRepository.\"\"\"\n return _clean_release_repository\n\n\n# #endregion get_clean_release_repository\n\n\n# #region get_clean_release_facade [C:1] [TYPE Function]\n# @BRIEF Dependency injector for CleanReleaseFacade.\n# @POST: Returns a facade instance with a fresh DB session.\ndef get_clean_release_facade(db=Depends(get_db)) -> CleanReleaseFacade:\n candidate_repo = CandidateRepository(db)\n artifact_repo = ArtifactRepository(db)\n manifest_repo = ManifestRepository(db)\n policy_repo = PolicyRepository(db)\n compliance_repo = ComplianceRepository(db)\n report_repo = ReportRepository(db)\n approval_repo = ApprovalRepository(db)\n publication_repo = PublicationRepository(db)\n audit_repo = AuditRepository(db)\n\n return CleanReleaseFacade(\n candidate_repo=candidate_repo,\n artifact_repo=artifact_repo,\n manifest_repo=manifest_repo,\n policy_repo=policy_repo,\n compliance_repo=compliance_repo,\n report_repo=report_repo,\n approval_repo=approval_repo,\n publication_repo=publication_repo,\n audit_repo=audit_repo,\n config_manager=get_config_manager(),\n )\n\n\n# #endregion get_clean_release_facade\n\n# #region oauth2_scheme [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF OAuth2 password bearer scheme for token extraction.\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\")\n# #endregion oauth2_scheme\n\n\n# #region get_current_user [C:3] [TYPE Function]\n# @RELATION CALLS -> AuthRepository\n# @BRIEF Dependency for retrieving currently authenticated user from a JWT.\n# @PRE: JWT token provided in Authorization header.\n# @POST: Returns User object if token is valid.\ndef get_current_user(token: str = Depends(oauth2_scheme), db=Depends(get_auth_db)):\n credentials_exception = HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n try:\n payload = decode_token(token)\n username_value = payload.get(\"sub\")\n if not isinstance(username_value, str) or not username_value:\n raise credentials_exception\n username = username_value\n except JWTError:\n raise credentials_exception\n\n repo = AuthRepository(db)\n user = repo.get_user_by_username(username)\n if user is None:\n raise credentials_exception\n return user\n\n\n# #endregion get_current_user\n\n\n# #region has_permission [C:3] [TYPE Function]\n# @RELATION CALLS -> AuthRepository\n# @BRIEF Dependency for checking if the current user has a specific permission.\n# @PRE: User is authenticated.\n# @POST: Returns True if user has permission.\ndef has_permission(resource: str, action: str):\n def permission_checker(current_user: User = Depends(get_current_user)):\n # Union of all permissions across all roles\n for role in current_user.roles:\n for perm in role.permissions:\n if perm.resource == resource and perm.action == action:\n return current_user\n\n # Special case for Admin role (full access)\n if any(role.name == \"Admin\" for role in current_user.roles):\n return current_user\n\n from .core.auth.logger import log_security_event\n\n log_security_event(\n \"PERMISSION_DENIED\",\n str(getattr(current_user, \"username\", \"unknown\")),\n {\"resource\": resource, \"action\": action},\n )\n\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"Permission denied for {resource}:{action}\",\n )\n\n return permission_checker\n\n\n# #endregion has_permission\n\n# #endregion AppDependencies\n" + "body": "# #region AppDependencies [C:4] [TYPE Module] [SEMANTICS fastapi, schedule, auth, api_key]\n# @BRIEF Manages creation and provision of shared application dependencies, such as PluginLoader and TaskManager, to avoid circular imports.\n# @LAYER: Core\n# @RELATION Used by main app and API routers to get access to shared instances.\n# @RELATION CALLS -> [CleanReleaseRepository]\n# @RELATION CALLS -> [ConfigManager]\n# @RELATION CALLS -> [PluginLoader]\n# @RELATION CALLS -> [SchedulerService]\n# @RELATION CALLS -> [TaskManager]\n# @RELATION CALLS -> [get_all_plugin_configs]\n# @RELATION CALLS -> [get_db]\n# @RELATION CALLS -> [APIKeyPrincipal]\n# @RELATION CALLS -> [get_api_key_principal]\n# @RELATION CALLS -> [info]\n\nimport json\n\nfrom dataclasses import dataclass, field\nfrom datetime import datetime, timezone\nfrom pathlib import Path\nfrom typing import Optional\n\nfrom fastapi import Depends, HTTPException, Request, status\nfrom fastapi.security import OAuth2PasswordBearer\nfrom jose import JWTError\n\nfrom .core.auth.jwt import decode_token\nfrom .core.auth.repository import AuthRepository\nfrom .core.config_manager import ConfigManager\nfrom .core.database import get_auth_db, get_db, init_db\nfrom .core.logger import logger\nfrom .core.plugin_loader import PluginLoader\nfrom .core.scheduler import SchedulerService\nfrom .core.task_manager import TaskManager\nfrom .models.api_key import APIKey\nfrom .models.auth import User\nfrom .services.clean_release.facade import CleanReleaseFacade\nfrom .services.clean_release.repositories import (\n ApprovalRepository,\n ArtifactRepository,\n AuditRepository,\n CandidateRepository,\n ComplianceRepository,\n ManifestRepository,\n PolicyRepository,\n PublicationRepository,\n ReportRepository,\n)\nfrom .services.clean_release.repository import CleanReleaseRepository\nfrom .services.mapping_service import MappingService\nfrom .services.resource_service import ResourceService\n\n# Initialize singletons lazily to avoid import-time DB side effects during test collection.\n# Use absolute path relative to this file to ensure plugins are found regardless of CWD\nproject_root = Path(__file__).parent.parent.parent\nconfig_path = project_root / \"config.json\"\n\nconfig_manager: ConfigManager | None = None\nplugin_loader: PluginLoader | None = None\ntask_manager: TaskManager | None = None\nscheduler_service: SchedulerService | None = None\nresource_service: ResourceService | None = None\n\n\n# #region get_config_manager [C:1] [TYPE Function]\n# @BRIEF Dependency injector for ConfigManager.\n# @PRE: Global config_manager must be initialized.\n# @POST: Returns shared ConfigManager instance.\ndef get_config_manager() -> ConfigManager:\n \"\"\"Dependency injector for ConfigManager.\"\"\"\n global config_manager\n if config_manager is None:\n init_db()\n config_manager = ConfigManager(config_path=str(config_path))\n return config_manager\n\n\n# #endregion get_config_manager\n\nplugin_dir = Path(__file__).parent / \"plugins\"\n\n# Clean Release Redesign Singletons\n# Note: These use get_db() which is a generator, so we need a way to provide a session.\n# For singletons in dependencies.py, we might need a different approach or\n# initialize them inside the dependency functions.\n\n\n# #region get_plugin_loader [C:1] [TYPE Function]\n# @BRIEF Dependency injector for PluginLoader.\n# @PRE: Global plugin_loader must be initialized.\n# @POST: Returns shared PluginLoader instance.\ndef get_plugin_loader() -> PluginLoader:\n \"\"\"Dependency injector for PluginLoader.\"\"\"\n global plugin_loader\n if plugin_loader is None:\n plugin_loader = PluginLoader(plugin_dir=str(plugin_dir))\n logger.info(f\"PluginLoader initialized with directory: {plugin_dir}\")\n logger.info(\n f\"Available plugins: {[config.name for config in plugin_loader.get_all_plugin_configs()]}\"\n )\n return plugin_loader\n\n\n# #endregion get_plugin_loader\n\n\n# #region get_task_manager [C:1] [TYPE Function]\n# @BRIEF Dependency injector for TaskManager.\n# @PRE: Global task_manager must be initialized.\n# @POST: Returns shared TaskManager instance.\ndef get_task_manager() -> TaskManager:\n \"\"\"Dependency injector for TaskManager.\"\"\"\n global task_manager\n if task_manager is None:\n task_manager = TaskManager(get_plugin_loader())\n logger.info(\"TaskManager initialized\")\n return task_manager\n\n\n# #endregion get_task_manager\n\n\n# #region get_scheduler_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for SchedulerService.\n# @PRE: Global scheduler_service must be initialized.\n# @POST: Returns shared SchedulerService instance.\ndef get_scheduler_service() -> SchedulerService:\n \"\"\"Dependency injector for SchedulerService.\"\"\"\n global scheduler_service\n if scheduler_service is None:\n scheduler_service = SchedulerService(get_task_manager(), get_config_manager())\n logger.info(\"SchedulerService initialized\")\n return scheduler_service\n\n\n# #endregion get_scheduler_service\n\n\n# #region get_resource_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for ResourceService.\n# @PRE: Global resource_service must be initialized.\n# @POST: Returns shared ResourceService instance.\ndef get_resource_service() -> ResourceService:\n \"\"\"Dependency injector for ResourceService.\"\"\"\n global resource_service\n if resource_service is None:\n resource_service = ResourceService()\n logger.info(\"ResourceService initialized\")\n return resource_service\n\n\n# #endregion get_resource_service\n\n\n# #region get_mapping_service [C:1] [TYPE Function]\n# @BRIEF Dependency injector for MappingService.\n# @PRE: Global config_manager must be initialized.\n# @POST: Returns new MappingService instance.\ndef get_mapping_service() -> MappingService:\n \"\"\"Dependency injector for MappingService.\"\"\"\n return MappingService(get_config_manager())\n\n\n# #endregion get_mapping_service\n\n\n_clean_release_repository = CleanReleaseRepository()\n\n\n# #region get_clean_release_repository [C:1] [TYPE Function]\n# @BRIEF Legacy compatibility shim for CleanReleaseRepository.\n# @POST: Returns a shared CleanReleaseRepository instance.\ndef get_clean_release_repository() -> CleanReleaseRepository:\n \"\"\"Legacy compatibility shim for CleanReleaseRepository.\"\"\"\n return _clean_release_repository\n\n\n# #endregion get_clean_release_repository\n\n\n# #region get_clean_release_facade [C:1] [TYPE Function]\n# @BRIEF Dependency injector for CleanReleaseFacade.\n# @POST: Returns a facade instance with a fresh DB session.\ndef get_clean_release_facade(db=Depends(get_db)) -> CleanReleaseFacade:\n candidate_repo = CandidateRepository(db)\n artifact_repo = ArtifactRepository(db)\n manifest_repo = ManifestRepository(db)\n policy_repo = PolicyRepository(db)\n compliance_repo = ComplianceRepository(db)\n report_repo = ReportRepository(db)\n approval_repo = ApprovalRepository(db)\n publication_repo = PublicationRepository(db)\n audit_repo = AuditRepository(db)\n\n return CleanReleaseFacade(\n candidate_repo=candidate_repo,\n artifact_repo=artifact_repo,\n manifest_repo=manifest_repo,\n policy_repo=policy_repo,\n compliance_repo=compliance_repo,\n report_repo=report_repo,\n approval_repo=approval_repo,\n publication_repo=publication_repo,\n audit_repo=audit_repo,\n config_manager=get_config_manager(),\n )\n\n\n# #endregion get_clean_release_facade\n\n# #region APIKeyPrincipal [C:1] [TYPE Class]\n# @BRIEF Dataclass representing an authenticated API key principal for service-to-service auth.\n@dataclass\nclass APIKeyPrincipal:\n name: str\n api_key_id: str\n environment_id: Optional[str] = None\n permissions: list[str] = field(default_factory=list)\n# #endregion APIKeyPrincipal\n\n\n# #region require_api_key_or_jwt [C:4] [TYPE Function]\n# @BRIEF Factory: creates a dependency that accepts either a valid API key (with permission check)\n# OR a JWT (with standard has_permission check). Returns the authenticated user/principal name.\n# JWT takes precedence when both auth methods are present.\n# When API key is used, its environment_id scope is enforced against the caller's environment_id.\n# @PRE required_api_permission is a dot-separated string e.g. \"maintenance:start\".\n# required_jwt_resource and required_jwt_action are the JWT permission to check.\n# environment_id is the target environment for the operation (may be None for cross-env ops).\n# @POST Returns str (username or api key name). Raises 400/401/403 if auth fails or scope mismatch.\n# @SIDE_EFFECT Updates APIKey.last_used_at on successful API key auth.\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\n# @RELATION DEPENDS_ON -> [AuthRepository]\n# @RELATION DEPENDS_ON -> [decode_token]\ndef require_api_key_or_jwt(\n required_api_permission: str,\n required_jwt_resource: str,\n required_jwt_action: str,\n environment_id: str | None = None,\n):\n \"\"\"Factory: creates a combined API-key-or-JWT auth dependency with environment scoping.\n\n JWT takes precedence when both Authorization: Bearer and X-API-Key are present.\n When API key auth is used, the key's environment_id scope is enforced:\n - If key.environment_id differs from environment_id → 400\n - If environment_id is None, the key's scope is used as default (auto-scope).\n\n Args:\n required_api_permission: Permission string to check against API key (e.g. 'maintenance:start').\n required_jwt_resource: JWT resource for has_permission fallback.\n required_jwt_action: JWT action for has_permission fallback.\n environment_id: Target environment for the operation. Pass None for cross-env operations.\n \"\"\"\n async def _auth_dependency(\n request: Request,\n db=Depends(get_db),\n auth_db=Depends(get_auth_db),\n token: str | None = Depends(oauth2_scheme_optional),\n ) -> str:\n from .core.auth.api_key import hash_api_key\n\n # Resolve effective environment_id: factory parameter > request body > None\n effective_env_id = environment_id\n if effective_env_id is None:\n try:\n body = await request.json()\n effective_env_id = body.get(\"environment_id\")\n except (json.JSONDecodeError, KeyError, AttributeError):\n pass\n\n # ── Try JWT auth first (JWT takes precedence over API key) ──\n if token:\n try:\n payload = decode_token(token)\n username_value = payload.get(\"sub\")\n if not isinstance(username_value, str) or not username_value:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n username = username_value\n except Exception:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n\n repo = AuthRepository(auth_db)\n user = repo.get_user_by_username(username)\n if user is None:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"User not found\",\n )\n\n # Check JWT permission (Admin has full access)\n has_perm = any(\n role.name == \"Admin\"\n for role in user.roles\n )\n if not has_perm:\n for role in user.roles:\n for perm in role.permissions:\n if perm.resource == required_jwt_resource and perm.action == required_jwt_action:\n has_perm = True\n break\n if has_perm:\n break\n\n if not has_perm:\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"Permission denied for {required_jwt_resource}:{required_jwt_action}\",\n )\n\n logger.info(f\"JWT auth: {user.username}\")\n return f\"jwt:{user.username}\"\n\n # ── Try API key auth ──\n raw_key = request.headers.get(\"X-API-Key\")\n if raw_key:\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if not api_key:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Invalid API key\",\n )\n if not api_key.active:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has been revoked\",\n )\n if api_key.expires_at:\n expires_at = api_key.expires_at\n if expires_at.tzinfo is None:\n expires_at = expires_at.replace(tzinfo=timezone.utc)\n if expires_at < datetime.now(timezone.utc):\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has expired\",\n )\n\n # Check API key has required permission\n api_permissions = list(api_key.permissions or [])\n if required_api_permission not in api_permissions:\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"API key lacks permission '{required_api_permission}'\",\n )\n\n # Environment scoping check: key's scope vs effective operation env\n key_env = api_key.environment_id\n if key_env is not None and effective_env_id is not None and key_env != effective_env_id:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"API key is restricted to environment '{key_env}'\",\n )\n\n # Update last_used_at (best-effort, non-blocking)\n api_key.last_used_at = datetime.now(timezone.utc)\n db.flush()\n\n logger.info(f\"API key auth: {api_key.name} ({api_key.prefix}...)\")\n return f\"api_key:{api_key.name}\"\n\n # ── Neither JWT nor API key provided ──\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Authentication required (API key or JWT)\",\n )\n\n return _auth_dependency\n\n\n# #endregion require_api_key_or_jwt\n\n\n# #region check_api_key_environment_scope [C:1] [TYPE Function]\n# @BRIEF Check the request's API key environment scope against a target env_id. Raises 400 if mismatch.\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\nasync def check_api_key_environment_scope(request: Request, db, target_env_id: str) -> None:\n \"\"\"Check the request's API key environment scope against a target environment_id.\n\n If the API key has an environment_id set and it differs from target_env_id,\n raises HTTP 400. This is used in route handlers where the target env_id\n is only known at request time (e.g., loaded from DB in end_maintenance).\n\n Args:\n request: FastAPI request object (to extract X-API-Key header).\n db: Database session.\n target_env_id: The target environment to validate against.\n \"\"\"\n from .core.auth.api_key import hash_api_key\n\n raw_key = request.headers.get(\"X-API-Key\")\n if not raw_key:\n return\n\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if api_key is None:\n return\n\n key_env = api_key.environment_id\n if key_env is not None and key_env != target_env_id:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"API key is restricted to environment '{key_env}'\",\n )\n# #endregion check_api_key_environment_scope\n\n\n# #region get_api_key_principal [C:3] [TYPE Function]\n# @BRIEF FastAPI dependency that reads X-API-Key header and returns APIKeyPrincipal or None.\n# @PRE X-API-Key header may be present in the request.\n# @POST If valid key: returns APIKeyPrincipal; if no header: returns None; if invalid: raises 401.\n# @SIDE_EFFECT Updates last_used_at on the APIKey row (non-blocking flush).\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\nasync def get_api_key_principal(\n request: Request,\n db=Depends(get_db),\n) -> Optional[APIKeyPrincipal]:\n \"\"\"Extract and validate API key from X-API-Key header.\n\n If no header is present, returns None (fall through to JWT auth).\n If header is present but invalid, raises 401.\n\n Returns:\n APIKeyPrincipal | None: Principal if valid API key, None if no header.\n \"\"\"\n from .core.auth.api_key import hash_api_key\n\n raw_key = request.headers.get(\"X-API-Key\")\n if not raw_key:\n return None\n\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n\n if not api_key:\n logger.warning(f\"API key auth failed: key not found (hash prefix: {raw_key[:11]}...)\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Invalid API key\",\n )\n\n if not api_key.active:\n logger.warning(f\"API key auth failed: key revoked (id: {api_key.id}, name: {api_key.name})\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has been revoked\",\n )\n\n if api_key.expires_at:\n expires_at = api_key.expires_at\n if expires_at.tzinfo is None:\n expires_at = expires_at.replace(tzinfo=timezone.utc)\n if expires_at < datetime.now(timezone.utc):\n logger.warning(f\"API key auth failed: key expired (id: {api_key.id}, name: {api_key.name})\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has expired\",\n )\n\n # Update last_used_at (non-blocking, best-effort)\n api_key.last_used_at = datetime.now(timezone.utc)\n db.flush()\n\n logger.info(f\"API key auth success: {api_key.name} ({api_key.prefix}...)\")\n return APIKeyPrincipal(\n name=api_key.name,\n api_key_id=api_key.id,\n environment_id=api_key.environment_id,\n permissions=list(api_key.permissions or []),\n )\n\n\n# #endregion get_api_key_principal\n\n\n# #region oauth2_scheme [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF OAuth2 password bearer scheme for token extraction (raises 401 on missing token).\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\", auto_error=True)\n# #endregion oauth2_scheme\n\n# #region oauth2_scheme_optional [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF Optional OAuth2 scheme — returns None instead of raising 401 when no token.\n# @RATIONALE Used in dual-auth routes (API key OR JWT) where JWT may be absent.\noauth2_scheme_optional = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\", auto_error=False)\n# #endregion oauth2_scheme_optional\n\n\n# #region get_current_user [C:3] [TYPE Function]\n# @RELATION CALLS -> AuthRepository\n# @BRIEF Dependency for retrieving currently authenticated user from a JWT.\n# @PRE: JWT token provided in Authorization header.\n# @POST: Returns User object if token is valid.\ndef get_current_user(token: str = Depends(oauth2_scheme), db=Depends(get_auth_db)):\n credentials_exception = HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n try:\n payload = decode_token(token)\n username_value = payload.get(\"sub\")\n if not isinstance(username_value, str) or not username_value:\n raise credentials_exception\n username = username_value\n except JWTError:\n raise credentials_exception\n\n repo = AuthRepository(db)\n user = repo.get_user_by_username(username)\n if user is None:\n raise credentials_exception\n return user\n\n\n# #endregion get_current_user\n\n\n# #region has_permission [C:3] [TYPE Function]\n# @RELATION CALLS -> AuthRepository\n# @BRIEF Dependency for checking if the current user has a specific permission.\n# @PRE: User is authenticated.\n# @POST: Returns True if user has permission.\ndef has_permission(resource: str, action: str):\n def permission_checker(current_user: User = Depends(get_current_user)):\n # Union of all permissions across all roles\n for role in current_user.roles:\n for perm in role.permissions:\n if perm.resource == resource and perm.action == action:\n return current_user\n\n # Special case for Admin role (full access)\n if any(role.name == \"Admin\" for role in current_user.roles):\n return current_user\n\n from .core.auth.logger import log_security_event\n\n log_security_event(\n \"PERMISSION_DENIED\",\n str(getattr(current_user, \"username\", \"unknown\")),\n {\"resource\": resource, \"action\": action},\n )\n\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"Permission denied for {resource}:{action}\",\n )\n\n return permission_checker\n\n\n# #endregion has_permission\n\n# #endregion AppDependencies\n" }, { "contract_id": "get_config_manager", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 58, - "end_line": 71, + "start_line": 65, + "end_line": 78, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31269,8 +32823,8 @@ "contract_id": "get_plugin_loader", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 81, - "end_line": 97, + "start_line": 88, + "end_line": 104, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31289,8 +32843,8 @@ "contract_id": "get_task_manager", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 100, - "end_line": 113, + "start_line": 107, + "end_line": 120, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31309,8 +32863,8 @@ "contract_id": "get_scheduler_service", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 116, - "end_line": 129, + "start_line": 123, + "end_line": 136, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31329,8 +32883,8 @@ "contract_id": "get_resource_service", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 132, - "end_line": 145, + "start_line": 139, + "end_line": 152, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31349,8 +32903,8 @@ "contract_id": "get_mapping_service", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 148, - "end_line": 157, + "start_line": 155, + "end_line": 164, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31369,8 +32923,8 @@ "contract_id": "get_clean_release_repository", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 163, - "end_line": 171, + "start_line": 170, + "end_line": 178, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31388,8 +32942,8 @@ "contract_id": "get_clean_release_facade", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 174, - "end_line": 202, + "start_line": 181, + "end_line": 209, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -31404,16 +32958,117 @@ "body": "# #region get_clean_release_facade [C:1] [TYPE Function]\n# @BRIEF Dependency injector for CleanReleaseFacade.\n# @POST: Returns a facade instance with a fresh DB session.\ndef get_clean_release_facade(db=Depends(get_db)) -> CleanReleaseFacade:\n candidate_repo = CandidateRepository(db)\n artifact_repo = ArtifactRepository(db)\n manifest_repo = ManifestRepository(db)\n policy_repo = PolicyRepository(db)\n compliance_repo = ComplianceRepository(db)\n report_repo = ReportRepository(db)\n approval_repo = ApprovalRepository(db)\n publication_repo = PublicationRepository(db)\n audit_repo = AuditRepository(db)\n\n return CleanReleaseFacade(\n candidate_repo=candidate_repo,\n artifact_repo=artifact_repo,\n manifest_repo=manifest_repo,\n policy_repo=policy_repo,\n compliance_repo=compliance_repo,\n report_repo=report_repo,\n approval_repo=approval_repo,\n publication_repo=publication_repo,\n audit_repo=audit_repo,\n config_manager=get_config_manager(),\n )\n\n\n# #endregion get_clean_release_facade\n" }, { - "contract_id": "oauth2_scheme", - "contract_type": "Variable", + "contract_id": "APIKeyPrincipal", + "contract_type": "Class", "file_path": "backend/src/dependencies.py", - "start_line": 204, - "end_line": 208, + "start_line": 211, + "end_line": 219, "tier": "TIER_1", "complexity": 1, "metadata": { "COMPLEXITY": 1, - "PURPOSE": "OAuth2 password bearer scheme for token extraction." + "PURPOSE": "Dataclass representing an authenticated API key principal for service-to-service auth." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region APIKeyPrincipal [C:1] [TYPE Class]\n# @BRIEF Dataclass representing an authenticated API key principal for service-to-service auth.\n@dataclass\nclass APIKeyPrincipal:\n name: str\n api_key_id: str\n environment_id: Optional[str] = None\n permissions: list[str] = field(default_factory=list)\n# #endregion APIKeyPrincipal\n" + }, + { + "contract_id": "require_api_key_or_jwt", + "contract_type": "Function", + "file_path": "backend/src/dependencies.py", + "start_line": 222, + "end_line": 379, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "Factory: creates a dependency that accepts either a valid API key (with permission check)" + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region require_api_key_or_jwt [C:4] [TYPE Function]\n# @BRIEF Factory: creates a dependency that accepts either a valid API key (with permission check)\n# OR a JWT (with standard has_permission check). Returns the authenticated user/principal name.\n# JWT takes precedence when both auth methods are present.\n# When API key is used, its environment_id scope is enforced against the caller's environment_id.\n# @PRE required_api_permission is a dot-separated string e.g. \"maintenance:start\".\n# required_jwt_resource and required_jwt_action are the JWT permission to check.\n# environment_id is the target environment for the operation (may be None for cross-env ops).\n# @POST Returns str (username or api key name). Raises 400/401/403 if auth fails or scope mismatch.\n# @SIDE_EFFECT Updates APIKey.last_used_at on successful API key auth.\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\n# @RELATION DEPENDS_ON -> [AuthRepository]\n# @RELATION DEPENDS_ON -> [decode_token]\ndef require_api_key_or_jwt(\n required_api_permission: str,\n required_jwt_resource: str,\n required_jwt_action: str,\n environment_id: str | None = None,\n):\n \"\"\"Factory: creates a combined API-key-or-JWT auth dependency with environment scoping.\n\n JWT takes precedence when both Authorization: Bearer and X-API-Key are present.\n When API key auth is used, the key's environment_id scope is enforced:\n - If key.environment_id differs from environment_id → 400\n - If environment_id is None, the key's scope is used as default (auto-scope).\n\n Args:\n required_api_permission: Permission string to check against API key (e.g. 'maintenance:start').\n required_jwt_resource: JWT resource for has_permission fallback.\n required_jwt_action: JWT action for has_permission fallback.\n environment_id: Target environment for the operation. Pass None for cross-env operations.\n \"\"\"\n async def _auth_dependency(\n request: Request,\n db=Depends(get_db),\n auth_db=Depends(get_auth_db),\n token: str | None = Depends(oauth2_scheme_optional),\n ) -> str:\n from .core.auth.api_key import hash_api_key\n\n # Resolve effective environment_id: factory parameter > request body > None\n effective_env_id = environment_id\n if effective_env_id is None:\n try:\n body = await request.json()\n effective_env_id = body.get(\"environment_id\")\n except (json.JSONDecodeError, KeyError, AttributeError):\n pass\n\n # ── Try JWT auth first (JWT takes precedence over API key) ──\n if token:\n try:\n payload = decode_token(token)\n username_value = payload.get(\"sub\")\n if not isinstance(username_value, str) or not username_value:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n username = username_value\n except Exception:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Could not validate credentials\",\n headers={\"WWW-Authenticate\": \"Bearer\"},\n )\n\n repo = AuthRepository(auth_db)\n user = repo.get_user_by_username(username)\n if user is None:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"User not found\",\n )\n\n # Check JWT permission (Admin has full access)\n has_perm = any(\n role.name == \"Admin\"\n for role in user.roles\n )\n if not has_perm:\n for role in user.roles:\n for perm in role.permissions:\n if perm.resource == required_jwt_resource and perm.action == required_jwt_action:\n has_perm = True\n break\n if has_perm:\n break\n\n if not has_perm:\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"Permission denied for {required_jwt_resource}:{required_jwt_action}\",\n )\n\n logger.info(f\"JWT auth: {user.username}\")\n return f\"jwt:{user.username}\"\n\n # ── Try API key auth ──\n raw_key = request.headers.get(\"X-API-Key\")\n if raw_key:\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if not api_key:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Invalid API key\",\n )\n if not api_key.active:\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has been revoked\",\n )\n if api_key.expires_at:\n expires_at = api_key.expires_at\n if expires_at.tzinfo is None:\n expires_at = expires_at.replace(tzinfo=timezone.utc)\n if expires_at < datetime.now(timezone.utc):\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has expired\",\n )\n\n # Check API key has required permission\n api_permissions = list(api_key.permissions or [])\n if required_api_permission not in api_permissions:\n raise HTTPException(\n status_code=status.HTTP_403_FORBIDDEN,\n detail=f\"API key lacks permission '{required_api_permission}'\",\n )\n\n # Environment scoping check: key's scope vs effective operation env\n key_env = api_key.environment_id\n if key_env is not None and effective_env_id is not None and key_env != effective_env_id:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"API key is restricted to environment '{key_env}'\",\n )\n\n # Update last_used_at (best-effort, non-blocking)\n api_key.last_used_at = datetime.now(timezone.utc)\n db.flush()\n\n logger.info(f\"API key auth: {api_key.name} ({api_key.prefix}...)\")\n return f\"api_key:{api_key.name}\"\n\n # ── Neither JWT nor API key provided ──\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Authentication required (API key or JWT)\",\n )\n\n return _auth_dependency\n\n\n# #endregion require_api_key_or_jwt\n" + }, + { + "contract_id": "check_api_key_environment_scope", + "contract_type": "Function", + "file_path": "backend/src/dependencies.py", + "start_line": 382, + "end_line": 415, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Check the request's API key environment scope against a target env_id. Raises 400 if mismatch." + }, + "relations": [ + { + "source_id": "check_api_key_environment_scope", + "relation_type": "DEPENDS_ON", + "target_id": "APIKeyModel", + "target_ref": "[APIKeyModel]" + }, + { + "source_id": "check_api_key_environment_scope", + "relation_type": "DEPENDS_ON", + "target_id": "hash_api_key", + "target_ref": "[hash_api_key]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region check_api_key_environment_scope [C:1] [TYPE Function]\n# @BRIEF Check the request's API key environment scope against a target env_id. Raises 400 if mismatch.\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\nasync def check_api_key_environment_scope(request: Request, db, target_env_id: str) -> None:\n \"\"\"Check the request's API key environment scope against a target environment_id.\n\n If the API key has an environment_id set and it differs from target_env_id,\n raises HTTP 400. This is used in route handlers where the target env_id\n is only known at request time (e.g., loaded from DB in end_maintenance).\n\n Args:\n request: FastAPI request object (to extract X-API-Key header).\n db: Database session.\n target_env_id: The target environment to validate against.\n \"\"\"\n from .core.auth.api_key import hash_api_key\n\n raw_key = request.headers.get(\"X-API-Key\")\n if not raw_key:\n return\n\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n if api_key is None:\n return\n\n key_env = api_key.environment_id\n if key_env is not None and key_env != target_env_id:\n raise HTTPException(\n status_code=status.HTTP_400_BAD_REQUEST,\n detail=f\"API key is restricted to environment '{key_env}'\",\n )\n# #endregion check_api_key_environment_scope\n" + }, + { + "contract_id": "get_api_key_principal", + "contract_type": "Function", + "file_path": "backend/src/dependencies.py", + "start_line": 418, + "end_line": 484, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "If valid key: returns APIKeyPrincipal; if no header: returns None; if invalid: raises 401.", + "PRE": "X-API-Key header may be present in the request.", + "PURPOSE": "FastAPI dependency that reads X-API-Key header and returns APIKeyPrincipal or None.", + "SIDE_EFFECT": "Updates last_used_at on the APIKey row (non-blocking flush)." + }, + "relations": [ + { + "source_id": "get_api_key_principal", + "relation_type": "DEPENDS_ON", + "target_id": "APIKeyModel", + "target_ref": "[APIKeyModel]" + }, + { + "source_id": "get_api_key_principal", + "relation_type": "DEPENDS_ON", + "target_id": "hash_api_key", + "target_ref": "[hash_api_key]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region get_api_key_principal [C:3] [TYPE Function]\n# @BRIEF FastAPI dependency that reads X-API-Key header and returns APIKeyPrincipal or None.\n# @PRE X-API-Key header may be present in the request.\n# @POST If valid key: returns APIKeyPrincipal; if no header: returns None; if invalid: raises 401.\n# @SIDE_EFFECT Updates last_used_at on the APIKey row (non-blocking flush).\n# @RELATION DEPENDS_ON -> [APIKeyModel]\n# @RELATION DEPENDS_ON -> [hash_api_key]\nasync def get_api_key_principal(\n request: Request,\n db=Depends(get_db),\n) -> Optional[APIKeyPrincipal]:\n \"\"\"Extract and validate API key from X-API-Key header.\n\n If no header is present, returns None (fall through to JWT auth).\n If header is present but invalid, raises 401.\n\n Returns:\n APIKeyPrincipal | None: Principal if valid API key, None if no header.\n \"\"\"\n from .core.auth.api_key import hash_api_key\n\n raw_key = request.headers.get(\"X-API-Key\")\n if not raw_key:\n return None\n\n key_hash = hash_api_key(raw_key)\n api_key = db.query(APIKey).filter(APIKey.key_hash == key_hash).first()\n\n if not api_key:\n logger.warning(f\"API key auth failed: key not found (hash prefix: {raw_key[:11]}...)\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"Invalid API key\",\n )\n\n if not api_key.active:\n logger.warning(f\"API key auth failed: key revoked (id: {api_key.id}, name: {api_key.name})\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has been revoked\",\n )\n\n if api_key.expires_at:\n expires_at = api_key.expires_at\n if expires_at.tzinfo is None:\n expires_at = expires_at.replace(tzinfo=timezone.utc)\n if expires_at < datetime.now(timezone.utc):\n logger.warning(f\"API key auth failed: key expired (id: {api_key.id}, name: {api_key.name})\")\n raise HTTPException(\n status_code=status.HTTP_401_UNAUTHORIZED,\n detail=\"API key has expired\",\n )\n\n # Update last_used_at (non-blocking, best-effort)\n api_key.last_used_at = datetime.now(timezone.utc)\n db.flush()\n\n logger.info(f\"API key auth success: {api_key.name} ({api_key.prefix}...)\")\n return APIKeyPrincipal(\n name=api_key.name,\n api_key_id=api_key.id,\n environment_id=api_key.environment_id,\n permissions=list(api_key.permissions or []),\n )\n\n\n# #endregion get_api_key_principal\n" + }, + { + "contract_id": "oauth2_scheme", + "contract_type": "Variable", + "file_path": "backend/src/dependencies.py", + "start_line": 487, + "end_line": 491, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "OAuth2 password bearer scheme for token extraction (raises 401 on missing token)." }, "relations": [ { @@ -31489,14 +33144,130 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region oauth2_scheme [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF OAuth2 password bearer scheme for token extraction.\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\")\n# #endregion oauth2_scheme\n" + "body": "# #region oauth2_scheme [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF OAuth2 password bearer scheme for token extraction (raises 401 on missing token).\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\", auto_error=True)\n# #endregion oauth2_scheme\n" + }, + { + "contract_id": "oauth2_scheme_optional", + "contract_type": "Variable", + "file_path": "backend/src/dependencies.py", + "start_line": 493, + "end_line": 498, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Optional OAuth2 scheme — returns None instead of raising 401 when no token.", + "RATIONALE": "Used in dual-auth routes (API key OR JWT) where JWT may be absent." + }, + "relations": [ + { + "source_id": "oauth2_scheme_optional", + "relation_type": "DEPENDS_ON", + "target_id": "OAuth2PasswordBearer", + "target_ref": "OAuth2PasswordBearer" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Variable'", + "detail": { + "actual_type": "Variable", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Variable' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Variable" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Variable'", + "detail": { + "actual_type": "Variable", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Variable' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Variable" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "RATIONALE", + "message": "@RATIONALE is not allowed for contract type 'Variable'", + "detail": { + "actual_type": "Variable", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RATIONALE", + "message": "@RATIONALE is forbidden for contract type 'Variable' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Variable" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'Variable' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Variable" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region oauth2_scheme_optional [C:1] [TYPE Variable]\n# @RELATION DEPENDS_ON -> OAuth2PasswordBearer\n# @BRIEF Optional OAuth2 scheme — returns None instead of raising 401 when no token.\n# @RATIONALE Used in dual-auth routes (API key OR JWT) where JWT may be absent.\noauth2_scheme_optional = OAuth2PasswordBearer(tokenUrl=\"/api/auth/login\", auto_error=False)\n# #endregion oauth2_scheme_optional\n" }, { "contract_id": "get_current_user", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 211, - "end_line": 238, + "start_line": 501, + "end_line": 528, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -31522,8 +33293,8 @@ "contract_id": "has_permission", "contract_type": "Function", "file_path": "backend/src/dependencies.py", - "start_line": 241, - "end_line": 274, + "start_line": 531, + "end_line": 564, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -31858,6 +33629,51 @@ "tier_source": "AutoCalculated", "body": "# #region test_environment_model [TYPE Function]\n# @RELATION BINDS_TO -> test_models\n# @BRIEF Tests that Environment model correctly stores values.\n# @PRE: Environment class is available.\n# @POST: Values are verified.\ndef test_environment_model():\n with belief_scope(\"test_environment_model\"):\n env = Environment(\n id=\"test-id\",\n name=\"test-env\",\n url=\"http://localhost:8088/api/v1\",\n username=\"admin\",\n password=\"password\",\n )\n assert env.id == \"test-id\"\n assert env.name == \"test-env\"\n assert env.url == \"http://localhost:8088/api/v1\"\n# #endregion test_environment_model\n" }, + { + "contract_id": "APIKeyModel", + "contract_type": "Module", + "file_path": "backend/src/models/api_key.py", + "start_line": 1, + "end_line": 36, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "INVARIANT": "Raw key is NEVER stored — shown once at creation and discarded.", + "LAYER": "Domain", + "PURPOSE": "SQLAlchemy model for API Key authentication — stores SHA-256 hash only, raw key shown once at creation." + }, + "relations": [ + { + "source_id": "APIKeyModel", + "relation_type": "DEPENDS_ON", + "target_id": "MappingModels", + "target_ref": "[MappingModels]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region APIKeyModel [C:1] [TYPE Module] [SEMANTICS sqlalchemy, api_key, auth, model]\n# @BRIEF SQLAlchemy model for API Key authentication — stores SHA-256 hash only, raw key shown once at creation.\n# @LAYER Domain\n# @RELATION DEPENDS_ON -> [MappingModels]\n# @INVARIANT key_hash is stored as SHA-256 hex digest (64 chars). prefix stores \"ssk_\" + first 7 chars.\n# @INVARIANT Raw key is NEVER stored — shown once at creation and discarded.\n\nimport uuid\nfrom datetime import datetime, timezone\n\nfrom sqlalchemy import Boolean, Column, DateTime, JSON, String\n\nfrom .mapping import Base\n\n\n# #region APIKey [C:1] [TYPE Class]\n# @BRIEF Stores API key metadata and SHA-256 hash for service-to-service authentication.\nclass APIKey(Base):\n __tablename__ = \"api_keys\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n key_hash = Column(String(64), unique=True, nullable=False, index=True) # SHA-256 hex digest\n prefix = Column(String(11), nullable=False) # \"ssk_\" + 7 chars\n name = Column(String(255), nullable=False) # Human-readable label\n environment_id = Column(String(50), nullable=True) # Scoped to environment; null = all\n permissions = Column(JSON, nullable=False) # e.g. [\"maintenance:start\", \"maintenance:end\"]\n active = Column(Boolean, default=True, nullable=False)\n created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)\n expires_at = Column(DateTime, nullable=True)\n last_used_at = Column(DateTime, nullable=True)\n\n def __repr__(self) -> str:\n return f\"\"\n\n# #endregion APIKey\n# #endregion APIKeyModel\n" + }, + { + "contract_id": "APIKey", + "contract_type": "Class", + "file_path": "backend/src/models/api_key.py", + "start_line": 16, + "end_line": 35, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Stores API key metadata and SHA-256 hash for service-to-service authentication." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region APIKey [C:1] [TYPE Class]\n# @BRIEF Stores API key metadata and SHA-256 hash for service-to-service authentication.\nclass APIKey(Base):\n __tablename__ = \"api_keys\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n key_hash = Column(String(64), unique=True, nullable=False, index=True) # SHA-256 hex digest\n prefix = Column(String(11), nullable=False) # \"ssk_\" + 7 chars\n name = Column(String(255), nullable=False) # Human-readable label\n environment_id = Column(String(50), nullable=True) # Scoped to environment; null = all\n permissions = Column(JSON, nullable=False) # e.g. [\"maintenance:start\", \"maintenance:end\"]\n active = Column(Boolean, default=True, nullable=False)\n created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)\n expires_at = Column(DateTime, nullable=True)\n last_used_at = Column(DateTime, nullable=True)\n\n def __repr__(self) -> str:\n return f\"\"\n\n# #endregion APIKey\n" + }, { "contract_id": "AssistantModels", "contract_type": "Module", @@ -34498,7 +36314,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetReviewSessionModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, dataset, review, session, model]\n# @BRIEF Session aggregate root and collaborator models for dataset review orchestration.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> [DatasetReviewEnums:Module]\n# @RELATION DEPENDS_ON -> [MappingModels]\n# @INVARIANT: Session and profile entities are strictly scoped to an authenticated user.\n# @PRE: Database engine initialized\n# @POST: Session ORM models registered with optimistic locking\n# @SIDE_EFFECT: Defines dataset review session tables\n# @DATA_CONTRACT: SessionData -> SessionRecord\n\nfrom datetime import datetime\nimport uuid\n\nfrom sqlalchemy import (\n Column,\n DateTime,\n Enum as SQLEnum,\n ForeignKey,\n Integer,\n String,\n)\nfrom sqlalchemy.orm import relationship\n\nfrom src.models.dataset_review_pkg._enums import (\n ReadinessState,\n RecommendedAction,\n SessionCollaboratorRole,\n SessionPhase,\n SessionStatus,\n)\nfrom src.models.mapping import Base\n\n\n# #region SessionCollaborator [C:2] [TYPE Class]\n# @BRIEF RBAC collaborator record linking a user to a dataset review session with a specific role.\n# @RELATION DEPENDS_ON -> [DatasetReviewSession]\nclass SessionCollaborator(Base):\n __tablename__ = \"session_collaborators\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n session_id = Column(\n String, ForeignKey(\"dataset_review_sessions.session_id\"), nullable=False\n )\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n role = Column(SQLEnum(SessionCollaboratorRole), nullable=False)\n added_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n\n session = relationship(\"DatasetReviewSession\", back_populates=\"collaborators\")\n user = relationship(\"User\")\n\n\n# #endregion SessionCollaborator\n\n\n# #region DatasetReviewSession [C:3] [TYPE Class]\n# @BRIEF Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.\n# @RELATION DEPENDS_ON -> [SessionCollaborator]\n# @RELATION DEPENDS_ON -> [DatasetProfile]\n# @RELATION DEPENDS_ON -> [ValidationFinding]\n# @RELATION DEPENDS_ON -> [SemanticSource]\n# @RELATION DEPENDS_ON -> [SemanticFieldEntry]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\n# @RELATION DEPENDS_ON -> [TemplateVariable]\n# @RELATION DEPENDS_ON -> [ExecutionMapping]\n# @RELATION DEPENDS_ON -> [ClarificationSession]\n# @RELATION DEPENDS_ON -> [CompiledPreview]\n# @RELATION DEPENDS_ON -> [DatasetRunContext]\n# @RELATION DEPENDS_ON -> [ExportArtifact]\n# @RELATION DEPENDS_ON -> [SessionEvent]\n# @INVARIANT: Optimistic-lock version column prevents lost-update races on concurrent mutations.\nclass DatasetReviewSession(Base):\n __tablename__ = \"dataset_review_sessions\"\n\n session_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n source_kind = Column(String, nullable=False)\n source_input = Column(String, nullable=False)\n dataset_ref = Column(String, nullable=False)\n dataset_id = Column(Integer, nullable=True)\n dashboard_id = Column(Integer, nullable=True)\n readiness_state = Column(\n SQLEnum(ReadinessState), nullable=False, default=ReadinessState.EMPTY\n )\n recommended_action = Column(\n SQLEnum(RecommendedAction),\n nullable=False,\n default=RecommendedAction.IMPORT_FROM_SUPERSET,\n )\n version = Column(Integer, nullable=False, default=0)\n __mapper_args__ = {\"version_id_col\": version, \"version_id_generator\": False}\n status = Column(\n SQLEnum(SessionStatus), nullable=False, default=SessionStatus.ACTIVE\n )\n current_phase = Column(\n SQLEnum(SessionPhase), nullable=False, default=SessionPhase.INTAKE\n )\n active_task_id = Column(String, nullable=True)\n last_preview_id = Column(String, nullable=True)\n last_run_context_id = Column(String, nullable=True)\n created_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n updated_at = Column(\n DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False\n )\n last_activity_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n closed_at = Column(DateTime, nullable=True)\n\n owner = relationship(\"User\")\n collaborators = relationship(\n \"SessionCollaborator\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n profile = relationship(\n \"DatasetProfile\",\n back_populates=\"session\",\n uselist=False,\n cascade=\"all, delete-orphan\",\n )\n findings = relationship(\n \"ValidationFinding\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_sources = relationship(\n \"SemanticSource\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_fields = relationship(\n \"SemanticFieldEntry\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n imported_filters = relationship(\n \"ImportedFilter\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n template_variables = relationship(\n \"TemplateVariable\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n execution_mappings = relationship(\n \"ExecutionMapping\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n clarification_sessions = relationship(\n \"ClarificationSession\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n previews = relationship(\n \"CompiledPreview\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n run_contexts = relationship(\n \"DatasetRunContext\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n export_artifacts = relationship(\n \"ExportArtifact\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n events = relationship(\n \"SessionEvent\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n\n\n# #endregion DatasetReviewSession\n\n\n# #endregion DatasetReviewSessionModels\n" + "body": "# #region DatasetReviewSessionModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, dataset, review, session, model]\n# @BRIEF Session aggregate root and collaborator models for dataset review orchestration.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> [DatasetReviewEnums:Module]\n# @RELATION DEPENDS_ON -> [MappingModels]\n# @INVARIANT: Session and profile entities are strictly scoped to an authenticated user.\n# @PRE: Database engine initialized\n# @POST: Session ORM models registered with optimistic locking\n# @SIDE_EFFECT: Defines dataset review session tables\n# @DATA_CONTRACT: SessionData -> SessionRecord\n\nfrom datetime import datetime\nimport uuid\n\nfrom sqlalchemy import (\n Column,\n DateTime,\n Enum as SQLEnum,\n ForeignKey,\n Integer,\n String,\n)\nfrom sqlalchemy.orm import relationship\n\nfrom src.models.dataset_review_pkg._enums import (\n ReadinessState,\n RecommendedAction,\n SessionCollaboratorRole,\n SessionPhase,\n SessionStatus,\n)\nfrom src.models.mapping import Base\n\n\n# #region SessionCollaborator [C:2] [TYPE Class]\n# @BRIEF RBAC collaborator record linking a user to a dataset review session with a specific role.\n# @RELATION DEPENDS_ON -> [DatasetReviewSession]\nclass SessionCollaborator(Base):\n __tablename__ = \"session_collaborators\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n session_id = Column(\n String, ForeignKey(\"dataset_review_sessions.session_id\"), nullable=False\n )\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n role = Column(SQLEnum(SessionCollaboratorRole), nullable=False)\n added_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n\n session = relationship(\"DatasetReviewSession\", back_populates=\"collaborators\")\n user = relationship(\"User\")\n\n\n# #endregion SessionCollaborator\n\n\n# #region DatasetReviewSession [C:3] [TYPE Class]\n# @BRIEF Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.\n# @RELATION DEPENDS_ON -> [SessionCollaborator]\n# @RELATION DEPENDS_ON -> [DatasetProfile]\n# @RELATION DEPENDS_ON -> [ValidationFinding]\n# @RELATION DEPENDS_ON -> [SemanticSource]\n# @RELATION DEPENDS_ON -> [SemanticFieldEntry]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\n# @RELATION DEPENDS_ON -> [TemplateVariable]\n# @RELATION DEPENDS_ON -> [ExecutionMapping]\n# @RELATION DEPENDS_ON -> [ClarificationSession]\n# @RELATION DEPENDS_ON -> [CompiledPreview]\n# @RELATION DEPENDS_ON -> [DatasetRunContext]\n# @RELATION DEPENDS_ON -> [ExportArtifact]\n# @RELATION DEPENDS_ON -> [SessionEvent]\n# @INVARIANT: Optimistic-lock version column prevents lost-update races on concurrent mutations.\nclass DatasetReviewSession(Base):\n __tablename__ = \"dataset_review_sessions\"\n\n session_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n source_kind = Column(String, nullable=False)\n source_input = Column(String, nullable=False)\n dataset_ref = Column(String, nullable=False)\n dataset_id = Column(Integer, nullable=True)\n dashboard_id = Column(Integer, nullable=True)\n readiness_state = Column(\n SQLEnum(ReadinessState), nullable=False, default=ReadinessState.EMPTY\n )\n recommended_action = Column(\n SQLEnum(RecommendedAction),\n nullable=False,\n default=RecommendedAction.IMPORT_FROM_SUPERSET,\n )\n version = Column(Integer, nullable=False, default=0)\n __mapper_args__ = {\"version_id_col\": version, \"version_id_generator\": False}\n status = Column(\n SQLEnum(SessionStatus), nullable=False, default=SessionStatus.ACTIVE\n )\n current_phase = Column(\n SQLEnum(SessionPhase), nullable=False, default=SessionPhase.INTAKE\n )\n active_task_id = Column(String, nullable=True)\n last_preview_id = Column(String, nullable=True)\n last_run_context_id = Column(String, nullable=True)\n created_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n updated_at = Column(\n DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False\n )\n last_activity_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n closed_at = Column(DateTime, nullable=True)\n\n owner = relationship(\"User\")\n collaborators = relationship(\n \"SessionCollaborator\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n profile = relationship(\n \"DatasetProfile\",\n back_populates=\"session\",\n uselist=False,\n cascade=\"all, delete-orphan\",\n )\n findings = relationship(\n \"ValidationFinding\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_sources = relationship(\n \"SemanticSource\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_fields = relationship(\n \"SemanticFieldEntry\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n imported_filters = relationship(\n \"ImportedFilter\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n template_variables = relationship(\n \"TemplateVariable\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n execution_mappings = relationship(\n \"ExecutionMapping\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n clarification_sessions = relationship(\n \"ClarificationSession\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n previews = relationship(\n \"CompiledPreview\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n run_contexts = relationship(\n \"DatasetRunContext\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n export_artifacts = relationship(\n \"ExportArtifact\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n events = relationship(\n \"SessionEvent\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n\n\n# #endregion DatasetReviewSession\n\n\n# #endregion DatasetReviewSessionModels\n" }, { "contract_id": "SessionCollaborator", @@ -34621,7 +36437,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DatasetReviewSession [C:3] [TYPE Class]\n# @BRIEF Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.\n# @RELATION DEPENDS_ON -> [SessionCollaborator]\n# @RELATION DEPENDS_ON -> [DatasetProfile]\n# @RELATION DEPENDS_ON -> [ValidationFinding]\n# @RELATION DEPENDS_ON -> [SemanticSource]\n# @RELATION DEPENDS_ON -> [SemanticFieldEntry]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\n# @RELATION DEPENDS_ON -> [TemplateVariable]\n# @RELATION DEPENDS_ON -> [ExecutionMapping]\n# @RELATION DEPENDS_ON -> [ClarificationSession]\n# @RELATION DEPENDS_ON -> [CompiledPreview]\n# @RELATION DEPENDS_ON -> [DatasetRunContext]\n# @RELATION DEPENDS_ON -> [ExportArtifact]\n# @RELATION DEPENDS_ON -> [SessionEvent]\n# @INVARIANT: Optimistic-lock version column prevents lost-update races on concurrent mutations.\nclass DatasetReviewSession(Base):\n __tablename__ = \"dataset_review_sessions\"\n\n session_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n source_kind = Column(String, nullable=False)\n source_input = Column(String, nullable=False)\n dataset_ref = Column(String, nullable=False)\n dataset_id = Column(Integer, nullable=True)\n dashboard_id = Column(Integer, nullable=True)\n readiness_state = Column(\n SQLEnum(ReadinessState), nullable=False, default=ReadinessState.EMPTY\n )\n recommended_action = Column(\n SQLEnum(RecommendedAction),\n nullable=False,\n default=RecommendedAction.IMPORT_FROM_SUPERSET,\n )\n version = Column(Integer, nullable=False, default=0)\n __mapper_args__ = {\"version_id_col\": version, \"version_id_generator\": False}\n status = Column(\n SQLEnum(SessionStatus), nullable=False, default=SessionStatus.ACTIVE\n )\n current_phase = Column(\n SQLEnum(SessionPhase), nullable=False, default=SessionPhase.INTAKE\n )\n active_task_id = Column(String, nullable=True)\n last_preview_id = Column(String, nullable=True)\n last_run_context_id = Column(String, nullable=True)\n created_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n updated_at = Column(\n DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False\n )\n last_activity_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n closed_at = Column(DateTime, nullable=True)\n\n owner = relationship(\"User\")\n collaborators = relationship(\n \"SessionCollaborator\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n profile = relationship(\n \"DatasetProfile\",\n back_populates=\"session\",\n uselist=False,\n cascade=\"all, delete-orphan\",\n )\n findings = relationship(\n \"ValidationFinding\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_sources = relationship(\n \"SemanticSource\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_fields = relationship(\n \"SemanticFieldEntry\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n imported_filters = relationship(\n \"ImportedFilter\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n template_variables = relationship(\n \"TemplateVariable\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n execution_mappings = relationship(\n \"ExecutionMapping\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n clarification_sessions = relationship(\n \"ClarificationSession\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n previews = relationship(\n \"CompiledPreview\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n run_contexts = relationship(\n \"DatasetRunContext\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n export_artifacts = relationship(\n \"ExportArtifact\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n events = relationship(\n \"SessionEvent\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n\n\n# #endregion DatasetReviewSession\n" + "body": "# #region DatasetReviewSession [C:3] [TYPE Class]\n# @BRIEF Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.\n# @RELATION DEPENDS_ON -> [SessionCollaborator]\n# @RELATION DEPENDS_ON -> [DatasetProfile]\n# @RELATION DEPENDS_ON -> [ValidationFinding]\n# @RELATION DEPENDS_ON -> [SemanticSource]\n# @RELATION DEPENDS_ON -> [SemanticFieldEntry]\n# @RELATION DEPENDS_ON -> [ImportedFilter]\n# @RELATION DEPENDS_ON -> [TemplateVariable]\n# @RELATION DEPENDS_ON -> [ExecutionMapping]\n# @RELATION DEPENDS_ON -> [ClarificationSession]\n# @RELATION DEPENDS_ON -> [CompiledPreview]\n# @RELATION DEPENDS_ON -> [DatasetRunContext]\n# @RELATION DEPENDS_ON -> [ExportArtifact]\n# @RELATION DEPENDS_ON -> [SessionEvent]\n# @INVARIANT: Optimistic-lock version column prevents lost-update races on concurrent mutations.\nclass DatasetReviewSession(Base):\n __tablename__ = \"dataset_review_sessions\"\n\n session_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n user_id = Column(String, ForeignKey(\"users.id\"), nullable=False)\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n source_kind = Column(String, nullable=False)\n source_input = Column(String, nullable=False)\n dataset_ref = Column(String, nullable=False)\n dataset_id = Column(Integer, nullable=True)\n dashboard_id = Column(Integer, nullable=True)\n readiness_state = Column(\n SQLEnum(ReadinessState), nullable=False, default=ReadinessState.EMPTY\n )\n recommended_action = Column(\n SQLEnum(RecommendedAction),\n nullable=False,\n default=RecommendedAction.IMPORT_FROM_SUPERSET,\n )\n version = Column(Integer, nullable=False, default=0)\n __mapper_args__ = {\"version_id_col\": version, \"version_id_generator\": False}\n status = Column(\n SQLEnum(SessionStatus), nullable=False, default=SessionStatus.ACTIVE\n )\n current_phase = Column(\n SQLEnum(SessionPhase), nullable=False, default=SessionPhase.INTAKE\n )\n active_task_id = Column(String, nullable=True)\n last_preview_id = Column(String, nullable=True)\n last_run_context_id = Column(String, nullable=True)\n created_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n updated_at = Column(\n DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False\n )\n last_activity_at = Column(DateTime, default=datetime.utcnow, nullable=False)\n closed_at = Column(DateTime, nullable=True)\n\n owner = relationship(\"User\")\n collaborators = relationship(\n \"SessionCollaborator\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n profile = relationship(\n \"DatasetProfile\",\n back_populates=\"session\",\n uselist=False,\n cascade=\"all, delete-orphan\",\n )\n findings = relationship(\n \"ValidationFinding\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_sources = relationship(\n \"SemanticSource\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n semantic_fields = relationship(\n \"SemanticFieldEntry\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n imported_filters = relationship(\n \"ImportedFilter\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n template_variables = relationship(\n \"TemplateVariable\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n execution_mappings = relationship(\n \"ExecutionMapping\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n clarification_sessions = relationship(\n \"ClarificationSession\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n previews = relationship(\n \"CompiledPreview\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n run_contexts = relationship(\n \"DatasetRunContext\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n export_artifacts = relationship(\n \"ExportArtifact\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n events = relationship(\n \"SessionEvent\", back_populates=\"session\", cascade=\"all, delete-orphan\"\n )\n\n\n# #endregion DatasetReviewSession\n" }, { "contract_id": "FilterStateModels", @@ -35326,6 +37142,201 @@ "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 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": "MaintenanceModels", + "contract_type": "Module", + "file_path": "backend/src/models/maintenance.py", + "start_line": 1, + "end_line": 215, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "INVARIANT": "MaintenanceSettings is a singleton row (id='default') enforced by CheckConstraint", + "LAYER": "Domain", + "PURPOSE": "SQLAlchemy models for the Maintenance Banner feature: event, banner, dashboard state, and settings." + }, + "relations": [ + { + "source_id": "MaintenanceModels", + "relation_type": "DEPENDS_ON", + "target_id": "sqlalchemy", + "target_ref": "[sqlalchemy]" + }, + { + "source_id": "MaintenanceModels", + "relation_type": "DEPENDS_ON", + "target_id": "MappingBase", + "target_ref": "[MappingBase]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceModels [C:2] [TYPE Module] [SEMANTICS sqlalchemy, maintenance, banner, event, settings, model]\n# @BRIEF SQLAlchemy models for the Maintenance Banner feature: event, banner, dashboard state, and settings.\n# @LAYER Domain\n# @RELATION DEPENDS_ON -> [sqlalchemy]\n# @RELATION DEPENDS_ON -> [MappingBase]\n# @INVARIANT MaintenanceDashboardBanner has unique partial index on (environment_id, dashboard_id) WHERE status='active'\n# @INVARIANT MaintenanceSettings is a singleton row (id='default') enforced by CheckConstraint\n\nimport enum\nimport uuid\n\nfrom sqlalchemy import (\n CheckConstraint,\n Column,\n DateTime,\n Enum as SQLEnum,\n ForeignKey,\n Index,\n Integer,\n JSON,\n String,\n Text,\n)\nfrom sqlalchemy.orm import relationship\nfrom sqlalchemy.sql import func\n\nfrom .mapping import Base\n\n\n# #region MaintenanceEventStatus [C:1] [TYPE Class]\nclass MaintenanceEventStatus(str, enum.Enum):\n PENDING = \"pending\"\n APPLYING = \"applying\"\n ACTIVE = \"active\"\n PARTIAL = \"partial\"\n ENDING = \"ending\"\n COMPLETED = \"completed\"\n FAILED = \"failed\"\n# #endregion MaintenanceEventStatus\n\n\n# #region MaintenanceDashboardBannerStatus [C:1] [TYPE Class]\nclass MaintenanceDashboardBannerStatus(str, enum.Enum):\n ACTIVE = \"active\"\n REMOVED = \"removed\"\n# #endregion MaintenanceDashboardBannerStatus\n\n\n# #region MaintenanceDashboardStateStatus [C:1] [TYPE Class]\nclass MaintenanceDashboardStateStatus(str, enum.Enum):\n PENDING_APPLY = \"pending_apply\"\n ACTIVE = \"active\"\n REMOVING = \"removing\"\n REMOVED = \"removed\"\n APPLY_FAILED = \"apply_failed\"\n REMOVAL_FAILED = \"removal_failed\"\n# #endregion MaintenanceDashboardStateStatus\n\n\n# #region DashboardScope [C:1] [TYPE Class]\nclass DashboardScope(str, enum.Enum):\n PUBLISHED_ONLY = \"published_only\"\n DRAFT_ONLY = \"draft_only\"\n ALL = \"all\"\n# #endregion DashboardScope\n\n\n# #region MaintenanceEvent [C:1] [TYPE Class]\n# @BRIEF A record of a maintenance event with table list, time window, status, and linked dashboard states.\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardState]\nclass MaintenanceEvent(Base):\n __tablename__ = \"maintenance_events\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n task_id = Column(String, nullable=True, index=True)\n environment_id = Column(String, nullable=False)\n tables = Column(JSON, nullable=False)\n start_time = Column(DateTime(timezone=True), nullable=False)\n end_time = Column(DateTime(timezone=True), nullable=True)\n message = Column(Text, nullable=True)\n status = Column(\n SQLEnum(MaintenanceEventStatus),\n nullable=False,\n default=MaintenanceEventStatus.PENDING,\n index=True,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n dashboard_states = relationship(\n \"MaintenanceDashboardState\",\n back_populates=\"maintenance_event\",\n cascade=\"all, delete-orphan\",\n )\n# #endregion MaintenanceEvent\n\n\n# #region MaintenanceDashboardBanner [C:1] [TYPE Class]\n# @BRIEF The canonical \"one chart per dashboard\" entity. Unique partial index enforces single active banner per dashboard.\n# @INVARIANT Unique partial index (environment_id, dashboard_id) WHERE status='active'\nclass MaintenanceDashboardBanner(Base):\n __tablename__ = \"maintenance_dashboard_banners\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n environment_id = Column(String, nullable=False)\n dashboard_id = Column(Integer, nullable=False, index=True)\n chart_id = Column(Integer, nullable=True)\n banner_text = Column(Text, nullable=True)\n status = Column(\n SQLEnum(MaintenanceDashboardBannerStatus),\n nullable=False,\n default=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n dashboard_states = relationship(\n \"MaintenanceDashboardState\", back_populates=\"banner\"\n )\n\n __table_args__ = (\n Index(\n \"ix_banner_unique_active\",\n \"environment_id\",\n \"dashboard_id\",\n unique=True,\n postgresql_where=(status == \"active\"),\n ),\n )\n# #endregion MaintenanceDashboardBanner\n\n\n# #region MaintenanceDashboardState [C:1] [TYPE Class]\n# @BRIEF Links a maintenance event to a dashboard via a banner. Tracks per-dashboard-per-event lifecycle.\n# @RELATION DEPENDS_ON -> [MaintenanceEvent]\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardBanner]\nclass MaintenanceDashboardState(Base):\n __tablename__ = \"maintenance_dashboard_states\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n event_id = Column(\n String, ForeignKey(\"maintenance_events.id\"), nullable=False, index=True\n )\n dashboard_id = Column(Integer, nullable=False, index=True)\n banner_id = Column(\n String,\n ForeignKey(\"maintenance_dashboard_banners.id\"),\n nullable=True,\n )\n status = Column(\n SQLEnum(MaintenanceDashboardStateStatus),\n nullable=False,\n default=MaintenanceDashboardStateStatus.PENDING_APPLY,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n maintenance_event = relationship(\n \"MaintenanceEvent\", back_populates=\"dashboard_states\"\n )\n banner = relationship(\n \"MaintenanceDashboardBanner\", back_populates=\"dashboard_states\"\n )\n\n __table_args__ = (\n Index(\"ix_mds_dashboard_status\", \"dashboard_id\", \"status\"),\n )\n# #endregion MaintenanceDashboardState\n\n\n# #region MaintenanceSettings [C:1] [TYPE Class]\n# @BRIEF Single-row maintenance mode configuration. Enforces singleton via CheckConstraint(id='default').\n# @INVARIANT id must always be 'default' — enforced by CheckConstraint\nclass MaintenanceSettings(Base):\n __tablename__ = \"maintenance_settings\"\n\n id = Column(String, primary_key=True, default=\"default\")\n target_environment_id = Column(String, nullable=False)\n display_timezone = Column(String, nullable=False, default=\"UTC\")\n banner_template = Column(\n Text,\n nullable=False,\n default=(\n '
\\n\\n'\n \"## ⚠️ Технические работы\\n\\n\"\n \"{message}\\n\\n\"\n \"**Начало:** {start_time}\\n\"\n \"**Конец:** {end_time}\\n\\n\"\n \"*Данные могут быть неполными или временно недоступны.*\\n\\n\"\n \"
\"\n ),\n )\n dashboard_scope = Column(\n SQLEnum(DashboardScope),\n nullable=False,\n default=DashboardScope.PUBLISHED_ONLY,\n )\n excluded_dashboard_ids = Column(JSON, nullable=False, default=list)\n forced_dashboard_ids = Column(JSON, nullable=False, default=list)\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n __table_args__ = (\n CheckConstraint(\"id = 'default'\", name=\"ck_settings_singleton\"),\n )\n# #endregion MaintenanceSettings\n\n# #endregion MaintenanceModels\n" + }, + { + "contract_id": "MaintenanceEventStatus", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 30, + "end_line": 39, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEventStatus [C:1] [TYPE Class]\nclass MaintenanceEventStatus(str, enum.Enum):\n PENDING = \"pending\"\n APPLYING = \"applying\"\n ACTIVE = \"active\"\n PARTIAL = \"partial\"\n ENDING = \"ending\"\n COMPLETED = \"completed\"\n FAILED = \"failed\"\n# #endregion MaintenanceEventStatus\n" + }, + { + "contract_id": "MaintenanceDashboardBannerStatus", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 42, + "end_line": 46, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardBannerStatus [C:1] [TYPE Class]\nclass MaintenanceDashboardBannerStatus(str, enum.Enum):\n ACTIVE = \"active\"\n REMOVED = \"removed\"\n# #endregion MaintenanceDashboardBannerStatus\n" + }, + { + "contract_id": "MaintenanceDashboardStateStatus", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 49, + "end_line": 57, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardStateStatus [C:1] [TYPE Class]\nclass MaintenanceDashboardStateStatus(str, enum.Enum):\n PENDING_APPLY = \"pending_apply\"\n ACTIVE = \"active\"\n REMOVING = \"removing\"\n REMOVED = \"removed\"\n APPLY_FAILED = \"apply_failed\"\n REMOVAL_FAILED = \"removal_failed\"\n# #endregion MaintenanceDashboardStateStatus\n" + }, + { + "contract_id": "DashboardScope", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 60, + "end_line": 65, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region DashboardScope [C:1] [TYPE Class]\nclass DashboardScope(str, enum.Enum):\n PUBLISHED_ONLY = \"published_only\"\n DRAFT_ONLY = \"draft_only\"\n ALL = \"all\"\n# #endregion DashboardScope\n" + }, + { + "contract_id": "MaintenanceEvent", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 68, + "end_line": 97, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "A record of a maintenance event with table list, time window, status, and linked dashboard states." + }, + "relations": [ + { + "source_id": "MaintenanceEvent", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceDashboardState", + "target_ref": "[MaintenanceDashboardState]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceEvent [C:1] [TYPE Class]\n# @BRIEF A record of a maintenance event with table list, time window, status, and linked dashboard states.\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardState]\nclass MaintenanceEvent(Base):\n __tablename__ = \"maintenance_events\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n task_id = Column(String, nullable=True, index=True)\n environment_id = Column(String, nullable=False)\n tables = Column(JSON, nullable=False)\n start_time = Column(DateTime(timezone=True), nullable=False)\n end_time = Column(DateTime(timezone=True), nullable=True)\n message = Column(Text, nullable=True)\n status = Column(\n SQLEnum(MaintenanceEventStatus),\n nullable=False,\n default=MaintenanceEventStatus.PENDING,\n index=True,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n dashboard_states = relationship(\n \"MaintenanceDashboardState\",\n back_populates=\"maintenance_event\",\n cascade=\"all, delete-orphan\",\n )\n# #endregion MaintenanceEvent\n" + }, + { + "contract_id": "MaintenanceDashboardBanner", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 100, + "end_line": 134, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "INVARIANT": "Unique partial index (environment_id, dashboard_id) WHERE status='active'", + "PURPOSE": "The canonical \"one chart per dashboard\" entity. Unique partial index enforces single active banner per dashboard." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardBanner [C:1] [TYPE Class]\n# @BRIEF The canonical \"one chart per dashboard\" entity. Unique partial index enforces single active banner per dashboard.\n# @INVARIANT Unique partial index (environment_id, dashboard_id) WHERE status='active'\nclass MaintenanceDashboardBanner(Base):\n __tablename__ = \"maintenance_dashboard_banners\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n environment_id = Column(String, nullable=False)\n dashboard_id = Column(Integer, nullable=False, index=True)\n chart_id = Column(Integer, nullable=True)\n banner_text = Column(Text, nullable=True)\n status = Column(\n SQLEnum(MaintenanceDashboardBannerStatus),\n nullable=False,\n default=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n dashboard_states = relationship(\n \"MaintenanceDashboardState\", back_populates=\"banner\"\n )\n\n __table_args__ = (\n Index(\n \"ix_banner_unique_active\",\n \"environment_id\",\n \"dashboard_id\",\n unique=True,\n postgresql_where=(status == \"active\"),\n ),\n )\n# #endregion MaintenanceDashboardBanner\n" + }, + { + "contract_id": "MaintenanceDashboardState", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 137, + "end_line": 174, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "Links a maintenance event to a dashboard via a banner. Tracks per-dashboard-per-event lifecycle." + }, + "relations": [ + { + "source_id": "MaintenanceDashboardState", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceEvent", + "target_ref": "[MaintenanceEvent]" + }, + { + "source_id": "MaintenanceDashboardState", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceDashboardBanner", + "target_ref": "[MaintenanceDashboardBanner]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardState [C:1] [TYPE Class]\n# @BRIEF Links a maintenance event to a dashboard via a banner. Tracks per-dashboard-per-event lifecycle.\n# @RELATION DEPENDS_ON -> [MaintenanceEvent]\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardBanner]\nclass MaintenanceDashboardState(Base):\n __tablename__ = \"maintenance_dashboard_states\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), index=True)\n event_id = Column(\n String, ForeignKey(\"maintenance_events.id\"), nullable=False, index=True\n )\n dashboard_id = Column(Integer, nullable=False, index=True)\n banner_id = Column(\n String,\n ForeignKey(\"maintenance_dashboard_banners.id\"),\n nullable=True,\n )\n status = Column(\n SQLEnum(MaintenanceDashboardStateStatus),\n nullable=False,\n default=MaintenanceDashboardStateStatus.PENDING_APPLY,\n )\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n maintenance_event = relationship(\n \"MaintenanceEvent\", back_populates=\"dashboard_states\"\n )\n banner = relationship(\n \"MaintenanceDashboardBanner\", back_populates=\"dashboard_states\"\n )\n\n __table_args__ = (\n Index(\"ix_mds_dashboard_status\", \"dashboard_id\", \"status\"),\n )\n# #endregion MaintenanceDashboardState\n" + }, + { + "contract_id": "MaintenanceSettings", + "contract_type": "Class", + "file_path": "backend/src/models/maintenance.py", + "start_line": 177, + "end_line": 213, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "INVARIANT": "id must always be 'default' — enforced by CheckConstraint", + "PURPOSE": "Single-row maintenance mode configuration. Enforces singleton via CheckConstraint(id='default')." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceSettings [C:1] [TYPE Class]\n# @BRIEF Single-row maintenance mode configuration. Enforces singleton via CheckConstraint(id='default').\n# @INVARIANT id must always be 'default' — enforced by CheckConstraint\nclass MaintenanceSettings(Base):\n __tablename__ = \"maintenance_settings\"\n\n id = Column(String, primary_key=True, default=\"default\")\n target_environment_id = Column(String, nullable=False)\n display_timezone = Column(String, nullable=False, default=\"UTC\")\n banner_template = Column(\n Text,\n nullable=False,\n default=(\n '
\\n\\n'\n \"## ⚠️ Технические работы\\n\\n\"\n \"{message}\\n\\n\"\n \"**Начало:** {start_time}\\n\"\n \"**Конец:** {end_time}\\n\\n\"\n \"*Данные могут быть неполными или временно недоступны.*\\n\\n\"\n \"
\"\n ),\n )\n dashboard_scope = Column(\n SQLEnum(DashboardScope),\n nullable=False,\n default=DashboardScope.PUBLISHED_ONLY,\n )\n excluded_dashboard_ids = Column(JSON, nullable=False, default=list)\n forced_dashboard_ids = Column(JSON, nullable=False, default=list)\n updated_at = Column(\n DateTime(timezone=True), server_default=func.now(), onupdate=func.now()\n )\n\n __table_args__ = (\n CheckConstraint(\"id = 'default'\", name=\"ck_settings_singleton\"),\n )\n# #endregion MaintenanceSettings\n" + }, { "contract_id": "MappingModels", "contract_type": "Module", @@ -35351,7 +37362,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MappingModels [C:5] [TYPE Module] [SEMANTICS sqlalchemy, mapping, model, schema, resource-type]\n#\n# @BRIEF Defines the database schema for environment metadata and database mappings using SQLAlchemy.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> sqlalchemy\n\n#\n# @INVARIANT: All primary keys are UUID strings.\n# CONSTRAINT: source_env_id and target_env_id must be valid environment IDs.\n# @PRE: Database engine initialized\n# @POST: Mapping ORM models registered with UUID primary keys\n# @SIDE_EFFECT: Defines environment/database/resource mapping tables\n# @DATA_CONTRACT: MappingData -> MappingRecord\n\nimport enum\nimport uuid\n\nfrom sqlalchemy import Boolean, Column, DateTime, Enum as SQLEnum, ForeignKey, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.sql import func\n\nBase = declarative_base()\n\n# #region ResourceType [C:1] [TYPE Class]\n# @BRIEF Enumeration of possible Superset resource types for ID mapping.\nclass ResourceType(str, enum.Enum):\n CHART = \"chart\"\n DATASET = \"dataset\"\n DASHBOARD = \"dashboard\"\n# #endregion ResourceType\n\n\n# #region MigrationStatus [C:1] [TYPE Class]\n# @BRIEF Enumeration of possible migration job statuses.\nclass MigrationStatus(enum.Enum):\n PENDING = \"PENDING\"\n RUNNING = \"RUNNING\"\n COMPLETED = \"COMPLETED\"\n FAILED = \"FAILED\"\n AWAITING_MAPPING = \"AWAITING_MAPPING\"\n# #endregion MigrationStatus\n\n# #region Environment [C:3] [TYPE Class]\n# @BRIEF Represents a Superset instance environment.\n# @RELATION DEPENDS_ON -> MappingModels\nclass Environment(Base):\n __tablename__ = \"environments\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n name = Column(String, nullable=False)\n url = Column(String, nullable=False)\n credentials_id = Column(String, nullable=False)\n# #endregion Environment\n\n# #region DatabaseMapping [C:3] [TYPE Class]\n# @BRIEF Represents a mapping between source and target databases.\nclass DatabaseMapping(Base):\n __tablename__ = \"database_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n source_db_uuid = Column(String, nullable=False)\n target_db_uuid = Column(String, nullable=False)\n source_db_name = Column(String, nullable=False)\n target_db_name = Column(String, nullable=False)\n engine = Column(String, nullable=True)\n# #endregion DatabaseMapping\n\n# #region MigrationJob [C:2] [TYPE Class]\n# @BRIEF Represents a single migration execution job.\nclass MigrationJob(Base):\n __tablename__ = \"migration_jobs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n status = Column(SQLEnum(MigrationStatus), default=MigrationStatus.PENDING)\n replace_db = Column(Boolean, default=False)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n# #endregion MigrationJob\n\n# #region ResourceMapping [C:3] [TYPE Class]\n# @BRIEF Maps a universal UUID for a resource to its actual ID on a specific environment.\n# @TEST_DATA: resource_mapping_record -> {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}\n# @RELATION DEPENDS_ON -> MappingModels\nclass ResourceMapping(Base):\n __tablename__ = \"resource_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n resource_type = Column(SQLEnum(ResourceType), nullable=False)\n uuid = Column(String, nullable=False)\n remote_integer_id = Column(String, nullable=False) # Stored as string to handle potentially large or composite IDs safely, though Superset usually uses integers.\n resource_name = Column(String, nullable=True) # Used for UI display\n last_synced_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ResourceMapping\n\n# #endregion MappingModels\n" + "body": "# #region MappingModels [C:5] [TYPE Module] [SEMANTICS sqlalchemy, mapping, model, schema, resource-type]\n#\n# @BRIEF Defines the database schema for environment metadata and database mappings using SQLAlchemy.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> sqlalchemy\n\n#\n# @INVARIANT: All primary keys are UUID strings.\n# CONSTRAINT: source_env_id and target_env_id must be valid environment IDs.\n# @PRE: Database engine initialized\n# @POST: Mapping ORM models registered with UUID primary keys\n# @SIDE_EFFECT: Defines environment/database/resource mapping tables\n# @DATA_CONTRACT: MappingData -> MappingRecord\n\nimport enum\nimport uuid\n\nfrom sqlalchemy import Boolean, Column, DateTime, Enum as SQLEnum, ForeignKey, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.sql import func\n\nBase = declarative_base()\n\n# #region ResourceType [C:1] [TYPE Class]\n# @BRIEF Enumeration of possible Superset resource types for ID mapping.\nclass ResourceType(str, enum.Enum):\n CHART = \"chart\"\n DATASET = \"dataset\"\n DASHBOARD = \"dashboard\"\n# #endregion ResourceType\n\n\n# #region MigrationStatus [C:1] [TYPE Class]\n# @BRIEF Enumeration of possible migration job statuses.\nclass MigrationStatus(enum.Enum):\n PENDING = \"PENDING\"\n RUNNING = \"RUNNING\"\n COMPLETED = \"COMPLETED\"\n FAILED = \"FAILED\"\n AWAITING_MAPPING = \"AWAITING_MAPPING\"\n# #endregion MigrationStatus\n\n# #region Environment [C:3] [TYPE Class]\n# @BRIEF Represents a Superset instance environment.\n# @RELATION DEPENDS_ON -> MappingModels\nclass Environment(Base):\n __tablename__ = \"environments\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n name = Column(String, nullable=False)\n url = Column(String, nullable=False)\n credentials_id = Column(String, nullable=False)\n# #endregion Environment\n\n# #region DatabaseMapping [C:3] [TYPE Class]\n# @BRIEF Represents a mapping between source and target databases.\nclass DatabaseMapping(Base):\n __tablename__ = \"database_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n source_db_uuid = Column(String, nullable=False)\n target_db_uuid = Column(String, nullable=False)\n source_db_name = Column(String, nullable=False)\n target_db_name = Column(String, nullable=False)\n engine = Column(String, nullable=True)\n# #endregion DatabaseMapping\n\n# #region MigrationJob [C:2] [TYPE Class]\n# @BRIEF Represents a single migration execution job.\nclass MigrationJob(Base):\n __tablename__ = \"migration_jobs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n status = Column(SQLEnum(MigrationStatus), default=MigrationStatus.PENDING)\n replace_db = Column(Boolean, default=False)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n# #endregion MigrationJob\n\n# #region ResourceMapping [C:3] [TYPE Class]\n# @BRIEF Maps a universal UUID for a resource to its actual ID on a specific environment.\n# @TEST_DATA: resource_mapping_record -> {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}\n# @RELATION DEPENDS_ON -> MappingModels\nclass ResourceMapping(Base):\n __tablename__ = \"resource_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n resource_type = Column(SQLEnum(ResourceType), nullable=False)\n uuid = Column(String, nullable=False)\n remote_integer_id = Column(String, nullable=False) # Stored as string to handle potentially large or composite IDs safely, though Superset usually uses integers.\n resource_name = Column(String, nullable=True) # Used for UI display\n last_synced_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ResourceMapping\n\n# #endregion MappingModels\n" }, { "contract_id": "ResourceType", @@ -35405,7 +37416,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MigrationJob [C:2] [TYPE Class]\n# @BRIEF Represents a single migration execution job.\nclass MigrationJob(Base):\n __tablename__ = \"migration_jobs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n status = Column(SQLEnum(MigrationStatus), default=MigrationStatus.PENDING)\n replace_db = Column(Boolean, default=False)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n# #endregion MigrationJob\n" + "body": "# #region MigrationJob [C:2] [TYPE Class]\n# @BRIEF Represents a single migration execution job.\nclass MigrationJob(Base):\n __tablename__ = \"migration_jobs\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n source_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n target_env_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n status = Column(SQLEnum(MigrationStatus), default=MigrationStatus.PENDING)\n replace_db = Column(Boolean, default=False)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n# #endregion MigrationJob\n" }, { "contract_id": "ResourceMapping", @@ -35438,7 +37449,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ResourceMapping [C:3] [TYPE Class]\n# @BRIEF Maps a universal UUID for a resource to its actual ID on a specific environment.\n# @TEST_DATA: resource_mapping_record -> {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}\n# @RELATION DEPENDS_ON -> MappingModels\nclass ResourceMapping(Base):\n __tablename__ = \"resource_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=False)\n resource_type = Column(SQLEnum(ResourceType), nullable=False)\n uuid = Column(String, nullable=False)\n remote_integer_id = Column(String, nullable=False) # Stored as string to handle potentially large or composite IDs safely, though Superset usually uses integers.\n resource_name = Column(String, nullable=True) # Used for UI display\n last_synced_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ResourceMapping\n" + "body": "# #region ResourceMapping [C:3] [TYPE Class]\n# @BRIEF Maps a universal UUID for a resource to its actual ID on a specific environment.\n# @TEST_DATA: resource_mapping_record -> {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}\n# @RELATION DEPENDS_ON -> MappingModels\nclass ResourceMapping(Base):\n __tablename__ = \"resource_mappings\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"CASCADE\"), nullable=False)\n resource_type = Column(SQLEnum(ResourceType), nullable=False)\n uuid = Column(String, nullable=False)\n remote_integer_id = Column(String, nullable=False) # Stored as string to handle potentially large or composite IDs safely, though Superset usually uses integers.\n resource_name = Column(String, nullable=True) # Used for UI display\n last_synced_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())\n# #endregion ResourceMapping\n" }, { "contract_id": "ProfileModels", @@ -35830,7 +37841,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region StorageModels [TYPE Module] [SEMANTICS pydantic, storage, model, backup, config]\n# @RATIONALE Fixed typo 'repositorys' → 'repositories' in FileCategory.REPOSITORY and StorageConfig.repo_path default. Breaking change documented for existing installations.\nfrom datetime import datetime\nfrom enum import Enum\nfrom pydantic import BaseModel, Field\n\n# #region FileCategory [C:1] [TYPE Class]\n# @BRIEF Enumeration of supported file categories in the storage system.\nclass FileCategory(str, Enum):\n BACKUP = \"backups\"\n REPOSITORY = \"repositories\"\n# #endregion FileCategory\n\n# #region StorageConfig [C:1] [TYPE Class]\n# @BRIEF Configuration model for the storage system, defining paths and naming patterns.\nclass StorageConfig(BaseModel):\n root_path: str = Field(default=\"backups\", description=\"Absolute path to the storage root directory.\")\n backup_path: str = Field(default=\"backups\", description=\"Subpath for backups.\")\n repo_path: str = Field(default=\"repositories\", description=\"Subpath for repositories.\")\n backup_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for backup directory structure.\")\n repo_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for repository directory structure.\")\n filename_pattern: str = Field(default=\"{name}_{timestamp}\", description=\"Pattern for filenames.\")\n# #endregion StorageConfig\n\n# #region StoredFile [C:1] [TYPE Class]\n# @BRIEF Data model representing metadata for a file stored in the system.\nclass StoredFile(BaseModel):\n name: str = Field(..., description=\"Name of the file (including extension).\")\n path: str = Field(..., description=\"Relative path from storage root.\")\n size: int = Field(..., ge=0, description=\"Size of the file in bytes.\")\n created_at: datetime = Field(..., description=\"Creation timestamp.\")\n category: FileCategory = Field(..., description=\"Category of the file.\")\n mime_type: str | None = Field(None, description=\"MIME type of the file.\")\n# #endregion StoredFile\n# #endregion StorageModels\n" + "body": "# #region StorageModels [TYPE Module] [SEMANTICS pydantic, storage, model, backup, config]\n# @RATIONALE Fixed typo 'repositorys' → 'repositories' in FileCategory.REPOSITORY and StorageConfig.repo_path default. Breaking change documented for existing installations.\nfrom datetime import datetime\nfrom enum import Enum\nfrom pydantic import BaseModel, Field\n\n# #region FileCategory [C:1] [TYPE Class]\n# @BRIEF Enumeration of supported file categories in the storage system.\nclass FileCategory(str, Enum):\n BACKUP = \"backups\"\n REPOSITORY = \"repositories\"\n# #endregion FileCategory\n\n# #region StorageConfig [C:1] [TYPE Class]\n# @BRIEF Configuration model for the storage system, defining paths and naming patterns.\nclass StorageConfig(BaseModel):\n root_path: str = Field(default=\"/app/storage\", description=\"Absolute path to the storage root directory.\")\n backup_path: str = Field(default=\"backups\", description=\"Subpath for backups.\")\n repo_path: str = Field(default=\"repositories\", description=\"Subpath for repositories.\")\n backup_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for backup directory structure.\")\n repo_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for repository directory structure.\")\n filename_pattern: str = Field(default=\"{name}_{timestamp}\", description=\"Pattern for filenames.\")\n# #endregion StorageConfig\n\n# #region StoredFile [C:1] [TYPE Class]\n# @BRIEF Data model representing metadata for a file stored in the system.\nclass StoredFile(BaseModel):\n name: str = Field(..., description=\"Name of the file (including extension).\")\n path: str = Field(..., description=\"Relative path from storage root.\")\n size: int = Field(..., ge=0, description=\"Size of the file in bytes.\")\n created_at: datetime = Field(..., description=\"Creation timestamp.\")\n category: FileCategory = Field(..., description=\"Category of the file.\")\n mime_type: str | None = Field(None, description=\"MIME type of the file.\")\n# #endregion StoredFile\n# #endregion StorageModels\n" }, { "contract_id": "FileCategory", @@ -35866,7 +37877,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region StorageConfig [C:1] [TYPE Class]\n# @BRIEF Configuration model for the storage system, defining paths and naming patterns.\nclass StorageConfig(BaseModel):\n root_path: str = Field(default=\"backups\", description=\"Absolute path to the storage root directory.\")\n backup_path: str = Field(default=\"backups\", description=\"Subpath for backups.\")\n repo_path: str = Field(default=\"repositories\", description=\"Subpath for repositories.\")\n backup_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for backup directory structure.\")\n repo_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for repository directory structure.\")\n filename_pattern: str = Field(default=\"{name}_{timestamp}\", description=\"Pattern for filenames.\")\n# #endregion StorageConfig\n" + "body": "# #region StorageConfig [C:1] [TYPE Class]\n# @BRIEF Configuration model for the storage system, defining paths and naming patterns.\nclass StorageConfig(BaseModel):\n root_path: str = Field(default=\"/app/storage\", description=\"Absolute path to the storage root directory.\")\n backup_path: str = Field(default=\"backups\", description=\"Subpath for backups.\")\n repo_path: str = Field(default=\"repositories\", description=\"Subpath for repositories.\")\n backup_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for backup directory structure.\")\n repo_structure_pattern: str = Field(default=\"{category}/\", description=\"Pattern for repository directory structure.\")\n filename_pattern: str = Field(default=\"{name}_{timestamp}\", description=\"Pattern for filenames.\")\n# #endregion StorageConfig\n" }, { "contract_id": "StoredFile", @@ -35911,7 +37922,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TaskModels [C:1] [TYPE Module] [SEMANTICS sqlalchemy, task, model, schema, execution, task-record]\n#\n# @BRIEF Defines the database schema for task execution records.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> sqlalchemy\n#\n# @INVARIANT: All primary keys are UUID strings.\n\nimport uuid\n\nfrom sqlalchemy import JSON, Column, DateTime, ForeignKey, Index, Integer, String, Text\nfrom sqlalchemy.sql import func\n\nfrom .mapping import Base\n\n\n# #region TaskRecord [C:1] [TYPE Class]\n# @BRIEF Represents a persistent record of a task execution.\nclass TaskRecord(Base):\n __tablename__ = \"task_records\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n type = Column(String, nullable=False) # e.g., \"backup\", \"migration\"\n status = Column(String, nullable=False) # Enum: \"PENDING\", \"RUNNING\", \"SUCCESS\", \"FAILED\"\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=True)\n started_at = Column(DateTime(timezone=True), nullable=True)\n finished_at = Column(DateTime(timezone=True), nullable=True)\n logs = Column(JSON, nullable=True) # Store structured logs as JSON (legacy, kept for backward compatibility)\n error = Column(String, nullable=True)\n result = Column(JSON, nullable=True)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n params = Column(JSON, nullable=True)\n# #endregion TaskRecord\n\n# #region TaskLogRecord [C:3] [TYPE Class]\n# @BRIEF Represents a single persistent log entry for a task.\n# @RELATION DEPENDS_ON -> TaskRecord\n# @INVARIANT: Each log entry belongs to exactly one task.\n#\n# @TEST_CONTRACT: TaskLogCreate ->\n# {\n# required_fields: {\n# task_id: str,\n# timestamp: datetime,\n# level: str,\n# source: str,\n# message: str\n# },\n# optional_fields: {\n# metadata_json: str,\n# id: int\n# },\n# invariants: [\n# \"task_id matches an existing TaskRecord.id\"\n# ]\n# }\n#\n# @TEST_FIXTURE: basic_info_log ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"INFO\",\n# source: \"system\",\n# message: \"Task initialization complete\"\n# }\n#\n# @TEST_EDGE: missing_required_field ->\n# {\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"ERROR\",\n# source: \"system\",\n# message: \"Missing task_id\"\n# }\n#\n# @TEST_EDGE: invalid_type ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: 500,\n# source: \"system\",\n# message: \"Integer level\"\n# }\n#\n# @TEST_EDGE: empty_message ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"DEBUG\",\n# source: \"system\",\n# message: \"\"\n# }\n#\n# @TEST_INVARIANT: exact_one_task_association -> verifies: [basic_info_log, missing_required_field]\nclass TaskLogRecord(Base):\n __tablename__ = \"task_logs\"\n\n id = Column(Integer, primary_key=True, autoincrement=True)\n task_id = Column(String, ForeignKey(\"task_records.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n timestamp = Column(DateTime(timezone=True), nullable=False, index=True)\n level = Column(String(16), nullable=False) # INFO, WARNING, ERROR, DEBUG\n source = Column(String(64), nullable=False, default=\"system\") # plugin, superset_api, git, etc.\n message = Column(Text, nullable=False)\n metadata_json = Column(Text, nullable=True) # JSON string for additional metadata\n\n # Composite indexes for efficient filtering\n __table_args__ = (\n Index('ix_task_logs_task_timestamp', 'task_id', 'timestamp'),\n Index('ix_task_logs_task_level', 'task_id', 'level'),\n Index('ix_task_logs_task_source', 'task_id', 'source'),\n )\n# #endregion TaskLogRecord\n\n# #endregion TaskModels\n" + "body": "# #region TaskModels [C:1] [TYPE Module] [SEMANTICS sqlalchemy, task, model, schema, execution, task-record]\n#\n# @BRIEF Defines the database schema for task execution records.\n# @LAYER: Domain\n# @RELATION DEPENDS_ON -> sqlalchemy\n#\n# @INVARIANT: All primary keys are UUID strings.\n\nimport uuid\n\nfrom sqlalchemy import JSON, Column, DateTime, ForeignKey, Index, Integer, String, Text\nfrom sqlalchemy.sql import func\n\nfrom .mapping import Base\n\n\n# #region TaskRecord [C:1] [TYPE Class]\n# @BRIEF Represents a persistent record of a task execution.\nclass TaskRecord(Base):\n __tablename__ = \"task_records\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n type = Column(String, nullable=False) # e.g., \"backup\", \"migration\"\n status = Column(String, nullable=False) # Enum: \"PENDING\", \"RUNNING\", \"SUCCESS\", \"FAILED\"\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"SET NULL\"), nullable=True)\n started_at = Column(DateTime(timezone=True), nullable=True)\n finished_at = Column(DateTime(timezone=True), nullable=True)\n logs = Column(JSON, nullable=True) # Store structured logs as JSON (legacy, kept for backward compatibility)\n error = Column(String, nullable=True)\n result = Column(JSON, nullable=True)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n params = Column(JSON, nullable=True)\n# #endregion TaskRecord\n\n# #region TaskLogRecord [C:3] [TYPE Class]\n# @BRIEF Represents a single persistent log entry for a task.\n# @RELATION DEPENDS_ON -> TaskRecord\n# @INVARIANT: Each log entry belongs to exactly one task.\n#\n# @TEST_CONTRACT: TaskLogCreate ->\n# {\n# required_fields: {\n# task_id: str,\n# timestamp: datetime,\n# level: str,\n# source: str,\n# message: str\n# },\n# optional_fields: {\n# metadata_json: str,\n# id: int\n# },\n# invariants: [\n# \"task_id matches an existing TaskRecord.id\"\n# ]\n# }\n#\n# @TEST_FIXTURE: basic_info_log ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"INFO\",\n# source: \"system\",\n# message: \"Task initialization complete\"\n# }\n#\n# @TEST_EDGE: missing_required_field ->\n# {\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"ERROR\",\n# source: \"system\",\n# message: \"Missing task_id\"\n# }\n#\n# @TEST_EDGE: invalid_type ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: 500,\n# source: \"system\",\n# message: \"Integer level\"\n# }\n#\n# @TEST_EDGE: empty_message ->\n# {\n# task_id: \"00000000-0000-0000-0000-000000000000\",\n# timestamp: \"2026-02-26T12:00:00Z\",\n# level: \"DEBUG\",\n# source: \"system\",\n# message: \"\"\n# }\n#\n# @TEST_INVARIANT: exact_one_task_association -> verifies: [basic_info_log, missing_required_field]\nclass TaskLogRecord(Base):\n __tablename__ = \"task_logs\"\n\n id = Column(Integer, primary_key=True, autoincrement=True)\n task_id = Column(String, ForeignKey(\"task_records.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n timestamp = Column(DateTime(timezone=True), nullable=False, index=True)\n level = Column(String(16), nullable=False) # INFO, WARNING, ERROR, DEBUG\n source = Column(String(64), nullable=False, default=\"system\") # plugin, superset_api, git, etc.\n message = Column(Text, nullable=False)\n metadata_json = Column(Text, nullable=True) # JSON string for additional metadata\n\n # Composite indexes for efficient filtering\n __table_args__ = (\n Index('ix_task_logs_task_timestamp', 'task_id', 'timestamp'),\n Index('ix_task_logs_task_level', 'task_id', 'level'),\n Index('ix_task_logs_task_source', 'task_id', 'source'),\n )\n# #endregion TaskLogRecord\n\n# #endregion TaskModels\n" }, { "contract_id": "TaskRecord", @@ -35929,7 +37940,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TaskRecord [C:1] [TYPE Class]\n# @BRIEF Represents a persistent record of a task execution.\nclass TaskRecord(Base):\n __tablename__ = \"task_records\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n type = Column(String, nullable=False) # e.g., \"backup\", \"migration\"\n status = Column(String, nullable=False) # Enum: \"PENDING\", \"RUNNING\", \"SUCCESS\", \"FAILED\"\n environment_id = Column(String, ForeignKey(\"environments.id\"), nullable=True)\n started_at = Column(DateTime(timezone=True), nullable=True)\n finished_at = Column(DateTime(timezone=True), nullable=True)\n logs = Column(JSON, nullable=True) # Store structured logs as JSON (legacy, kept for backward compatibility)\n error = Column(String, nullable=True)\n result = Column(JSON, nullable=True)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n params = Column(JSON, nullable=True)\n# #endregion TaskRecord\n" + "body": "# #region TaskRecord [C:1] [TYPE Class]\n# @BRIEF Represents a persistent record of a task execution.\nclass TaskRecord(Base):\n __tablename__ = \"task_records\"\n\n id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))\n type = Column(String, nullable=False) # e.g., \"backup\", \"migration\"\n status = Column(String, nullable=False) # Enum: \"PENDING\", \"RUNNING\", \"SUCCESS\", \"FAILED\"\n environment_id = Column(String, ForeignKey(\"environments.id\", ondelete=\"SET NULL\"), nullable=True)\n started_at = Column(DateTime(timezone=True), nullable=True)\n finished_at = Column(DateTime(timezone=True), nullable=True)\n logs = Column(JSON, nullable=True) # Store structured logs as JSON (legacy, kept for backward compatibility)\n error = Column(String, nullable=True)\n result = Column(JSON, nullable=True)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n params = Column(JSON, nullable=True)\n# #endregion TaskRecord\n" }, { "contract_id": "TaskLogRecord", @@ -36004,7 +38015,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslateModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, translate, model, schema, dashboard, llm]\n# @BRIEF SQLAlchemy ORM models for LLM-based SQL/dashboard translation across dialects.\n# @LAYER: Domain\n# @RELATION INHERITS -> [MappingModels]\n\nfrom datetime import UTC, datetime\nimport uuid\n\nfrom sqlalchemy import JSON, Boolean, Column, DateTime, Float, ForeignKey, Index, Integer, String, Text, UniqueConstraint\nfrom sqlalchemy.orm import relationship\n\nfrom .mapping import Base\n\n\ndef generate_uuid():\n return str(uuid.uuid4())\n\n\n# #region TranslationJob [TYPE Class]\n# @BRIEF A translation job representing a multi-dialect conversion task with column mappings, LLM config, and dictionary attachments.\n# @RATIONALE: Snapshot isolation — in-progress runs use config snapshot; config edits affect future runs only.\n# @REJECTED: Invalidating in-progress runs on config edit would break scheduled run continuity.\nclass TranslationJob(Base):\n __tablename__ = \"translation_jobs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n description = Column(Text, nullable=True)\n source_dialect = Column(String, nullable=False)\n target_dialect = Column(String, nullable=False)\n database_dialect = Column(String, nullable=True, comment=\"Detected dialect from Superset connection at save time\")\n status = Column(String, nullable=False, default=\"DRAFT\") # DRAFT, READY, RUNNING, COMPLETED, FAILED, CANCELLED\n\n # Datasource & target table configuration\n source_datasource_id = Column(String, nullable=True, comment=\"Superset datasource ID\")\n source_table = Column(String, nullable=True, comment=\"Source table name resolved from datasource\")\n target_schema = Column(String, nullable=True, comment=\"Target table schema\")\n target_table = Column(String, nullable=True, comment=\"Target table name\")\n\n # Column mapping\n source_key_cols = Column(JSON, nullable=True, comment=\"Source key column names for composite key\")\n target_key_cols = Column(JSON, nullable=True, comment=\"Target key column names for composite key\")\n translation_column = Column(String, nullable=True, comment=\"Source column whose values will be translated\")\n target_column = Column(String, nullable=True, comment=\"Target column for translated output (defaults to translation_column)\")\n target_language_column = Column(String, nullable=True, comment=\"Target column for language code (e.g. 'ru', 'en')\")\n target_source_column = Column(String, nullable=True, comment=\"Target column for source/original text\")\n target_source_language_column = Column(String, nullable=True, comment=\"Target column for detected source language (BCP-47)\")\n context_columns = Column(JSON, nullable=True, comment=\"Context column names included in LLM prompt\")\n\n # LLM & processing settings\n # source_language removed — deprecated, auto-detected per row by LLM; use TranslationLanguage.source_language_detected instead\n target_languages = Column(JSON, nullable=True, comment=\"List of BCP-47 target language codes (multi-language support)\")\n provider_id = Column(String, nullable=True, comment=\"LLM provider ID\")\n batch_size = Column(Integer, nullable=False, default=50, comment=\"Records per batch\")\n disable_reasoning = Column(Boolean, default=False, comment=\"If true, pass reasoning_effort:none to LLM to save output tokens\")\n upsert_strategy = Column(String, nullable=False, default=\"MERGE\", comment=\"MERGE, INSERT, UPDATE\")\n\n # Environment association\n environment_id = Column(String, nullable=True, comment=\"Superset environment ID for datasource access\")\n target_database_id = Column(String, nullable=True, comment=\"Superset database ID for SQL Lab insert target\")\n\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationJob\n\n\n# #region TranslationRun [TYPE Class]\n# @BRIEF Represents a single execution of a translation job, capturing status, timing, and Superset execution metadata.\nclass TranslationRun(Base):\n __tablename__ = \"translation_runs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED\n trigger_type = Column(String, nullable=True, comment=\"manual, scheduled, retry, baseline_expired\")\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n error_message = Column(Text, nullable=True)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n insert_status = Column(String, nullable=True, comment=\"Status of the Superset insert/update operation\")\n superset_execution_id = Column(String, nullable=True, comment=\"Superset execution/task ID\")\n superset_execution_log = Column(JSON, nullable=True, comment=\"Superset execution log output\")\n config_snapshot = Column(JSON, nullable=True, comment=\"Snapshot of job config at run creation time\")\n key_hash = Column(String, nullable=True, comment=\"Hash of source key fields for dedup\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at run time\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n language_stats = relationship(\"TranslationRunLanguageStats\", back_populates=\"run\")\n# #endregion TranslationRun\n\n\n# #region TranslationBatch [TYPE Class]\n# @BRIEF Groups translation records within a run into manageable batches with timing and record counts.\nclass TranslationBatch(Base):\n __tablename__ = \"translation_batches\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False, index=True)\n batch_index = Column(Integer, nullable=False)\n status = Column(String, nullable=False, default=\"PENDING\")\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationBatch\n\n\n# #region TranslationRecord [TYPE Class]\n# @BRIEF Individual translation result for a single SQL statement or dashboard element, tracking source, target, and error state.\nclass TranslationRecord(Base):\n __tablename__ = \"translation_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n batch_id = Column(String, ForeignKey(\"translation_batches.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True) # query, dashboard, chart, dataset\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, SUCCESS, FAILED, SKIPPED\n error_message = Column(Text, nullable=True)\n token_count_input = Column(Integer, nullable=True)\n token_count_output = Column(Integer, nullable=True)\n translation_duration_ms = Column(Integer, nullable=True)\n source_hash = Column(String, nullable=True,\n comment=\"SHA256(source_text+context+dict_snapshot_hash+config_hash) for cache dedup — excludes key/identifier columns\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationLanguage\", back_populates=\"record\")\n\n __table_args__ = (\n Index(\"ix_translation_records_run_status\", \"run_id\", \"status\"),\n Index(\"ix_translation_records_source_hash_status\", \"source_hash\", \"status\"),\n )\n# #endregion TranslationRecord\n\n\n# #region TranslationEvent [TYPE Class]\n# @BRIEF Audit/event log for translation operations, with optional run_id for context.\nclass TranslationEvent(Base):\n __tablename__ = \"translation_events\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True, index=True)\n event_type = Column(String, nullable=False) # JOB_CREATED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, etc.\n event_data = Column(JSON, nullable=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationEvent\n\n\n# #region TranslationPreviewSession [TYPE Class]\n# @BRIEF A preview session allowing users to review proposed translations before applying them.\nclass TranslationPreviewSession(Base):\n __tablename__ = \"translation_preview_sessions\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True)\n status = Column(String, nullable=False, default=\"ACTIVE\") # ACTIVE, APPLIED, DISCARDED, EXPIRED\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n expires_at = Column(DateTime, nullable=True)\n# #endregion TranslationPreviewSession\n\n\n# #region TranslationPreviewRecord [TYPE Class]\n# @BRIEF Individual preview entry within a preview session, showing original and translated content side by side.\nclass TranslationPreviewRecord(Base):\n __tablename__ = \"translation_preview_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n session_id = Column(String, ForeignKey(\"translation_preview_sessions.id\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True)\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, APPROVED, REJECTED\n feedback = Column(Text, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationPreviewLanguage\", back_populates=\"preview_record\")\n# #endregion TranslationPreviewRecord\n\n\n# #region TerminologyDictionary [TYPE Class]\n# @BRIEF A named collection of terminology mappings used during translation to ensure consistent term translation.\nclass TerminologyDictionary(Base):\n __tablename__ = \"terminology_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n description = Column(Text, nullable=True)\n source_dialect = Column(String, nullable=False)\n target_dialect = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TerminologyDictionary\n\n\n# #region DictionaryEntry [TYPE Class]\n# @BRIEF A single term mapping entry with case-insensitive unique constraint on source_term_normalized and origin tracking.\nclass DictionaryEntry(Base):\n __tablename__ = \"dictionary_entries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\"), nullable=False, index=True)\n source_term = Column(String, nullable=False)\n source_term_normalized = Column(String, nullable=False)\n target_term = Column(String, nullable=False)\n source_language = Column(String, nullable=False, comment=\"BCP-47 source language code\")\n target_language = Column(String, nullable=False, comment=\"BCP-47 target language code\")\n context_notes = Column(Text, nullable=True)\n context_data = Column(JSON, nullable=True, comment=\"Structured context for term usage\")\n usage_notes = Column(Text, nullable=True, comment=\"Usage guidance for the term mapping\")\n has_context = Column(Boolean, default=False, comment=\"Whether context_data is populated\")\n context_source = Column(String, nullable=True, comment=\"auto|auto_with_edits|manual|bulk\")\n origin_source_language = Column(String, nullable=True, comment=\"Original source language of the term\")\n origin_run_id = Column(String, nullable=True, comment=\"Run ID from which this correction originated\")\n origin_row_key = Column(String, nullable=True, comment=\"Row key within the run that triggered this correction\")\n origin_user_id = Column(String, nullable=True, comment=\"User who submitted the correction\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"dictionary_id\", \"source_term_normalized\", \"source_language\", \"target_language\",\n name=\"uq_dict_source_term_lang\"\n ),\n Index(\"idx_dict_entry_lang\", \"source_language\", \"target_language\"),\n Index(\"idx_dict_has_context\", \"has_context\"),\n )\n# #endregion DictionaryEntry\n\n\n# #region TranslationSchedule [TYPE Class]\n# @BRIEF Defines a cron-based schedule for recurring translation jobs.\nclass TranslationSchedule(Base):\n __tablename__ = \"translation_schedules\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n cron_expression = Column(String, nullable=False)\n timezone = Column(String, nullable=False, default=\"UTC\")\n is_active = Column(Boolean, default=True)\n last_run_at = Column(DateTime, nullable=True)\n next_run_at = Column(DateTime, nullable=True)\n execution_mode = Column(String, nullable=False, default=\"full\", comment=\"full, new_key_only\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationSchedule\n\n\n# #region TranslationJobDictionary [TYPE Class]\n# @BRIEF Many-to-many association between translation jobs and terminology dictionaries.\nclass TranslationJobDictionary(Base):\n __tablename__ = \"translation_job_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\"), nullable=False, index=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"job_id\", \"dictionary_id\",\n name=\"uq_job_dictionary\"\n ),\n )\n# #endregion TranslationJobDictionary\n\n\n# #region MetricSnapshot [TYPE Class]\n# @BRIEF Captures translation performance metrics at a point in time with config/content/dictionary hash keys for aggregation.\nclass MetricSnapshot(Base):\n __tablename__ = \"translation_metric_snapshots\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True, index=True)\n key_hash = Column(String, nullable=False, comment=\"Hash of dimension key fields for aggregation\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at capture time\")\n covers_events_before = Column(DateTime, nullable=True, comment=\"Indicates snapshot covers events before this timestamp\")\n total_jobs = Column(Integer, default=0)\n total_runs = Column(Integer, default=0)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n avg_duration_ms = Column(Integer, nullable=True)\n p50_duration_ms = Column(Integer, nullable=True)\n p95_duration_ms = Column(Integer, nullable=True)\n p99_duration_ms = Column(Integer, nullable=True)\n per_language_metrics = Column(JSON, nullable=True, comment=\"Per-language cumulative metrics: {lang: {cumulative_tokens, cumulative_cost, runs}}\")\n snapshot_date = Column(DateTime, nullable=False, default=lambda: datetime.now(UTC))\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n Index(\"ix_metric_snapshots_job_date\", \"job_id\", \"snapshot_date\"),\n )\n# #endregion MetricSnapshot\n\n\n# #region TranslationLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language translation result for a single record, supporting multi-language output.\nclass TranslationLanguage(Base):\n __tablename__ = \"translation_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n record_id = Column(String, ForeignKey(\"translation_records.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und' for undetermined\")\n translated_value = Column(Text, nullable=True, comment=\"LLM-generated translation\")\n user_edit = Column(Text, nullable=True, comment=\"User-edited translation\")\n final_value = Column(Text, nullable=True, comment=\"Final resolved value (translated or user edit)\")\n status = Column(String, default=\"pending\", comment=\"pending|translated|approved|edited|rejected|failed|skipped\")\n error_message = Column(Text, nullable=True)\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n language_overridden = Column(Boolean, default=False, comment=\"Source language was manually overridden by user\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n record = relationship(\"TranslationRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"record_id\", \"language_code\", name=\"uq_record_language\"),\n Index(\"idx_tl_language\", \"language_code\"),\n Index(\"idx_tl_record_lang\", \"record_id\", \"language_code\"),\n )\n# #endregion TranslationLanguage\n\n\n# #region TranslationPreviewLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language preview entry within a preview session.\nclass TranslationPreviewLanguage(Base):\n __tablename__ = \"translation_preview_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n preview_record_id = Column(String, ForeignKey(\"translation_preview_records.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und'\")\n translated_value = Column(Text, nullable=True)\n user_edit = Column(Text, nullable=True)\n final_value = Column(Text, nullable=True)\n status = Column(String, default=\"pending\", comment=\"pending|approved|edited|rejected\")\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n preview_record = relationship(\"TranslationPreviewRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"preview_record_id\", \"language_code\", name=\"uq_preview_record_language\"),\n )\n# #endregion TranslationPreviewLanguage\n\n\n# #region TranslationRunLanguageStats [C:1] [TYPE Class]\n# @BRIEF Per-language statistics for a translation run (row counts, tokens, cost).\nclass TranslationRunLanguageStats(Base):\n __tablename__ = \"translation_run_language_stats\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n total_rows = Column(Integer, default=0)\n translated_rows = Column(Integer, default=0)\n failed_rows = Column(Integer, default=0)\n skipped_rows = Column(Integer, default=0)\n token_count = Column(Integer, default=0)\n estimated_cost = Column(Float, default=0.0)\n\n run = relationship(\"TranslationRun\", back_populates=\"language_stats\")\n\n __table_args__ = (\n UniqueConstraint(\"run_id\", \"language_code\", name=\"uq_run_language\"),\n Index(\"idx_rls_run\", \"run_id\"),\n )\n# #endregion TranslationRunLanguageStats\n\n\n# #endregion TranslateModels\n" + "body": "# #region TranslateModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, translate, model, schema, dashboard, llm]\n# @BRIEF SQLAlchemy ORM models for LLM-based SQL/dashboard translation across dialects.\n# @LAYER: Domain\n# @RELATION INHERITS -> [MappingModels]\n\nfrom datetime import UTC, datetime\nimport uuid\n\nfrom sqlalchemy import JSON, Boolean, Column, DateTime, Float, ForeignKey, Index, Integer, String, Text, UniqueConstraint\nfrom sqlalchemy.orm import relationship\n\nfrom .mapping import Base\n\n\ndef generate_uuid():\n return str(uuid.uuid4())\n\n\n# #region TranslationJob [TYPE Class]\n# @BRIEF A translation job representing a multi-dialect conversion task with column mappings, LLM config, and dictionary attachments.\n# @RATIONALE: Snapshot isolation — in-progress runs use config snapshot; config edits affect future runs only.\n# @REJECTED: Invalidating in-progress runs on config edit would break scheduled run continuity.\nclass TranslationJob(Base):\n __tablename__ = \"translation_jobs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n description = Column(Text, nullable=True)\n source_dialect = Column(String, nullable=False)\n target_dialect = Column(String, nullable=False)\n database_dialect = Column(String, nullable=True, comment=\"Detected dialect from Superset connection at save time\")\n status = Column(String, nullable=False, default=\"DRAFT\") # DRAFT, READY, RUNNING, COMPLETED, FAILED, CANCELLED\n\n # Datasource & target table configuration\n source_datasource_id = Column(String, nullable=True, comment=\"Superset datasource ID\")\n source_table = Column(String, nullable=True, comment=\"Source table name resolved from datasource\")\n target_schema = Column(String, nullable=True, comment=\"Target table schema\")\n target_table = Column(String, nullable=True, comment=\"Target table name\")\n\n # Column mapping\n source_key_cols = Column(JSON, nullable=True, comment=\"Source key column names for composite key\")\n target_key_cols = Column(JSON, nullable=True, comment=\"Target key column names for composite key\")\n translation_column = Column(String, nullable=True, comment=\"Source column whose values will be translated\")\n target_column = Column(String, nullable=True, comment=\"Target column for translated output (defaults to translation_column)\")\n target_language_column = Column(String, nullable=True, comment=\"Target column for language code (e.g. 'ru', 'en')\")\n target_source_column = Column(String, nullable=True, comment=\"Target column for source/original text\")\n target_source_language_column = Column(String, nullable=True, comment=\"Target column for detected source language (BCP-47)\")\n context_columns = Column(JSON, nullable=True, comment=\"Context column names included in LLM prompt\")\n\n # LLM & processing settings\n # source_language removed — deprecated, auto-detected per row by LLM; use TranslationLanguage.source_language_detected instead\n target_languages = Column(JSON, nullable=True, comment=\"List of BCP-47 target language codes (multi-language support)\")\n provider_id = Column(String, nullable=True, comment=\"LLM provider ID\")\n batch_size = Column(Integer, nullable=False, default=50, comment=\"Records per batch\")\n disable_reasoning = Column(Boolean, default=False, comment=\"If true, pass reasoning_effort:none to LLM to save output tokens\")\n upsert_strategy = Column(String, nullable=False, default=\"MERGE\", comment=\"MERGE, INSERT, UPDATE\")\n\n # Environment association\n environment_id = Column(String, nullable=True, comment=\"Superset environment ID for datasource access\")\n target_database_id = Column(String, nullable=True, comment=\"Superset database ID for SQL Lab insert target\")\n\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationJob\n\n\n# #region TranslationRun [TYPE Class]\n# @BRIEF Represents a single execution of a translation job, capturing status, timing, and Superset execution metadata.\nclass TranslationRun(Base):\n __tablename__ = \"translation_runs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED\n trigger_type = Column(String, nullable=True, comment=\"manual, scheduled, retry, baseline_expired\")\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n error_message = Column(Text, nullable=True)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n insert_status = Column(String, nullable=True, comment=\"Status of the Superset insert/update operation\")\n superset_execution_id = Column(String, nullable=True, comment=\"Superset execution/task ID\")\n superset_execution_log = Column(JSON, nullable=True, comment=\"Superset execution log output\")\n config_snapshot = Column(JSON, nullable=True, comment=\"Snapshot of job config at run creation time\")\n key_hash = Column(String, nullable=True, comment=\"Hash of source key fields for dedup\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at run time\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n language_stats = relationship(\"TranslationRunLanguageStats\", back_populates=\"run\")\n# #endregion TranslationRun\n\n\n# #region TranslationBatch [TYPE Class]\n# @BRIEF Groups translation records within a run into manageable batches with timing and record counts.\nclass TranslationBatch(Base):\n __tablename__ = \"translation_batches\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n batch_index = Column(Integer, nullable=False)\n status = Column(String, nullable=False, default=\"PENDING\")\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationBatch\n\n\n# #region TranslationRecord [TYPE Class]\n# @BRIEF Individual translation result for a single SQL statement or dashboard element, tracking source, target, and error state.\nclass TranslationRecord(Base):\n __tablename__ = \"translation_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n batch_id = Column(String, ForeignKey(\"translation_batches.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True) # query, dashboard, chart, dataset\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, SUCCESS, FAILED, SKIPPED\n error_message = Column(Text, nullable=True)\n token_count_input = Column(Integer, nullable=True)\n token_count_output = Column(Integer, nullable=True)\n translation_duration_ms = Column(Integer, nullable=True)\n source_hash = Column(String, nullable=True,\n comment=\"SHA256(source_text+context+dict_snapshot_hash+config_hash) for cache dedup — excludes key/identifier columns\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationLanguage\", back_populates=\"record\")\n\n __table_args__ = (\n Index(\"ix_translation_records_run_status\", \"run_id\", \"status\"),\n Index(\"ix_translation_records_source_hash_status\", \"source_hash\", \"status\"),\n )\n# #endregion TranslationRecord\n\n\n# #region TranslationEvent [TYPE Class]\n# @BRIEF Audit/event log for translation operations, with optional run_id for context.\nclass TranslationEvent(Base):\n __tablename__ = \"translation_events\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True, index=True)\n event_type = Column(String, nullable=False) # JOB_CREATED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, etc.\n event_data = Column(JSON, nullable=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationEvent\n\n\n# #region TranslationPreviewSession [TYPE Class]\n# @BRIEF A preview session allowing users to review proposed translations before applying them.\nclass TranslationPreviewSession(Base):\n __tablename__ = \"translation_preview_sessions\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True)\n status = Column(String, nullable=False, default=\"ACTIVE\") # ACTIVE, APPLIED, DISCARDED, EXPIRED\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n expires_at = Column(DateTime, nullable=True)\n# #endregion TranslationPreviewSession\n\n\n# #region TranslationPreviewRecord [TYPE Class]\n# @BRIEF Individual preview entry within a preview session, showing original and translated content side by side.\nclass TranslationPreviewRecord(Base):\n __tablename__ = \"translation_preview_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n session_id = Column(String, ForeignKey(\"translation_preview_sessions.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True)\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, APPROVED, REJECTED\n feedback = Column(Text, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationPreviewLanguage\", back_populates=\"preview_record\")\n# #endregion TranslationPreviewRecord\n\n\n# #region TerminologyDictionary [TYPE Class]\n# @BRIEF A named collection of terminology mappings used during translation to ensure consistent term translation.\nclass TerminologyDictionary(Base):\n __tablename__ = \"terminology_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n name = Column(String, nullable=False)\n description = Column(Text, nullable=True)\n source_dialect = Column(String, nullable=False)\n target_dialect = Column(String, nullable=False)\n is_active = Column(Boolean, default=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TerminologyDictionary\n\n\n# #region DictionaryEntry [TYPE Class]\n# @BRIEF A single term mapping entry with case-insensitive unique constraint on source_term_normalized and origin tracking.\nclass DictionaryEntry(Base):\n __tablename__ = \"dictionary_entries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_term = Column(String, nullable=False)\n source_term_normalized = Column(String, nullable=False)\n target_term = Column(String, nullable=False)\n source_language = Column(String, nullable=False, comment=\"BCP-47 source language code\")\n target_language = Column(String, nullable=False, comment=\"BCP-47 target language code\")\n context_notes = Column(Text, nullable=True)\n context_data = Column(JSON, nullable=True, comment=\"Structured context for term usage\")\n usage_notes = Column(Text, nullable=True, comment=\"Usage guidance for the term mapping\")\n has_context = Column(Boolean, default=False, comment=\"Whether context_data is populated\")\n context_source = Column(String, nullable=True, comment=\"auto|auto_with_edits|manual|bulk\")\n origin_source_language = Column(String, nullable=True, comment=\"Original source language of the term\")\n origin_run_id = Column(String, nullable=True, comment=\"Run ID from which this correction originated\")\n origin_row_key = Column(String, nullable=True, comment=\"Row key within the run that triggered this correction\")\n origin_user_id = Column(String, nullable=True, comment=\"User who submitted the correction\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"dictionary_id\", \"source_term_normalized\", \"source_language\", \"target_language\",\n name=\"uq_dict_source_term_lang\"\n ),\n Index(\"idx_dict_entry_lang\", \"source_language\", \"target_language\"),\n Index(\"idx_dict_has_context\", \"has_context\"),\n )\n# #endregion DictionaryEntry\n\n\n# #region TranslationSchedule [TYPE Class]\n# @BRIEF Defines a cron-based schedule for recurring translation jobs.\nclass TranslationSchedule(Base):\n __tablename__ = \"translation_schedules\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n cron_expression = Column(String, nullable=False)\n timezone = Column(String, nullable=False, default=\"UTC\")\n is_active = Column(Boolean, default=True)\n last_run_at = Column(DateTime, nullable=True)\n next_run_at = Column(DateTime, nullable=True)\n execution_mode = Column(String, nullable=False, default=\"full\", comment=\"full, new_key_only\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationSchedule\n\n\n# #region TranslationJobDictionary [TYPE Class]\n# @BRIEF Many-to-many association between translation jobs and terminology dictionaries.\nclass TranslationJobDictionary(Base):\n __tablename__ = \"translation_job_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"job_id\", \"dictionary_id\",\n name=\"uq_job_dictionary\"\n ),\n )\n# #endregion TranslationJobDictionary\n\n\n# #region MetricSnapshot [TYPE Class]\n# @BRIEF Captures translation performance metrics at a point in time with config/content/dictionary hash keys for aggregation.\nclass MetricSnapshot(Base):\n __tablename__ = \"translation_metric_snapshots\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True, index=True)\n key_hash = Column(String, nullable=False, comment=\"Hash of dimension key fields for aggregation\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at capture time\")\n covers_events_before = Column(DateTime, nullable=True, comment=\"Indicates snapshot covers events before this timestamp\")\n total_jobs = Column(Integer, default=0)\n total_runs = Column(Integer, default=0)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n avg_duration_ms = Column(Integer, nullable=True)\n p50_duration_ms = Column(Integer, nullable=True)\n p95_duration_ms = Column(Integer, nullable=True)\n p99_duration_ms = Column(Integer, nullable=True)\n per_language_metrics = Column(JSON, nullable=True, comment=\"Per-language cumulative metrics: {lang: {cumulative_tokens, cumulative_cost, runs}}\")\n snapshot_date = Column(DateTime, nullable=False, default=lambda: datetime.now(UTC))\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n Index(\"ix_metric_snapshots_job_date\", \"job_id\", \"snapshot_date\"),\n )\n# #endregion MetricSnapshot\n\n\n# #region TranslationLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language translation result for a single record, supporting multi-language output.\nclass TranslationLanguage(Base):\n __tablename__ = \"translation_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n record_id = Column(String, ForeignKey(\"translation_records.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und' for undetermined\")\n translated_value = Column(Text, nullable=True, comment=\"LLM-generated translation\")\n user_edit = Column(Text, nullable=True, comment=\"User-edited translation\")\n final_value = Column(Text, nullable=True, comment=\"Final resolved value (translated or user edit)\")\n status = Column(String, default=\"pending\", comment=\"pending|translated|approved|edited|rejected|failed|skipped\")\n error_message = Column(Text, nullable=True)\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n language_overridden = Column(Boolean, default=False, comment=\"Source language was manually overridden by user\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n record = relationship(\"TranslationRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"record_id\", \"language_code\", name=\"uq_record_language\"),\n Index(\"idx_tl_language\", \"language_code\"),\n Index(\"idx_tl_record_lang\", \"record_id\", \"language_code\"),\n )\n# #endregion TranslationLanguage\n\n\n# #region TranslationPreviewLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language preview entry within a preview session.\nclass TranslationPreviewLanguage(Base):\n __tablename__ = \"translation_preview_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n preview_record_id = Column(String, ForeignKey(\"translation_preview_records.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und'\")\n translated_value = Column(Text, nullable=True)\n user_edit = Column(Text, nullable=True)\n final_value = Column(Text, nullable=True)\n status = Column(String, default=\"pending\", comment=\"pending|approved|edited|rejected\")\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n preview_record = relationship(\"TranslationPreviewRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"preview_record_id\", \"language_code\", name=\"uq_preview_record_language\"),\n )\n# #endregion TranslationPreviewLanguage\n\n\n# #region TranslationRunLanguageStats [C:1] [TYPE Class]\n# @BRIEF Per-language statistics for a translation run (row counts, tokens, cost).\nclass TranslationRunLanguageStats(Base):\n __tablename__ = \"translation_run_language_stats\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n total_rows = Column(Integer, default=0)\n translated_rows = Column(Integer, default=0)\n failed_rows = Column(Integer, default=0)\n skipped_rows = Column(Integer, default=0)\n token_count = Column(Integer, default=0)\n estimated_cost = Column(Float, default=0.0)\n\n run = relationship(\"TranslationRun\", back_populates=\"language_stats\")\n\n __table_args__ = (\n UniqueConstraint(\"run_id\", \"language_code\", name=\"uq_run_language\"),\n Index(\"idx_rls_run\", \"run_id\"),\n )\n# #endregion TranslationRunLanguageStats\n\n\n# #endregion TranslateModels\n" }, { "contract_id": "TranslationJob", @@ -36040,7 +38051,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationRun [TYPE Class]\n# @BRIEF Represents a single execution of a translation job, capturing status, timing, and Superset execution metadata.\nclass TranslationRun(Base):\n __tablename__ = \"translation_runs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED\n trigger_type = Column(String, nullable=True, comment=\"manual, scheduled, retry, baseline_expired\")\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n error_message = Column(Text, nullable=True)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n insert_status = Column(String, nullable=True, comment=\"Status of the Superset insert/update operation\")\n superset_execution_id = Column(String, nullable=True, comment=\"Superset execution/task ID\")\n superset_execution_log = Column(JSON, nullable=True, comment=\"Superset execution log output\")\n config_snapshot = Column(JSON, nullable=True, comment=\"Snapshot of job config at run creation time\")\n key_hash = Column(String, nullable=True, comment=\"Hash of source key fields for dedup\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at run time\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n language_stats = relationship(\"TranslationRunLanguageStats\", back_populates=\"run\")\n# #endregion TranslationRun\n" + "body": "# #region TranslationRun [TYPE Class]\n# @BRIEF Represents a single execution of a translation job, capturing status, timing, and Superset execution metadata.\nclass TranslationRun(Base):\n __tablename__ = \"translation_runs\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED\n trigger_type = Column(String, nullable=True, comment=\"manual, scheduled, retry, baseline_expired\")\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n error_message = Column(Text, nullable=True)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n insert_status = Column(String, nullable=True, comment=\"Status of the Superset insert/update operation\")\n superset_execution_id = Column(String, nullable=True, comment=\"Superset execution/task ID\")\n superset_execution_log = Column(JSON, nullable=True, comment=\"Superset execution log output\")\n config_snapshot = Column(JSON, nullable=True, comment=\"Snapshot of job config at run creation time\")\n key_hash = Column(String, nullable=True, comment=\"Hash of source key fields for dedup\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at run time\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n language_stats = relationship(\"TranslationRunLanguageStats\", back_populates=\"run\")\n# #endregion TranslationRun\n" }, { "contract_id": "TranslationBatch", @@ -36057,7 +38068,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationBatch [TYPE Class]\n# @BRIEF Groups translation records within a run into manageable batches with timing and record counts.\nclass TranslationBatch(Base):\n __tablename__ = \"translation_batches\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False, index=True)\n batch_index = Column(Integer, nullable=False)\n status = Column(String, nullable=False, default=\"PENDING\")\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationBatch\n" + "body": "# #region TranslationBatch [TYPE Class]\n# @BRIEF Groups translation records within a run into manageable batches with timing and record counts.\nclass TranslationBatch(Base):\n __tablename__ = \"translation_batches\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n batch_index = Column(Integer, nullable=False)\n status = Column(String, nullable=False, default=\"PENDING\")\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n started_at = Column(DateTime, nullable=True)\n completed_at = Column(DateTime, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationBatch\n" }, { "contract_id": "TranslationRecord", @@ -36074,7 +38085,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationRecord [TYPE Class]\n# @BRIEF Individual translation result for a single SQL statement or dashboard element, tracking source, target, and error state.\nclass TranslationRecord(Base):\n __tablename__ = \"translation_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n batch_id = Column(String, ForeignKey(\"translation_batches.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True) # query, dashboard, chart, dataset\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, SUCCESS, FAILED, SKIPPED\n error_message = Column(Text, nullable=True)\n token_count_input = Column(Integer, nullable=True)\n token_count_output = Column(Integer, nullable=True)\n translation_duration_ms = Column(Integer, nullable=True)\n source_hash = Column(String, nullable=True,\n comment=\"SHA256(source_text+context+dict_snapshot_hash+config_hash) for cache dedup — excludes key/identifier columns\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationLanguage\", back_populates=\"record\")\n\n __table_args__ = (\n Index(\"ix_translation_records_run_status\", \"run_id\", \"status\"),\n Index(\"ix_translation_records_source_hash_status\", \"source_hash\", \"status\"),\n )\n# #endregion TranslationRecord\n" + "body": "# #region TranslationRecord [TYPE Class]\n# @BRIEF Individual translation result for a single SQL statement or dashboard element, tracking source, target, and error state.\nclass TranslationRecord(Base):\n __tablename__ = \"translation_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n batch_id = Column(String, ForeignKey(\"translation_batches.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True) # query, dashboard, chart, dataset\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, SUCCESS, FAILED, SKIPPED\n error_message = Column(Text, nullable=True)\n token_count_input = Column(Integer, nullable=True)\n token_count_output = Column(Integer, nullable=True)\n translation_duration_ms = Column(Integer, nullable=True)\n source_hash = Column(String, nullable=True,\n comment=\"SHA256(source_text+context+dict_snapshot_hash+config_hash) for cache dedup — excludes key/identifier columns\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationLanguage\", back_populates=\"record\")\n\n __table_args__ = (\n Index(\"ix_translation_records_run_status\", \"run_id\", \"status\"),\n Index(\"ix_translation_records_source_hash_status\", \"source_hash\", \"status\"),\n )\n# #endregion TranslationRecord\n" }, { "contract_id": "TranslationEvent", @@ -36091,7 +38102,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationEvent [TYPE Class]\n# @BRIEF Audit/event log for translation operations, with optional run_id for context.\nclass TranslationEvent(Base):\n __tablename__ = \"translation_events\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True, index=True)\n event_type = Column(String, nullable=False) # JOB_CREATED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, etc.\n event_data = Column(JSON, nullable=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationEvent\n" + "body": "# #region TranslationEvent [TYPE Class]\n# @BRIEF Audit/event log for translation operations, with optional run_id for context.\nclass TranslationEvent(Base):\n __tablename__ = \"translation_events\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True, index=True)\n event_type = Column(String, nullable=False) # JOB_CREATED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, etc.\n event_data = Column(JSON, nullable=True)\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n# #endregion TranslationEvent\n" }, { "contract_id": "TranslationPreviewSession", @@ -36108,7 +38119,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationPreviewSession [TYPE Class]\n# @BRIEF A preview session allowing users to review proposed translations before applying them.\nclass TranslationPreviewSession(Base):\n __tablename__ = \"translation_preview_sessions\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True)\n status = Column(String, nullable=False, default=\"ACTIVE\") # ACTIVE, APPLIED, DISCARDED, EXPIRED\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n expires_at = Column(DateTime, nullable=True)\n# #endregion TranslationPreviewSession\n" + "body": "# #region TranslationPreviewSession [TYPE Class]\n# @BRIEF A preview session allowing users to review proposed translations before applying them.\nclass TranslationPreviewSession(Base):\n __tablename__ = \"translation_preview_sessions\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True)\n status = Column(String, nullable=False, default=\"ACTIVE\") # ACTIVE, APPLIED, DISCARDED, EXPIRED\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n expires_at = Column(DateTime, nullable=True)\n# #endregion TranslationPreviewSession\n" }, { "contract_id": "TranslationPreviewRecord", @@ -36125,7 +38136,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationPreviewRecord [TYPE Class]\n# @BRIEF Individual preview entry within a preview session, showing original and translated content side by side.\nclass TranslationPreviewRecord(Base):\n __tablename__ = \"translation_preview_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n session_id = Column(String, ForeignKey(\"translation_preview_sessions.id\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True)\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, APPROVED, REJECTED\n feedback = Column(Text, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationPreviewLanguage\", back_populates=\"preview_record\")\n# #endregion TranslationPreviewRecord\n" + "body": "# #region TranslationPreviewRecord [TYPE Class]\n# @BRIEF Individual preview entry within a preview session, showing original and translated content side by side.\nclass TranslationPreviewRecord(Base):\n __tablename__ = \"translation_preview_records\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n session_id = Column(String, ForeignKey(\"translation_preview_sessions.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_sql = Column(Text, nullable=True)\n target_sql = Column(Text, nullable=True)\n source_object_type = Column(String, nullable=True)\n source_object_id = Column(String, nullable=True)\n source_object_name = Column(String, nullable=True)\n source_data = Column(JSON, nullable=True, comment=\"Original source row key columns for upsert matching\")\n status = Column(String, nullable=False, default=\"PENDING\") # PENDING, APPROVED, REJECTED\n feedback = Column(Text, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n languages = relationship(\"TranslationPreviewLanguage\", back_populates=\"preview_record\")\n# #endregion TranslationPreviewRecord\n" }, { "contract_id": "TerminologyDictionary", @@ -36159,7 +38170,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region DictionaryEntry [TYPE Class]\n# @BRIEF A single term mapping entry with case-insensitive unique constraint on source_term_normalized and origin tracking.\nclass DictionaryEntry(Base):\n __tablename__ = \"dictionary_entries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\"), nullable=False, index=True)\n source_term = Column(String, nullable=False)\n source_term_normalized = Column(String, nullable=False)\n target_term = Column(String, nullable=False)\n source_language = Column(String, nullable=False, comment=\"BCP-47 source language code\")\n target_language = Column(String, nullable=False, comment=\"BCP-47 target language code\")\n context_notes = Column(Text, nullable=True)\n context_data = Column(JSON, nullable=True, comment=\"Structured context for term usage\")\n usage_notes = Column(Text, nullable=True, comment=\"Usage guidance for the term mapping\")\n has_context = Column(Boolean, default=False, comment=\"Whether context_data is populated\")\n context_source = Column(String, nullable=True, comment=\"auto|auto_with_edits|manual|bulk\")\n origin_source_language = Column(String, nullable=True, comment=\"Original source language of the term\")\n origin_run_id = Column(String, nullable=True, comment=\"Run ID from which this correction originated\")\n origin_row_key = Column(String, nullable=True, comment=\"Row key within the run that triggered this correction\")\n origin_user_id = Column(String, nullable=True, comment=\"User who submitted the correction\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"dictionary_id\", \"source_term_normalized\", \"source_language\", \"target_language\",\n name=\"uq_dict_source_term_lang\"\n ),\n Index(\"idx_dict_entry_lang\", \"source_language\", \"target_language\"),\n Index(\"idx_dict_has_context\", \"has_context\"),\n )\n# #endregion DictionaryEntry\n" + "body": "# #region DictionaryEntry [TYPE Class]\n# @BRIEF A single term mapping entry with case-insensitive unique constraint on source_term_normalized and origin tracking.\nclass DictionaryEntry(Base):\n __tablename__ = \"dictionary_entries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n source_term = Column(String, nullable=False)\n source_term_normalized = Column(String, nullable=False)\n target_term = Column(String, nullable=False)\n source_language = Column(String, nullable=False, comment=\"BCP-47 source language code\")\n target_language = Column(String, nullable=False, comment=\"BCP-47 target language code\")\n context_notes = Column(Text, nullable=True)\n context_data = Column(JSON, nullable=True, comment=\"Structured context for term usage\")\n usage_notes = Column(Text, nullable=True, comment=\"Usage guidance for the term mapping\")\n has_context = Column(Boolean, default=False, comment=\"Whether context_data is populated\")\n context_source = Column(String, nullable=True, comment=\"auto|auto_with_edits|manual|bulk\")\n origin_source_language = Column(String, nullable=True, comment=\"Original source language of the term\")\n origin_run_id = Column(String, nullable=True, comment=\"Run ID from which this correction originated\")\n origin_row_key = Column(String, nullable=True, comment=\"Row key within the run that triggered this correction\")\n origin_user_id = Column(String, nullable=True, comment=\"User who submitted the correction\")\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"dictionary_id\", \"source_term_normalized\", \"source_language\", \"target_language\",\n name=\"uq_dict_source_term_lang\"\n ),\n Index(\"idx_dict_entry_lang\", \"source_language\", \"target_language\"),\n Index(\"idx_dict_has_context\", \"has_context\"),\n )\n# #endregion DictionaryEntry\n" }, { "contract_id": "TranslationSchedule", @@ -36176,7 +38187,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationSchedule [TYPE Class]\n# @BRIEF Defines a cron-based schedule for recurring translation jobs.\nclass TranslationSchedule(Base):\n __tablename__ = \"translation_schedules\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n cron_expression = Column(String, nullable=False)\n timezone = Column(String, nullable=False, default=\"UTC\")\n is_active = Column(Boolean, default=True)\n last_run_at = Column(DateTime, nullable=True)\n next_run_at = Column(DateTime, nullable=True)\n execution_mode = Column(String, nullable=False, default=\"full\", comment=\"full, new_key_only\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationSchedule\n" + "body": "# #region TranslationSchedule [TYPE Class]\n# @BRIEF Defines a cron-based schedule for recurring translation jobs.\nclass TranslationSchedule(Base):\n __tablename__ = \"translation_schedules\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n cron_expression = Column(String, nullable=False)\n timezone = Column(String, nullable=False, default=\"UTC\")\n is_active = Column(Boolean, default=True)\n last_run_at = Column(DateTime, nullable=True)\n next_run_at = Column(DateTime, nullable=True)\n execution_mode = Column(String, nullable=False, default=\"full\", comment=\"full, new_key_only\")\n created_by = Column(String, nullable=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))\n# #endregion TranslationSchedule\n" }, { "contract_id": "TranslationJobDictionary", @@ -36193,7 +38204,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationJobDictionary [TYPE Class]\n# @BRIEF Many-to-many association between translation jobs and terminology dictionaries.\nclass TranslationJobDictionary(Base):\n __tablename__ = \"translation_job_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\"), nullable=False, index=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"job_id\", \"dictionary_id\",\n name=\"uq_job_dictionary\"\n ),\n )\n# #endregion TranslationJobDictionary\n" + "body": "# #region TranslationJobDictionary [TYPE Class]\n# @BRIEF Many-to-many association between translation jobs and terminology dictionaries.\nclass TranslationJobDictionary(Base):\n __tablename__ = \"translation_job_dictionaries\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n dictionary_id = Column(String, ForeignKey(\"terminology_dictionaries.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n UniqueConstraint(\n \"job_id\", \"dictionary_id\",\n name=\"uq_job_dictionary\"\n ),\n )\n# #endregion TranslationJobDictionary\n" }, { "contract_id": "MetricSnapshot", @@ -36210,7 +38221,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region MetricSnapshot [TYPE Class]\n# @BRIEF Captures translation performance metrics at a point in time with config/content/dictionary hash keys for aggregation.\nclass MetricSnapshot(Base):\n __tablename__ = \"translation_metric_snapshots\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=True, index=True)\n key_hash = Column(String, nullable=False, comment=\"Hash of dimension key fields for aggregation\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at capture time\")\n covers_events_before = Column(DateTime, nullable=True, comment=\"Indicates snapshot covers events before this timestamp\")\n total_jobs = Column(Integer, default=0)\n total_runs = Column(Integer, default=0)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n avg_duration_ms = Column(Integer, nullable=True)\n p50_duration_ms = Column(Integer, nullable=True)\n p95_duration_ms = Column(Integer, nullable=True)\n p99_duration_ms = Column(Integer, nullable=True)\n per_language_metrics = Column(JSON, nullable=True, comment=\"Per-language cumulative metrics: {lang: {cumulative_tokens, cumulative_cost, runs}}\")\n snapshot_date = Column(DateTime, nullable=False, default=lambda: datetime.now(UTC))\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n Index(\"ix_metric_snapshots_job_date\", \"job_id\", \"snapshot_date\"),\n )\n# #endregion MetricSnapshot\n" + "body": "# #region MetricSnapshot [TYPE Class]\n# @BRIEF Captures translation performance metrics at a point in time with config/content/dictionary hash keys for aggregation.\nclass MetricSnapshot(Base):\n __tablename__ = \"translation_metric_snapshots\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n job_id = Column(String, ForeignKey(\"translation_jobs.id\", ondelete=\"CASCADE\"), nullable=False, index=True)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"SET NULL\"), nullable=True, index=True)\n key_hash = Column(String, nullable=False, comment=\"Hash of dimension key fields for aggregation\")\n config_hash = Column(String, nullable=True, comment=\"Hash of translation configuration state\")\n dict_snapshot_hash = Column(String, nullable=True, comment=\"Hash of dictionary state at capture time\")\n covers_events_before = Column(DateTime, nullable=True, comment=\"Indicates snapshot covers events before this timestamp\")\n total_jobs = Column(Integer, default=0)\n total_runs = Column(Integer, default=0)\n total_records = Column(Integer, default=0)\n successful_records = Column(Integer, default=0)\n failed_records = Column(Integer, default=0)\n skipped_records = Column(Integer, default=0)\n avg_duration_ms = Column(Integer, nullable=True)\n p50_duration_ms = Column(Integer, nullable=True)\n p95_duration_ms = Column(Integer, nullable=True)\n p99_duration_ms = Column(Integer, nullable=True)\n per_language_metrics = Column(JSON, nullable=True, comment=\"Per-language cumulative metrics: {lang: {cumulative_tokens, cumulative_cost, runs}}\")\n snapshot_date = Column(DateTime, nullable=False, default=lambda: datetime.now(UTC))\n created_at = Column(DateTime, default=lambda: datetime.now(UTC))\n\n __table_args__ = (\n Index(\"ix_metric_snapshots_job_date\", \"job_id\", \"snapshot_date\"),\n )\n# #endregion MetricSnapshot\n" }, { "contract_id": "TranslationLanguage", @@ -36228,7 +38239,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language translation result for a single record, supporting multi-language output.\nclass TranslationLanguage(Base):\n __tablename__ = \"translation_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n record_id = Column(String, ForeignKey(\"translation_records.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und' for undetermined\")\n translated_value = Column(Text, nullable=True, comment=\"LLM-generated translation\")\n user_edit = Column(Text, nullable=True, comment=\"User-edited translation\")\n final_value = Column(Text, nullable=True, comment=\"Final resolved value (translated or user edit)\")\n status = Column(String, default=\"pending\", comment=\"pending|translated|approved|edited|rejected|failed|skipped\")\n error_message = Column(Text, nullable=True)\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n language_overridden = Column(Boolean, default=False, comment=\"Source language was manually overridden by user\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n record = relationship(\"TranslationRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"record_id\", \"language_code\", name=\"uq_record_language\"),\n Index(\"idx_tl_language\", \"language_code\"),\n Index(\"idx_tl_record_lang\", \"record_id\", \"language_code\"),\n )\n# #endregion TranslationLanguage\n" + "body": "# #region TranslationLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language translation result for a single record, supporting multi-language output.\nclass TranslationLanguage(Base):\n __tablename__ = \"translation_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n record_id = Column(String, ForeignKey(\"translation_records.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und' for undetermined\")\n translated_value = Column(Text, nullable=True, comment=\"LLM-generated translation\")\n user_edit = Column(Text, nullable=True, comment=\"User-edited translation\")\n final_value = Column(Text, nullable=True, comment=\"Final resolved value (translated or user edit)\")\n status = Column(String, default=\"pending\", comment=\"pending|translated|approved|edited|rejected|failed|skipped\")\n error_message = Column(Text, nullable=True)\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n language_overridden = Column(Boolean, default=False, comment=\"Source language was manually overridden by user\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n record = relationship(\"TranslationRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"record_id\", \"language_code\", name=\"uq_record_language\"),\n Index(\"idx_tl_language\", \"language_code\"),\n Index(\"idx_tl_record_lang\", \"record_id\", \"language_code\"),\n )\n# #endregion TranslationLanguage\n" }, { "contract_id": "TranslationPreviewLanguage", @@ -36246,7 +38257,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationPreviewLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language preview entry within a preview session.\nclass TranslationPreviewLanguage(Base):\n __tablename__ = \"translation_preview_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n preview_record_id = Column(String, ForeignKey(\"translation_preview_records.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und'\")\n translated_value = Column(Text, nullable=True)\n user_edit = Column(Text, nullable=True)\n final_value = Column(Text, nullable=True)\n status = Column(String, default=\"pending\", comment=\"pending|approved|edited|rejected\")\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n preview_record = relationship(\"TranslationPreviewRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"preview_record_id\", \"language_code\", name=\"uq_preview_record_language\"),\n )\n# #endregion TranslationPreviewLanguage\n" + "body": "# #region TranslationPreviewLanguage [C:1] [TYPE Class]\n# @BRIEF Per-language preview entry within a preview session.\nclass TranslationPreviewLanguage(Base):\n __tablename__ = \"translation_preview_languages\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n preview_record_id = Column(String, ForeignKey(\"translation_preview_records.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n source_language_detected = Column(String, nullable=True, comment=\"BCP-47 or 'und'\")\n translated_value = Column(Text, nullable=True)\n user_edit = Column(Text, nullable=True)\n final_value = Column(Text, nullable=True)\n status = Column(String, default=\"pending\", comment=\"pending|approved|edited|rejected\")\n needs_review = Column(Boolean, default=False, comment=\"Flagged because source language could not be determined\")\n created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))\n\n preview_record = relationship(\"TranslationPreviewRecord\", back_populates=\"languages\")\n\n __table_args__ = (\n UniqueConstraint(\"preview_record_id\", \"language_code\", name=\"uq_preview_record_language\"),\n )\n# #endregion TranslationPreviewLanguage\n" }, { "contract_id": "TranslationRunLanguageStats", @@ -36264,7 +38275,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TranslationRunLanguageStats [C:1] [TYPE Class]\n# @BRIEF Per-language statistics for a translation run (row counts, tokens, cost).\nclass TranslationRunLanguageStats(Base):\n __tablename__ = \"translation_run_language_stats\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n total_rows = Column(Integer, default=0)\n translated_rows = Column(Integer, default=0)\n failed_rows = Column(Integer, default=0)\n skipped_rows = Column(Integer, default=0)\n token_count = Column(Integer, default=0)\n estimated_cost = Column(Float, default=0.0)\n\n run = relationship(\"TranslationRun\", back_populates=\"language_stats\")\n\n __table_args__ = (\n UniqueConstraint(\"run_id\", \"language_code\", name=\"uq_run_language\"),\n Index(\"idx_rls_run\", \"run_id\"),\n )\n# #endregion TranslationRunLanguageStats\n" + "body": "# #region TranslationRunLanguageStats [C:1] [TYPE Class]\n# @BRIEF Per-language statistics for a translation run (row counts, tokens, cost).\nclass TranslationRunLanguageStats(Base):\n __tablename__ = \"translation_run_language_stats\"\n\n id = Column(String, primary_key=True, default=generate_uuid)\n run_id = Column(String, ForeignKey(\"translation_runs.id\", ondelete=\"CASCADE\"), nullable=False)\n language_code = Column(String, nullable=False, comment=\"BCP-47 language code\")\n total_rows = Column(Integer, default=0)\n translated_rows = Column(Integer, default=0)\n failed_rows = Column(Integer, default=0)\n skipped_rows = Column(Integer, default=0)\n token_count = Column(Integer, default=0)\n estimated_cost = Column(Float, default=0.0)\n\n run = relationship(\"TranslationRun\", back_populates=\"language_stats\")\n\n __table_args__ = (\n UniqueConstraint(\"run_id\", \"language_code\", name=\"uq_run_language\"),\n Index(\"idx_rls_run\", \"run_id\"),\n )\n# #endregion TranslationRunLanguageStats\n" }, { "contract_id": "src.plugins", @@ -36533,7 +38544,7 @@ "contract_type": "Module", "file_path": "backend/src/plugins/git_plugin.py", "start_line": 1, - "end_line": 368, + "end_line": 358, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -36604,14 +38615,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region GitPluginModule [C:4] [TYPE Module] [SEMANTICS git, versioning, deploy, sync, superset, backup, transactional]\n#\n# @BRIEF Предоставляет плагин для версионирования и развертывания дашбордов Superset.\n# @LAYER: Plugin\n# @RELATION INHERITS_FROM -> src.core.plugin_base.PluginBase\n# @RELATION USES -> src.services.git_service.GitService\n# @RELATION USES -> src.core.superset_client.SupersetClient\n# @RELATION USES -> src.core.config_manager.ConfigManager\n# @RELATION USES -> TaskContext\n#\n# @INVARIANT: Все операции с Git должны выполняться через GitService.\n# @CONSTRAINT: Плагин работает только с распакованными YAML-экспортами Superset.\n# @INVARIANT: _handle_sync сохраняет backup управляемых директорий перед удалением;\n# при ошибке распаковки backup восстанавливается.\n\nimport io\nimport os\nfrom pathlib import Path\nimport shutil\nimport time\nfrom typing import Any\nimport zipfile\n\nfrom src.core.config_manager import ConfigManager\nfrom src.core.logger import belief_scope, logger as app_logger\nfrom src.core.plugin_base import PluginBase\nfrom src.core.superset_client import SupersetClient\nfrom src.core.task_manager.context import TaskContext\nfrom src.services.git_service import GitService\n\n\n# #region GitPlugin [TYPE Class]\n# @BRIEF Реализация плагина Git Integration для управления версиями дашбордов.\nclass GitPlugin(PluginBase):\n\n # region __init__ [TYPE Function]\n # @PURPOSE: Инициализирует плагин и его зависимости.\n # @PRE: config.json exists or shared config_manager is available.\n # @POST: Инициализированы git_service и config_manager.\n def __init__(self):\n with belief_scope(\"GitPlugin.__init__\"):\n app_logger.info(\"Initializing GitPlugin.\")\n self.git_service = GitService()\n\n # Robust config path resolution:\n # 1. Try absolute path from src/dependencies.py style if possible\n # 2. Try relative paths based on common execution patterns\n if os.path.exists(\"../config.json\"):\n config_path = \"../config.json\"\n elif os.path.exists(\"config.json\"):\n config_path = \"config.json\"\n else:\n # Fallback to the one initialized in dependencies if we can import it\n try:\n from src.dependencies import config_manager\n self.config_manager = config_manager\n app_logger.info(\"GitPlugin initialized using shared config_manager.\")\n return\n except Exception:\n config_path = \"config.json\"\n\n self.config_manager = ConfigManager(config_path)\n app_logger.info(f\"GitPlugin initialized with {config_path}\")\n # endregion __init__\n\n @property\n # region id [C:1] [TYPE Function]\n def id(self) -> str:\n return \"git-integration\"\n # endregion id\n\n @property\n # region name [C:1] [TYPE Function]\n def name(self) -> str:\n return \"Git Integration\"\n # endregion name\n\n @property\n # region description [C:1] [TYPE Function]\n def description(self) -> str:\n return \"Version control for Superset dashboards\"\n # endregion description\n\n @property\n # region version [C:1] [TYPE Function]\n def version(self) -> str:\n return \"0.1.0\"\n # endregion version\n\n @property\n # region ui_route [C:1] [TYPE Function]\n def ui_route(self) -> str:\n return \"/git\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Возвращает JSON-схему параметров для выполнения задач плагина.\n # @PRE: GitPlugin is initialized.\n # @POST: Returns a JSON schema dictionary.\n # @RETURN: Dict[str, Any] - Схема параметров.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"operation\": {\"type\": \"string\", \"enum\": [\"sync\", \"deploy\", \"history\"]},\n \"dashboard_id\": {\"type\": \"integer\"},\n \"environment_id\": {\"type\": \"string\"},\n \"source_env_id\": {\"type\": \"string\"}\n },\n \"required\": [\"operation\", \"dashboard_id\"]\n }\n # endregion get_schema\n\n # region initialize [C:1] [TYPE Function]\n async def initialize(self):\n app_logger.reason(\"Initializing Git Integration Plugin logic.\", extra={\"src\": \"GitPlugin.initialize\"})\n # endregion initialize\n\n # region execute [C:3] [TYPE Function]\n # @PURPOSE: Main task executor with TaskContext support.\n # @RELATION: CALLS -> self._handle_sync\n # @RELATION: CALLS -> self._handle_deploy\n async def execute(self, task_data: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.execute\"):\n operation = task_data.get(\"operation\")\n dashboard_id = task_data.get(\"dashboard_id\")\n\n # Use TaskContext logger if available, otherwise fall back to app_logger\n log = context.logger if context else app_logger\n\n # Create sub-loggers for different components\n git_log = log.with_source(\"git\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing operation: {operation} for dashboard {dashboard_id}\")\n\n if operation == \"sync\":\n source_env_id = task_data.get(\"source_env_id\")\n result = await self._handle_sync(dashboard_id, source_env_id, log, git_log, superset_log)\n elif operation == \"deploy\":\n env_id = task_data.get(\"environment_id\")\n result = await self._handle_deploy(dashboard_id, env_id, log, git_log, superset_log)\n elif operation == \"history\":\n result = {\"status\": \"success\", \"message\": \"History available via API\"}\n else:\n log.error(f\"Unknown operation: {operation}\")\n raise ValueError(f\"Unknown operation: {operation}\")\n\n log.info(f\"Operation {operation} completed.\")\n return result\n # endregion execute\n\n # region _handle_sync [C:4] [TYPE Function] [SEMANTICS git,sync,backup,transactional]\n # @PURPOSE: Экспортирует дашборд из Superset и распаковывает в Git-репозиторий с backup/restore.\n # @PRE: Репозиторий для дашборда должен существовать.\n # @POST: Файлы в репозитории обновлены до текущего состояния в Superset.\n # Управляемые директории backup-ируются перед удалением; при ошибке распаковки backup восстанавливается.\n # @SIDE_EFFECT: Изменяет файлы в локальной рабочей директории репозитория.\n # Создаёт временный backup в /tmp/ss-tools-backup-{dashboard_id}-{timestamp}/.\n # @RETURN: Dict[str, str] - Результат синхронизации.\n # @RELATION: CALLS -> src.services.git_service.GitService.get_repo\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.export_dashboard\n async def _handle_sync(self, dashboard_id: int, source_env_id: str | None = None, log=None, git_log=None, superset_log=None) -> dict[str, str]:\n with belief_scope(\"GitPlugin._handle_sync\"):\n try:\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Target repo path: {repo_path}\")\n\n env = self._get_env(source_env_id)\n client = SupersetClient(env)\n client.authenticate()\n\n superset_log.info(f\"Exporting dashboard {dashboard_id} from {env.name}\")\n zip_bytes, _ = client.export_dashboard(dashboard_id)\n\n git_log.info(f\"Unpacking export to {repo_path}\")\n\n managed_dirs = [\"dashboards\", \"charts\", \"datasets\", \"databases\"]\n managed_files = [\"metadata.yaml\"]\n\n # Fix 1: Create backup before deleting managed files\n backup_dir = Path(f\"/tmp/ss-tools-backup-{dashboard_id}-{time.time_ns()}\")\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.copytree(d_path, backup_dir / d)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n (backup_dir / f).parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(f_path, backup_dir / f)\n\n # Delete old managed files\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.rmtree(d_path)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n f_path.unlink()\n\n try:\n with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:\n namelist = zf.namelist()\n if not namelist:\n raise ValueError(\"Export ZIP is empty\")\n root_folder = namelist[0].split('/')[0]\n git_log.info(f\"Detected root folder in ZIP: {root_folder}\")\n for member in zf.infolist():\n if member.filename.startswith(root_folder + \"/\") and len(member.filename) > len(root_folder) + 1:\n relative_path = member.filename[len(root_folder)+1:]\n target_path = repo_path / relative_path\n if member.is_dir():\n target_path.mkdir(parents=True, exist_ok=True)\n else:\n target_path.parent.mkdir(parents=True, exist_ok=True)\n with zf.open(member) as source, open(target_path, \"wb\") as target:\n shutil.copyfileobj(source, target)\n except Exception:\n # Fix 1: Restore backup on unzip failure\n if backup_dir.exists():\n for d in managed_dirs:\n src = backup_dir / d\n if src.exists():\n dst = repo_path / d\n if dst.exists():\n shutil.rmtree(dst)\n shutil.copytree(src, dst)\n for f in managed_files:\n src = backup_dir / f\n if src.exists():\n dst = repo_path / f\n dst.parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(src, dst)\n raise\n\n # Fix 1: Remove backup on success\n if backup_dir.exists():\n shutil.rmtree(backup_dir, ignore_errors=True)\n\n try:\n repo.git.add(A=True)\n app_logger.reason(\"Changes staged in git\", extra={\"src\": \"_handle_sync\"})\n except Exception as ge:\n app_logger.explore(f\"Failed to stage changes: {ge}\", extra={\"src\": \"_handle_sync\"})\n\n app_logger.info(f\"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.\")\n return {\"status\": \"success\", \"message\": \"Dashboard synced and flattened in local repository\"}\n\n except Exception as e:\n app_logger.error(f\"[_handle_sync][Coherence:Failed] Sync failed: {e}\")\n raise\n # endregion _handle_sync\n\n # region _handle_deploy [C:4] [TYPE Function] [SEMANTICS git,deploy,zip]\n # @PURPOSE: Packages repository into ZIP and imports into target Superset environment.\n # @POST: Dashboard imported into target Superset.\n # @SIDE_EFFECT: Creates and removes temporary ZIP file.\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.import_dashboard\n async def _handle_deploy(self, dashboard_id: int, env_id: str, log=None, git_log=None, superset_log=None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin._handle_deploy\"):\n try:\n if not env_id:\n raise ValueError(\"Target environment ID required for deployment\")\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Packing repository {repo_path} for deployment.\")\n zip_buffer = io.BytesIO()\n root_dir_name = f\"dashboard_export_{dashboard_id}\"\n with zipfile.ZipFile(zip_buffer, \"w\", zipfile.ZIP_DEFLATED) as zf:\n for root, dirs, files in os.walk(repo_path):\n if \".git\" in dirs:\n dirs.remove(\".git\")\n for file in files:\n if file == \".git\" or file.endswith(\".zip\"):\n continue\n file_path = Path(root) / file\n arcname = Path(root_dir_name) / file_path.relative_to(repo_path)\n zf.write(file_path, arcname)\n zip_buffer.seek(0)\n env = self.config_manager.get_environment(env_id)\n if not env:\n raise ValueError(f\"Environment {env_id} not found\")\n client = SupersetClient(env)\n client.authenticate()\n temp_zip_path = repo_path / f\"deploy_{dashboard_id}.zip\"\n git_log.info(f\"Saving temporary zip to {temp_zip_path}\")\n with open(temp_zip_path, \"wb\") as f:\n f.write(zip_buffer.getvalue())\n\n try:\n app_logger.reason(f\"Importing dashboard to {env.name}\", extra={\"src\": \"_handle_deploy\"})\n result = client.import_dashboard(temp_zip_path)\n app_logger.info(f\"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.\")\n return {\"status\": \"success\", \"message\": f\"Dashboard deployed to {env.name}\", \"details\": result}\n finally:\n if temp_zip_path.exists():\n os.remove(temp_zip_path)\n\n except Exception as e:\n app_logger.error(f\"[_handle_deploy][Coherence:Failed] Deployment failed: {e}\")\n raise\n # endregion _handle_deploy\n\n # region _get_env [C:4] [TYPE Function] [SEMANTICS env,config,strict]\n # @PURPOSE: Вспомогательный метод для получения конфигурации окружения.\n # @PARAM: env_id (Optional[str]) - ID окружения.\n # @PRE: env_id is a string or None.\n # @POST: Returns an Environment object from config or DB.\n # When env_id is explicitly provided and not found, raises ValueError (no fallback).\n # @RETURN: Environment - Объект конфигурации окружения.\n def _get_env(self, env_id: str | None = None):\n with belief_scope(\"GitPlugin._get_env\"):\n app_logger.reason(f\"Fetching environment for ID: {env_id}\", extra={\"src\": \"_get_env\"})\n\n # Priority 1: ConfigManager (config.json)\n if env_id:\n env = self.config_manager.get_environment(env_id)\n if env:\n app_logger.reflect(f\"Found environment by ID in ConfigManager: {env.name}\", extra={\"src\": \"_get_env\"})\n return env\n\n # Priority 2: Database (DeploymentEnvironment)\n from src.core.database import SessionLocal\n from src.models.git import DeploymentEnvironment\n\n db = SessionLocal()\n try:\n if env_id:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.id == env_id).first()\n else:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.is_active).first()\n if not db_env:\n db_env = db.query(DeploymentEnvironment).first()\n\n if db_env:\n app_logger.reflect(f\"Found environment in DB: {db_env.name}\", extra={\"src\": \"_get_env\"})\n from src.core.config_models import Environment\n return Environment(\n id=db_env.id,\n name=db_env.name,\n url=db_env.superset_url,\n username=\"admin\",\n password=db_env.superset_token,\n verify_ssl=True\n )\n\n # Fix 7: Strict check — if env_id was explicitly provided but not found, raise immediately\n if env_id:\n raise ValueError(f\"Environment '{env_id}' not found in ConfigManager or database\")\n finally:\n db.close()\n\n # Priority 3: fallback to first env only when no specific env_id was requested\n envs = self.config_manager.get_environments()\n if envs and not env_id:\n app_logger.reflect(f\"Using first environment from ConfigManager: {envs[0].name}\", extra={\"src\": \"_get_env\"})\n return envs[0]\n\n app_logger.error(f\"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}\")\n raise ValueError(\"No environments configured. Please add a Superset Environment in Settings.\")\n # endregion _get_env\n\n# #endregion GitPlugin\n# #endregion GitPluginModule\n" + "body": "# #region GitPluginModule [C:4] [TYPE Module] [SEMANTICS git, versioning, deploy, sync, superset, backup, transactional]\n#\n# @BRIEF Предоставляет плагин для версионирования и развертывания дашбордов Superset.\n# @LAYER: Plugin\n# @RELATION INHERITS_FROM -> src.core.plugin_base.PluginBase\n# @RELATION USES -> src.services.git_service.GitService\n# @RELATION USES -> src.core.superset_client.SupersetClient\n# @RELATION USES -> src.core.config_manager.ConfigManager\n# @RELATION USES -> TaskContext\n#\n# @INVARIANT: Все операции с Git должны выполняться через GitService.\n# @CONSTRAINT: Плагин работает только с распакованными YAML-экспортами Superset.\n# @INVARIANT: _handle_sync сохраняет backup управляемых директорий перед удалением;\n# при ошибке распаковки backup восстанавливается.\n\nimport io\nimport os\nfrom pathlib import Path\nimport shutil\nimport time\nfrom typing import Any\nimport zipfile\n\nfrom src.core.config_manager import ConfigManager\nfrom src.core.logger import belief_scope, logger as app_logger\nfrom src.core.plugin_base import PluginBase\nfrom src.core.superset_client import SupersetClient\nfrom src.core.task_manager.context import TaskContext\nfrom src.services.git_service import GitService\n\n\n# #region GitPlugin [TYPE Class]\n# @BRIEF Реализация плагина Git Integration для управления версиями дашбордов.\nclass GitPlugin(PluginBase):\n\n # region __init__ [TYPE Function]\n # @PURPOSE: Инициализирует плагин и его зависимости.\n # @PRE: shared config_manager доступен через src.dependencies.\n # @POST: Инициализированы git_service и config_manager.\n def __init__(self):\n with belief_scope(\"GitPlugin.__init__\"):\n app_logger.info(\"Initializing GitPlugin.\")\n self.git_service = GitService()\n\n # Используем shared config_manager из dependencies\n try:\n from src.dependencies import config_manager\n self.config_manager = config_manager\n app_logger.info(\"GitPlugin initialized using shared config_manager.\")\n except Exception as exc:\n app_logger.error(f\"GitPlugin: failed to get shared config_manager: {exc}\")\n self.config_manager = ConfigManager()\n app_logger.info(\"GitPlugin initialized with fallback ConfigManager.\")\n # endregion __init__\n\n @property\n # region id [C:1] [TYPE Function]\n def id(self) -> str:\n return \"git-integration\"\n # endregion id\n\n @property\n # region name [C:1] [TYPE Function]\n def name(self) -> str:\n return \"Git Integration\"\n # endregion name\n\n @property\n # region description [C:1] [TYPE Function]\n def description(self) -> str:\n return \"Version control for Superset dashboards\"\n # endregion description\n\n @property\n # region version [C:1] [TYPE Function]\n def version(self) -> str:\n return \"0.1.0\"\n # endregion version\n\n @property\n # region ui_route [C:1] [TYPE Function]\n def ui_route(self) -> str:\n return \"/git\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Возвращает JSON-схему параметров для выполнения задач плагина.\n # @PRE: GitPlugin is initialized.\n # @POST: Returns a JSON schema dictionary.\n # @RETURN: Dict[str, Any] - Схема параметров.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"operation\": {\"type\": \"string\", \"enum\": [\"sync\", \"deploy\", \"history\"]},\n \"dashboard_id\": {\"type\": \"integer\"},\n \"environment_id\": {\"type\": \"string\"},\n \"source_env_id\": {\"type\": \"string\"}\n },\n \"required\": [\"operation\", \"dashboard_id\"]\n }\n # endregion get_schema\n\n # region initialize [C:1] [TYPE Function]\n async def initialize(self):\n app_logger.reason(\"Initializing Git Integration Plugin logic.\", extra={\"src\": \"GitPlugin.initialize\"})\n # endregion initialize\n\n # region execute [C:3] [TYPE Function]\n # @PURPOSE: Main task executor with TaskContext support.\n # @RELATION: CALLS -> self._handle_sync\n # @RELATION: CALLS -> self._handle_deploy\n async def execute(self, task_data: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.execute\"):\n operation = task_data.get(\"operation\")\n dashboard_id = task_data.get(\"dashboard_id\")\n\n # Use TaskContext logger if available, otherwise fall back to app_logger\n log = context.logger if context else app_logger\n\n # Create sub-loggers for different components\n git_log = log.with_source(\"git\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing operation: {operation} for dashboard {dashboard_id}\")\n\n if operation == \"sync\":\n source_env_id = task_data.get(\"source_env_id\")\n result = await self._handle_sync(dashboard_id, source_env_id, log, git_log, superset_log)\n elif operation == \"deploy\":\n env_id = task_data.get(\"environment_id\")\n result = await self._handle_deploy(dashboard_id, env_id, log, git_log, superset_log)\n elif operation == \"history\":\n result = {\"status\": \"success\", \"message\": \"History available via API\"}\n else:\n log.error(f\"Unknown operation: {operation}\")\n raise ValueError(f\"Unknown operation: {operation}\")\n\n log.info(f\"Operation {operation} completed.\")\n return result\n # endregion execute\n\n # region _handle_sync [C:4] [TYPE Function] [SEMANTICS git,sync,backup,transactional]\n # @PURPOSE: Экспортирует дашборд из Superset и распаковывает в Git-репозиторий с backup/restore.\n # @PRE: Репозиторий для дашборда должен существовать.\n # @POST: Файлы в репозитории обновлены до текущего состояния в Superset.\n # Управляемые директории backup-ируются перед удалением; при ошибке распаковки backup восстанавливается.\n # @SIDE_EFFECT: Изменяет файлы в локальной рабочей директории репозитория.\n # Создаёт временный backup в /tmp/ss-tools-backup-{dashboard_id}-{timestamp}/.\n # @RETURN: Dict[str, str] - Результат синхронизации.\n # @RELATION: CALLS -> src.services.git_service.GitService.get_repo\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.export_dashboard\n async def _handle_sync(self, dashboard_id: int, source_env_id: str | None = None, log=None, git_log=None, superset_log=None) -> dict[str, str]:\n with belief_scope(\"GitPlugin._handle_sync\"):\n try:\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Target repo path: {repo_path}\")\n\n env = self._get_env(source_env_id)\n client = SupersetClient(env)\n client.authenticate()\n\n superset_log.info(f\"Exporting dashboard {dashboard_id} from {env.name}\")\n zip_bytes, _ = client.export_dashboard(dashboard_id)\n\n git_log.info(f\"Unpacking export to {repo_path}\")\n\n managed_dirs = [\"dashboards\", \"charts\", \"datasets\", \"databases\"]\n managed_files = [\"metadata.yaml\"]\n\n # Fix 1: Create backup before deleting managed files\n backup_dir = Path(f\"/tmp/ss-tools-backup-{dashboard_id}-{time.time_ns()}\")\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.copytree(d_path, backup_dir / d)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n (backup_dir / f).parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(f_path, backup_dir / f)\n\n # Delete old managed files\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.rmtree(d_path)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n f_path.unlink()\n\n try:\n with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:\n namelist = zf.namelist()\n if not namelist:\n raise ValueError(\"Export ZIP is empty\")\n root_folder = namelist[0].split('/')[0]\n git_log.info(f\"Detected root folder in ZIP: {root_folder}\")\n for member in zf.infolist():\n if member.filename.startswith(root_folder + \"/\") and len(member.filename) > len(root_folder) + 1:\n relative_path = member.filename[len(root_folder)+1:]\n target_path = repo_path / relative_path\n if member.is_dir():\n target_path.mkdir(parents=True, exist_ok=True)\n else:\n target_path.parent.mkdir(parents=True, exist_ok=True)\n with zf.open(member) as source, open(target_path, \"wb\") as target:\n shutil.copyfileobj(source, target)\n except Exception:\n # Fix 1: Restore backup on unzip failure\n if backup_dir.exists():\n for d in managed_dirs:\n src = backup_dir / d\n if src.exists():\n dst = repo_path / d\n if dst.exists():\n shutil.rmtree(dst)\n shutil.copytree(src, dst)\n for f in managed_files:\n src = backup_dir / f\n if src.exists():\n dst = repo_path / f\n dst.parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(src, dst)\n raise\n\n # Fix 1: Remove backup on success\n if backup_dir.exists():\n shutil.rmtree(backup_dir, ignore_errors=True)\n\n try:\n repo.git.add(A=True)\n app_logger.reason(\"Changes staged in git\", extra={\"src\": \"_handle_sync\"})\n except Exception as ge:\n app_logger.explore(f\"Failed to stage changes: {ge}\", extra={\"src\": \"_handle_sync\"})\n\n app_logger.info(f\"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.\")\n return {\"status\": \"success\", \"message\": \"Dashboard synced and flattened in local repository\"}\n\n except Exception as e:\n app_logger.error(f\"[_handle_sync][Coherence:Failed] Sync failed: {e}\")\n raise\n # endregion _handle_sync\n\n # region _handle_deploy [C:4] [TYPE Function] [SEMANTICS git,deploy,zip]\n # @PURPOSE: Packages repository into ZIP and imports into target Superset environment.\n # @POST: Dashboard imported into target Superset.\n # @SIDE_EFFECT: Creates and removes temporary ZIP file.\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.import_dashboard\n async def _handle_deploy(self, dashboard_id: int, env_id: str, log=None, git_log=None, superset_log=None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin._handle_deploy\"):\n try:\n if not env_id:\n raise ValueError(\"Target environment ID required for deployment\")\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Packing repository {repo_path} for deployment.\")\n zip_buffer = io.BytesIO()\n root_dir_name = f\"dashboard_export_{dashboard_id}\"\n with zipfile.ZipFile(zip_buffer, \"w\", zipfile.ZIP_DEFLATED) as zf:\n for root, dirs, files in os.walk(repo_path):\n if \".git\" in dirs:\n dirs.remove(\".git\")\n for file in files:\n if file == \".git\" or file.endswith(\".zip\"):\n continue\n file_path = Path(root) / file\n arcname = Path(root_dir_name) / file_path.relative_to(repo_path)\n zf.write(file_path, arcname)\n zip_buffer.seek(0)\n env = self.config_manager.get_environment(env_id)\n if not env:\n raise ValueError(f\"Environment {env_id} not found\")\n client = SupersetClient(env)\n client.authenticate()\n temp_zip_path = repo_path / f\"deploy_{dashboard_id}.zip\"\n git_log.info(f\"Saving temporary zip to {temp_zip_path}\")\n with open(temp_zip_path, \"wb\") as f:\n f.write(zip_buffer.getvalue())\n\n try:\n app_logger.reason(f\"Importing dashboard to {env.name}\", extra={\"src\": \"_handle_deploy\"})\n result = client.import_dashboard(temp_zip_path)\n app_logger.info(f\"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.\")\n return {\"status\": \"success\", \"message\": f\"Dashboard deployed to {env.name}\", \"details\": result}\n finally:\n if temp_zip_path.exists():\n os.remove(temp_zip_path)\n\n except Exception as e:\n app_logger.error(f\"[_handle_deploy][Coherence:Failed] Deployment failed: {e}\")\n raise\n # endregion _handle_deploy\n\n # region _get_env [C:4] [TYPE Function] [SEMANTICS env,config,strict]\n # @PURPOSE: Вспомогательный метод для получения конфигурации окружения.\n # @PARAM: env_id (Optional[str]) - ID окружения.\n # @PRE: env_id is a string or None.\n # @POST: Returns an Environment object from config or DB.\n # When env_id is explicitly provided and not found, raises ValueError (no fallback).\n # @RETURN: Environment - Объект конфигурации окружения.\n def _get_env(self, env_id: str | None = None):\n with belief_scope(\"GitPlugin._get_env\"):\n app_logger.reason(f\"Fetching environment for ID: {env_id}\", extra={\"src\": \"_get_env\"})\n\n # Priority 1: ConfigManager (config.json)\n if env_id:\n env = self.config_manager.get_environment(env_id)\n if env:\n app_logger.reflect(f\"Found environment by ID in ConfigManager: {env.name}\", extra={\"src\": \"_get_env\"})\n return env\n\n # Priority 2: Database (DeploymentEnvironment)\n from src.core.database import SessionLocal\n from src.models.git import DeploymentEnvironment\n\n db = SessionLocal()\n try:\n if env_id:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.id == env_id).first()\n else:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.is_active).first()\n if not db_env:\n db_env = db.query(DeploymentEnvironment).first()\n\n if db_env:\n app_logger.reflect(f\"Found environment in DB: {db_env.name}\", extra={\"src\": \"_get_env\"})\n from src.core.config_models import Environment\n return Environment(\n id=db_env.id,\n name=db_env.name,\n url=db_env.superset_url,\n username=\"admin\",\n password=db_env.superset_token,\n verify_ssl=True\n )\n\n # Fix 7: Strict check — if env_id was explicitly provided but not found, raise immediately\n if env_id:\n raise ValueError(f\"Environment '{env_id}' not found in ConfigManager or database\")\n finally:\n db.close()\n\n # Priority 3: fallback to first env only when no specific env_id was requested\n envs = self.config_manager.get_environments()\n if envs and not env_id:\n app_logger.reflect(f\"Using first environment from ConfigManager: {envs[0].name}\", extra={\"src\": \"_get_env\"})\n return envs[0]\n\n app_logger.error(f\"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}\")\n raise ValueError(\"No environments configured. Please add a Superset Environment in Settings.\")\n # endregion _get_env\n\n# #endregion GitPlugin\n# #endregion GitPluginModule\n" }, { "contract_id": "GitPlugin", "contract_type": "Class", "file_path": "backend/src/plugins/git_plugin.py", "start_line": 32, - "end_line": 367, + "end_line": 357, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -36621,7 +38632,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region GitPlugin [TYPE Class]\n# @BRIEF Реализация плагина Git Integration для управления версиями дашбордов.\nclass GitPlugin(PluginBase):\n\n # region __init__ [TYPE Function]\n # @PURPOSE: Инициализирует плагин и его зависимости.\n # @PRE: config.json exists or shared config_manager is available.\n # @POST: Инициализированы git_service и config_manager.\n def __init__(self):\n with belief_scope(\"GitPlugin.__init__\"):\n app_logger.info(\"Initializing GitPlugin.\")\n self.git_service = GitService()\n\n # Robust config path resolution:\n # 1. Try absolute path from src/dependencies.py style if possible\n # 2. Try relative paths based on common execution patterns\n if os.path.exists(\"../config.json\"):\n config_path = \"../config.json\"\n elif os.path.exists(\"config.json\"):\n config_path = \"config.json\"\n else:\n # Fallback to the one initialized in dependencies if we can import it\n try:\n from src.dependencies import config_manager\n self.config_manager = config_manager\n app_logger.info(\"GitPlugin initialized using shared config_manager.\")\n return\n except Exception:\n config_path = \"config.json\"\n\n self.config_manager = ConfigManager(config_path)\n app_logger.info(f\"GitPlugin initialized with {config_path}\")\n # endregion __init__\n\n @property\n # region id [C:1] [TYPE Function]\n def id(self) -> str:\n return \"git-integration\"\n # endregion id\n\n @property\n # region name [C:1] [TYPE Function]\n def name(self) -> str:\n return \"Git Integration\"\n # endregion name\n\n @property\n # region description [C:1] [TYPE Function]\n def description(self) -> str:\n return \"Version control for Superset dashboards\"\n # endregion description\n\n @property\n # region version [C:1] [TYPE Function]\n def version(self) -> str:\n return \"0.1.0\"\n # endregion version\n\n @property\n # region ui_route [C:1] [TYPE Function]\n def ui_route(self) -> str:\n return \"/git\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Возвращает JSON-схему параметров для выполнения задач плагина.\n # @PRE: GitPlugin is initialized.\n # @POST: Returns a JSON schema dictionary.\n # @RETURN: Dict[str, Any] - Схема параметров.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"operation\": {\"type\": \"string\", \"enum\": [\"sync\", \"deploy\", \"history\"]},\n \"dashboard_id\": {\"type\": \"integer\"},\n \"environment_id\": {\"type\": \"string\"},\n \"source_env_id\": {\"type\": \"string\"}\n },\n \"required\": [\"operation\", \"dashboard_id\"]\n }\n # endregion get_schema\n\n # region initialize [C:1] [TYPE Function]\n async def initialize(self):\n app_logger.reason(\"Initializing Git Integration Plugin logic.\", extra={\"src\": \"GitPlugin.initialize\"})\n # endregion initialize\n\n # region execute [C:3] [TYPE Function]\n # @PURPOSE: Main task executor with TaskContext support.\n # @RELATION: CALLS -> self._handle_sync\n # @RELATION: CALLS -> self._handle_deploy\n async def execute(self, task_data: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.execute\"):\n operation = task_data.get(\"operation\")\n dashboard_id = task_data.get(\"dashboard_id\")\n\n # Use TaskContext logger if available, otherwise fall back to app_logger\n log = context.logger if context else app_logger\n\n # Create sub-loggers for different components\n git_log = log.with_source(\"git\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing operation: {operation} for dashboard {dashboard_id}\")\n\n if operation == \"sync\":\n source_env_id = task_data.get(\"source_env_id\")\n result = await self._handle_sync(dashboard_id, source_env_id, log, git_log, superset_log)\n elif operation == \"deploy\":\n env_id = task_data.get(\"environment_id\")\n result = await self._handle_deploy(dashboard_id, env_id, log, git_log, superset_log)\n elif operation == \"history\":\n result = {\"status\": \"success\", \"message\": \"History available via API\"}\n else:\n log.error(f\"Unknown operation: {operation}\")\n raise ValueError(f\"Unknown operation: {operation}\")\n\n log.info(f\"Operation {operation} completed.\")\n return result\n # endregion execute\n\n # region _handle_sync [C:4] [TYPE Function] [SEMANTICS git,sync,backup,transactional]\n # @PURPOSE: Экспортирует дашборд из Superset и распаковывает в Git-репозиторий с backup/restore.\n # @PRE: Репозиторий для дашборда должен существовать.\n # @POST: Файлы в репозитории обновлены до текущего состояния в Superset.\n # Управляемые директории backup-ируются перед удалением; при ошибке распаковки backup восстанавливается.\n # @SIDE_EFFECT: Изменяет файлы в локальной рабочей директории репозитория.\n # Создаёт временный backup в /tmp/ss-tools-backup-{dashboard_id}-{timestamp}/.\n # @RETURN: Dict[str, str] - Результат синхронизации.\n # @RELATION: CALLS -> src.services.git_service.GitService.get_repo\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.export_dashboard\n async def _handle_sync(self, dashboard_id: int, source_env_id: str | None = None, log=None, git_log=None, superset_log=None) -> dict[str, str]:\n with belief_scope(\"GitPlugin._handle_sync\"):\n try:\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Target repo path: {repo_path}\")\n\n env = self._get_env(source_env_id)\n client = SupersetClient(env)\n client.authenticate()\n\n superset_log.info(f\"Exporting dashboard {dashboard_id} from {env.name}\")\n zip_bytes, _ = client.export_dashboard(dashboard_id)\n\n git_log.info(f\"Unpacking export to {repo_path}\")\n\n managed_dirs = [\"dashboards\", \"charts\", \"datasets\", \"databases\"]\n managed_files = [\"metadata.yaml\"]\n\n # Fix 1: Create backup before deleting managed files\n backup_dir = Path(f\"/tmp/ss-tools-backup-{dashboard_id}-{time.time_ns()}\")\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.copytree(d_path, backup_dir / d)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n (backup_dir / f).parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(f_path, backup_dir / f)\n\n # Delete old managed files\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.rmtree(d_path)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n f_path.unlink()\n\n try:\n with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:\n namelist = zf.namelist()\n if not namelist:\n raise ValueError(\"Export ZIP is empty\")\n root_folder = namelist[0].split('/')[0]\n git_log.info(f\"Detected root folder in ZIP: {root_folder}\")\n for member in zf.infolist():\n if member.filename.startswith(root_folder + \"/\") and len(member.filename) > len(root_folder) + 1:\n relative_path = member.filename[len(root_folder)+1:]\n target_path = repo_path / relative_path\n if member.is_dir():\n target_path.mkdir(parents=True, exist_ok=True)\n else:\n target_path.parent.mkdir(parents=True, exist_ok=True)\n with zf.open(member) as source, open(target_path, \"wb\") as target:\n shutil.copyfileobj(source, target)\n except Exception:\n # Fix 1: Restore backup on unzip failure\n if backup_dir.exists():\n for d in managed_dirs:\n src = backup_dir / d\n if src.exists():\n dst = repo_path / d\n if dst.exists():\n shutil.rmtree(dst)\n shutil.copytree(src, dst)\n for f in managed_files:\n src = backup_dir / f\n if src.exists():\n dst = repo_path / f\n dst.parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(src, dst)\n raise\n\n # Fix 1: Remove backup on success\n if backup_dir.exists():\n shutil.rmtree(backup_dir, ignore_errors=True)\n\n try:\n repo.git.add(A=True)\n app_logger.reason(\"Changes staged in git\", extra={\"src\": \"_handle_sync\"})\n except Exception as ge:\n app_logger.explore(f\"Failed to stage changes: {ge}\", extra={\"src\": \"_handle_sync\"})\n\n app_logger.info(f\"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.\")\n return {\"status\": \"success\", \"message\": \"Dashboard synced and flattened in local repository\"}\n\n except Exception as e:\n app_logger.error(f\"[_handle_sync][Coherence:Failed] Sync failed: {e}\")\n raise\n # endregion _handle_sync\n\n # region _handle_deploy [C:4] [TYPE Function] [SEMANTICS git,deploy,zip]\n # @PURPOSE: Packages repository into ZIP and imports into target Superset environment.\n # @POST: Dashboard imported into target Superset.\n # @SIDE_EFFECT: Creates and removes temporary ZIP file.\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.import_dashboard\n async def _handle_deploy(self, dashboard_id: int, env_id: str, log=None, git_log=None, superset_log=None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin._handle_deploy\"):\n try:\n if not env_id:\n raise ValueError(\"Target environment ID required for deployment\")\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Packing repository {repo_path} for deployment.\")\n zip_buffer = io.BytesIO()\n root_dir_name = f\"dashboard_export_{dashboard_id}\"\n with zipfile.ZipFile(zip_buffer, \"w\", zipfile.ZIP_DEFLATED) as zf:\n for root, dirs, files in os.walk(repo_path):\n if \".git\" in dirs:\n dirs.remove(\".git\")\n for file in files:\n if file == \".git\" or file.endswith(\".zip\"):\n continue\n file_path = Path(root) / file\n arcname = Path(root_dir_name) / file_path.relative_to(repo_path)\n zf.write(file_path, arcname)\n zip_buffer.seek(0)\n env = self.config_manager.get_environment(env_id)\n if not env:\n raise ValueError(f\"Environment {env_id} not found\")\n client = SupersetClient(env)\n client.authenticate()\n temp_zip_path = repo_path / f\"deploy_{dashboard_id}.zip\"\n git_log.info(f\"Saving temporary zip to {temp_zip_path}\")\n with open(temp_zip_path, \"wb\") as f:\n f.write(zip_buffer.getvalue())\n\n try:\n app_logger.reason(f\"Importing dashboard to {env.name}\", extra={\"src\": \"_handle_deploy\"})\n result = client.import_dashboard(temp_zip_path)\n app_logger.info(f\"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.\")\n return {\"status\": \"success\", \"message\": f\"Dashboard deployed to {env.name}\", \"details\": result}\n finally:\n if temp_zip_path.exists():\n os.remove(temp_zip_path)\n\n except Exception as e:\n app_logger.error(f\"[_handle_deploy][Coherence:Failed] Deployment failed: {e}\")\n raise\n # endregion _handle_deploy\n\n # region _get_env [C:4] [TYPE Function] [SEMANTICS env,config,strict]\n # @PURPOSE: Вспомогательный метод для получения конфигурации окружения.\n # @PARAM: env_id (Optional[str]) - ID окружения.\n # @PRE: env_id is a string or None.\n # @POST: Returns an Environment object from config or DB.\n # When env_id is explicitly provided and not found, raises ValueError (no fallback).\n # @RETURN: Environment - Объект конфигурации окружения.\n def _get_env(self, env_id: str | None = None):\n with belief_scope(\"GitPlugin._get_env\"):\n app_logger.reason(f\"Fetching environment for ID: {env_id}\", extra={\"src\": \"_get_env\"})\n\n # Priority 1: ConfigManager (config.json)\n if env_id:\n env = self.config_manager.get_environment(env_id)\n if env:\n app_logger.reflect(f\"Found environment by ID in ConfigManager: {env.name}\", extra={\"src\": \"_get_env\"})\n return env\n\n # Priority 2: Database (DeploymentEnvironment)\n from src.core.database import SessionLocal\n from src.models.git import DeploymentEnvironment\n\n db = SessionLocal()\n try:\n if env_id:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.id == env_id).first()\n else:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.is_active).first()\n if not db_env:\n db_env = db.query(DeploymentEnvironment).first()\n\n if db_env:\n app_logger.reflect(f\"Found environment in DB: {db_env.name}\", extra={\"src\": \"_get_env\"})\n from src.core.config_models import Environment\n return Environment(\n id=db_env.id,\n name=db_env.name,\n url=db_env.superset_url,\n username=\"admin\",\n password=db_env.superset_token,\n verify_ssl=True\n )\n\n # Fix 7: Strict check — if env_id was explicitly provided but not found, raise immediately\n if env_id:\n raise ValueError(f\"Environment '{env_id}' not found in ConfigManager or database\")\n finally:\n db.close()\n\n # Priority 3: fallback to first env only when no specific env_id was requested\n envs = self.config_manager.get_environments()\n if envs and not env_id:\n app_logger.reflect(f\"Using first environment from ConfigManager: {envs[0].name}\", extra={\"src\": \"_get_env\"})\n return envs[0]\n\n app_logger.error(f\"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}\")\n raise ValueError(\"No environments configured. Please add a Superset Environment in Settings.\")\n # endregion _get_env\n\n# #endregion GitPlugin\n" + "body": "# #region GitPlugin [TYPE Class]\n# @BRIEF Реализация плагина Git Integration для управления версиями дашбордов.\nclass GitPlugin(PluginBase):\n\n # region __init__ [TYPE Function]\n # @PURPOSE: Инициализирует плагин и его зависимости.\n # @PRE: shared config_manager доступен через src.dependencies.\n # @POST: Инициализированы git_service и config_manager.\n def __init__(self):\n with belief_scope(\"GitPlugin.__init__\"):\n app_logger.info(\"Initializing GitPlugin.\")\n self.git_service = GitService()\n\n # Используем shared config_manager из dependencies\n try:\n from src.dependencies import config_manager\n self.config_manager = config_manager\n app_logger.info(\"GitPlugin initialized using shared config_manager.\")\n except Exception as exc:\n app_logger.error(f\"GitPlugin: failed to get shared config_manager: {exc}\")\n self.config_manager = ConfigManager()\n app_logger.info(\"GitPlugin initialized with fallback ConfigManager.\")\n # endregion __init__\n\n @property\n # region id [C:1] [TYPE Function]\n def id(self) -> str:\n return \"git-integration\"\n # endregion id\n\n @property\n # region name [C:1] [TYPE Function]\n def name(self) -> str:\n return \"Git Integration\"\n # endregion name\n\n @property\n # region description [C:1] [TYPE Function]\n def description(self) -> str:\n return \"Version control for Superset dashboards\"\n # endregion description\n\n @property\n # region version [C:1] [TYPE Function]\n def version(self) -> str:\n return \"0.1.0\"\n # endregion version\n\n @property\n # region ui_route [C:1] [TYPE Function]\n def ui_route(self) -> str:\n return \"/git\"\n # endregion ui_route\n\n # region get_schema [TYPE Function]\n # @PURPOSE: Возвращает JSON-схему параметров для выполнения задач плагина.\n # @PRE: GitPlugin is initialized.\n # @POST: Returns a JSON schema dictionary.\n # @RETURN: Dict[str, Any] - Схема параметров.\n def get_schema(self) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.get_schema\"):\n return {\n \"type\": \"object\",\n \"properties\": {\n \"operation\": {\"type\": \"string\", \"enum\": [\"sync\", \"deploy\", \"history\"]},\n \"dashboard_id\": {\"type\": \"integer\"},\n \"environment_id\": {\"type\": \"string\"},\n \"source_env_id\": {\"type\": \"string\"}\n },\n \"required\": [\"operation\", \"dashboard_id\"]\n }\n # endregion get_schema\n\n # region initialize [C:1] [TYPE Function]\n async def initialize(self):\n app_logger.reason(\"Initializing Git Integration Plugin logic.\", extra={\"src\": \"GitPlugin.initialize\"})\n # endregion initialize\n\n # region execute [C:3] [TYPE Function]\n # @PURPOSE: Main task executor with TaskContext support.\n # @RELATION: CALLS -> self._handle_sync\n # @RELATION: CALLS -> self._handle_deploy\n async def execute(self, task_data: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin.execute\"):\n operation = task_data.get(\"operation\")\n dashboard_id = task_data.get(\"dashboard_id\")\n\n # Use TaskContext logger if available, otherwise fall back to app_logger\n log = context.logger if context else app_logger\n\n # Create sub-loggers for different components\n git_log = log.with_source(\"git\") if context else log\n superset_log = log.with_source(\"superset_api\") if context else log\n\n log.info(f\"Executing operation: {operation} for dashboard {dashboard_id}\")\n\n if operation == \"sync\":\n source_env_id = task_data.get(\"source_env_id\")\n result = await self._handle_sync(dashboard_id, source_env_id, log, git_log, superset_log)\n elif operation == \"deploy\":\n env_id = task_data.get(\"environment_id\")\n result = await self._handle_deploy(dashboard_id, env_id, log, git_log, superset_log)\n elif operation == \"history\":\n result = {\"status\": \"success\", \"message\": \"History available via API\"}\n else:\n log.error(f\"Unknown operation: {operation}\")\n raise ValueError(f\"Unknown operation: {operation}\")\n\n log.info(f\"Operation {operation} completed.\")\n return result\n # endregion execute\n\n # region _handle_sync [C:4] [TYPE Function] [SEMANTICS git,sync,backup,transactional]\n # @PURPOSE: Экспортирует дашборд из Superset и распаковывает в Git-репозиторий с backup/restore.\n # @PRE: Репозиторий для дашборда должен существовать.\n # @POST: Файлы в репозитории обновлены до текущего состояния в Superset.\n # Управляемые директории backup-ируются перед удалением; при ошибке распаковки backup восстанавливается.\n # @SIDE_EFFECT: Изменяет файлы в локальной рабочей директории репозитория.\n # Создаёт временный backup в /tmp/ss-tools-backup-{dashboard_id}-{timestamp}/.\n # @RETURN: Dict[str, str] - Результат синхронизации.\n # @RELATION: CALLS -> src.services.git_service.GitService.get_repo\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.export_dashboard\n async def _handle_sync(self, dashboard_id: int, source_env_id: str | None = None, log=None, git_log=None, superset_log=None) -> dict[str, str]:\n with belief_scope(\"GitPlugin._handle_sync\"):\n try:\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Target repo path: {repo_path}\")\n\n env = self._get_env(source_env_id)\n client = SupersetClient(env)\n client.authenticate()\n\n superset_log.info(f\"Exporting dashboard {dashboard_id} from {env.name}\")\n zip_bytes, _ = client.export_dashboard(dashboard_id)\n\n git_log.info(f\"Unpacking export to {repo_path}\")\n\n managed_dirs = [\"dashboards\", \"charts\", \"datasets\", \"databases\"]\n managed_files = [\"metadata.yaml\"]\n\n # Fix 1: Create backup before deleting managed files\n backup_dir = Path(f\"/tmp/ss-tools-backup-{dashboard_id}-{time.time_ns()}\")\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.copytree(d_path, backup_dir / d)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n (backup_dir / f).parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(f_path, backup_dir / f)\n\n # Delete old managed files\n for d in managed_dirs:\n d_path = repo_path / d\n if d_path.exists() and d_path.is_dir():\n shutil.rmtree(d_path)\n for f in managed_files:\n f_path = repo_path / f\n if f_path.exists():\n f_path.unlink()\n\n try:\n with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:\n namelist = zf.namelist()\n if not namelist:\n raise ValueError(\"Export ZIP is empty\")\n root_folder = namelist[0].split('/')[0]\n git_log.info(f\"Detected root folder in ZIP: {root_folder}\")\n for member in zf.infolist():\n if member.filename.startswith(root_folder + \"/\") and len(member.filename) > len(root_folder) + 1:\n relative_path = member.filename[len(root_folder)+1:]\n target_path = repo_path / relative_path\n if member.is_dir():\n target_path.mkdir(parents=True, exist_ok=True)\n else:\n target_path.parent.mkdir(parents=True, exist_ok=True)\n with zf.open(member) as source, open(target_path, \"wb\") as target:\n shutil.copyfileobj(source, target)\n except Exception:\n # Fix 1: Restore backup on unzip failure\n if backup_dir.exists():\n for d in managed_dirs:\n src = backup_dir / d\n if src.exists():\n dst = repo_path / d\n if dst.exists():\n shutil.rmtree(dst)\n shutil.copytree(src, dst)\n for f in managed_files:\n src = backup_dir / f\n if src.exists():\n dst = repo_path / f\n dst.parent.mkdir(parents=True, exist_ok=True)\n shutil.copy2(src, dst)\n raise\n\n # Fix 1: Remove backup on success\n if backup_dir.exists():\n shutil.rmtree(backup_dir, ignore_errors=True)\n\n try:\n repo.git.add(A=True)\n app_logger.reason(\"Changes staged in git\", extra={\"src\": \"_handle_sync\"})\n except Exception as ge:\n app_logger.explore(f\"Failed to stage changes: {ge}\", extra={\"src\": \"_handle_sync\"})\n\n app_logger.info(f\"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.\")\n return {\"status\": \"success\", \"message\": \"Dashboard synced and flattened in local repository\"}\n\n except Exception as e:\n app_logger.error(f\"[_handle_sync][Coherence:Failed] Sync failed: {e}\")\n raise\n # endregion _handle_sync\n\n # region _handle_deploy [C:4] [TYPE Function] [SEMANTICS git,deploy,zip]\n # @PURPOSE: Packages repository into ZIP and imports into target Superset environment.\n # @POST: Dashboard imported into target Superset.\n # @SIDE_EFFECT: Creates and removes temporary ZIP file.\n # @RELATION: CALLS -> src.core.superset_client.SupersetClient.import_dashboard\n async def _handle_deploy(self, dashboard_id: int, env_id: str, log=None, git_log=None, superset_log=None) -> dict[str, Any]:\n with belief_scope(\"GitPlugin._handle_deploy\"):\n try:\n if not env_id:\n raise ValueError(\"Target environment ID required for deployment\")\n repo = self.git_service.get_repo(dashboard_id)\n repo_path = Path(repo.working_dir)\n git_log.info(f\"Packing repository {repo_path} for deployment.\")\n zip_buffer = io.BytesIO()\n root_dir_name = f\"dashboard_export_{dashboard_id}\"\n with zipfile.ZipFile(zip_buffer, \"w\", zipfile.ZIP_DEFLATED) as zf:\n for root, dirs, files in os.walk(repo_path):\n if \".git\" in dirs:\n dirs.remove(\".git\")\n for file in files:\n if file == \".git\" or file.endswith(\".zip\"):\n continue\n file_path = Path(root) / file\n arcname = Path(root_dir_name) / file_path.relative_to(repo_path)\n zf.write(file_path, arcname)\n zip_buffer.seek(0)\n env = self.config_manager.get_environment(env_id)\n if not env:\n raise ValueError(f\"Environment {env_id} not found\")\n client = SupersetClient(env)\n client.authenticate()\n temp_zip_path = repo_path / f\"deploy_{dashboard_id}.zip\"\n git_log.info(f\"Saving temporary zip to {temp_zip_path}\")\n with open(temp_zip_path, \"wb\") as f:\n f.write(zip_buffer.getvalue())\n\n try:\n app_logger.reason(f\"Importing dashboard to {env.name}\", extra={\"src\": \"_handle_deploy\"})\n result = client.import_dashboard(temp_zip_path)\n app_logger.info(f\"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.\")\n return {\"status\": \"success\", \"message\": f\"Dashboard deployed to {env.name}\", \"details\": result}\n finally:\n if temp_zip_path.exists():\n os.remove(temp_zip_path)\n\n except Exception as e:\n app_logger.error(f\"[_handle_deploy][Coherence:Failed] Deployment failed: {e}\")\n raise\n # endregion _handle_deploy\n\n # region _get_env [C:4] [TYPE Function] [SEMANTICS env,config,strict]\n # @PURPOSE: Вспомогательный метод для получения конфигурации окружения.\n # @PARAM: env_id (Optional[str]) - ID окружения.\n # @PRE: env_id is a string or None.\n # @POST: Returns an Environment object from config or DB.\n # When env_id is explicitly provided and not found, raises ValueError (no fallback).\n # @RETURN: Environment - Объект конфигурации окружения.\n def _get_env(self, env_id: str | None = None):\n with belief_scope(\"GitPlugin._get_env\"):\n app_logger.reason(f\"Fetching environment for ID: {env_id}\", extra={\"src\": \"_get_env\"})\n\n # Priority 1: ConfigManager (config.json)\n if env_id:\n env = self.config_manager.get_environment(env_id)\n if env:\n app_logger.reflect(f\"Found environment by ID in ConfigManager: {env.name}\", extra={\"src\": \"_get_env\"})\n return env\n\n # Priority 2: Database (DeploymentEnvironment)\n from src.core.database import SessionLocal\n from src.models.git import DeploymentEnvironment\n\n db = SessionLocal()\n try:\n if env_id:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.id == env_id).first()\n else:\n db_env = db.query(DeploymentEnvironment).filter(DeploymentEnvironment.is_active).first()\n if not db_env:\n db_env = db.query(DeploymentEnvironment).first()\n\n if db_env:\n app_logger.reflect(f\"Found environment in DB: {db_env.name}\", extra={\"src\": \"_get_env\"})\n from src.core.config_models import Environment\n return Environment(\n id=db_env.id,\n name=db_env.name,\n url=db_env.superset_url,\n username=\"admin\",\n password=db_env.superset_token,\n verify_ssl=True\n )\n\n # Fix 7: Strict check — if env_id was explicitly provided but not found, raise immediately\n if env_id:\n raise ValueError(f\"Environment '{env_id}' not found in ConfigManager or database\")\n finally:\n db.close()\n\n # Priority 3: fallback to first env only when no specific env_id was requested\n envs = self.config_manager.get_environments()\n if envs and not env_id:\n app_logger.reflect(f\"Using first environment from ConfigManager: {envs[0].name}\", extra={\"src\": \"_get_env\"})\n return envs[0]\n\n app_logger.error(f\"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}\")\n raise ValueError(\"No environments configured. Please add a Superset Environment in Settings.\")\n # endregion _get_env\n\n# #endregion GitPlugin\n" }, { "contract_id": "LLMAnalysisPackage", @@ -36953,7 +38964,7 @@ "contract_type": "Module", "file_path": "backend/src/plugins/llm_analysis/service.py", "start_line": 1, - "end_line": 1095, + "end_line": 1174, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -36987,14 +38998,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\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" + "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 re\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, plus diagnostic viewport screenshots of tabs that had chart load errors.\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 # Extra diagnostic screenshots saved as output_path__tab_{tab_text}.png for each tab with chart errors.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes PNG files; 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 # Collects errored_tabs — those where chart content fails to render within timeout.\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors.\n # @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.\n # @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.\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 # Collects errored_tabs — those where chart content fails to render within timeout.\n # These are later screenshotted individually for LLM diagnostic value.\n processed_tabs = set()\n errored_tabs = [] # Collects {tab_text, depth, error} for tabs with chart load failures\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 errored_tabs.append({\n \"tab_text\": tab_text,\n \"tab_index\": i,\n \"depth\": depth,\n \"error\": \"content_verification_timeout\"\n })\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 errored_tabs.append({\n \"tab_text\": f\"tab_{depth}_{i}\",\n \"tab_index\": i,\n \"depth\": depth,\n \"error\": f\"processing_exception: {tab_e!s}\"\n })\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 # Log summary of errored tabs\n if errored_tabs:\n logger.info(f\"[TabSwitching] {len(errored_tabs)} tab(s) with errors detected. \"\n f\"Errored tabs: {[t['tab_text'] for t in errored_tabs]}\")\n else:\n logger.info(\"[TabSwitching] No tab errors detected during preload\")\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\n # 3. Screenshot errored tabs (diagnostic viewport shots)\n # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors.\n # Only screenshots tabs that had errors during preload, plus always keeps the main tab.\n # Errored tab screenshots are viewport-only (no full-page resize) to minimize overhead.\n if errored_tabs:\n logger.info(f\"[TabSwitching] Capturing {len(errored_tabs)} errored tab screenshot(s)...\")\n screenshotted_tabs = set()\n for tab_info in errored_tabs:\n try:\n tab_text = tab_info[\"tab_text\"]\n\n # Dedup: skip if already screenshotted\n if tab_text in screenshotted_tabs:\n continue\n screenshotted_tabs.add(tab_text)\n\n # Sanitize tab text for filename\n safe_tab = re.sub(r'[^\\w\\-_ ]', '', tab_text).strip().replace(' ', '_')[:40]\n if not safe_tab:\n safe_tab = f\"tab_{tab_info.get('depth', 0)}_{tab_info.get('tab_index', 0)}\"\n\n # Build tab path robustly (handle any extension or no extension)\n base = output_path[:-4] if output_path.lower().endswith('.png') else output_path\n tab_path = f\"{base}__tab_{safe_tab}.png\"\n\n # Switch to the errored tab — try exact text match first\n errored_tab_el = page.get_by_role(\"tab\", name=tab_text, exact=True)\n if not await errored_tab_el.is_visible():\n # Fallback: try nth-child by index\n tab_index = tab_info.get(\"tab_index\")\n if tab_index is not None:\n errored_tab_el = page.locator('.ant-tabs-tab').nth(tab_index)\n if await errored_tab_el.is_visible():\n await errored_tab_el.click()\n await asyncio.sleep(0.5)\n await self._wait_for_charts_stabilized(page, timeout_ms=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n await page.screenshot(path=tab_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n tab_size = os.path.getsize(tab_path) if os.path.exists(tab_path) else 0\n logger.info(f\"[TabSwitching] Errored tab screenshot saved: {tab_path} ({tab_size} bytes)\")\n else:\n logger.warning(f\"[TabSwitching] Errored tab '{tab_text}' not visible, skipping screenshot\")\n except Exception as tab_shot_err:\n logger.warning(f\"[TabSwitching] Failed to screenshot errored tab '{tab_info.get('tab_text')}': {tab_shot_err}\")\n\n # Return to first tab after errored tab screenshots\n try:\n first_tab_el = page.locator('.ant-tabs-nav-list .ant-tabs-tab').first\n if await first_tab_el.is_visible():\n await first_tab_el.click()\n await asyncio.sleep(0.5)\n except Exception:\n pass\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": 41, - "end_line": 790, + "start_line": 42, + "end_line": 869, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -37004,14 +39015,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._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" + "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, plus diagnostic viewport screenshots of tabs that had chart load errors.\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 # Extra diagnostic screenshots saved as output_path__tab_{tab_text}.png for each tab with chart errors.\n # @SIDE_EFFECT Launches a browser, performs UI login, switches tabs, writes PNG files; 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 # Collects errored_tabs — those where chart content fails to render within timeout.\n # @UX_STATE [CalculatingHeight] -> Determining dashboard dimensions\n # @UX_STATE [Capturing] -> Executing CDP screenshot\n # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors.\n # @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.\n # @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.\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 # Collects errored_tabs — those where chart content fails to render within timeout.\n # These are later screenshotted individually for LLM diagnostic value.\n processed_tabs = set()\n errored_tabs = [] # Collects {tab_text, depth, error} for tabs with chart load failures\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 errored_tabs.append({\n \"tab_text\": tab_text,\n \"tab_index\": i,\n \"depth\": depth,\n \"error\": \"content_verification_timeout\"\n })\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 errored_tabs.append({\n \"tab_text\": f\"tab_{depth}_{i}\",\n \"tab_index\": i,\n \"depth\": depth,\n \"error\": f\"processing_exception: {tab_e!s}\"\n })\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 # Log summary of errored tabs\n if errored_tabs:\n logger.info(f\"[TabSwitching] {len(errored_tabs)} tab(s) with errors detected. \"\n f\"Errored tabs: {[t['tab_text'] for t in errored_tabs]}\")\n else:\n logger.info(\"[TabSwitching] No tab errors detected during preload\")\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\n # 3. Screenshot errored tabs (diagnostic viewport shots)\n # @UX_STATE [CapturingErroredTabs] -> Taking viewport screenshots of tabs with chart errors.\n # Only screenshots tabs that had errors during preload, plus always keeps the main tab.\n # Errored tab screenshots are viewport-only (no full-page resize) to minimize overhead.\n if errored_tabs:\n logger.info(f\"[TabSwitching] Capturing {len(errored_tabs)} errored tab screenshot(s)...\")\n screenshotted_tabs = set()\n for tab_info in errored_tabs:\n try:\n tab_text = tab_info[\"tab_text\"]\n\n # Dedup: skip if already screenshotted\n if tab_text in screenshotted_tabs:\n continue\n screenshotted_tabs.add(tab_text)\n\n # Sanitize tab text for filename\n safe_tab = re.sub(r'[^\\w\\-_ ]', '', tab_text).strip().replace(' ', '_')[:40]\n if not safe_tab:\n safe_tab = f\"tab_{tab_info.get('depth', 0)}_{tab_info.get('tab_index', 0)}\"\n\n # Build tab path robustly (handle any extension or no extension)\n base = output_path[:-4] if output_path.lower().endswith('.png') else output_path\n tab_path = f\"{base}__tab_{safe_tab}.png\"\n\n # Switch to the errored tab — try exact text match first\n errored_tab_el = page.get_by_role(\"tab\", name=tab_text, exact=True)\n if not await errored_tab_el.is_visible():\n # Fallback: try nth-child by index\n tab_index = tab_info.get(\"tab_index\")\n if tab_index is not None:\n errored_tab_el = page.locator('.ant-tabs-tab').nth(tab_index)\n if await errored_tab_el.is_visible():\n await errored_tab_el.click()\n await asyncio.sleep(0.5)\n await self._wait_for_charts_stabilized(page, timeout_ms=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n await page.screenshot(path=tab_path, timeout=PLAYWRIGHT_SHORT_TIMEOUT_MS)\n tab_size = os.path.getsize(tab_path) if os.path.exists(tab_path) else 0\n logger.info(f\"[TabSwitching] Errored tab screenshot saved: {tab_path} ({tab_size} bytes)\")\n else:\n logger.warning(f\"[TabSwitching] Errored tab '{tab_text}' not visible, skipping screenshot\")\n except Exception as tab_shot_err:\n logger.warning(f\"[TabSwitching] Failed to screenshot errored tab '{tab_info.get('tab_text')}': {tab_shot_err}\")\n\n # Return to first tab after errored tab screenshots\n try:\n first_tab_el = page.locator('.ant-tabs-nav-list .ant-tabs-tab').first\n if await first_tab_el.is_visible():\n await first_tab_el.click()\n await asyncio.sleep(0.5)\n except Exception:\n pass\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": 792, - "end_line": 1093, + "start_line": 871, + "end_line": 1172, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -37023,6 +39034,24 @@ "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\n# #endregion LLMClient\n" }, + { + "contract_id": "MaintenanceBannerPlugin", + "contract_type": "Module", + "file_path": "backend/src/plugins/maintenance_banner.py", + "start_line": 1, + "end_line": 176, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "TaskManager plugin for executing maintenance banner operations (start, end, end-all)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceBannerPlugin [C:4] [TYPE Module] [SEMANTICS plugin, maintenance, banner, execution, task]\n# @BRIEF TaskManager plugin for executing maintenance banner operations (start, end, end-all).\n# Dispatches to MaintenanceService based on operation type in params.\n# @LAYER Plugin\n# @RELATION IMPLEMENTS -> [PluginBase]\n# @RELATION DEPENDS_ON -> [MaintenanceServiceModule]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskContext]\n# @INVARIANT TaskManager executes this plugin with params containing operation and event_id.\n\nfrom typing import Any\n\nfrom ..core.database import SessionLocal\nfrom ..core.logger import belief_scope, logger as app_logger\nfrom ..core.plugin_base import PluginBase\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager.context import TaskContext\nfrom ..dependencies import get_config_manager\nfrom ..models.maintenance import MaintenanceSettings\nfrom ..services.maintenance import end_all_maintenance, end_maintenance, start_maintenance\n\n\n# #region MaintenanceBannerPlugin [C:4] [TYPE Class]\n# @BRIEF Plugin for executing maintenance banner operations asynchronously via TaskManager.\n# @RELATION CALLS -> [start_maintenance]\n# @RELATION CALLS -> [end_maintenance]\n# @RELATION CALLS -> [end_all_maintenance]\nclass MaintenanceBannerPlugin(PluginBase):\n \"\"\"TaskManager plugin for maintenance banner operations.\"\"\"\n\n # #region id [TYPE Property]\n @property\n def id(self) -> str:\n return \"maintenance_banner_apply\"\n # #endregion id\n\n # #region name [TYPE Property]\n @property\n def name(self) -> str:\n return \"Maintenance Banner\"\n # #endregion name\n\n # #region description [TYPE Property]\n @property\n def description(self) -> str:\n return \"Applies or removes maintenance banners on Superset dashboards.\"\n # #endregion description\n\n # #region version [TYPE Property]\n @property\n def version(self) -> str:\n return \"1.0.0\"\n # #endregion version\n\n # #region ui_route [TYPE Property]\n @property\n def ui_route(self) -> str:\n return \"\" # No UI route — async-only\n # #endregion ui_route\n\n # #region get_schema [TYPE Function]\n def get_schema(self) -> dict[str, Any]:\n return {\n \"type\": \"object\",\n \"properties\": {\n \"operation\": {\n \"type\": \"string\",\n \"enum\": [\"start\", \"end\", \"end_all\"],\n \"title\": \"Operation\",\n },\n \"event_id\": {\n \"type\": \"string\",\n \"title\": \"Maintenance Event ID\",\n },\n \"environment_id\": {\n \"type\": \"string\",\n \"title\": \"Target Environment ID\",\n },\n },\n \"required\": [\"operation\"],\n }\n # #endregion get_schema\n\n # #region execute [TYPE Function] [C:4]\n # @BRIEF Execute maintenance operation based on params.operation.\n # @PARAM params contains: operation (start|end|end_all), event_id, environment_id.\n # @PARAM context TaskContext for logging.\n # @PRE DB and Superset available.\n # @POST Operation completed. Results returned as dict.\n # @SIDE_EFFECT Modifies Superset dashboards, writes DB rows.\n async def execute(\n self,\n params: dict[str, Any],\n context: TaskContext | None = None,\n ) -> dict[str, Any]:\n with belief_scope(\"MaintenanceBannerPlugin.execute\"):\n operation = params.get(\"operation\", \"start\")\n event_id = params.get(\"event_id\", \"\")\n environment_id = params.get(\"environment_id\", \"\")\n\n app_logger.reason(\n \"Executing maintenance operation\",\n extra={\n \"operation\": operation,\n \"event_id\": event_id,\n \"environment_id\": environment_id,\n },\n )\n\n db = SessionLocal()\n try:\n # Resolve environment\n if not environment_id:\n settings = db.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n if settings:\n environment_id = settings.target_environment_id\n\n if not environment_id:\n config_manager = get_config_manager()\n envs = config_manager.get_environments()\n if envs:\n environment_id = envs[0].id\n\n env = None\n config_manager = get_config_manager()\n for e in config_manager.get_environments():\n if e.id == environment_id:\n env = e\n break\n\n if not env:\n app_logger.explore(\n \"Environment not found\",\n extra={\"environment_id\": environment_id},\n error=\"EnvironmentNotFound\",\n )\n return {\"status\": \"failed\", \"error\": f\"Environment {environment_id} not found\"}\n\n superset_client = SupersetClient(env)\n\n if operation == \"start\":\n if not event_id:\n return {\"status\": \"failed\", \"error\": \"event_id required for start\"}\n result = start_maintenance(event_id, db, superset_client)\n elif operation == \"end\":\n if not event_id:\n return {\"status\": \"failed\", \"error\": \"event_id required for end\"}\n result = end_maintenance(event_id, db, superset_client)\n elif operation == \"end_all\":\n result = end_all_maintenance(db, superset_client)\n else:\n result = {\"status\": \"failed\", \"error\": f\"Unknown operation: {operation}\"}\n\n db.commit()\n app_logger.reflect(\n \"Maintenance operation completed\",\n extra={\"operation\": operation, \"result\": result},\n )\n return result\n\n except Exception as e:\n db.rollback()\n app_logger.explore(\n \"Maintenance operation failed\",\n extra={\"operation\": operation, \"event_id\": event_id},\n error=str(e),\n )\n return {\"status\": \"failed\", \"error\": str(e)}\n finally:\n db.close()\n # #endregion execute\n# #endregion MaintenanceBannerPlugin\n\n# #endregion MaintenanceBannerPlugin\n" + }, { "contract_id": "MapperPluginModule", "contract_type": "Module", @@ -44242,7 +46271,7 @@ "contract_type": "Module", "file_path": "backend/src/scripts/seed_superset_load_test.py", "start_line": 1, - "end_line": 402, + "end_line": 392, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -44269,7 +46298,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region SeedSupersetLoadTestScript [C:5] [TYPE Module] [SEMANTICS superset, validate]\n#\n# @BRIEF Creates randomized load-test data in Superset by cloning chart configurations and creating dashboards in target environments.\n# @LAYER: Infrastructure\n# @RELATION USES -> [ConfigManager]\n# @RELATION USES -> [SupersetClient]\n# @INVARIANT: Created chart and dashboard names are globally unique for one script run.\n# @DATA_CONTRACT: CLIArgs -> TestDataSummary\n\nimport argparse\nimport json\nfrom pathlib import Path\nimport random\nimport sys\nimport uuid\n\nsys.path.append(str(Path(__file__).parent.parent.parent))\n\nfrom src.core.config_manager import ConfigManager\nfrom src.core.config_models import Environment\nfrom src.core.cot_logger import seed_trace_id\nfrom src.core.logger import belief_scope, logger\nfrom src.core.superset_client import SupersetClient\n\n\n# #region _parse_args [TYPE Function]\n# @BRIEF Parses CLI arguments for load-test data generation.\n# @PRE: Script is called from CLI.\n# @POST: Returns validated argument namespace.\ndef _parse_args() -> argparse.Namespace:\n parser = argparse.ArgumentParser(\n description=\"Seed Superset with load-test charts and dashboards\"\n )\n parser.add_argument(\n \"--envs\", nargs=\"+\", default=[\"ss1\", \"ss2\"], help=\"Target environment IDs\"\n )\n parser.add_argument(\n \"--charts\", type=int, default=10000, help=\"Target number of charts to create\"\n )\n parser.add_argument(\n \"--dashboards\",\n type=int,\n default=500,\n help=\"Target number of dashboards to create\",\n )\n parser.add_argument(\n \"--template-pool-size\",\n type=int,\n default=200,\n help=\"How many source charts to sample as templates per env\",\n )\n parser.add_argument(\n \"--seed\", type=int, default=None, help=\"Optional RNG seed for reproducibility\"\n )\n parser.add_argument(\n \"--max-errors\",\n type=int,\n default=100,\n help=\"Stop early if errors exceed this threshold\",\n )\n parser.add_argument(\n \"--dry-run\", action=\"store_true\", help=\"Do not write data, only validate setup\"\n )\n return parser.parse_args()\n\n\n# #endregion _parse_args\n\n\n# #region _extract_result_payload [TYPE Function]\n# @BRIEF Normalizes Superset API payloads that may be wrapped in `result`.\n# @PRE: payload is a JSON-decoded API response.\n# @POST: Returns the unwrapped object when present.\ndef _extract_result_payload(payload: dict) -> dict:\n result = payload.get(\"result\")\n if isinstance(result, dict):\n return result\n return payload\n\n\n# #endregion _extract_result_payload\n\n\n# #region _extract_created_id [TYPE Function]\n# @BRIEF Extracts object ID from create/update API response.\n# @PRE: payload is a JSON-decoded API response.\n# @POST: Returns integer object ID or None if missing.\ndef _extract_created_id(payload: dict) -> int | None:\n direct_id = payload.get(\"id\")\n if isinstance(direct_id, int):\n return direct_id\n result = payload.get(\"result\")\n if isinstance(result, dict) and isinstance(result.get(\"id\"), int):\n return int(result[\"id\"])\n return None\n\n\n# #endregion _extract_created_id\n\n\n# #region _generate_unique_name [TYPE Function]\n# @BRIEF Generates globally unique random names for charts/dashboards.\n# @PRE: used_names is mutable set for collision tracking.\n# @POST: Returns a unique string and stores it in used_names.\ndef _generate_unique_name(prefix: str, used_names: set[str], rng: random.Random) -> str:\n adjectives = [\n \"amber\",\n \"rapid\",\n \"frozen\",\n \"delta\",\n \"lunar\",\n \"vector\",\n \"cobalt\",\n \"silent\",\n \"neon\",\n \"solar\",\n ]\n nouns = [\n \"falcon\",\n \"matrix\",\n \"signal\",\n \"harbor\",\n \"stream\",\n \"vertex\",\n \"bridge\",\n \"orbit\",\n \"pulse\",\n \"forge\",\n ]\n while True:\n token = uuid.uuid4().hex[:8]\n candidate = f\"{prefix}_{rng.choice(adjectives)}_{rng.choice(nouns)}_{rng.randint(100, 999)}_{token}\"\n if candidate not in used_names:\n used_names.add(candidate)\n return candidate\n\n\n# #endregion _generate_unique_name\n\n\n# #region _resolve_target_envs [TYPE Function]\n# @BRIEF Resolves requested environment IDs from configuration.\n# @PRE: env_ids is non-empty.\n# @POST: Returns mapping env_id -> configured environment object.\ndef _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]:\n config_manager = ConfigManager()\n configured = {env.id: env for env in config_manager.get_environments()}\n resolved: dict[str, Environment] = {}\n\n if not configured:\n for config_path in [Path(\"config.json\"), Path(\"backend/config.json\")]:\n if not config_path.exists():\n continue\n try:\n payload = json.loads(config_path.read_text(encoding=\"utf-8\"))\n env_rows = payload.get(\"environments\", [])\n for row in env_rows:\n env = Environment(**row)\n configured[env.id] = env\n except Exception as exc:\n logger.reflect(\n f\"Failed loading environments from {config_path}: {exc}\",\n extra={\"src\": \"_resolve_target_envs\"},\n )\n\n for env_id in env_ids:\n env = configured.get(env_id)\n if env is None:\n raise ValueError(f\"Environment '{env_id}' not found in configuration\")\n resolved[env_id] = env\n\n return resolved\n\n\n# #endregion _resolve_target_envs\n\n\n# #region _build_chart_template_pool [TYPE Function]\n# @BRIEF Builds a pool of source chart templates to clone in one environment.\n# @PRE: Client is authenticated.\n# @POST: Returns non-empty list of chart payload templates.\ndef _build_chart_template_pool(\n client: SupersetClient, pool_size: int, rng: random.Random\n) -> list[dict]:\n list_query = {\n \"page\": 0,\n \"page_size\": 1000,\n \"columns\": [\n \"id\",\n \"slice_name\",\n \"datasource_id\",\n \"datasource_type\",\n \"viz_type\",\n \"params\",\n \"query_context\",\n ],\n }\n rows = client.network.fetch_paginated_data(\n endpoint=\"/chart/\",\n pagination_options={\"base_query\": list_query, \"results_field\": \"result\"},\n )\n\n candidates = [row for row in rows if isinstance(row, dict) and row.get(\"id\")]\n if not candidates:\n raise RuntimeError(\"No source charts available for templating\")\n\n selected = (\n candidates\n if len(candidates) <= pool_size\n else rng.sample(candidates, pool_size)\n )\n templates: list[dict] = []\n\n for row in selected:\n chart_id = int(row[\"id\"])\n detail_payload = client.get_chart(chart_id)\n detail = _extract_result_payload(detail_payload)\n\n datasource_id = detail.get(\"datasource_id\")\n datasource_type = (\n detail.get(\"datasource_type\") or row.get(\"datasource_type\") or \"table\"\n )\n if datasource_id is None:\n continue\n\n params_value = detail.get(\"params\")\n if isinstance(params_value, dict):\n params_value = json.dumps(params_value)\n\n query_context_value = detail.get(\"query_context\")\n if isinstance(query_context_value, dict):\n query_context_value = json.dumps(query_context_value)\n\n templates.append(\n {\n \"datasource_id\": int(datasource_id),\n \"datasource_type\": str(datasource_type),\n \"viz_type\": detail.get(\"viz_type\") or row.get(\"viz_type\"),\n \"params\": params_value,\n \"query_context\": query_context_value,\n }\n )\n\n if not templates:\n raise RuntimeError(\"Could not build templates with datasource metadata\")\n\n return templates\n\n\n# #endregion _build_chart_template_pool\n\n\n# #region seed_superset_load_data [TYPE Function]\n# @BRIEF Creates dashboards and cloned charts for load testing across target environments.\n# @PRE: Target environments must be reachable and authenticated.\n# @POST: Returns execution statistics dictionary.\n# @SIDE_EFFECT: Creates objects in Superset environments.\ndef seed_superset_load_data(args: argparse.Namespace) -> dict:\n seed_trace_id()\n rng = random.Random(args.seed)\n env_map = _resolve_target_envs(args.envs)\n\n clients: dict[str, SupersetClient] = {}\n templates_by_env: dict[str, list[dict]] = {}\n created_dashboards: dict[str, list[int]] = {env_id: [] for env_id in env_map}\n created_charts: dict[str, list[int]] = {env_id: [] for env_id in env_map}\n used_chart_names: set[str] = set()\n used_dashboard_names: set[str] = set()\n\n for env_id, env in env_map.items():\n client = SupersetClient(env)\n client.authenticate()\n clients[env_id] = client\n templates_by_env[env_id] = _build_chart_template_pool(\n client, args.template_pool_size, rng\n )\n logger.reason(\n f\"Environment {env_id}: loaded {len(templates_by_env[env_id])} chart templates\",\n extra={\"src\": \"seed_superset_load_data\"},\n )\n\n errors = 0\n env_ids = list(env_map.keys())\n\n for idx in range(args.dashboards):\n env_id = (\n env_ids[idx % len(env_ids)] if idx < len(env_ids) else rng.choice(env_ids)\n )\n dashboard_title = _generate_unique_name(\"lt_dash\", used_dashboard_names, rng)\n\n if args.dry_run:\n logger.reflect(\n f\"Dry-run dashboard create: env={env_id}, title={dashboard_title}\",\n extra={\"src\": \"seed_superset_load_data\"},\n )\n continue\n\n try:\n payload = {\"dashboard_title\": dashboard_title, \"published\": False}\n created = clients[env_id].network.request(\n \"POST\", \"/dashboard/\", data=json.dumps(payload)\n )\n dashboard_id = _extract_created_id(created)\n if dashboard_id is None:\n raise RuntimeError(f\"Dashboard create response missing id: {created}\")\n created_dashboards[env_id].append(dashboard_id)\n except Exception as exc:\n errors += 1\n logger.explore(f\"Failed creating dashboard in {env_id}: {exc}\", extra={\"src\": \"seed_superset_load_data\"})\n if errors >= args.max_errors:\n raise RuntimeError(\n f\"Stopping due to max errors reached ({errors})\"\n ) from exc\n\n if args.dry_run:\n return {\n \"dry_run\": True,\n \"templates_by_env\": {k: len(v) for k, v in templates_by_env.items()},\n \"charts_target\": args.charts,\n \"dashboards_target\": args.dashboards,\n }\n\n for env_id in env_ids:\n if not created_dashboards[env_id]:\n raise RuntimeError(\n f\"No dashboards created in environment {env_id}; cannot bind charts\"\n )\n\n for index in range(args.charts):\n env_id = rng.choice(env_ids)\n client = clients[env_id]\n template = rng.choice(templates_by_env[env_id])\n dashboard_id = rng.choice(created_dashboards[env_id])\n chart_name = _generate_unique_name(\"lt_chart\", used_chart_names, rng)\n\n payload = {\n \"slice_name\": chart_name,\n \"datasource_id\": template[\"datasource_id\"],\n \"datasource_type\": template[\"datasource_type\"],\n \"dashboards\": [dashboard_id],\n }\n if template.get(\"viz_type\"):\n payload[\"viz_type\"] = template[\"viz_type\"]\n if template.get(\"params\"):\n payload[\"params\"] = template[\"params\"]\n if template.get(\"query_context\"):\n payload[\"query_context\"] = template[\"query_context\"]\n\n try:\n created = client.network.request(\n \"POST\", \"/chart/\", data=json.dumps(payload)\n )\n chart_id = _extract_created_id(created)\n if chart_id is None:\n raise RuntimeError(f\"Chart create response missing id: {created}\")\n created_charts[env_id].append(chart_id)\n\n if (index + 1) % 500 == 0:\n logger.reason(f\"Created {index + 1}/{args.charts} charts\", extra={\"src\": \"seed_superset_load_data\"})\n except Exception as exc:\n errors += 1\n logger.explore(f\"Failed creating chart in {env_id}: {exc}\", extra={\"src\": \"seed_superset_load_data\"})\n if errors >= args.max_errors:\n raise RuntimeError(\n f\"Stopping due to max errors reached ({errors})\"\n ) from exc\n\n return {\n \"dry_run\": False,\n \"errors\": errors,\n \"dashboards\": {env_id: len(ids) for env_id, ids in created_dashboards.items()},\n \"charts\": {env_id: len(ids) for env_id, ids in created_charts.items()},\n \"total_dashboards\": sum(len(ids) for ids in created_dashboards.values()),\n \"total_charts\": sum(len(ids) for ids in created_charts.values()),\n }\n\n\n# #endregion seed_superset_load_data\n\n\n# #region main [TYPE Function]\n# @BRIEF CLI entrypoint for Superset load-test data seeding.\n# @PRE: Command line arguments are valid.\n# @POST: Prints summary and exits with non-zero status on failure.\ndef main() -> None:\n seed_trace_id()\n with belief_scope(\"seed_superset_load_test.main\"):\n args = _parse_args()\n result = seed_superset_load_data(args)\n logger.reflect(\n f\"Result summary: {json.dumps(result, ensure_ascii=True)}\",\n extra={\"src\": \"main\"},\n )\n\n\n# #endregion main\n\n\nif __name__ == \"__main__\":\n main()\n\n# #endregion SeedSupersetLoadTestScript\n" + "body": "# #region SeedSupersetLoadTestScript [C:5] [TYPE Module] [SEMANTICS superset, validate]\n#\n# @BRIEF Creates randomized load-test data in Superset by cloning chart configurations and creating dashboards in target environments.\n# @LAYER: Infrastructure\n# @RELATION USES -> [ConfigManager]\n# @RELATION USES -> [SupersetClient]\n# @INVARIANT: Created chart and dashboard names are globally unique for one script run.\n# @DATA_CONTRACT: CLIArgs -> TestDataSummary\n\nimport argparse\nimport json\nfrom pathlib import Path\nimport random\nimport sys\nimport uuid\n\nsys.path.append(str(Path(__file__).parent.parent.parent))\n\nfrom src.core.config_manager import ConfigManager\nfrom src.core.config_models import Environment\nfrom src.core.cot_logger import seed_trace_id\nfrom src.core.logger import belief_scope, logger\nfrom src.core.superset_client import SupersetClient\n\n\n# #region _parse_args [TYPE Function]\n# @BRIEF Parses CLI arguments for load-test data generation.\n# @PRE: Script is called from CLI.\n# @POST: Returns validated argument namespace.\ndef _parse_args() -> argparse.Namespace:\n parser = argparse.ArgumentParser(\n description=\"Seed Superset with load-test charts and dashboards\"\n )\n parser.add_argument(\n \"--envs\", nargs=\"+\", default=[\"ss1\", \"ss2\"], help=\"Target environment IDs\"\n )\n parser.add_argument(\n \"--charts\", type=int, default=10000, help=\"Target number of charts to create\"\n )\n parser.add_argument(\n \"--dashboards\",\n type=int,\n default=500,\n help=\"Target number of dashboards to create\",\n )\n parser.add_argument(\n \"--template-pool-size\",\n type=int,\n default=200,\n help=\"How many source charts to sample as templates per env\",\n )\n parser.add_argument(\n \"--seed\", type=int, default=None, help=\"Optional RNG seed for reproducibility\"\n )\n parser.add_argument(\n \"--max-errors\",\n type=int,\n default=100,\n help=\"Stop early if errors exceed this threshold\",\n )\n parser.add_argument(\n \"--dry-run\", action=\"store_true\", help=\"Do not write data, only validate setup\"\n )\n return parser.parse_args()\n\n\n# #endregion _parse_args\n\n\n# #region _extract_result_payload [TYPE Function]\n# @BRIEF Normalizes Superset API payloads that may be wrapped in `result`.\n# @PRE: payload is a JSON-decoded API response.\n# @POST: Returns the unwrapped object when present.\ndef _extract_result_payload(payload: dict) -> dict:\n result = payload.get(\"result\")\n if isinstance(result, dict):\n return result\n return payload\n\n\n# #endregion _extract_result_payload\n\n\n# #region _extract_created_id [TYPE Function]\n# @BRIEF Extracts object ID from create/update API response.\n# @PRE: payload is a JSON-decoded API response.\n# @POST: Returns integer object ID or None if missing.\ndef _extract_created_id(payload: dict) -> int | None:\n direct_id = payload.get(\"id\")\n if isinstance(direct_id, int):\n return direct_id\n result = payload.get(\"result\")\n if isinstance(result, dict) and isinstance(result.get(\"id\"), int):\n return int(result[\"id\"])\n return None\n\n\n# #endregion _extract_created_id\n\n\n# #region _generate_unique_name [TYPE Function]\n# @BRIEF Generates globally unique random names for charts/dashboards.\n# @PRE: used_names is mutable set for collision tracking.\n# @POST: Returns a unique string and stores it in used_names.\ndef _generate_unique_name(prefix: str, used_names: set[str], rng: random.Random) -> str:\n adjectives = [\n \"amber\",\n \"rapid\",\n \"frozen\",\n \"delta\",\n \"lunar\",\n \"vector\",\n \"cobalt\",\n \"silent\",\n \"neon\",\n \"solar\",\n ]\n nouns = [\n \"falcon\",\n \"matrix\",\n \"signal\",\n \"harbor\",\n \"stream\",\n \"vertex\",\n \"bridge\",\n \"orbit\",\n \"pulse\",\n \"forge\",\n ]\n while True:\n token = uuid.uuid4().hex[:8]\n candidate = f\"{prefix}_{rng.choice(adjectives)}_{rng.choice(nouns)}_{rng.randint(100, 999)}_{token}\"\n if candidate not in used_names:\n used_names.add(candidate)\n return candidate\n\n\n# #endregion _generate_unique_name\n\n\n# #region _resolve_target_envs [TYPE Function]\n# @BRIEF Resolves requested environment IDs from configuration.\n# @PRE: env_ids is non-empty.\n# @POST: Returns mapping env_id -> configured environment object.\ndef _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]:\n config_manager = ConfigManager()\n configured = {env.id: env for env in config_manager.get_environments()}\n resolved: dict[str, Environment] = {}\n\n if not configured:\n logger.reflect(\n \"No environments found in DB — seed script requires environments configured via API first\",\n extra={\"src\": \"_resolve_target_envs\"},\n )\n\n for env_id in env_ids:\n env = configured.get(env_id)\n if env is None:\n raise ValueError(f\"Environment '{env_id}' not found in configuration\")\n resolved[env_id] = env\n\n return resolved\n\n\n# #endregion _resolve_target_envs\n\n\n# #region _build_chart_template_pool [TYPE Function]\n# @BRIEF Builds a pool of source chart templates to clone in one environment.\n# @PRE: Client is authenticated.\n# @POST: Returns non-empty list of chart payload templates.\ndef _build_chart_template_pool(\n client: SupersetClient, pool_size: int, rng: random.Random\n) -> list[dict]:\n list_query = {\n \"page\": 0,\n \"page_size\": 1000,\n \"columns\": [\n \"id\",\n \"slice_name\",\n \"datasource_id\",\n \"datasource_type\",\n \"viz_type\",\n \"params\",\n \"query_context\",\n ],\n }\n rows = client.network.fetch_paginated_data(\n endpoint=\"/chart/\",\n pagination_options={\"base_query\": list_query, \"results_field\": \"result\"},\n )\n\n candidates = [row for row in rows if isinstance(row, dict) and row.get(\"id\")]\n if not candidates:\n raise RuntimeError(\"No source charts available for templating\")\n\n selected = (\n candidates\n if len(candidates) <= pool_size\n else rng.sample(candidates, pool_size)\n )\n templates: list[dict] = []\n\n for row in selected:\n chart_id = int(row[\"id\"])\n detail_payload = client.get_chart(chart_id)\n detail = _extract_result_payload(detail_payload)\n\n datasource_id = detail.get(\"datasource_id\")\n datasource_type = (\n detail.get(\"datasource_type\") or row.get(\"datasource_type\") or \"table\"\n )\n if datasource_id is None:\n continue\n\n params_value = detail.get(\"params\")\n if isinstance(params_value, dict):\n params_value = json.dumps(params_value)\n\n query_context_value = detail.get(\"query_context\")\n if isinstance(query_context_value, dict):\n query_context_value = json.dumps(query_context_value)\n\n templates.append(\n {\n \"datasource_id\": int(datasource_id),\n \"datasource_type\": str(datasource_type),\n \"viz_type\": detail.get(\"viz_type\") or row.get(\"viz_type\"),\n \"params\": params_value,\n \"query_context\": query_context_value,\n }\n )\n\n if not templates:\n raise RuntimeError(\"Could not build templates with datasource metadata\")\n\n return templates\n\n\n# #endregion _build_chart_template_pool\n\n\n# #region seed_superset_load_data [TYPE Function]\n# @BRIEF Creates dashboards and cloned charts for load testing across target environments.\n# @PRE: Target environments must be reachable and authenticated.\n# @POST: Returns execution statistics dictionary.\n# @SIDE_EFFECT: Creates objects in Superset environments.\ndef seed_superset_load_data(args: argparse.Namespace) -> dict:\n seed_trace_id()\n rng = random.Random(args.seed)\n env_map = _resolve_target_envs(args.envs)\n\n clients: dict[str, SupersetClient] = {}\n templates_by_env: dict[str, list[dict]] = {}\n created_dashboards: dict[str, list[int]] = {env_id: [] for env_id in env_map}\n created_charts: dict[str, list[int]] = {env_id: [] for env_id in env_map}\n used_chart_names: set[str] = set()\n used_dashboard_names: set[str] = set()\n\n for env_id, env in env_map.items():\n client = SupersetClient(env)\n client.authenticate()\n clients[env_id] = client\n templates_by_env[env_id] = _build_chart_template_pool(\n client, args.template_pool_size, rng\n )\n logger.reason(\n f\"Environment {env_id}: loaded {len(templates_by_env[env_id])} chart templates\",\n extra={\"src\": \"seed_superset_load_data\"},\n )\n\n errors = 0\n env_ids = list(env_map.keys())\n\n for idx in range(args.dashboards):\n env_id = (\n env_ids[idx % len(env_ids)] if idx < len(env_ids) else rng.choice(env_ids)\n )\n dashboard_title = _generate_unique_name(\"lt_dash\", used_dashboard_names, rng)\n\n if args.dry_run:\n logger.reflect(\n f\"Dry-run dashboard create: env={env_id}, title={dashboard_title}\",\n extra={\"src\": \"seed_superset_load_data\"},\n )\n continue\n\n try:\n payload = {\"dashboard_title\": dashboard_title, \"published\": False}\n created = clients[env_id].network.request(\n \"POST\", \"/dashboard/\", data=json.dumps(payload)\n )\n dashboard_id = _extract_created_id(created)\n if dashboard_id is None:\n raise RuntimeError(f\"Dashboard create response missing id: {created}\")\n created_dashboards[env_id].append(dashboard_id)\n except Exception as exc:\n errors += 1\n logger.explore(f\"Failed creating dashboard in {env_id}: {exc}\", extra={\"src\": \"seed_superset_load_data\"})\n if errors >= args.max_errors:\n raise RuntimeError(\n f\"Stopping due to max errors reached ({errors})\"\n ) from exc\n\n if args.dry_run:\n return {\n \"dry_run\": True,\n \"templates_by_env\": {k: len(v) for k, v in templates_by_env.items()},\n \"charts_target\": args.charts,\n \"dashboards_target\": args.dashboards,\n }\n\n for env_id in env_ids:\n if not created_dashboards[env_id]:\n raise RuntimeError(\n f\"No dashboards created in environment {env_id}; cannot bind charts\"\n )\n\n for index in range(args.charts):\n env_id = rng.choice(env_ids)\n client = clients[env_id]\n template = rng.choice(templates_by_env[env_id])\n dashboard_id = rng.choice(created_dashboards[env_id])\n chart_name = _generate_unique_name(\"lt_chart\", used_chart_names, rng)\n\n payload = {\n \"slice_name\": chart_name,\n \"datasource_id\": template[\"datasource_id\"],\n \"datasource_type\": template[\"datasource_type\"],\n \"dashboards\": [dashboard_id],\n }\n if template.get(\"viz_type\"):\n payload[\"viz_type\"] = template[\"viz_type\"]\n if template.get(\"params\"):\n payload[\"params\"] = template[\"params\"]\n if template.get(\"query_context\"):\n payload[\"query_context\"] = template[\"query_context\"]\n\n try:\n created = client.network.request(\n \"POST\", \"/chart/\", data=json.dumps(payload)\n )\n chart_id = _extract_created_id(created)\n if chart_id is None:\n raise RuntimeError(f\"Chart create response missing id: {created}\")\n created_charts[env_id].append(chart_id)\n\n if (index + 1) % 500 == 0:\n logger.reason(f\"Created {index + 1}/{args.charts} charts\", extra={\"src\": \"seed_superset_load_data\"})\n except Exception as exc:\n errors += 1\n logger.explore(f\"Failed creating chart in {env_id}: {exc}\", extra={\"src\": \"seed_superset_load_data\"})\n if errors >= args.max_errors:\n raise RuntimeError(\n f\"Stopping due to max errors reached ({errors})\"\n ) from exc\n\n return {\n \"dry_run\": False,\n \"errors\": errors,\n \"dashboards\": {env_id: len(ids) for env_id, ids in created_dashboards.items()},\n \"charts\": {env_id: len(ids) for env_id, ids in created_charts.items()},\n \"total_dashboards\": sum(len(ids) for ids in created_dashboards.values()),\n \"total_charts\": sum(len(ids) for ids in created_charts.values()),\n }\n\n\n# #endregion seed_superset_load_data\n\n\n# #region main [TYPE Function]\n# @BRIEF CLI entrypoint for Superset load-test data seeding.\n# @PRE: Command line arguments are valid.\n# @POST: Prints summary and exits with non-zero status on failure.\ndef main() -> None:\n seed_trace_id()\n with belief_scope(\"seed_superset_load_test.main\"):\n args = _parse_args()\n result = seed_superset_load_data(args)\n logger.reflect(\n f\"Result summary: {json.dumps(result, ensure_ascii=True)}\",\n extra={\"src\": \"main\"},\n )\n\n\n# #endregion main\n\n\nif __name__ == \"__main__\":\n main()\n\n# #endregion SeedSupersetLoadTestScript\n" }, { "contract_id": "_parse_args", @@ -44352,7 +46381,7 @@ "contract_type": "Function", "file_path": "backend/src/scripts/seed_superset_load_test.py", "start_line": 141, - "end_line": 175, + "end_line": 165, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -44364,14 +46393,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region _resolve_target_envs [TYPE Function]\n# @BRIEF Resolves requested environment IDs from configuration.\n# @PRE: env_ids is non-empty.\n# @POST: Returns mapping env_id -> configured environment object.\ndef _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]:\n config_manager = ConfigManager()\n configured = {env.id: env for env in config_manager.get_environments()}\n resolved: dict[str, Environment] = {}\n\n if not configured:\n for config_path in [Path(\"config.json\"), Path(\"backend/config.json\")]:\n if not config_path.exists():\n continue\n try:\n payload = json.loads(config_path.read_text(encoding=\"utf-8\"))\n env_rows = payload.get(\"environments\", [])\n for row in env_rows:\n env = Environment(**row)\n configured[env.id] = env\n except Exception as exc:\n logger.reflect(\n f\"Failed loading environments from {config_path}: {exc}\",\n extra={\"src\": \"_resolve_target_envs\"},\n )\n\n for env_id in env_ids:\n env = configured.get(env_id)\n if env is None:\n raise ValueError(f\"Environment '{env_id}' not found in configuration\")\n resolved[env_id] = env\n\n return resolved\n\n\n# #endregion _resolve_target_envs\n" + "body": "# #region _resolve_target_envs [TYPE Function]\n# @BRIEF Resolves requested environment IDs from configuration.\n# @PRE: env_ids is non-empty.\n# @POST: Returns mapping env_id -> configured environment object.\ndef _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]:\n config_manager = ConfigManager()\n configured = {env.id: env for env in config_manager.get_environments()}\n resolved: dict[str, Environment] = {}\n\n if not configured:\n logger.reflect(\n \"No environments found in DB — seed script requires environments configured via API first\",\n extra={\"src\": \"_resolve_target_envs\"},\n )\n\n for env_id in env_ids:\n env = configured.get(env_id)\n if env is None:\n raise ValueError(f\"Environment '{env_id}' not found in configuration\")\n resolved[env_id] = env\n\n return resolved\n\n\n# #endregion _resolve_target_envs\n" }, { "contract_id": "_build_chart_template_pool", "contract_type": "Function", "file_path": "backend/src/scripts/seed_superset_load_test.py", - "start_line": 178, - "end_line": 250, + "start_line": 168, + "end_line": 240, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -44389,8 +46418,8 @@ "contract_id": "seed_superset_load_data", "contract_type": "Function", "file_path": "backend/src/scripts/seed_superset_load_test.py", - "start_line": 253, - "end_line": 378, + "start_line": 243, + "end_line": 368, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -44409,8 +46438,8 @@ "contract_id": "main", "contract_type": "Function", "file_path": "backend/src/scripts/seed_superset_load_test.py", - "start_line": 381, - "end_line": 396, + "start_line": 371, + "end_line": 386, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -48857,7 +50886,7 @@ "contract_type": "Module", "file_path": "backend/src/services/health_service.py", "start_line": 1, - "end_line": 378, + "end_line": 382, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -48913,14 +50942,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region health_service [C:3] [TYPE Module] [SEMANTICS sqlalchemy, health, dashboard, validation, aggregate]\n# @BRIEF Business logic for aggregating dashboard health status from validation records.\n# @LAYER: Domain/Service\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\n\nimport os\nimport time\nfrom typing import Any, cast\n\nfrom sqlalchemy import func\nfrom sqlalchemy.orm import Session\n\nfrom ..core.logger import logger\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager import TaskManager\nfrom ..core.task_manager.cleanup import TaskCleanupService\nfrom ..models.llm import ValidationRecord\nfrom ..schemas.health import DashboardHealthItem, HealthSummaryResponse\n\n\ndef _empty_dashboard_meta() -> dict[str, str | None]:\n return cast(dict[str, str | None], {\"slug\": None, \"title\": None})\n\n\n# #region HealthService [C:4] [TYPE Class]\n# @BRIEF Aggregate latest dashboard validation state and manage persisted health report lifecycle.\n# @PRE: Service is constructed with a live SQLAlchemy session and optional config manager.\n# @POST: Exposes health summary aggregation and validation report deletion operations.\n# @SIDE_EFFECT: Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.\n# @DATA_CONTRACT: Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [DashboardHealthItem]\n# @RELATION DEPENDS_ON -> [HealthSummaryResponse]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\nclass HealthService:\n _dashboard_summary_cache: dict[\n str, tuple[float, dict[str, dict[str, str | None]]]\n ] = {}\n _dashboard_summary_cache_ttl_seconds = 60.0\n\n \"\"\"\n @PURPOSE: Service for managing and querying dashboard health data.\n \"\"\"\n\n # region HealthService_init [TYPE Function]\n # @PURPOSE: Initialize health service with DB session and optional config access for dashboard metadata resolution.\n # @PRE: db is a valid SQLAlchemy session.\n # @POST: Service is ready to aggregate summaries and delete health reports.\n # @SIDE_EFFECT: Initializes per-instance dashboard metadata cache.\n # @DATA_CONTRACT: Input[db: Session, config_manager: Optional[Any]] -> Output[HealthService]\n # @RELATION: [BINDS_TO] ->[HealthService]\n def __init__(self, db: Session, config_manager=None):\n self.db = db\n self.config_manager = config_manager\n self._dashboard_meta_cache: dict[tuple[str, str], dict[str, str | None]] = {}\n\n # endregion HealthService_init\n\n # region _prime_dashboard_meta_cache [TYPE Function]\n # @PURPOSE: Warm dashboard slug/title cache with one Superset list fetch per environment.\n # @PRE: records may contain mixed numeric and slug dashboard identifiers.\n # @POST: Numeric dashboard ids for known environments are cached when discoverable.\n # @SIDE_EFFECT: May call Superset dashboard list API once per referenced environment.\n # @DATA_CONTRACT: Input[records: List[ValidationRecord]] -> Output[None]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[ConfigManager]\n # @RELATION: [DEPENDS_ON] ->[SupersetClient]\n def _prime_dashboard_meta_cache(self, records: list[ValidationRecord]) -> None:\n if not self.config_manager or not records:\n return\n\n numeric_ids_by_env: dict[str, set[str]] = {}\n for record in records:\n environment_id = str(record.environment_id or \"\").strip()\n dashboard_id = str(record.dashboard_id or \"\").strip()\n if not environment_id or not dashboard_id or not dashboard_id.isdigit():\n continue\n cache_key = (environment_id, dashboard_id)\n if cache_key in self._dashboard_meta_cache:\n continue\n numeric_ids_by_env.setdefault(environment_id, set()).add(dashboard_id)\n\n if not numeric_ids_by_env:\n return\n\n environments = {\n str(getattr(env, \"id\", \"\")).strip(): env\n for env in self.config_manager.get_environments()\n if str(getattr(env, \"id\", \"\")).strip()\n }\n\n for environment_id, dashboard_ids in numeric_ids_by_env.items():\n env = environments.get(environment_id)\n if not env:\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n continue\n\n try:\n cached_meta = self.__class__._dashboard_summary_cache.get(\n environment_id\n )\n dashboard_meta_map: dict[str, dict[str, str | None]]\n if (\n cached_meta is not None\n and (time.monotonic() - cached_meta[0])\n < self.__class__._dashboard_summary_cache_ttl_seconds\n ):\n cached_meta_data = cast(\n tuple[float, dict[str, dict[str, str | None]]],\n cached_meta,\n )\n dashboard_meta_map = cached_meta_data[1]\n else:\n dashboards = SupersetClient(env).get_dashboards_summary()\n dashboard_meta_map = {\n str(item.get(\"id\")): {\n \"slug\": item.get(\"slug\"),\n \"title\": item.get(\"title\"),\n }\n for item in dashboards\n if str(item.get(\"id\") or \"\").strip()\n }\n self.__class__._dashboard_summary_cache[environment_id] = (\n time.monotonic(),\n dashboard_meta_map,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n dashboard_meta_map.get(\n dashboard_id,\n _empty_dashboard_meta(),\n )\n )\n except Exception as exc:\n logger.warning(\n \"[HealthService][_prime_dashboard_meta_cache] Failed to preload dashboard metadata for env=%s: %s\",\n environment_id,\n exc,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n\n # endregion _prime_dashboard_meta_cache\n\n # region _resolve_dashboard_meta [TYPE Function]\n # @PURPOSE: Resolve slug/title for a dashboard referenced by persisted validation record.\n # @PRE: dashboard_id may be numeric or slug-like; environment_id may be empty.\n # @POST: Returns dict with `slug` and `title` keys, using cache when possible.\n # @SIDE_EFFECT: Writes default cache entries for unresolved numeric dashboard ids.\n def _resolve_dashboard_meta(\n self, dashboard_id: str, environment_id: str | None\n ) -> dict[str, str | None]:\n normalized_dashboard_id = str(dashboard_id or \"\").strip()\n normalized_environment_id = str(environment_id or \"\").strip()\n if not normalized_dashboard_id:\n return _empty_dashboard_meta()\n\n if not normalized_dashboard_id.isdigit():\n return {\"slug\": normalized_dashboard_id, \"title\": None}\n\n if not self.config_manager or not normalized_environment_id:\n return _empty_dashboard_meta()\n\n cache_key = (normalized_environment_id, normalized_dashboard_id)\n cached = self._dashboard_meta_cache.get(cache_key)\n if cached is not None:\n return cached\n\n meta = _empty_dashboard_meta()\n self._dashboard_meta_cache[cache_key] = meta\n return meta\n\n # endregion _resolve_dashboard_meta\n\n # region get_health_summary [TYPE Function]\n # @PURPOSE: Aggregate latest validation status per dashboard and enrich rows with dashboard slug/title.\n # @PRE: environment_id may be omitted to aggregate across all environments.\n # @POST: Returns HealthSummaryResponse with counts and latest record row per dashboard.\n # @SIDE_EFFECT: May call Superset API to resolve dashboard metadata.\n # @DATA_CONTRACT: Input[environment_id: Optional[str]] -> Output[HealthSummaryResponse]\n # @RELATION: [CALLS] ->[_prime_dashboard_meta_cache]\n # @RELATION: [CALLS] ->[_resolve_dashboard_meta]\n async def get_health_summary(\n self, environment_id: str = \"\"\n ) -> HealthSummaryResponse:\n \"\"\"\n @PURPOSE: Aggregates the latest validation status for all dashboards.\n @PRE: environment_id (optional) to filter by environment.\n @POST: Returns a HealthSummaryResponse with aggregated status counts and items.\n \"\"\"\n # [REASON] We need the latest ValidationRecord for each unique dashboard_id.\n # We use a subquery to find the max timestamp per dashboard_id.\n\n subquery = self.db.query(\n ValidationRecord.dashboard_id,\n func.max(ValidationRecord.timestamp).label(\"max_ts\"),\n )\n if environment_id:\n subquery = subquery.filter(\n ValidationRecord.environment_id == environment_id\n )\n subquery = subquery.group_by(ValidationRecord.dashboard_id).subquery()\n\n query = self.db.query(ValidationRecord).join(\n subquery,\n (ValidationRecord.dashboard_id == subquery.c.dashboard_id)\n & (ValidationRecord.timestamp == subquery.c.max_ts),\n )\n\n records = query.all()\n\n self._prime_dashboard_meta_cache(records)\n\n items = []\n pass_count = 0\n warn_count = 0\n fail_count = 0\n unknown_count = 0\n\n for rec in records:\n record = cast(Any, rec)\n status = str(record.status or \"\").upper()\n if status == \"PASS\":\n pass_count += 1\n elif status == \"WARN\":\n warn_count += 1\n elif status == \"FAIL\":\n fail_count += 1\n else:\n unknown_count += 1\n status = \"UNKNOWN\"\n\n record_id = str(record.id or \"\")\n dashboard_id = str(record.dashboard_id or \"\")\n resolved_environment_id = (\n str(record.environment_id)\n if record.environment_id is not None\n else None\n )\n response_environment_id = (\n resolved_environment_id\n if resolved_environment_id is not None\n else \"unknown\"\n )\n task_id = str(record.task_id) if record.task_id is not None else None\n summary = str(record.summary) if record.summary is not None else None\n timestamp = cast(Any, record.timestamp)\n\n meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id)\n items.append(\n DashboardHealthItem(\n record_id=record_id,\n dashboard_id=dashboard_id,\n dashboard_slug=meta.get(\"slug\"),\n dashboard_title=meta.get(\"title\"),\n environment_id=response_environment_id,\n status=status,\n last_check=timestamp,\n task_id=task_id,\n summary=summary,\n )\n )\n\n logger.info(\n f\"[HealthService][get_health_summary] Aggregated {len(items)} dashboard health records.\"\n )\n\n return HealthSummaryResponse(\n items=items,\n pass_count=pass_count,\n warn_count=warn_count,\n fail_count=fail_count,\n unknown_count=unknown_count,\n )\n\n # endregion get_health_summary\n\n # region delete_validation_report [TYPE Function]\n # @PURPOSE: Delete one persisted health report and optionally clean linked task/log artifacts.\n # @PRE: record_id is a validation record identifier.\n # @POST: Returns True only when a matching record was deleted.\n # @SIDE_EFFECT: Deletes DB rows, optional screenshot file, and optional task/log persistence.\n # @DATA_CONTRACT: Input[record_id: str, task_manager: Optional[TaskManager]] -> Output[bool]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[TaskManager]\n # @RELATION: [DEPENDS_ON] ->[TaskCleanupService]\n def delete_validation_report(\n self, record_id: str, task_manager: TaskManager | None = None\n ) -> bool:\n record = (\n self.db.query(ValidationRecord)\n .filter(ValidationRecord.id == record_id)\n .first()\n )\n if not record:\n return False\n\n peer_query = self.db.query(ValidationRecord).filter(\n ValidationRecord.dashboard_id == record.dashboard_id\n )\n if record.environment_id is None:\n peer_query = peer_query.filter(ValidationRecord.environment_id.is_(None))\n else:\n peer_query = peer_query.filter(\n ValidationRecord.environment_id == record.environment_id\n )\n\n records_to_delete = peer_query.all()\n screenshot_paths = [\n str(item.screenshot_path or \"\").strip()\n for item in records_to_delete\n if str(item.screenshot_path or \"\").strip()\n ]\n task_ids = {\n str(item.task_id or \"\").strip()\n for item in records_to_delete\n if str(item.task_id or \"\").strip()\n }\n\n logger.info(\n \"[HealthService][delete_validation_report] Removing %s validation record(s) for dashboard=%s environment=%s triggered_by_record=%s\",\n len(records_to_delete),\n record.dashboard_id,\n record.environment_id,\n record_id,\n )\n\n for item in records_to_delete:\n self.db.delete(item)\n self.db.commit()\n\n for screenshot_path in screenshot_paths:\n try:\n if os.path.exists(screenshot_path):\n os.remove(screenshot_path)\n except OSError as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to remove screenshot %s: %s\",\n screenshot_path,\n exc,\n )\n\n if task_ids and task_manager and self.config_manager:\n try:\n cleanup_service = TaskCleanupService(\n task_manager.persistence_service,\n task_manager.log_persistence_service,\n self.config_manager,\n )\n for task_id in task_ids:\n task_manager.tasks.pop(task_id, None)\n cleanup_service.delete_task_with_logs(task_id)\n except Exception as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to cleanup linked task/logs for dashboard=%s environment=%s: %s\",\n record.dashboard_id,\n record.environment_id,\n exc,\n )\n\n return True\n\n # endregion delete_validation_report\n\n\n# #endregion HealthService\n\n# #endregion health_service\n" + "body": "# #region health_service [C:3] [TYPE Module] [SEMANTICS sqlalchemy, health, dashboard, validation, aggregate]\n# @BRIEF Business logic for aggregating dashboard health status from validation records.\n# @LAYER: Domain/Service\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\n\nfrom datetime import UTC\nimport os\nimport time\nfrom typing import Any, cast\n\nfrom sqlalchemy import func\nfrom sqlalchemy.orm import Session\n\nfrom ..core.logger import logger\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager import TaskManager\nfrom ..core.task_manager.cleanup import TaskCleanupService\nfrom ..models.llm import ValidationRecord\nfrom ..schemas.health import DashboardHealthItem, HealthSummaryResponse\n\n\ndef _empty_dashboard_meta() -> dict[str, str | None]:\n return cast(dict[str, str | None], {\"slug\": None, \"title\": None})\n\n\n# #region HealthService [C:4] [TYPE Class]\n# @BRIEF Aggregate latest dashboard validation state and manage persisted health report lifecycle.\n# @PRE: Service is constructed with a live SQLAlchemy session and optional config manager.\n# @POST: Exposes health summary aggregation and validation report deletion operations.\n# @SIDE_EFFECT: Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.\n# @DATA_CONTRACT: Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [DashboardHealthItem]\n# @RELATION DEPENDS_ON -> [HealthSummaryResponse]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\nclass HealthService:\n _dashboard_summary_cache: dict[\n str, tuple[float, dict[str, dict[str, str | None]]]\n ] = {}\n _dashboard_summary_cache_ttl_seconds = 60.0\n\n \"\"\"\n @PURPOSE: Service for managing and querying dashboard health data.\n \"\"\"\n\n # region HealthService_init [TYPE Function]\n # @PURPOSE: Initialize health service with DB session and optional config access for dashboard metadata resolution.\n # @PRE: db is a valid SQLAlchemy session.\n # @POST: Service is ready to aggregate summaries and delete health reports.\n # @SIDE_EFFECT: Initializes per-instance dashboard metadata cache.\n # @DATA_CONTRACT: Input[db: Session, config_manager: Optional[Any]] -> Output[HealthService]\n # @RELATION: [BINDS_TO] ->[HealthService]\n def __init__(self, db: Session, config_manager=None):\n self.db = db\n self.config_manager = config_manager\n self._dashboard_meta_cache: dict[tuple[str, str], dict[str, str | None]] = {}\n\n # endregion HealthService_init\n\n # region _prime_dashboard_meta_cache [TYPE Function]\n # @PURPOSE: Warm dashboard slug/title cache with one Superset list fetch per environment.\n # @PRE: records may contain mixed numeric and slug dashboard identifiers.\n # @POST: Numeric dashboard ids for known environments are cached when discoverable.\n # @SIDE_EFFECT: May call Superset dashboard list API once per referenced environment.\n # @DATA_CONTRACT: Input[records: List[ValidationRecord]] -> Output[None]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[ConfigManager]\n # @RELATION: [DEPENDS_ON] ->[SupersetClient]\n def _prime_dashboard_meta_cache(self, records: list[ValidationRecord]) -> None:\n if not self.config_manager or not records:\n return\n\n numeric_ids_by_env: dict[str, set[str]] = {}\n for record in records:\n environment_id = str(record.environment_id or \"\").strip()\n dashboard_id = str(record.dashboard_id or \"\").strip()\n if not environment_id or not dashboard_id or not dashboard_id.isdigit():\n continue\n cache_key = (environment_id, dashboard_id)\n if cache_key in self._dashboard_meta_cache:\n continue\n numeric_ids_by_env.setdefault(environment_id, set()).add(dashboard_id)\n\n if not numeric_ids_by_env:\n return\n\n environments = {\n str(getattr(env, \"id\", \"\")).strip(): env\n for env in self.config_manager.get_environments()\n if str(getattr(env, \"id\", \"\")).strip()\n }\n\n for environment_id, dashboard_ids in numeric_ids_by_env.items():\n env = environments.get(environment_id)\n if not env:\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n continue\n\n try:\n cached_meta = self.__class__._dashboard_summary_cache.get(\n environment_id\n )\n dashboard_meta_map: dict[str, dict[str, str | None]]\n if (\n cached_meta is not None\n and (time.monotonic() - cached_meta[0])\n < self.__class__._dashboard_summary_cache_ttl_seconds\n ):\n cached_meta_data = cast(\n tuple[float, dict[str, dict[str, str | None]]],\n cached_meta,\n )\n dashboard_meta_map = cached_meta_data[1]\n else:\n dashboards = SupersetClient(env).get_dashboards_summary()\n dashboard_meta_map = {\n str(item.get(\"id\")): {\n \"slug\": item.get(\"slug\"),\n \"title\": item.get(\"title\"),\n }\n for item in dashboards\n if str(item.get(\"id\") or \"\").strip()\n }\n self.__class__._dashboard_summary_cache[environment_id] = (\n time.monotonic(),\n dashboard_meta_map,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n dashboard_meta_map.get(\n dashboard_id,\n _empty_dashboard_meta(),\n )\n )\n except Exception as exc:\n logger.warning(\n \"[HealthService][_prime_dashboard_meta_cache] Failed to preload dashboard metadata for env=%s: %s\",\n environment_id,\n exc,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n\n # endregion _prime_dashboard_meta_cache\n\n # region _resolve_dashboard_meta [TYPE Function]\n # @PURPOSE: Resolve slug/title for a dashboard referenced by persisted validation record.\n # @PRE: dashboard_id may be numeric or slug-like; environment_id may be empty.\n # @POST: Returns dict with `slug` and `title` keys, using cache when possible.\n # @SIDE_EFFECT: Writes default cache entries for unresolved numeric dashboard ids.\n def _resolve_dashboard_meta(\n self, dashboard_id: str, environment_id: str | None\n ) -> dict[str, str | None]:\n normalized_dashboard_id = str(dashboard_id or \"\").strip()\n normalized_environment_id = str(environment_id or \"\").strip()\n if not normalized_dashboard_id:\n return _empty_dashboard_meta()\n\n if not normalized_dashboard_id.isdigit():\n return {\"slug\": normalized_dashboard_id, \"title\": None}\n\n if not self.config_manager or not normalized_environment_id:\n return _empty_dashboard_meta()\n\n cache_key = (normalized_environment_id, normalized_dashboard_id)\n cached = self._dashboard_meta_cache.get(cache_key)\n if cached is not None:\n return cached\n\n meta = _empty_dashboard_meta()\n self._dashboard_meta_cache[cache_key] = meta\n return meta\n\n # endregion _resolve_dashboard_meta\n\n # region get_health_summary [TYPE Function]\n # @PURPOSE: Aggregate latest validation status per dashboard and enrich rows with dashboard slug/title.\n # @PRE: environment_id may be omitted to aggregate across all environments.\n # @POST: Returns HealthSummaryResponse with counts and latest record row per dashboard.\n # @SIDE_EFFECT: May call Superset API to resolve dashboard metadata.\n # @DATA_CONTRACT: Input[environment_id: Optional[str]] -> Output[HealthSummaryResponse]\n # @RELATION: [CALLS] ->[_prime_dashboard_meta_cache]\n # @RELATION: [CALLS] ->[_resolve_dashboard_meta]\n async def get_health_summary(\n self, environment_id: str = \"\"\n ) -> HealthSummaryResponse:\n \"\"\"\n @PURPOSE: Aggregates the latest validation status for all dashboards.\n @PRE: environment_id (optional) to filter by environment.\n @POST: Returns a HealthSummaryResponse with aggregated status counts and items.\n \"\"\"\n # [REASON] We need the latest ValidationRecord for each unique dashboard_id.\n # We use a subquery to find the max timestamp per dashboard_id.\n\n subquery = self.db.query(\n ValidationRecord.dashboard_id,\n func.max(ValidationRecord.timestamp).label(\"max_ts\"),\n )\n if environment_id:\n subquery = subquery.filter(\n ValidationRecord.environment_id == environment_id\n )\n subquery = subquery.group_by(ValidationRecord.dashboard_id).subquery()\n\n query = self.db.query(ValidationRecord).join(\n subquery,\n (ValidationRecord.dashboard_id == subquery.c.dashboard_id)\n & (ValidationRecord.timestamp == subquery.c.max_ts),\n )\n\n records = query.all()\n\n self._prime_dashboard_meta_cache(records)\n\n items = []\n pass_count = 0\n warn_count = 0\n fail_count = 0\n unknown_count = 0\n\n for rec in records:\n record = cast(Any, rec)\n status = str(record.status or \"\").upper()\n if status == \"PASS\":\n pass_count += 1\n elif status == \"WARN\":\n warn_count += 1\n elif status == \"FAIL\":\n fail_count += 1\n else:\n unknown_count += 1\n status = \"UNKNOWN\"\n\n record_id = str(record.id or \"\")\n dashboard_id = str(record.dashboard_id or \"\")\n resolved_environment_id = (\n str(record.environment_id)\n if record.environment_id is not None\n else None\n )\n response_environment_id = (\n resolved_environment_id\n if resolved_environment_id is not None\n else \"unknown\"\n )\n task_id = str(record.task_id) if record.task_id is not None else None\n summary = str(record.summary) if record.summary is not None else None\n timestamp = cast(Any, record.timestamp)\n # Ensure timestamp is timezone-aware (DB stores naive UTC)\n if timestamp is not None and timestamp.tzinfo is None:\n timestamp = timestamp.replace(tzinfo=UTC)\n\n meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id)\n items.append(\n DashboardHealthItem(\n record_id=record_id,\n dashboard_id=dashboard_id,\n dashboard_slug=meta.get(\"slug\"),\n dashboard_title=meta.get(\"title\"),\n environment_id=response_environment_id,\n status=status,\n last_check=timestamp,\n task_id=task_id,\n summary=summary,\n )\n )\n\n logger.info(\n f\"[HealthService][get_health_summary] Aggregated {len(items)} dashboard health records.\"\n )\n\n return HealthSummaryResponse(\n items=items,\n pass_count=pass_count,\n warn_count=warn_count,\n fail_count=fail_count,\n unknown_count=unknown_count,\n )\n\n # endregion get_health_summary\n\n # region delete_validation_report [TYPE Function]\n # @PURPOSE: Delete one persisted health report and optionally clean linked task/log artifacts.\n # @PRE: record_id is a validation record identifier.\n # @POST: Returns True only when a matching record was deleted.\n # @SIDE_EFFECT: Deletes DB rows, optional screenshot file, and optional task/log persistence.\n # @DATA_CONTRACT: Input[record_id: str, task_manager: Optional[TaskManager]] -> Output[bool]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[TaskManager]\n # @RELATION: [DEPENDS_ON] ->[TaskCleanupService]\n def delete_validation_report(\n self, record_id: str, task_manager: TaskManager | None = None\n ) -> bool:\n record = (\n self.db.query(ValidationRecord)\n .filter(ValidationRecord.id == record_id)\n .first()\n )\n if not record:\n return False\n\n peer_query = self.db.query(ValidationRecord).filter(\n ValidationRecord.dashboard_id == record.dashboard_id\n )\n if record.environment_id is None:\n peer_query = peer_query.filter(ValidationRecord.environment_id.is_(None))\n else:\n peer_query = peer_query.filter(\n ValidationRecord.environment_id == record.environment_id\n )\n\n records_to_delete = peer_query.all()\n screenshot_paths = [\n str(item.screenshot_path or \"\").strip()\n for item in records_to_delete\n if str(item.screenshot_path or \"\").strip()\n ]\n task_ids = {\n str(item.task_id or \"\").strip()\n for item in records_to_delete\n if str(item.task_id or \"\").strip()\n }\n\n logger.info(\n \"[HealthService][delete_validation_report] Removing %s validation record(s) for dashboard=%s environment=%s triggered_by_record=%s\",\n len(records_to_delete),\n record.dashboard_id,\n record.environment_id,\n record_id,\n )\n\n for item in records_to_delete:\n self.db.delete(item)\n self.db.commit()\n\n for screenshot_path in screenshot_paths:\n try:\n if os.path.exists(screenshot_path):\n os.remove(screenshot_path)\n except OSError as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to remove screenshot %s: %s\",\n screenshot_path,\n exc,\n )\n\n if task_ids and task_manager and self.config_manager:\n try:\n cleanup_service = TaskCleanupService(\n task_manager.persistence_service,\n task_manager.log_persistence_service,\n self.config_manager,\n )\n for task_id in task_ids:\n task_manager.tasks.pop(task_id, None)\n cleanup_service.delete_task_with_logs(task_id)\n except Exception as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to cleanup linked task/logs for dashboard=%s environment=%s: %s\",\n record.dashboard_id,\n record.environment_id,\n exc,\n )\n\n return True\n\n # endregion delete_validation_report\n\n\n# #endregion HealthService\n\n# #endregion health_service\n" }, { "contract_id": "HealthService", "contract_type": "Class", "file_path": "backend/src/services/health_service.py", - "start_line": 28, - "end_line": 376, + "start_line": 29, + "end_line": 380, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -48972,7 +51001,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region HealthService [C:4] [TYPE Class]\n# @BRIEF Aggregate latest dashboard validation state and manage persisted health report lifecycle.\n# @PRE: Service is constructed with a live SQLAlchemy session and optional config manager.\n# @POST: Exposes health summary aggregation and validation report deletion operations.\n# @SIDE_EFFECT: Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.\n# @DATA_CONTRACT: Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [DashboardHealthItem]\n# @RELATION DEPENDS_ON -> [HealthSummaryResponse]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\nclass HealthService:\n _dashboard_summary_cache: dict[\n str, tuple[float, dict[str, dict[str, str | None]]]\n ] = {}\n _dashboard_summary_cache_ttl_seconds = 60.0\n\n \"\"\"\n @PURPOSE: Service for managing and querying dashboard health data.\n \"\"\"\n\n # region HealthService_init [TYPE Function]\n # @PURPOSE: Initialize health service with DB session and optional config access for dashboard metadata resolution.\n # @PRE: db is a valid SQLAlchemy session.\n # @POST: Service is ready to aggregate summaries and delete health reports.\n # @SIDE_EFFECT: Initializes per-instance dashboard metadata cache.\n # @DATA_CONTRACT: Input[db: Session, config_manager: Optional[Any]] -> Output[HealthService]\n # @RELATION: [BINDS_TO] ->[HealthService]\n def __init__(self, db: Session, config_manager=None):\n self.db = db\n self.config_manager = config_manager\n self._dashboard_meta_cache: dict[tuple[str, str], dict[str, str | None]] = {}\n\n # endregion HealthService_init\n\n # region _prime_dashboard_meta_cache [TYPE Function]\n # @PURPOSE: Warm dashboard slug/title cache with one Superset list fetch per environment.\n # @PRE: records may contain mixed numeric and slug dashboard identifiers.\n # @POST: Numeric dashboard ids for known environments are cached when discoverable.\n # @SIDE_EFFECT: May call Superset dashboard list API once per referenced environment.\n # @DATA_CONTRACT: Input[records: List[ValidationRecord]] -> Output[None]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[ConfigManager]\n # @RELATION: [DEPENDS_ON] ->[SupersetClient]\n def _prime_dashboard_meta_cache(self, records: list[ValidationRecord]) -> None:\n if not self.config_manager or not records:\n return\n\n numeric_ids_by_env: dict[str, set[str]] = {}\n for record in records:\n environment_id = str(record.environment_id or \"\").strip()\n dashboard_id = str(record.dashboard_id or \"\").strip()\n if not environment_id or not dashboard_id or not dashboard_id.isdigit():\n continue\n cache_key = (environment_id, dashboard_id)\n if cache_key in self._dashboard_meta_cache:\n continue\n numeric_ids_by_env.setdefault(environment_id, set()).add(dashboard_id)\n\n if not numeric_ids_by_env:\n return\n\n environments = {\n str(getattr(env, \"id\", \"\")).strip(): env\n for env in self.config_manager.get_environments()\n if str(getattr(env, \"id\", \"\")).strip()\n }\n\n for environment_id, dashboard_ids in numeric_ids_by_env.items():\n env = environments.get(environment_id)\n if not env:\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n continue\n\n try:\n cached_meta = self.__class__._dashboard_summary_cache.get(\n environment_id\n )\n dashboard_meta_map: dict[str, dict[str, str | None]]\n if (\n cached_meta is not None\n and (time.monotonic() - cached_meta[0])\n < self.__class__._dashboard_summary_cache_ttl_seconds\n ):\n cached_meta_data = cast(\n tuple[float, dict[str, dict[str, str | None]]],\n cached_meta,\n )\n dashboard_meta_map = cached_meta_data[1]\n else:\n dashboards = SupersetClient(env).get_dashboards_summary()\n dashboard_meta_map = {\n str(item.get(\"id\")): {\n \"slug\": item.get(\"slug\"),\n \"title\": item.get(\"title\"),\n }\n for item in dashboards\n if str(item.get(\"id\") or \"\").strip()\n }\n self.__class__._dashboard_summary_cache[environment_id] = (\n time.monotonic(),\n dashboard_meta_map,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n dashboard_meta_map.get(\n dashboard_id,\n _empty_dashboard_meta(),\n )\n )\n except Exception as exc:\n logger.warning(\n \"[HealthService][_prime_dashboard_meta_cache] Failed to preload dashboard metadata for env=%s: %s\",\n environment_id,\n exc,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n\n # endregion _prime_dashboard_meta_cache\n\n # region _resolve_dashboard_meta [TYPE Function]\n # @PURPOSE: Resolve slug/title for a dashboard referenced by persisted validation record.\n # @PRE: dashboard_id may be numeric or slug-like; environment_id may be empty.\n # @POST: Returns dict with `slug` and `title` keys, using cache when possible.\n # @SIDE_EFFECT: Writes default cache entries for unresolved numeric dashboard ids.\n def _resolve_dashboard_meta(\n self, dashboard_id: str, environment_id: str | None\n ) -> dict[str, str | None]:\n normalized_dashboard_id = str(dashboard_id or \"\").strip()\n normalized_environment_id = str(environment_id or \"\").strip()\n if not normalized_dashboard_id:\n return _empty_dashboard_meta()\n\n if not normalized_dashboard_id.isdigit():\n return {\"slug\": normalized_dashboard_id, \"title\": None}\n\n if not self.config_manager or not normalized_environment_id:\n return _empty_dashboard_meta()\n\n cache_key = (normalized_environment_id, normalized_dashboard_id)\n cached = self._dashboard_meta_cache.get(cache_key)\n if cached is not None:\n return cached\n\n meta = _empty_dashboard_meta()\n self._dashboard_meta_cache[cache_key] = meta\n return meta\n\n # endregion _resolve_dashboard_meta\n\n # region get_health_summary [TYPE Function]\n # @PURPOSE: Aggregate latest validation status per dashboard and enrich rows with dashboard slug/title.\n # @PRE: environment_id may be omitted to aggregate across all environments.\n # @POST: Returns HealthSummaryResponse with counts and latest record row per dashboard.\n # @SIDE_EFFECT: May call Superset API to resolve dashboard metadata.\n # @DATA_CONTRACT: Input[environment_id: Optional[str]] -> Output[HealthSummaryResponse]\n # @RELATION: [CALLS] ->[_prime_dashboard_meta_cache]\n # @RELATION: [CALLS] ->[_resolve_dashboard_meta]\n async def get_health_summary(\n self, environment_id: str = \"\"\n ) -> HealthSummaryResponse:\n \"\"\"\n @PURPOSE: Aggregates the latest validation status for all dashboards.\n @PRE: environment_id (optional) to filter by environment.\n @POST: Returns a HealthSummaryResponse with aggregated status counts and items.\n \"\"\"\n # [REASON] We need the latest ValidationRecord for each unique dashboard_id.\n # We use a subquery to find the max timestamp per dashboard_id.\n\n subquery = self.db.query(\n ValidationRecord.dashboard_id,\n func.max(ValidationRecord.timestamp).label(\"max_ts\"),\n )\n if environment_id:\n subquery = subquery.filter(\n ValidationRecord.environment_id == environment_id\n )\n subquery = subquery.group_by(ValidationRecord.dashboard_id).subquery()\n\n query = self.db.query(ValidationRecord).join(\n subquery,\n (ValidationRecord.dashboard_id == subquery.c.dashboard_id)\n & (ValidationRecord.timestamp == subquery.c.max_ts),\n )\n\n records = query.all()\n\n self._prime_dashboard_meta_cache(records)\n\n items = []\n pass_count = 0\n warn_count = 0\n fail_count = 0\n unknown_count = 0\n\n for rec in records:\n record = cast(Any, rec)\n status = str(record.status or \"\").upper()\n if status == \"PASS\":\n pass_count += 1\n elif status == \"WARN\":\n warn_count += 1\n elif status == \"FAIL\":\n fail_count += 1\n else:\n unknown_count += 1\n status = \"UNKNOWN\"\n\n record_id = str(record.id or \"\")\n dashboard_id = str(record.dashboard_id or \"\")\n resolved_environment_id = (\n str(record.environment_id)\n if record.environment_id is not None\n else None\n )\n response_environment_id = (\n resolved_environment_id\n if resolved_environment_id is not None\n else \"unknown\"\n )\n task_id = str(record.task_id) if record.task_id is not None else None\n summary = str(record.summary) if record.summary is not None else None\n timestamp = cast(Any, record.timestamp)\n\n meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id)\n items.append(\n DashboardHealthItem(\n record_id=record_id,\n dashboard_id=dashboard_id,\n dashboard_slug=meta.get(\"slug\"),\n dashboard_title=meta.get(\"title\"),\n environment_id=response_environment_id,\n status=status,\n last_check=timestamp,\n task_id=task_id,\n summary=summary,\n )\n )\n\n logger.info(\n f\"[HealthService][get_health_summary] Aggregated {len(items)} dashboard health records.\"\n )\n\n return HealthSummaryResponse(\n items=items,\n pass_count=pass_count,\n warn_count=warn_count,\n fail_count=fail_count,\n unknown_count=unknown_count,\n )\n\n # endregion get_health_summary\n\n # region delete_validation_report [TYPE Function]\n # @PURPOSE: Delete one persisted health report and optionally clean linked task/log artifacts.\n # @PRE: record_id is a validation record identifier.\n # @POST: Returns True only when a matching record was deleted.\n # @SIDE_EFFECT: Deletes DB rows, optional screenshot file, and optional task/log persistence.\n # @DATA_CONTRACT: Input[record_id: str, task_manager: Optional[TaskManager]] -> Output[bool]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[TaskManager]\n # @RELATION: [DEPENDS_ON] ->[TaskCleanupService]\n def delete_validation_report(\n self, record_id: str, task_manager: TaskManager | None = None\n ) -> bool:\n record = (\n self.db.query(ValidationRecord)\n .filter(ValidationRecord.id == record_id)\n .first()\n )\n if not record:\n return False\n\n peer_query = self.db.query(ValidationRecord).filter(\n ValidationRecord.dashboard_id == record.dashboard_id\n )\n if record.environment_id is None:\n peer_query = peer_query.filter(ValidationRecord.environment_id.is_(None))\n else:\n peer_query = peer_query.filter(\n ValidationRecord.environment_id == record.environment_id\n )\n\n records_to_delete = peer_query.all()\n screenshot_paths = [\n str(item.screenshot_path or \"\").strip()\n for item in records_to_delete\n if str(item.screenshot_path or \"\").strip()\n ]\n task_ids = {\n str(item.task_id or \"\").strip()\n for item in records_to_delete\n if str(item.task_id or \"\").strip()\n }\n\n logger.info(\n \"[HealthService][delete_validation_report] Removing %s validation record(s) for dashboard=%s environment=%s triggered_by_record=%s\",\n len(records_to_delete),\n record.dashboard_id,\n record.environment_id,\n record_id,\n )\n\n for item in records_to_delete:\n self.db.delete(item)\n self.db.commit()\n\n for screenshot_path in screenshot_paths:\n try:\n if os.path.exists(screenshot_path):\n os.remove(screenshot_path)\n except OSError as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to remove screenshot %s: %s\",\n screenshot_path,\n exc,\n )\n\n if task_ids and task_manager and self.config_manager:\n try:\n cleanup_service = TaskCleanupService(\n task_manager.persistence_service,\n task_manager.log_persistence_service,\n self.config_manager,\n )\n for task_id in task_ids:\n task_manager.tasks.pop(task_id, None)\n cleanup_service.delete_task_with_logs(task_id)\n except Exception as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to cleanup linked task/logs for dashboard=%s environment=%s: %s\",\n record.dashboard_id,\n record.environment_id,\n exc,\n )\n\n return True\n\n # endregion delete_validation_report\n\n\n# #endregion HealthService\n" + "body": "# #region HealthService [C:4] [TYPE Class]\n# @BRIEF Aggregate latest dashboard validation state and manage persisted health report lifecycle.\n# @PRE: Service is constructed with a live SQLAlchemy session and optional config manager.\n# @POST: Exposes health summary aggregation and validation report deletion operations.\n# @SIDE_EFFECT: Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.\n# @DATA_CONTRACT: Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]\n# @RELATION DEPENDS_ON -> [ValidationRecord]\n# @RELATION DEPENDS_ON -> [DashboardHealthItem]\n# @RELATION DEPENDS_ON -> [HealthSummaryResponse]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskCleanupService]\n# @RELATION DEPENDS_ON -> [TaskManager]\nclass HealthService:\n _dashboard_summary_cache: dict[\n str, tuple[float, dict[str, dict[str, str | None]]]\n ] = {}\n _dashboard_summary_cache_ttl_seconds = 60.0\n\n \"\"\"\n @PURPOSE: Service for managing and querying dashboard health data.\n \"\"\"\n\n # region HealthService_init [TYPE Function]\n # @PURPOSE: Initialize health service with DB session and optional config access for dashboard metadata resolution.\n # @PRE: db is a valid SQLAlchemy session.\n # @POST: Service is ready to aggregate summaries and delete health reports.\n # @SIDE_EFFECT: Initializes per-instance dashboard metadata cache.\n # @DATA_CONTRACT: Input[db: Session, config_manager: Optional[Any]] -> Output[HealthService]\n # @RELATION: [BINDS_TO] ->[HealthService]\n def __init__(self, db: Session, config_manager=None):\n self.db = db\n self.config_manager = config_manager\n self._dashboard_meta_cache: dict[tuple[str, str], dict[str, str | None]] = {}\n\n # endregion HealthService_init\n\n # region _prime_dashboard_meta_cache [TYPE Function]\n # @PURPOSE: Warm dashboard slug/title cache with one Superset list fetch per environment.\n # @PRE: records may contain mixed numeric and slug dashboard identifiers.\n # @POST: Numeric dashboard ids for known environments are cached when discoverable.\n # @SIDE_EFFECT: May call Superset dashboard list API once per referenced environment.\n # @DATA_CONTRACT: Input[records: List[ValidationRecord]] -> Output[None]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[ConfigManager]\n # @RELATION: [DEPENDS_ON] ->[SupersetClient]\n def _prime_dashboard_meta_cache(self, records: list[ValidationRecord]) -> None:\n if not self.config_manager or not records:\n return\n\n numeric_ids_by_env: dict[str, set[str]] = {}\n for record in records:\n environment_id = str(record.environment_id or \"\").strip()\n dashboard_id = str(record.dashboard_id or \"\").strip()\n if not environment_id or not dashboard_id or not dashboard_id.isdigit():\n continue\n cache_key = (environment_id, dashboard_id)\n if cache_key in self._dashboard_meta_cache:\n continue\n numeric_ids_by_env.setdefault(environment_id, set()).add(dashboard_id)\n\n if not numeric_ids_by_env:\n return\n\n environments = {\n str(getattr(env, \"id\", \"\")).strip(): env\n for env in self.config_manager.get_environments()\n if str(getattr(env, \"id\", \"\")).strip()\n }\n\n for environment_id, dashboard_ids in numeric_ids_by_env.items():\n env = environments.get(environment_id)\n if not env:\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n continue\n\n try:\n cached_meta = self.__class__._dashboard_summary_cache.get(\n environment_id\n )\n dashboard_meta_map: dict[str, dict[str, str | None]]\n if (\n cached_meta is not None\n and (time.monotonic() - cached_meta[0])\n < self.__class__._dashboard_summary_cache_ttl_seconds\n ):\n cached_meta_data = cast(\n tuple[float, dict[str, dict[str, str | None]]],\n cached_meta,\n )\n dashboard_meta_map = cached_meta_data[1]\n else:\n dashboards = SupersetClient(env).get_dashboards_summary()\n dashboard_meta_map = {\n str(item.get(\"id\")): {\n \"slug\": item.get(\"slug\"),\n \"title\": item.get(\"title\"),\n }\n for item in dashboards\n if str(item.get(\"id\") or \"\").strip()\n }\n self.__class__._dashboard_summary_cache[environment_id] = (\n time.monotonic(),\n dashboard_meta_map,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n dashboard_meta_map.get(\n dashboard_id,\n _empty_dashboard_meta(),\n )\n )\n except Exception as exc:\n logger.warning(\n \"[HealthService][_prime_dashboard_meta_cache] Failed to preload dashboard metadata for env=%s: %s\",\n environment_id,\n exc,\n )\n for dashboard_id in dashboard_ids:\n self._dashboard_meta_cache[(environment_id, dashboard_id)] = (\n _empty_dashboard_meta()\n )\n\n # endregion _prime_dashboard_meta_cache\n\n # region _resolve_dashboard_meta [TYPE Function]\n # @PURPOSE: Resolve slug/title for a dashboard referenced by persisted validation record.\n # @PRE: dashboard_id may be numeric or slug-like; environment_id may be empty.\n # @POST: Returns dict with `slug` and `title` keys, using cache when possible.\n # @SIDE_EFFECT: Writes default cache entries for unresolved numeric dashboard ids.\n def _resolve_dashboard_meta(\n self, dashboard_id: str, environment_id: str | None\n ) -> dict[str, str | None]:\n normalized_dashboard_id = str(dashboard_id or \"\").strip()\n normalized_environment_id = str(environment_id or \"\").strip()\n if not normalized_dashboard_id:\n return _empty_dashboard_meta()\n\n if not normalized_dashboard_id.isdigit():\n return {\"slug\": normalized_dashboard_id, \"title\": None}\n\n if not self.config_manager or not normalized_environment_id:\n return _empty_dashboard_meta()\n\n cache_key = (normalized_environment_id, normalized_dashboard_id)\n cached = self._dashboard_meta_cache.get(cache_key)\n if cached is not None:\n return cached\n\n meta = _empty_dashboard_meta()\n self._dashboard_meta_cache[cache_key] = meta\n return meta\n\n # endregion _resolve_dashboard_meta\n\n # region get_health_summary [TYPE Function]\n # @PURPOSE: Aggregate latest validation status per dashboard and enrich rows with dashboard slug/title.\n # @PRE: environment_id may be omitted to aggregate across all environments.\n # @POST: Returns HealthSummaryResponse with counts and latest record row per dashboard.\n # @SIDE_EFFECT: May call Superset API to resolve dashboard metadata.\n # @DATA_CONTRACT: Input[environment_id: Optional[str]] -> Output[HealthSummaryResponse]\n # @RELATION: [CALLS] ->[_prime_dashboard_meta_cache]\n # @RELATION: [CALLS] ->[_resolve_dashboard_meta]\n async def get_health_summary(\n self, environment_id: str = \"\"\n ) -> HealthSummaryResponse:\n \"\"\"\n @PURPOSE: Aggregates the latest validation status for all dashboards.\n @PRE: environment_id (optional) to filter by environment.\n @POST: Returns a HealthSummaryResponse with aggregated status counts and items.\n \"\"\"\n # [REASON] We need the latest ValidationRecord for each unique dashboard_id.\n # We use a subquery to find the max timestamp per dashboard_id.\n\n subquery = self.db.query(\n ValidationRecord.dashboard_id,\n func.max(ValidationRecord.timestamp).label(\"max_ts\"),\n )\n if environment_id:\n subquery = subquery.filter(\n ValidationRecord.environment_id == environment_id\n )\n subquery = subquery.group_by(ValidationRecord.dashboard_id).subquery()\n\n query = self.db.query(ValidationRecord).join(\n subquery,\n (ValidationRecord.dashboard_id == subquery.c.dashboard_id)\n & (ValidationRecord.timestamp == subquery.c.max_ts),\n )\n\n records = query.all()\n\n self._prime_dashboard_meta_cache(records)\n\n items = []\n pass_count = 0\n warn_count = 0\n fail_count = 0\n unknown_count = 0\n\n for rec in records:\n record = cast(Any, rec)\n status = str(record.status or \"\").upper()\n if status == \"PASS\":\n pass_count += 1\n elif status == \"WARN\":\n warn_count += 1\n elif status == \"FAIL\":\n fail_count += 1\n else:\n unknown_count += 1\n status = \"UNKNOWN\"\n\n record_id = str(record.id or \"\")\n dashboard_id = str(record.dashboard_id or \"\")\n resolved_environment_id = (\n str(record.environment_id)\n if record.environment_id is not None\n else None\n )\n response_environment_id = (\n resolved_environment_id\n if resolved_environment_id is not None\n else \"unknown\"\n )\n task_id = str(record.task_id) if record.task_id is not None else None\n summary = str(record.summary) if record.summary is not None else None\n timestamp = cast(Any, record.timestamp)\n # Ensure timestamp is timezone-aware (DB stores naive UTC)\n if timestamp is not None and timestamp.tzinfo is None:\n timestamp = timestamp.replace(tzinfo=UTC)\n\n meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id)\n items.append(\n DashboardHealthItem(\n record_id=record_id,\n dashboard_id=dashboard_id,\n dashboard_slug=meta.get(\"slug\"),\n dashboard_title=meta.get(\"title\"),\n environment_id=response_environment_id,\n status=status,\n last_check=timestamp,\n task_id=task_id,\n summary=summary,\n )\n )\n\n logger.info(\n f\"[HealthService][get_health_summary] Aggregated {len(items)} dashboard health records.\"\n )\n\n return HealthSummaryResponse(\n items=items,\n pass_count=pass_count,\n warn_count=warn_count,\n fail_count=fail_count,\n unknown_count=unknown_count,\n )\n\n # endregion get_health_summary\n\n # region delete_validation_report [TYPE Function]\n # @PURPOSE: Delete one persisted health report and optionally clean linked task/log artifacts.\n # @PRE: record_id is a validation record identifier.\n # @POST: Returns True only when a matching record was deleted.\n # @SIDE_EFFECT: Deletes DB rows, optional screenshot file, and optional task/log persistence.\n # @DATA_CONTRACT: Input[record_id: str, task_manager: Optional[TaskManager]] -> Output[bool]\n # @RELATION: [DEPENDS_ON] ->[ValidationRecord]\n # @RELATION: [DEPENDS_ON] ->[TaskManager]\n # @RELATION: [DEPENDS_ON] ->[TaskCleanupService]\n def delete_validation_report(\n self, record_id: str, task_manager: TaskManager | None = None\n ) -> bool:\n record = (\n self.db.query(ValidationRecord)\n .filter(ValidationRecord.id == record_id)\n .first()\n )\n if not record:\n return False\n\n peer_query = self.db.query(ValidationRecord).filter(\n ValidationRecord.dashboard_id == record.dashboard_id\n )\n if record.environment_id is None:\n peer_query = peer_query.filter(ValidationRecord.environment_id.is_(None))\n else:\n peer_query = peer_query.filter(\n ValidationRecord.environment_id == record.environment_id\n )\n\n records_to_delete = peer_query.all()\n screenshot_paths = [\n str(item.screenshot_path or \"\").strip()\n for item in records_to_delete\n if str(item.screenshot_path or \"\").strip()\n ]\n task_ids = {\n str(item.task_id or \"\").strip()\n for item in records_to_delete\n if str(item.task_id or \"\").strip()\n }\n\n logger.info(\n \"[HealthService][delete_validation_report] Removing %s validation record(s) for dashboard=%s environment=%s triggered_by_record=%s\",\n len(records_to_delete),\n record.dashboard_id,\n record.environment_id,\n record_id,\n )\n\n for item in records_to_delete:\n self.db.delete(item)\n self.db.commit()\n\n for screenshot_path in screenshot_paths:\n try:\n if os.path.exists(screenshot_path):\n os.remove(screenshot_path)\n except OSError as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to remove screenshot %s: %s\",\n screenshot_path,\n exc,\n )\n\n if task_ids and task_manager and self.config_manager:\n try:\n cleanup_service = TaskCleanupService(\n task_manager.persistence_service,\n task_manager.log_persistence_service,\n self.config_manager,\n )\n for task_id in task_ids:\n task_manager.tasks.pop(task_id, None)\n cleanup_service.delete_task_with_logs(task_id)\n except Exception as exc:\n logger.warning(\n \"[HealthService][delete_validation_report] Failed to cleanup linked task/logs for dashboard=%s environment=%s: %s\",\n record.dashboard_id,\n record.environment_id,\n exc,\n )\n\n return True\n\n # endregion delete_validation_report\n\n\n# #endregion HealthService\n" }, { "contract_id": "llm_prompt_templates", @@ -49516,6 +51545,409 @@ "tier_source": "AutoCalculated", "body": "# #region LLMProviderService [C:3] [TYPE Class]\n# @BRIEF Service to manage LLM provider lifecycle.\n# @RELATION DEPENDS_ON -> [LLMProvider]\n# @RELATION DEPENDS_ON -> [EncryptionManager]\n# @RELATION DEPENDS_ON -> [LLMProviderConfig]\nclass LLMProviderService:\n # region LLMProviderService_init [TYPE Function]\n # @PURPOSE: Initialize the service with database session.\n # @PRE: db must be a valid SQLAlchemy Session.\n # @POST: Service ready for provider operations.\n # @RELATION: [DEPENDS_ON] ->[EncryptionManager]\n def __init__(self, db: Session):\n self.db = db\n self.encryption = EncryptionManager()\n\n # endregion LLMProviderService_init\n\n # region get_all_providers [TYPE Function]\n # @PURPOSE: Returns all configured LLM providers.\n # @PRE: Database connection must be active.\n # @POST: Returns list of all LLMProvider records.\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n def get_all_providers(self) -> list[LLMProvider]:\n with belief_scope(\"get_all_providers\"):\n return self.db.query(LLMProvider).all()\n\n # endregion get_all_providers\n\n # region get_provider [TYPE Function]\n # @PURPOSE: Returns a single LLM provider by ID.\n # @PRE: provider_id must be a valid string.\n # @POST: Returns LLMProvider or None if not found.\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n def get_provider(self, provider_id: str) -> LLMProvider | None:\n with belief_scope(\"get_provider\"):\n return (\n self.db.query(LLMProvider).filter(LLMProvider.id == provider_id).first()\n )\n\n # endregion get_provider\n\n # region create_provider [TYPE Function]\n # @PURPOSE: Creates a new LLM provider with encrypted API key.\n # @PRE: config must contain valid provider configuration.\n # @POST: New provider created and persisted to database.\n # @RELATION: [DEPENDS_ON] ->[LLMProviderConfig]\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n # @RELATION: [CALLS] ->[encrypt]\n def create_provider(self, config: \"LLMProviderConfig\") -> LLMProvider:\n with belief_scope(\"create_provider\"):\n encrypted_key = self.encryption.encrypt(config.api_key)\n db_provider = LLMProvider(\n provider_type=config.provider_type.value,\n name=config.name,\n base_url=config.base_url,\n api_key=encrypted_key,\n default_model=config.default_model,\n is_active=config.is_active,\n is_multimodal=config.is_multimodal,\n )\n self.db.add(db_provider)\n self.db.commit()\n self.db.refresh(db_provider)\n return db_provider\n\n # endregion create_provider\n\n # region update_provider [TYPE Function]\n # @PURPOSE: Updates an existing LLM provider.\n # @PRE: provider_id must exist, config must be valid.\n # @POST: Provider updated and persisted to database.\n # @RELATION: [DEPENDS_ON] ->[LLMProviderConfig]\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n # @RELATION: [CALLS] ->[encrypt]\n def update_provider(\n self, provider_id: str, config: \"LLMProviderConfig\"\n ) -> LLMProvider | None:\n with belief_scope(\"update_provider\"):\n db_provider = self.get_provider(provider_id)\n if not db_provider:\n return None\n\n db_provider.provider_type = config.provider_type.value\n db_provider.name = config.name\n db_provider.base_url = config.base_url\n # Ignore masked/placeholder values; they are display-only and must not overwrite secrets.\n if not is_masked_or_placeholder(config.api_key):\n db_provider.api_key = self.encryption.encrypt(config.api_key)\n db_provider.default_model = config.default_model\n db_provider.is_active = config.is_active\n db_provider.is_multimodal = config.is_multimodal\n\n self.db.commit()\n self.db.refresh(db_provider)\n return db_provider\n\n # endregion update_provider\n\n # region delete_provider [TYPE Function]\n # @PURPOSE: Deletes an LLM provider.\n # @PRE: provider_id must exist.\n # @POST: Provider removed from database.\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n def delete_provider(self, provider_id: str) -> bool:\n with belief_scope(\"delete_provider\"):\n db_provider = self.get_provider(provider_id)\n if not db_provider:\n return False\n self.db.delete(db_provider)\n self.db.commit()\n return True\n\n # endregion delete_provider\n\n # region get_decrypted_api_key [TYPE Function]\n # @PURPOSE: Returns the decrypted API key for a provider.\n # @PRE: provider_id must exist with valid encrypted key.\n # @POST: Returns decrypted API key or None on failure.\n # @RELATION: [DEPENDS_ON] ->[LLMProvider]\n # @RELATION: [CALLS] ->[decrypt]\n def get_decrypted_api_key(self, provider_id: str) -> str | None:\n with belief_scope(\"get_decrypted_api_key\"):\n db_provider = self.get_provider(provider_id)\n if not db_provider:\n logger.warning(\n f\"[get_decrypted_api_key] Provider {provider_id} not found in database\"\n )\n return None\n\n logger.info(f\"[get_decrypted_api_key] Provider found: {db_provider.id}\")\n logger.info(\n f\"[get_decrypted_api_key] Encrypted API key length: {len(db_provider.api_key) if db_provider.api_key else 0}\"\n )\n\n try:\n decrypted_key = self.encryption.decrypt(db_provider.api_key)\n logger.info(\n f\"[get_decrypted_api_key] Decryption successful, key length: {len(decrypted_key) if decrypted_key else 0}\"\n )\n return decrypted_key\n except InvalidTag as e:\n logger.error(\n f\"[get_decrypted_api_key] Integrity check failed (InvalidTag): {e!s}. \"\n \"The encrypted API key may be corrupted or the ENCRYPTION_KEY has changed.\"\n )\n return None\n except ValueError as e:\n logger.error(\n f\"[get_decrypted_api_key] Decryption format error (ValueError): {e!s}. \"\n \"The encrypted data may not be valid Fernet ciphertext.\"\n )\n return None\n except Exception as e:\n logger.error(\n f\"[get_decrypted_api_key] Decryption failed with unexpected error \"\n f\"({type(e).__name__}): {e!s}\"\n )\n return None\n\n # endregion get_decrypted_api_key\n\n\n# #endregion LLMProviderService\n" }, + { + "contract_id": "MaintenancePackage", + "contract_type": "Package", + "file_path": "backend/src/services/maintenance/__init__.py", + "start_line": 1, + "end_line": 30, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "LAYER": "Service", + "PURPOSE": "Maintenance Banner service package. Re-exports all public orchestrators and helpers." + }, + "relations": [ + { + "source_id": "MaintenancePackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceOrchestrators", + "target_ref": "[MaintenanceOrchestrators]" + }, + { + "source_id": "MaintenancePackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceDashboardScanner", + "target_ref": "[MaintenanceDashboardScanner]" + }, + { + "source_id": "MaintenancePackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceBannerRenderer", + "target_ref": "[MaintenanceBannerRenderer]" + }, + { + "source_id": "MaintenancePackage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceChartManager", + "target_ref": "[MaintenanceChartManager]" + } + ], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "LAYER", + "message": "@LAYER is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Package'", + "detail": { + "actual_type": "Package", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION is forbidden for contract type 'Package' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Package" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenancePackage [C:1] [TYPE Package] [SEMANTICS maintenance, service, package]\n# @BRIEF Maintenance Banner service package. Re-exports all public orchestrators and helpers.\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [MaintenanceOrchestrators]\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardScanner]\n# @RELATION DEPENDS_ON -> [MaintenanceBannerRenderer]\n# @RELATION DEPENDS_ON -> [MaintenanceChartManager]\n\nfrom ._banner_renderer import build_banner_text, rebuild_banner\nfrom ._chart_manager import ensure_banner_chart\nfrom ._dashboard_scanner import find_affected_dashboards\nfrom ._orchestrators import (\n build_idempotency_key,\n end_all_maintenance,\n end_maintenance,\n start_maintenance,\n)\n\n__all__ = [\n \"build_banner_text\",\n \"build_idempotency_key\",\n \"end_all_maintenance\",\n \"end_maintenance\",\n \"ensure_banner_chart\",\n \"find_affected_dashboards\",\n \"rebuild_banner\",\n \"start_maintenance\",\n]\n\n# #endregion MaintenancePackage\n" + }, + { + "contract_id": "MaintenanceBannerRenderer", + "contract_type": "Module", + "file_path": "backend/src/services/maintenance/_banner_renderer.py", + "start_line": 1, + "end_line": 254, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Banner text rendering and rebuild helpers. Build aggregated markdown from" + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceBannerRenderer [C:3] [TYPE Module] [SEMANTICS maintenance, banner, renderer, text]\n# @BRIEF Banner text rendering and rebuild helpers. Build aggregated markdown from\n# active maintenance events, format with template, apply HTML escaping.\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [MaintenanceModels]\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\n\nimport html\nimport re as _re\nfrom datetime import datetime\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ...core.logger import belief_scope, logger as app_logger\nfrom ...core.superset_client import SupersetClient\nfrom ...models.maintenance import (\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n MaintenanceDashboardState,\n MaintenanceDashboardStateStatus,\n MaintenanceEvent,\n MaintenanceEventStatus,\n MaintenanceSettings,\n)\n\n\n# #region build_banner_text [C:3] [TYPE Function] [SEMANTICS maintenance, banner, text, template, rendering]\n# @BRIEF Build aggregated banner markdown text from events using settings template.\n# Single event: substitute {start_time}, {end_time}, {message} directly.\n# Multiple events: render each event as sub-block, combine as {message}.\n# Missing variables → empty string. Message is HTML-escaped.\n# @PRE events is a non-empty list of dicts with start_time, end_time, message keys.\n# template is a non-empty string.\n# @POST Returns str with substituted template or empty string on failure.\ndef build_banner_text(\n events: list[dict[str, Any]],\n template: str,\n display_timezone: str = \"UTC\",\n) -> str:\n with belief_scope(\n \"build_banner_text\",\n f\"events={len(events)}\",\n ):\n if not events:\n app_logger.reflect(\"No events, returning empty string\")\n return \"\"\n\n def _format_dt(dt_str: str | None) -> str:\n \"\"\"Format datetime string for display.\"\"\"\n if not dt_str:\n return \"уточняется\"\n try:\n dt = datetime.fromisoformat(dt_str.replace(\"Z\", \"+00:00\"))\n return dt.strftime(\"%Y-%m-%d %H:%M\")\n except (ValueError, TypeError):\n return dt_str or \"уточняется\"\n\n def _event_substitutions(event: dict[str, Any]) -> dict[str, str]:\n \"\"\"Build substitution dict for a single event.\"\"\"\n msg = event.get(\"message\") or \"\"\n escaped_msg = html.escape(msg) if msg else \"\"\n return {\n \"start_time\": _format_dt(event.get(\"start_time\")),\n \"end_time\": _format_dt(event.get(\"end_time\")),\n \"message\": escaped_msg,\n }\n\n if len(events) == 1:\n subs = _event_substitutions(events[0])\n result = template\n for key, value in subs.items():\n result = result.replace(f\"{{{key}}}\", value)\n # Remove any remaining unreplaced variables\n result = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", result)\n app_logger.reflect(\"Banner text built (single event)\")\n return result\n\n # Multiple events: build aggregated message, substitute as {message}\n event_blocks: list[str] = []\n for i, event in enumerate(events):\n subs = _event_substitutions(event)\n block = template\n for key, value in subs.items():\n block = block.replace(f\"{{{key}}}\", value)\n block = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", block)\n event_blocks.append(block)\n\n combined_message = \"\\n\\n---\\n\\n\".join(event_blocks)\n\n # Build aggregator template (use first event for start/end if uniform)\n result = template\n result = result.replace(\"{message}\", combined_message)\n if len(events) == 1:\n subs = _event_substitutions(events[0])\n for key in (\"start_time\", \"end_time\"):\n result = result.replace(f\"{{{key}}}\", subs.get(key, \"\"))\n else:\n result = result.replace(\"{start_time}\", \"\")\n result = result.replace(\"{end_time}\", \"\")\n result = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", result)\n\n app_logger.reflect(\"Banner text built (multi-event)\")\n return result\n# #endregion build_banner_text\n\n\n# #region _build_banner_text_for_dashboard [C:2] [TYPE Function]\n# @BRIEF Build aggregated banner text for a banner based on all active events linked to it.\ndef _build_banner_text_for_dashboard(\n banner_id: str,\n db_session: Session,\n template: str,\n timezone_str: str,\n) -> str:\n try:\n # Find all active dashboard states linked to this banner\n active_states = (\n db_session.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.banner_id == banner_id,\n MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE,\n )\n .all()\n )\n\n if not active_states:\n return \"\"\n\n # Load events for each state\n events_data: list[dict[str, Any]] = []\n for state in active_states:\n ev = (\n db_session.query(MaintenanceEvent)\n .filter(MaintenanceEvent.id == state.event_id)\n .first()\n )\n if ev and ev.status in (\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n MaintenanceEventStatus.APPLYING,\n ):\n events_data.append(\n {\n \"start_time\": ev.start_time.isoformat() if ev.start_time else None,\n \"end_time\": ev.end_time.isoformat() if ev.end_time else None,\n \"message\": ev.message or \"\",\n }\n )\n\n if not events_data:\n return \"\"\n\n return build_banner_text(events_data, template, timezone_str)\n except Exception as e:\n app_logger.explore(\n \"Failed to build banner text\",\n extra={\"banner_id\": banner_id},\n error=str(e),\n )\n return \"\"\n# #endregion _build_banner_text_for_dashboard\n\n\n# #region rebuild_banner [C:3] [TYPE Function] [SEMANTICS maintenance, banner, rebuild, text, update]\n# @BRIEF Rebuild aggregated banner text for a banner and update the Superset chart.\n# Query all active MaintenanceDashboardState records linked to banner,\n# build aggregated text via build_banner_text, update markdown chart in Superset.\n# @PRE banner_id points to an active MaintenanceDashboardBanner with a valid chart_id.\n# @POST Banner chart in Superset updated with current aggregated text. DB banner_text updated.\n# @SIDE_EFFECT Modifies Superset chart. Writes DB.\n# @RELATION DEPENDS_ON -> [build_banner_text]\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\ndef rebuild_banner(\n banner_id: str,\n db_session: Session,\n superset_client: SupersetClient,\n) -> bool:\n with belief_scope(\"rebuild_banner\", f\"banner_id={banner_id}\"):\n app_logger.reason(\n \"Rebuilding banner text\",\n extra={\"banner_id\": banner_id},\n )\n\n banner = db_session.query(MaintenanceDashboardBanner).filter(\n MaintenanceDashboardBanner.id == banner_id\n ).first()\n if not banner:\n app_logger.explore(\n \"Banner not found\",\n extra={\"banner_id\": banner_id},\n error=\"BannerNotFound\",\n )\n return False\n\n if banner.status != MaintenanceDashboardBannerStatus.ACTIVE:\n app_logger.reflect(\n \"Banner not active, skipping\",\n extra={\"banner_id\": banner_id, \"status\": banner.status.value},\n )\n return False\n\n # Load settings for template\n settings = db_session.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n template = settings.banner_template if settings else \"\"\n timezone_str = settings.display_timezone if settings else \"UTC\"\n\n # Build aggregated text\n banner_text = _build_banner_text_for_dashboard(\n banner_id, db_session, template, timezone_str\n )\n\n if not banner_text and banner.chart_id:\n # No active events — should be handled by end_maintenance, but clean up just in case\n app_logger.reflect(\n \"No active events for banner, marking as REMOVED\",\n extra={\"banner_id\": banner_id},\n )\n banner.status = MaintenanceDashboardBannerStatus.REMOVED\n db_session.flush()\n return True\n\n # Update banner on dashboard (native MARKDOWN in layout)\n if banner.chart_id:\n try:\n superset_client.update_banner_on_dashboard(\n banner.dashboard_id, banner.chart_id, banner_text\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to update banner on dashboard during rebuild\",\n extra={\n \"chart_id\": banner.chart_id,\n \"banner_id\": banner_id,\n \"dashboard_id\": banner.dashboard_id,\n },\n error=str(e),\n )\n return False\n\n # Update DB\n banner.banner_text = banner_text\n db_session.flush()\n\n app_logger.reflect(\n \"Banner rebuilt successfully\",\n extra={\"banner_id\": banner_id},\n )\n return True\n# #endregion rebuild_banner\n\n# #endregion MaintenanceBannerRenderer\n" + }, + { + "contract_id": "build_banner_text", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_banner_renderer.py", + "start_line": 28, + "end_line": 105, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Build aggregated banner markdown text from events using settings template." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region build_banner_text [C:3] [TYPE Function] [SEMANTICS maintenance, banner, text, template, rendering]\n# @BRIEF Build aggregated banner markdown text from events using settings template.\n# Single event: substitute {start_time}, {end_time}, {message} directly.\n# Multiple events: render each event as sub-block, combine as {message}.\n# Missing variables → empty string. Message is HTML-escaped.\n# @PRE events is a non-empty list of dicts with start_time, end_time, message keys.\n# template is a non-empty string.\n# @POST Returns str with substituted template or empty string on failure.\ndef build_banner_text(\n events: list[dict[str, Any]],\n template: str,\n display_timezone: str = \"UTC\",\n) -> str:\n with belief_scope(\n \"build_banner_text\",\n f\"events={len(events)}\",\n ):\n if not events:\n app_logger.reflect(\"No events, returning empty string\")\n return \"\"\n\n def _format_dt(dt_str: str | None) -> str:\n \"\"\"Format datetime string for display.\"\"\"\n if not dt_str:\n return \"уточняется\"\n try:\n dt = datetime.fromisoformat(dt_str.replace(\"Z\", \"+00:00\"))\n return dt.strftime(\"%Y-%m-%d %H:%M\")\n except (ValueError, TypeError):\n return dt_str or \"уточняется\"\n\n def _event_substitutions(event: dict[str, Any]) -> dict[str, str]:\n \"\"\"Build substitution dict for a single event.\"\"\"\n msg = event.get(\"message\") or \"\"\n escaped_msg = html.escape(msg) if msg else \"\"\n return {\n \"start_time\": _format_dt(event.get(\"start_time\")),\n \"end_time\": _format_dt(event.get(\"end_time\")),\n \"message\": escaped_msg,\n }\n\n if len(events) == 1:\n subs = _event_substitutions(events[0])\n result = template\n for key, value in subs.items():\n result = result.replace(f\"{{{key}}}\", value)\n # Remove any remaining unreplaced variables\n result = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", result)\n app_logger.reflect(\"Banner text built (single event)\")\n return result\n\n # Multiple events: build aggregated message, substitute as {message}\n event_blocks: list[str] = []\n for i, event in enumerate(events):\n subs = _event_substitutions(event)\n block = template\n for key, value in subs.items():\n block = block.replace(f\"{{{key}}}\", value)\n block = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", block)\n event_blocks.append(block)\n\n combined_message = \"\\n\\n---\\n\\n\".join(event_blocks)\n\n # Build aggregator template (use first event for start/end if uniform)\n result = template\n result = result.replace(\"{message}\", combined_message)\n if len(events) == 1:\n subs = _event_substitutions(events[0])\n for key in (\"start_time\", \"end_time\"):\n result = result.replace(f\"{{{key}}}\", subs.get(key, \"\"))\n else:\n result = result.replace(\"{start_time}\", \"\")\n result = result.replace(\"{end_time}\", \"\")\n result = _re.sub(r\"\\{[a-zA-Z_]+\\}\", \"\", result)\n\n app_logger.reflect(\"Banner text built (multi-event)\")\n return result\n# #endregion build_banner_text\n" + }, + { + "contract_id": "_build_banner_text_for_dashboard", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_banner_renderer.py", + "start_line": 108, + "end_line": 162, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Build aggregated banner text for a banner based on all active events linked to it." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _build_banner_text_for_dashboard [C:2] [TYPE Function]\n# @BRIEF Build aggregated banner text for a banner based on all active events linked to it.\ndef _build_banner_text_for_dashboard(\n banner_id: str,\n db_session: Session,\n template: str,\n timezone_str: str,\n) -> str:\n try:\n # Find all active dashboard states linked to this banner\n active_states = (\n db_session.query(MaintenanceDashboardState)\n .filter(\n MaintenanceDashboardState.banner_id == banner_id,\n MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE,\n )\n .all()\n )\n\n if not active_states:\n return \"\"\n\n # Load events for each state\n events_data: list[dict[str, Any]] = []\n for state in active_states:\n ev = (\n db_session.query(MaintenanceEvent)\n .filter(MaintenanceEvent.id == state.event_id)\n .first()\n )\n if ev and ev.status in (\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n MaintenanceEventStatus.APPLYING,\n ):\n events_data.append(\n {\n \"start_time\": ev.start_time.isoformat() if ev.start_time else None,\n \"end_time\": ev.end_time.isoformat() if ev.end_time else None,\n \"message\": ev.message or \"\",\n }\n )\n\n if not events_data:\n return \"\"\n\n return build_banner_text(events_data, template, timezone_str)\n except Exception as e:\n app_logger.explore(\n \"Failed to build banner text\",\n extra={\"banner_id\": banner_id},\n error=str(e),\n )\n return \"\"\n# #endregion _build_banner_text_for_dashboard\n" + }, + { + "contract_id": "rebuild_banner", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_banner_renderer.py", + "start_line": 165, + "end_line": 252, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Rebuild aggregated banner text for a banner and update the Superset chart." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region rebuild_banner [C:3] [TYPE Function] [SEMANTICS maintenance, banner, rebuild, text, update]\n# @BRIEF Rebuild aggregated banner text for a banner and update the Superset chart.\n# Query all active MaintenanceDashboardState records linked to banner,\n# build aggregated text via build_banner_text, update markdown chart in Superset.\n# @PRE banner_id points to an active MaintenanceDashboardBanner with a valid chart_id.\n# @POST Banner chart in Superset updated with current aggregated text. DB banner_text updated.\n# @SIDE_EFFECT Modifies Superset chart. Writes DB.\n# @RELATION DEPENDS_ON -> [build_banner_text]\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\ndef rebuild_banner(\n banner_id: str,\n db_session: Session,\n superset_client: SupersetClient,\n) -> bool:\n with belief_scope(\"rebuild_banner\", f\"banner_id={banner_id}\"):\n app_logger.reason(\n \"Rebuilding banner text\",\n extra={\"banner_id\": banner_id},\n )\n\n banner = db_session.query(MaintenanceDashboardBanner).filter(\n MaintenanceDashboardBanner.id == banner_id\n ).first()\n if not banner:\n app_logger.explore(\n \"Banner not found\",\n extra={\"banner_id\": banner_id},\n error=\"BannerNotFound\",\n )\n return False\n\n if banner.status != MaintenanceDashboardBannerStatus.ACTIVE:\n app_logger.reflect(\n \"Banner not active, skipping\",\n extra={\"banner_id\": banner_id, \"status\": banner.status.value},\n )\n return False\n\n # Load settings for template\n settings = db_session.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n template = settings.banner_template if settings else \"\"\n timezone_str = settings.display_timezone if settings else \"UTC\"\n\n # Build aggregated text\n banner_text = _build_banner_text_for_dashboard(\n banner_id, db_session, template, timezone_str\n )\n\n if not banner_text and banner.chart_id:\n # No active events — should be handled by end_maintenance, but clean up just in case\n app_logger.reflect(\n \"No active events for banner, marking as REMOVED\",\n extra={\"banner_id\": banner_id},\n )\n banner.status = MaintenanceDashboardBannerStatus.REMOVED\n db_session.flush()\n return True\n\n # Update banner on dashboard (native MARKDOWN in layout)\n if banner.chart_id:\n try:\n superset_client.update_banner_on_dashboard(\n banner.dashboard_id, banner.chart_id, banner_text\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to update banner on dashboard during rebuild\",\n extra={\n \"chart_id\": banner.chart_id,\n \"banner_id\": banner_id,\n \"dashboard_id\": banner.dashboard_id,\n },\n error=str(e),\n )\n return False\n\n # Update DB\n banner.banner_text = banner_text\n db_session.flush()\n\n app_logger.reflect(\n \"Banner rebuilt successfully\",\n extra={\"banner_id\": banner_id},\n )\n return True\n# #endregion rebuild_banner\n" + }, + { + "contract_id": "MaintenanceChartManager", + "contract_type": "Module", + "file_path": "backend/src/services/maintenance/_chart_manager.py", + "start_line": 1, + "end_line": 359, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Chart operations for maintenance banners: create/get banner charts, process" + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceChartManager [C:3] [TYPE Module] [SEMANTICS maintenance, chart, banner, lifecycle]\n# @BRIEF Chart operations for maintenance banners: create/get banner charts, process\n# per-dashboard state transitions for start and end orchestrators.\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\n# @RELATION DEPENDS_ON -> [MaintenanceModels]\n\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ...core.logger import belief_scope, logger as app_logger\nfrom ...core.superset_client import SupersetClient\nfrom ...models.maintenance import (\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n MaintenanceDashboardState,\n MaintenanceDashboardStateStatus,\n MaintenanceEvent,\n MaintenanceEventStatus,\n MaintenanceSettings,\n)\nfrom ._banner_renderer import _build_banner_text_for_dashboard, rebuild_banner\nfrom ._dashboard_scanner import _resolve_dashboard_title\n\n\n# #region ensure_banner_chart [C:3] [TYPE Function] [SEMANTICS maintenance, banner, chart, creation]\n# @BRIEF Get or create a MaintenanceDashboardBanner for a dashboard in the target environment.\n# If an active banner exists in DB, return it. Otherwise, create a markdown chart in Superset,\n# update dashboard layout, and store the banner row.\n# @PRE dashboard_id exists in Superset. superset_client has write access.\n# @POST Returns MaintenanceDashboardBanner with chart_id set. Chart is placed at top of dashboard.\n# @SIDE_EFFECT Creates chart in Superset, modifies dashboard layout, writes DB row.\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\ndef ensure_banner_chart(\n dashboard_id: int,\n environment_id: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> MaintenanceDashboardBanner:\n with belief_scope(\n \"ensure_banner_chart\",\n f\"dashboard_id={dashboard_id}\",\n ):\n app_logger.reason(\n \"Ensuring banner chart exists\",\n extra={\"dashboard_id\": dashboard_id},\n )\n\n # Check for existing active banner\n existing = (\n db_session.query(MaintenanceDashboardBanner)\n .filter(\n MaintenanceDashboardBanner.dashboard_id == dashboard_id,\n MaintenanceDashboardBanner.environment_id == environment_id,\n MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE,\n )\n .first()\n )\n if existing:\n app_logger.reason(\n \"Found existing active banner, verifying chart in Superset\",\n extra={\"banner_id\": existing.id, \"chart_id\": existing.chart_id},\n )\n # Verify the chart still exists in Superset\n try:\n superset_client.get_chart(existing.chart_id)\n app_logger.reflect(\n \"Existing banner chart is alive, reusing\",\n extra={\"banner_id\": existing.id, \"chart_id\": existing.chart_id},\n )\n return existing\n except Exception:\n app_logger.explore(\n \"Existing banner chart is stale (not found in Superset), marking as REMOVED\",\n extra={\n \"banner_id\": existing.id,\n \"chart_id\": existing.chart_id,\n },\n )\n existing.status = MaintenanceDashboardBannerStatus.REMOVED\n db_session.flush()\n # Fall through to create a new chart\n\n # Create markdown chart in Superset\n try:\n chart_id = superset_client.create_markdown_chart(\n dashboard_id, \"*Maintenance banner placeholder*\"\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to create markdown chart\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n\n # Insert chart at top of dashboard layout\n try:\n superset_client.update_dashboard_layout(dashboard_id, chart_id)\n except Exception as e:\n app_logger.explore(\n \"Failed to update dashboard layout, deleting chart\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n error=str(e),\n )\n # Clean up the chart we just created\n try:\n superset_client.delete_chart(chart_id)\n except Exception:\n pass\n raise\n\n # Persist banner row\n banner = MaintenanceDashboardBanner(\n environment_id=environment_id,\n dashboard_id=dashboard_id,\n chart_id=chart_id,\n banner_text=\"\",\n status=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n db_session.add(banner)\n db_session.flush()\n\n app_logger.reflect(\n \"Banner chart created and persisted\",\n extra={\n \"banner_id\": banner.id,\n \"chart_id\": chart_id,\n \"dashboard_id\": dashboard_id,\n },\n )\n return banner\n# #endregion ensure_banner_chart\n\n\n# #region _process_dashboards_for_start [C:3] [TYPE Function]\n# @BRIEF Process each dashboard for a start maintenance event: ensure banner chart,\n# create dashboard state, build banner text, update chart markdown.\n# @SIDE_EFFECT Creates/updates Superset charts, writes DB rows.\n# @RELATION CALLS -> [ensure_banner_chart]\n# @RELATION CALLS -> [_build_banner_text_for_dashboard]\n# @RELATION CALLS -> [_resolve_dashboard_title]\ndef _process_dashboards_for_start(\n dashboard_ids: list[int],\n event_id: str,\n environment_id: str,\n template: str,\n timezone_str: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[MaintenanceDashboardBanner]]:\n successful_dashboards: list[dict[str, Any]] = []\n failed_dashboards: list[dict[str, Any]] = []\n banners_created: list[MaintenanceDashboardBanner] = []\n\n for dash_id in dashboard_ids:\n app_logger.reason(\n \"Processing dashboard\",\n extra={\"dashboard_id\": dash_id, \"event_id\": event_id},\n )\n try:\n # Ensure banner chart exists\n banner = ensure_banner_chart(\n dash_id,\n environment_id,\n superset_client,\n db_session,\n )\n banners_created.append(banner)\n\n # Create dashboard state\n state = MaintenanceDashboardState(\n event_id=event_id,\n dashboard_id=dash_id,\n banner_id=banner.id,\n status=MaintenanceDashboardStateStatus.ACTIVE,\n )\n db_session.add(state)\n db_session.flush() # Ensure state is visible to subsequent queries\n\n # Build banner text for this dashboard's active events\n banner_text = _build_banner_text_for_dashboard(\n banner.id, db_session, template, timezone_str\n )\n\n # Update banner content on dashboard (native MARKDOWN in layout)\n if banner.chart_id:\n try:\n superset_client.update_banner_on_dashboard(\n dash_id, banner.chart_id, banner_text\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to update banner on dashboard\",\n extra={\n \"chart_id\": banner.chart_id,\n \"dashboard_id\": dash_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.APPLY_FAILED\n failed_dashboards.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Update banner text in DB\n banner.banner_text = banner_text\n db_session.flush()\n\n # Resolve dashboard title\n title = _resolve_dashboard_title(dash_id, superset_client)\n successful_dashboards.append(\n {\n \"id\": dash_id,\n \"title\": title,\n \"chart_id\": banner.chart_id,\n }\n )\n app_logger.reflect(\n \"Dashboard processed successfully\",\n extra={\"dashboard_id\": dash_id},\n )\n\n except Exception as e:\n app_logger.explore(\n \"Failed to process dashboard\",\n extra={\"dashboard_id\": dash_id},\n error=str(e),\n )\n failed_dashboards.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n\n return successful_dashboards, failed_dashboards, banners_created\n# #endregion _process_dashboards_for_start\n\n\n# #region _process_states_for_end [C:3] [TYPE Function]\n# @BRIEF Process each dashboard state for an end maintenance event: if other events\n# still use same banner → rebuild; if no other events → remove banner (chart + layout).\n# @SIDE_EFFECT Modifies Superset dashboards (removes charts, updates layouts). Writes DB.\n# @RELATION CALLS -> [rebuild_banner]\ndef _process_states_for_end(\n states: list[MaintenanceDashboardState],\n event_id: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> tuple[int, list[dict[str, Any]]]:\n removed_count = 0\n failed_removals: list[dict[str, Any]] = []\n\n for state in states:\n dash_id = state.dashboard_id\n app_logger.reason(\n \"Processing dashboard state for end\",\n extra={\"dashboard_id\": dash_id, \"state_id\": state.id},\n )\n\n try:\n banner_id = state.banner_id\n if not banner_id:\n # No banner linked, just mark as removed\n state.status = MaintenanceDashboardStateStatus.REMOVED\n removed_count += 1\n continue\n\n # Check if other active events still use this banner\n other_active = db_session.query(MaintenanceDashboardState).filter(\n MaintenanceDashboardState.banner_id == banner_id,\n MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardState.event_id != event_id,\n ).count()\n\n banner = db_session.query(MaintenanceDashboardBanner).filter(\n MaintenanceDashboardBanner.id == banner_id\n ).first()\n\n if other_active > 0 and banner:\n # Other events still active — rebuild banner text\n state.status = MaintenanceDashboardStateStatus.REMOVED\n db_session.flush()\n rebuild_banner(banner_id, db_session, superset_client)\n app_logger.reflect(\n \"Banner rebuilt after removing event\",\n extra={\"banner_id\": banner_id, \"dashboard_id\": dash_id},\n )\n elif banner:\n # No other events — remove banner entirely\n state.status = MaintenanceDashboardStateStatus.REMOVING\n db_session.flush()\n\n # Remove chart from layout\n if banner.chart_id:\n try:\n superset_client.remove_chart_from_layout(\n dash_id, banner.chart_id\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to remove chart from layout\",\n extra={\n \"dashboard_id\": dash_id,\n \"chart_id\": banner.chart_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Delete chart\n try:\n superset_client.delete_chart(banner.chart_id)\n except Exception as e:\n app_logger.explore(\n \"Failed to delete chart\",\n extra={\n \"chart_id\": banner.chart_id,\n \"dashboard_id\": dash_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Mark banner as removed\n banner.status = MaintenanceDashboardBannerStatus.REMOVED\n state.status = MaintenanceDashboardStateStatus.REMOVED\n app_logger.reflect(\n \"Banner fully removed\",\n extra={\"banner_id\": banner_id, \"dashboard_id\": dash_id},\n )\n else:\n state.status = MaintenanceDashboardStateStatus.REMOVED\n\n removed_count += 1\n\n except Exception as e:\n app_logger.explore(\n \"Failed to end maintenance for dashboard\",\n extra={\"dashboard_id\": dash_id},\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n\n return removed_count, failed_removals\n# #endregion _process_states_for_end\n\n# #endregion MaintenanceChartManager\n" + }, + { + "contract_id": "ensure_banner_chart", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_chart_manager.py", + "start_line": 27, + "end_line": 134, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Get or create a MaintenanceDashboardBanner for a dashboard in the target environment." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region ensure_banner_chart [C:3] [TYPE Function] [SEMANTICS maintenance, banner, chart, creation]\n# @BRIEF Get or create a MaintenanceDashboardBanner for a dashboard in the target environment.\n# If an active banner exists in DB, return it. Otherwise, create a markdown chart in Superset,\n# update dashboard layout, and store the banner row.\n# @PRE dashboard_id exists in Superset. superset_client has write access.\n# @POST Returns MaintenanceDashboardBanner with chart_id set. Chart is placed at top of dashboard.\n# @SIDE_EFFECT Creates chart in Superset, modifies dashboard layout, writes DB row.\n# @RELATION DEPENDS_ON -> [SupersetDashboardsWriteMixin]\ndef ensure_banner_chart(\n dashboard_id: int,\n environment_id: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> MaintenanceDashboardBanner:\n with belief_scope(\n \"ensure_banner_chart\",\n f\"dashboard_id={dashboard_id}\",\n ):\n app_logger.reason(\n \"Ensuring banner chart exists\",\n extra={\"dashboard_id\": dashboard_id},\n )\n\n # Check for existing active banner\n existing = (\n db_session.query(MaintenanceDashboardBanner)\n .filter(\n MaintenanceDashboardBanner.dashboard_id == dashboard_id,\n MaintenanceDashboardBanner.environment_id == environment_id,\n MaintenanceDashboardBanner.status == MaintenanceDashboardBannerStatus.ACTIVE,\n )\n .first()\n )\n if existing:\n app_logger.reason(\n \"Found existing active banner, verifying chart in Superset\",\n extra={\"banner_id\": existing.id, \"chart_id\": existing.chart_id},\n )\n # Verify the chart still exists in Superset\n try:\n superset_client.get_chart(existing.chart_id)\n app_logger.reflect(\n \"Existing banner chart is alive, reusing\",\n extra={\"banner_id\": existing.id, \"chart_id\": existing.chart_id},\n )\n return existing\n except Exception:\n app_logger.explore(\n \"Existing banner chart is stale (not found in Superset), marking as REMOVED\",\n extra={\n \"banner_id\": existing.id,\n \"chart_id\": existing.chart_id,\n },\n )\n existing.status = MaintenanceDashboardBannerStatus.REMOVED\n db_session.flush()\n # Fall through to create a new chart\n\n # Create markdown chart in Superset\n try:\n chart_id = superset_client.create_markdown_chart(\n dashboard_id, \"*Maintenance banner placeholder*\"\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to create markdown chart\",\n extra={\"dashboard_id\": dashboard_id},\n error=str(e),\n )\n raise\n\n # Insert chart at top of dashboard layout\n try:\n superset_client.update_dashboard_layout(dashboard_id, chart_id)\n except Exception as e:\n app_logger.explore(\n \"Failed to update dashboard layout, deleting chart\",\n extra={\"dashboard_id\": dashboard_id, \"chart_id\": chart_id},\n error=str(e),\n )\n # Clean up the chart we just created\n try:\n superset_client.delete_chart(chart_id)\n except Exception:\n pass\n raise\n\n # Persist banner row\n banner = MaintenanceDashboardBanner(\n environment_id=environment_id,\n dashboard_id=dashboard_id,\n chart_id=chart_id,\n banner_text=\"\",\n status=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n db_session.add(banner)\n db_session.flush()\n\n app_logger.reflect(\n \"Banner chart created and persisted\",\n extra={\n \"banner_id\": banner.id,\n \"chart_id\": chart_id,\n \"dashboard_id\": dashboard_id,\n },\n )\n return banner\n# #endregion ensure_banner_chart\n" + }, + { + "contract_id": "_process_dashboards_for_start", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_chart_manager.py", + "start_line": 137, + "end_line": 237, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Process each dashboard for a start maintenance event: ensure banner chart," + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _process_dashboards_for_start [C:3] [TYPE Function]\n# @BRIEF Process each dashboard for a start maintenance event: ensure banner chart,\n# create dashboard state, build banner text, update chart markdown.\n# @SIDE_EFFECT Creates/updates Superset charts, writes DB rows.\n# @RELATION CALLS -> [ensure_banner_chart]\n# @RELATION CALLS -> [_build_banner_text_for_dashboard]\n# @RELATION CALLS -> [_resolve_dashboard_title]\ndef _process_dashboards_for_start(\n dashboard_ids: list[int],\n event_id: str,\n environment_id: str,\n template: str,\n timezone_str: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[MaintenanceDashboardBanner]]:\n successful_dashboards: list[dict[str, Any]] = []\n failed_dashboards: list[dict[str, Any]] = []\n banners_created: list[MaintenanceDashboardBanner] = []\n\n for dash_id in dashboard_ids:\n app_logger.reason(\n \"Processing dashboard\",\n extra={\"dashboard_id\": dash_id, \"event_id\": event_id},\n )\n try:\n # Ensure banner chart exists\n banner = ensure_banner_chart(\n dash_id,\n environment_id,\n superset_client,\n db_session,\n )\n banners_created.append(banner)\n\n # Create dashboard state\n state = MaintenanceDashboardState(\n event_id=event_id,\n dashboard_id=dash_id,\n banner_id=banner.id,\n status=MaintenanceDashboardStateStatus.ACTIVE,\n )\n db_session.add(state)\n db_session.flush() # Ensure state is visible to subsequent queries\n\n # Build banner text for this dashboard's active events\n banner_text = _build_banner_text_for_dashboard(\n banner.id, db_session, template, timezone_str\n )\n\n # Update banner content on dashboard (native MARKDOWN in layout)\n if banner.chart_id:\n try:\n superset_client.update_banner_on_dashboard(\n dash_id, banner.chart_id, banner_text\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to update banner on dashboard\",\n extra={\n \"chart_id\": banner.chart_id,\n \"dashboard_id\": dash_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.APPLY_FAILED\n failed_dashboards.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Update banner text in DB\n banner.banner_text = banner_text\n db_session.flush()\n\n # Resolve dashboard title\n title = _resolve_dashboard_title(dash_id, superset_client)\n successful_dashboards.append(\n {\n \"id\": dash_id,\n \"title\": title,\n \"chart_id\": banner.chart_id,\n }\n )\n app_logger.reflect(\n \"Dashboard processed successfully\",\n extra={\"dashboard_id\": dash_id},\n )\n\n except Exception as e:\n app_logger.explore(\n \"Failed to process dashboard\",\n extra={\"dashboard_id\": dash_id},\n error=str(e),\n )\n failed_dashboards.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n\n return successful_dashboards, failed_dashboards, banners_created\n# #endregion _process_dashboards_for_start\n" + }, + { + "contract_id": "_process_states_for_end", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_chart_manager.py", + "start_line": 240, + "end_line": 357, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Process each dashboard state for an end maintenance event: if other events" + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _process_states_for_end [C:3] [TYPE Function]\n# @BRIEF Process each dashboard state for an end maintenance event: if other events\n# still use same banner → rebuild; if no other events → remove banner (chart + layout).\n# @SIDE_EFFECT Modifies Superset dashboards (removes charts, updates layouts). Writes DB.\n# @RELATION CALLS -> [rebuild_banner]\ndef _process_states_for_end(\n states: list[MaintenanceDashboardState],\n event_id: str,\n superset_client: SupersetClient,\n db_session: Session,\n) -> tuple[int, list[dict[str, Any]]]:\n removed_count = 0\n failed_removals: list[dict[str, Any]] = []\n\n for state in states:\n dash_id = state.dashboard_id\n app_logger.reason(\n \"Processing dashboard state for end\",\n extra={\"dashboard_id\": dash_id, \"state_id\": state.id},\n )\n\n try:\n banner_id = state.banner_id\n if not banner_id:\n # No banner linked, just mark as removed\n state.status = MaintenanceDashboardStateStatus.REMOVED\n removed_count += 1\n continue\n\n # Check if other active events still use this banner\n other_active = db_session.query(MaintenanceDashboardState).filter(\n MaintenanceDashboardState.banner_id == banner_id,\n MaintenanceDashboardState.status == MaintenanceDashboardStateStatus.ACTIVE,\n MaintenanceDashboardState.event_id != event_id,\n ).count()\n\n banner = db_session.query(MaintenanceDashboardBanner).filter(\n MaintenanceDashboardBanner.id == banner_id\n ).first()\n\n if other_active > 0 and banner:\n # Other events still active — rebuild banner text\n state.status = MaintenanceDashboardStateStatus.REMOVED\n db_session.flush()\n rebuild_banner(banner_id, db_session, superset_client)\n app_logger.reflect(\n \"Banner rebuilt after removing event\",\n extra={\"banner_id\": banner_id, \"dashboard_id\": dash_id},\n )\n elif banner:\n # No other events — remove banner entirely\n state.status = MaintenanceDashboardStateStatus.REMOVING\n db_session.flush()\n\n # Remove chart from layout\n if banner.chart_id:\n try:\n superset_client.remove_chart_from_layout(\n dash_id, banner.chart_id\n )\n except Exception as e:\n app_logger.explore(\n \"Failed to remove chart from layout\",\n extra={\n \"dashboard_id\": dash_id,\n \"chart_id\": banner.chart_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Delete chart\n try:\n superset_client.delete_chart(banner.chart_id)\n except Exception as e:\n app_logger.explore(\n \"Failed to delete chart\",\n extra={\n \"chart_id\": banner.chart_id,\n \"dashboard_id\": dash_id,\n },\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n continue\n\n # Mark banner as removed\n banner.status = MaintenanceDashboardBannerStatus.REMOVED\n state.status = MaintenanceDashboardStateStatus.REMOVED\n app_logger.reflect(\n \"Banner fully removed\",\n extra={\"banner_id\": banner_id, \"dashboard_id\": dash_id},\n )\n else:\n state.status = MaintenanceDashboardStateStatus.REMOVED\n\n removed_count += 1\n\n except Exception as e:\n app_logger.explore(\n \"Failed to end maintenance for dashboard\",\n extra={\"dashboard_id\": dash_id},\n error=str(e),\n )\n state.status = MaintenanceDashboardStateStatus.REMOVAL_FAILED\n failed_removals.append(\n {\"id\": dash_id, \"title\": str(dash_id), \"error\": str(e)}\n )\n\n return removed_count, failed_removals\n# #endregion _process_states_for_end\n" + }, + { + "contract_id": "MaintenanceDashboardScanner", + "contract_type": "Module", + "file_path": "backend/src/services/maintenance/_dashboard_scanner.py", + "start_line": 1, + "end_line": 205, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Dashboard discovery and filtering helpers for maintenance banner feature." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceDashboardScanner [C:3] [TYPE Module] [SEMANTICS maintenance, dashboard, scanner, tables]\n# @BRIEF Dashboard discovery and filtering helpers for maintenance banner feature.\n# Scan Superset datasets, match tables, apply scope/excluded/forced filters.\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [SqlTableExtractorModule]\n# @RELATION DEPENDS_ON -> [MaintenanceModels]\n\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ...core.logger import belief_scope, logger as app_logger\nfrom ...core.superset_client import SupersetClient\nfrom ...models.maintenance import DashboardScope, MaintenanceSettings\nfrom ..sql_table_extractor import extract_tables_from_sql\n\n\n# #region find_affected_dashboards [C:3] [TYPE Function] [SEMANTICS maintenance, dashboard, discovery, tables]\n# @BRIEF Find all dashboard IDs whose datasets reference any of the given tables.\n# Supports both table-based (schema, table_name) and virtual SQL datasets (via SqlTableExtractor).\n# Applies scope/excluded/forced filtering from MaintenanceSettings.\n# @PRE tables is a non-empty list of \"schema.table\" strings. superset_client is authenticated.\n# @POST Returns a deduplicated list of dashboard IDs that should receive banners.\n# @SIDE_EFFECT Fetches all datasets from Superset (paginated). May be slow with many datasets.\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [SqlTableExtractorModule]\ndef find_affected_dashboards(\n tables: list[str],\n superset_client: SupersetClient,\n settings: MaintenanceSettings | None = None,\n) -> list[int]:\n with belief_scope(\n \"find_affected_dashboards\",\n f\"tables={tables}\",\n ):\n app_logger.reason(\n \"Finding affected dashboards\",\n extra={\"tables\": tables},\n )\n\n if not tables:\n app_logger.reflect(\"No tables provided, returning empty\")\n return []\n\n # Normalize input tables to lowercase set for matching\n target_tables = {t.lower().strip() for t in tables if t.strip()}\n if not target_tables:\n return []\n\n # Fetch all datasets from Superset\n try:\n _, datasets = superset_client.get_datasets()\n except Exception as e:\n app_logger.explore(\n \"Failed to fetch datasets from Superset\",\n extra={},\n error=str(e),\n )\n raise\n\n app_logger.reason(\n f\"Scanning {len(datasets)} datasets for table references\",\n extra={\"target_tables\": list(target_tables)},\n )\n\n matched_dashboard_ids: set[int] = set()\n\n for ds in datasets:\n ds_schema = (ds.get(\"schema\") or \"\").lower().strip()\n ds_table = (ds.get(\"table_name\") or \"\").lower().strip()\n is_virtual = ds.get(\"is_sqllab_view\", False) or ds.get(\"sql\", \"\") not in (\n None,\n \"\",\n )\n ds_sql = ds.get(\"sql\") or \"\"\n ds_id = ds.get(\"id\")\n\n # Phase 1: Table-based match\n if not is_virtual and ds_schema and ds_table:\n qualified = f\"{ds_schema}.{ds_table}\"\n if qualified in target_tables:\n linked = _get_linked_dashboards(superset_client, ds_id)\n matched_dashboard_ids.update(linked)\n continue\n\n # Phase 2: Virtual/SQL dataset — extract tables from SQL text\n if is_virtual and ds_sql:\n extracted = extract_tables_from_sql(ds_sql)\n if extracted & target_tables:\n linked = _get_linked_dashboards(superset_client, ds_id)\n matched_dashboard_ids.update(linked)\n\n app_logger.reflect(\n f\"Found {len(matched_dashboard_ids)} affected dashboards\",\n extra={\"dashboard_ids\": list(matched_dashboard_ids)},\n )\n\n # Apply filtering from settings\n result = _apply_dashboard_filters(\n list(matched_dashboard_ids), superset_client, settings\n )\n\n app_logger.reflect(\n f\"After filtering: {len(result)} dashboards\",\n extra={\"dashboard_ids\": result},\n )\n return result\n# #endregion find_affected_dashboards\n\n\n# #region _get_linked_dashboards [C:2] [TYPE Function]\n# @BRIEF Fetch linked dashboards for a dataset from Superset.\n# @SIDE_EFFECT Calls Superset API.\ndef _get_linked_dashboards(\n superset_client: SupersetClient,\n dataset_id: int | None,\n) -> set[int]:\n if not dataset_id:\n return set()\n try:\n detail = superset_client.get_dataset_detail(dataset_id)\n linked = detail.get(\"linked_dashboards\", [])\n return {int(d[\"id\"]) for d in linked if d.get(\"id\")}\n except Exception as e:\n app_logger.explore(\n \"Failed to fetch linked dashboards\",\n extra={\"dataset_id\": dataset_id},\n error=str(e),\n )\n return set()\n# #endregion _get_linked_dashboards\n\n\n# #region _apply_dashboard_filters [C:2] [TYPE Function]\n# @BRIEF Apply scope (published/draft/all), excluded, and forced filters from settings.\ndef _apply_dashboard_filters(\n dashboard_ids: list[int],\n superset_client: SupersetClient,\n settings: MaintenanceSettings | None,\n) -> list[int]:\n if not settings:\n return dashboard_ids\n\n # If forced list exists, include those unconditionally\n forced_ids = set(settings.forced_dashboard_ids or [])\n excluded_ids = set(settings.excluded_dashboard_ids or [])\n\n # Apply scope filtering\n if settings.dashboard_scope != DashboardScope.ALL:\n try:\n _, all_dashboards = superset_client.get_dashboards()\n scope = settings.dashboard_scope\n filtered: list[int] = []\n for did in dashboard_ids:\n dash = next(\n (d for d in all_dashboards if d.get(\"id\") == did), None\n )\n if dash is None:\n continue\n is_published = dash.get(\"published\", True)\n if scope == DashboardScope.PUBLISHED_ONLY and not is_published:\n continue\n if scope == DashboardScope.DRAFT_ONLY and is_published:\n continue\n filtered.append(did)\n dashboard_ids = filtered\n except Exception as e:\n app_logger.explore(\n \"Scope filtering failed, proceeding without it\",\n extra={},\n error=str(e),\n )\n\n # Apply excluded (forced overrides excluded per FR-009-b)\n result = [\n did for did in dashboard_ids if did not in excluded_ids or did in forced_ids\n ]\n\n # Add forced dashboards that are not already included\n for fid in forced_ids:\n if fid not in result:\n result.append(fid)\n\n return result\n# #endregion _apply_dashboard_filters\n\n\n# #region _resolve_dashboard_title [C:2] [TYPE Function]\n# @BRIEF Resolve dashboard title from Superset by ID.\ndef _resolve_dashboard_title(\n dashboard_id: int,\n superset_client: SupersetClient,\n) -> str:\n try:\n _, dashboards = superset_client.get_dashboards()\n for d in dashboards:\n if d.get(\"id\") == dashboard_id:\n return d.get(\"dashboard_title\") or d.get(\"title\") or str(dashboard_id)\n except Exception:\n pass\n return str(dashboard_id)\n# #endregion _resolve_dashboard_title\n\n# #endregion MaintenanceDashboardScanner\n" + }, + { + "contract_id": "find_affected_dashboards", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_dashboard_scanner.py", + "start_line": 19, + "end_line": 109, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Find all dashboard IDs whose datasets reference any of the given tables." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region find_affected_dashboards [C:3] [TYPE Function] [SEMANTICS maintenance, dashboard, discovery, tables]\n# @BRIEF Find all dashboard IDs whose datasets reference any of the given tables.\n# Supports both table-based (schema, table_name) and virtual SQL datasets (via SqlTableExtractor).\n# Applies scope/excluded/forced filtering from MaintenanceSettings.\n# @PRE tables is a non-empty list of \"schema.table\" strings. superset_client is authenticated.\n# @POST Returns a deduplicated list of dashboard IDs that should receive banners.\n# @SIDE_EFFECT Fetches all datasets from Superset (paginated). May be slow with many datasets.\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [SqlTableExtractorModule]\ndef find_affected_dashboards(\n tables: list[str],\n superset_client: SupersetClient,\n settings: MaintenanceSettings | None = None,\n) -> list[int]:\n with belief_scope(\n \"find_affected_dashboards\",\n f\"tables={tables}\",\n ):\n app_logger.reason(\n \"Finding affected dashboards\",\n extra={\"tables\": tables},\n )\n\n if not tables:\n app_logger.reflect(\"No tables provided, returning empty\")\n return []\n\n # Normalize input tables to lowercase set for matching\n target_tables = {t.lower().strip() for t in tables if t.strip()}\n if not target_tables:\n return []\n\n # Fetch all datasets from Superset\n try:\n _, datasets = superset_client.get_datasets()\n except Exception as e:\n app_logger.explore(\n \"Failed to fetch datasets from Superset\",\n extra={},\n error=str(e),\n )\n raise\n\n app_logger.reason(\n f\"Scanning {len(datasets)} datasets for table references\",\n extra={\"target_tables\": list(target_tables)},\n )\n\n matched_dashboard_ids: set[int] = set()\n\n for ds in datasets:\n ds_schema = (ds.get(\"schema\") or \"\").lower().strip()\n ds_table = (ds.get(\"table_name\") or \"\").lower().strip()\n is_virtual = ds.get(\"is_sqllab_view\", False) or ds.get(\"sql\", \"\") not in (\n None,\n \"\",\n )\n ds_sql = ds.get(\"sql\") or \"\"\n ds_id = ds.get(\"id\")\n\n # Phase 1: Table-based match\n if not is_virtual and ds_schema and ds_table:\n qualified = f\"{ds_schema}.{ds_table}\"\n if qualified in target_tables:\n linked = _get_linked_dashboards(superset_client, ds_id)\n matched_dashboard_ids.update(linked)\n continue\n\n # Phase 2: Virtual/SQL dataset — extract tables from SQL text\n if is_virtual and ds_sql:\n extracted = extract_tables_from_sql(ds_sql)\n if extracted & target_tables:\n linked = _get_linked_dashboards(superset_client, ds_id)\n matched_dashboard_ids.update(linked)\n\n app_logger.reflect(\n f\"Found {len(matched_dashboard_ids)} affected dashboards\",\n extra={\"dashboard_ids\": list(matched_dashboard_ids)},\n )\n\n # Apply filtering from settings\n result = _apply_dashboard_filters(\n list(matched_dashboard_ids), superset_client, settings\n )\n\n app_logger.reflect(\n f\"After filtering: {len(result)} dashboards\",\n extra={\"dashboard_ids\": result},\n )\n return result\n# #endregion find_affected_dashboards\n" + }, + { + "contract_id": "_get_linked_dashboards", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_dashboard_scanner.py", + "start_line": 112, + "end_line": 132, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Fetch linked dashboards for a dataset from Superset.", + "SIDE_EFFECT": "Calls Superset API." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _get_linked_dashboards [C:2] [TYPE Function]\n# @BRIEF Fetch linked dashboards for a dataset from Superset.\n# @SIDE_EFFECT Calls Superset API.\ndef _get_linked_dashboards(\n superset_client: SupersetClient,\n dataset_id: int | None,\n) -> set[int]:\n if not dataset_id:\n return set()\n try:\n detail = superset_client.get_dataset_detail(dataset_id)\n linked = detail.get(\"linked_dashboards\", [])\n return {int(d[\"id\"]) for d in linked if d.get(\"id\")}\n except Exception as e:\n app_logger.explore(\n \"Failed to fetch linked dashboards\",\n extra={\"dataset_id\": dataset_id},\n error=str(e),\n )\n return set()\n# #endregion _get_linked_dashboards\n" + }, + { + "contract_id": "_apply_dashboard_filters", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_dashboard_scanner.py", + "start_line": 135, + "end_line": 186, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Apply scope (published/draft/all), excluded, and forced filters from settings." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _apply_dashboard_filters [C:2] [TYPE Function]\n# @BRIEF Apply scope (published/draft/all), excluded, and forced filters from settings.\ndef _apply_dashboard_filters(\n dashboard_ids: list[int],\n superset_client: SupersetClient,\n settings: MaintenanceSettings | None,\n) -> list[int]:\n if not settings:\n return dashboard_ids\n\n # If forced list exists, include those unconditionally\n forced_ids = set(settings.forced_dashboard_ids or [])\n excluded_ids = set(settings.excluded_dashboard_ids or [])\n\n # Apply scope filtering\n if settings.dashboard_scope != DashboardScope.ALL:\n try:\n _, all_dashboards = superset_client.get_dashboards()\n scope = settings.dashboard_scope\n filtered: list[int] = []\n for did in dashboard_ids:\n dash = next(\n (d for d in all_dashboards if d.get(\"id\") == did), None\n )\n if dash is None:\n continue\n is_published = dash.get(\"published\", True)\n if scope == DashboardScope.PUBLISHED_ONLY and not is_published:\n continue\n if scope == DashboardScope.DRAFT_ONLY and is_published:\n continue\n filtered.append(did)\n dashboard_ids = filtered\n except Exception as e:\n app_logger.explore(\n \"Scope filtering failed, proceeding without it\",\n extra={},\n error=str(e),\n )\n\n # Apply excluded (forced overrides excluded per FR-009-b)\n result = [\n did for did in dashboard_ids if did not in excluded_ids or did in forced_ids\n ]\n\n # Add forced dashboards that are not already included\n for fid in forced_ids:\n if fid not in result:\n result.append(fid)\n\n return result\n# #endregion _apply_dashboard_filters\n" + }, + { + "contract_id": "_resolve_dashboard_title", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_dashboard_scanner.py", + "start_line": 189, + "end_line": 203, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Resolve dashboard title from Superset by ID." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region _resolve_dashboard_title [C:2] [TYPE Function]\n# @BRIEF Resolve dashboard title from Superset by ID.\ndef _resolve_dashboard_title(\n dashboard_id: int,\n superset_client: SupersetClient,\n) -> str:\n try:\n _, dashboards = superset_client.get_dashboards()\n for d in dashboards:\n if d.get(\"id\") == dashboard_id:\n return d.get(\"dashboard_title\") or d.get(\"title\") or str(dashboard_id)\n except Exception:\n pass\n return str(dashboard_id)\n# #endregion _resolve_dashboard_title\n" + }, + { + "contract_id": "MaintenanceOrchestrators", + "contract_type": "Module", + "file_path": "backend/src/services/maintenance/_orchestrators.py", + "start_line": 1, + "end_line": 338, + "tier": "TIER_2", + "complexity": 4, + "metadata": { + "COMPLEXITY": 4, + "PURPOSE": "C4 orchestrators for maintenance event lifecycle: start, end, end-all." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region MaintenanceOrchestrators [C:4] [TYPE Module] [SEMANTICS maintenance, orchestrator, lifecycle]\n# @BRIEF C4 orchestrators for maintenance event lifecycle: start, end, end-all.\n# Private helpers extracted to sub-modules. All orchestrators use belief runtime.\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [MaintenanceModels]\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [MaintenanceDashboardScanner]\n# @RELATION DEPENDS_ON -> [MaintenanceBannerRenderer]\n# @RELATION DEPENDS_ON -> [MaintenanceChartManager]\n# @INVARIANT C4 methods use belief_scope + REASON/REFLECT/EXPLORE markers.\n# @INVARIANT Idempotency key: sorted lowercased (tables, start_time, end_time). message NOT in key.\n\nfrom datetime import datetime, timezone\nfrom typing import Any\n\nfrom sqlalchemy.orm import Session\n\nfrom ...core.logger import belief_scope, logger as app_logger\nfrom ...core.superset_client import SupersetClient\nfrom ...models.maintenance import (\n MaintenanceDashboardState,\n MaintenanceEvent,\n MaintenanceEventStatus,\n MaintenanceSettings,\n)\nfrom ._chart_manager import _process_dashboards_for_start, _process_states_for_end\nfrom ._dashboard_scanner import find_affected_dashboards\n\n\n# #region build_idempotency_key [C:2] [TYPE Function]\n# @BRIEF Build idempotency key from (tables, start_time, end_time). Sorted lowercased tables, ISO timestamps.\n# @PRE tables is a list of strings. start_time is a datetime or None. end_time is a datetime or None.\n# @POST Returns a tuple of (frozenset(str), str|None, str|None) for DB comparison.\n# @RATIONALE message is intentionally excluded from key per spec — different message with same tables/times = same event.\ndef build_idempotency_key(\n tables: list[str],\n start_time: datetime | None,\n end_time: datetime | None,\n) -> tuple[frozenset[str], str | None, str | None]:\n sorted_tables = sorted(t.strip().lower() for t in tables if t.strip())\n start_key = start_time.isoformat() if start_time else None\n end_key = end_time.isoformat() if end_time else None\n return (frozenset(sorted_tables), start_key, end_key)\n# #endregion build_idempotency_key\n\n\n# #region start_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, start, orchestration, async]\n# @BRIEF C4 orchestrator for starting a maintenance event. Runs inside a TaskManager task.\n# Idempotency check with SELECT ... FOR UPDATE. Creates event states, finds dashboards,\n# ensures banner charts, builds text, updates charts. Event transitions to ACTIVE or PARTIAL.\n# @PRE event_id points to a valid MaintenanceEvent with status=PENDING.\n# @POST Event and dashboard states transitioned to ACTIVE/PARTIAL/APPLY_FAILED.\n# Banner charts created and updated in Superset.\n# @SIDE_EFFECT Modifies Superset dashboards (creates/updates charts, modifies layouts).\n# Writes multiple DB rows (dashboard states, banner updates).\n# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers.\n# @RELATION CALLS -> [find_affected_dashboards]\n# @RELATION CALLS -> [_process_dashboards_for_start]\ndef start_maintenance(\n event_id: str,\n db_session: Session,\n superset_client: SupersetClient,\n) -> dict[str, Any]:\n with belief_scope(\"start_maintenance\", f\"event_id={event_id}\"):\n app_logger.reason(\n \"Starting maintenance event\",\n extra={\"event_id\": event_id},\n )\n\n # Load event\n event = db_session.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == event_id\n ).with_for_update().first()\n if not event:\n app_logger.explore(\n \"Event not found\",\n extra={\"event_id\": event_id},\n error=\"EventNotFound\",\n )\n return {\"maintenance_id\": event_id, \"status\": \"failed\", \"error\": \"Event not found\"}\n\n if event.status != MaintenanceEventStatus.PENDING:\n app_logger.reflect(\n \"Event already processed\",\n extra={\"event_id\": event_id, \"status\": event.status.value},\n )\n return {\"maintenance_id\": event_id, \"status\": event.status.value}\n\n # Transition to APPLYING\n event.status = MaintenanceEventStatus.APPLYING\n db_session.flush()\n\n # Load settings\n settings = db_session.query(MaintenanceSettings).filter(\n MaintenanceSettings.id == \"default\"\n ).first()\n environment_id = settings.target_environment_id if settings else event.environment_id\n template = settings.banner_template if settings else \"\"\n timezone_str = settings.display_timezone if settings else \"UTC\"\n\n # Find affected dashboards\n try:\n dashboard_ids = find_affected_dashboards(\n event.tables,\n superset_client,\n settings,\n )\n except Exception as e:\n app_logger.explore(\n \"Dashboard discovery failed\",\n extra={\"event_id\": event_id},\n error=str(e),\n )\n event.status = MaintenanceEventStatus.FAILED\n db_session.flush()\n return {\n \"maintenance_id\": event_id,\n \"status\": \"failed\",\n \"error\": str(e),\n \"affected_dashboards\": 0,\n \"dashboards\": [],\n \"failed_dashboards\": [],\n \"unmatched_tables\": [],\n }\n\n if not dashboard_ids:\n app_logger.reflect(\n \"No matching dashboards found\",\n extra={\"event_id\": event_id},\n )\n event.status = MaintenanceEventStatus.ACTIVE\n db_session.flush()\n return {\n \"maintenance_id\": event_id,\n \"status\": \"no_match\",\n \"affected_dashboards\": 0,\n \"dashboards\": [],\n \"failed_dashboards\": [],\n \"unmatched_tables\": [\n t for t in event.tables if t not in dashboard_ids\n ],\n }\n\n # Process each dashboard\n successful_dashboards, failed_dashboards, _ = _process_dashboards_for_start(\n dashboard_ids,\n event_id,\n environment_id,\n template,\n timezone_str,\n superset_client,\n db_session,\n )\n\n # Determine final event status\n if not failed_dashboards:\n event.status = MaintenanceEventStatus.ACTIVE\n elif successful_dashboards:\n event.status = MaintenanceEventStatus.PARTIAL\n else:\n event.status = MaintenanceEventStatus.FAILED\n\n db_session.flush()\n\n result = {\n \"maintenance_id\": event_id,\n \"status\": event.status.value,\n \"affected_dashboards\": len(successful_dashboards),\n \"dashboards\": successful_dashboards,\n \"failed_dashboards\": failed_dashboards,\n \"unmatched_tables\": [],\n }\n\n app_logger.reflect(\n \"Maintenance start completed\",\n extra={\n \"event_id\": event_id,\n \"status\": event.status.value,\n \"successful\": len(successful_dashboards),\n \"failed\": len(failed_dashboards),\n },\n )\n return result\n# #endregion start_maintenance\n\n\n# #region end_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, end, orchestration, async, removal]\n# @BRIEF C4 orchestrator for ending a maintenance event. Runs inside a TaskManager task.\n# Event → ENDING. Delegates per-state processing to _process_states_for_end.\n# Event → COMPLETED when done.\n# @PRE event_id points to a valid active MaintenanceEvent.\n# @POST Event transitions to COMPLETED. Dashboard states cleaned up. Charts removed when no other events.\n# @SIDE_EFFECT Modifies Superset dashboards (removes charts, updates layouts). Writes DB.\n# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers.\n# @RELATION CALLS -> [_process_states_for_end]\ndef end_maintenance(\n event_id: str,\n db_session: Session,\n superset_client: SupersetClient,\n) -> dict[str, Any]:\n with belief_scope(\"end_maintenance\", f\"event_id={event_id}\"):\n app_logger.reason(\n \"Ending maintenance event\",\n extra={\"event_id\": event_id},\n )\n\n # Load event with lock\n event = db_session.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == event_id\n ).with_for_update().first()\n if not event:\n app_logger.explore(\n \"Event not found\",\n extra={\"event_id\": event_id},\n error=\"EventNotFound\",\n )\n return {\"maintenance_id\": event_id, \"status\": \"failed\", \"error\": \"Event not found\"}\n\n # Idempotent: already completed\n if event.status == MaintenanceEventStatus.COMPLETED:\n app_logger.reflect(\n \"Event already completed, idempotent\",\n extra={\"event_id\": event_id},\n )\n return {\"maintenance_id\": event_id, \"status\": \"already_completed\", \"removed_from\": 0, \"failed_removals\": []}\n\n # Transition to ENDING\n event.status = MaintenanceEventStatus.ENDING\n db_session.flush()\n\n # Find all dashboard states for this event\n states = db_session.query(MaintenanceDashboardState).filter(\n MaintenanceDashboardState.event_id == event_id\n ).all()\n\n # Delegate per-state processing\n removed_count, failed_removals = _process_states_for_end(\n states, event_id, superset_client, db_session,\n )\n\n # Transition event to COMPLETED (even if some removals failed)\n event.status = MaintenanceEventStatus.COMPLETED\n db_session.flush()\n\n result = {\n \"maintenance_id\": event_id,\n \"status\": \"completed\" if not failed_removals else \"partial\",\n \"removed_from\": removed_count,\n \"failed_removals\": failed_removals,\n }\n\n app_logger.reflect(\n \"Maintenance end completed\",\n extra={\n \"event_id\": event_id,\n \"removed\": removed_count,\n \"failed\": len(failed_removals),\n },\n )\n return result\n# #endregion end_maintenance\n\n\n# #region end_all_maintenance [C:4] [TYPE Function] [SEMANTICS maintenance, end-all, orchestration, bulk]\n# @BRIEF End ALL active maintenance events. Iterates active events, calls end_maintenance for each.\n# @PRE None.\n# @POST All events ended. All banners removed or rebuilt (last event removed).\n# @SIDE_EFFECT Modifies multiple Superset dashboards. Writes multiple DB rows.\n# @BELIEF Uses belief_scope with REASON/REFLECT/EXPLORE markers.\n# @RELATION CALLS -> [end_maintenance]\ndef end_all_maintenance(\n db_session: Session,\n superset_client: SupersetClient,\n) -> dict[str, Any]:\n with belief_scope(\"end_all_maintenance\"):\n app_logger.reason(\"Ending all active maintenance events\")\n\n active_events = db_session.query(MaintenanceEvent).filter(\n MaintenanceEvent.status.in_([\n MaintenanceEventStatus.ACTIVE,\n MaintenanceEventStatus.PARTIAL,\n MaintenanceEventStatus.APPLYING,\n ])\n ).all()\n\n if not active_events:\n app_logger.reflect(\"No active events to end\")\n return {\n \"status\": \"completed\",\n \"closed_events\": 0,\n \"removed_from\": 0,\n \"failed_removals\": [],\n }\n\n total_removed = 0\n all_failed: list[dict[str, Any]] = []\n closed_count = 0\n\n for event in active_events:\n app_logger.reason(\n \"Ending event\",\n extra={\"event_id\": event.id},\n )\n try:\n result = end_maintenance(\n event.id, db_session, superset_client\n )\n total_removed += result.get(\"removed_from\", 0)\n all_failed.extend(result.get(\"failed_removals\", []))\n closed_count += 1\n except Exception as e:\n app_logger.explore(\n \"Failed to end event\",\n extra={\"event_id\": event.id},\n error=str(e),\n )\n all_failed.append(\n {\"id\": 0, \"title\": event.id, \"error\": str(e)}\n )\n\n app_logger.reflect(\n \"All events ended\",\n extra={\n \"closed\": closed_count,\n \"removed\": total_removed,\n \"failed\": len(all_failed),\n },\n )\n\n return {\n \"status\": \"completed\" if not all_failed else \"partial\",\n \"closed_events\": closed_count,\n \"removed_from\": total_removed,\n \"failed_removals\": all_failed,\n }\n# #endregion end_all_maintenance\n\n# #endregion MaintenanceOrchestrators\n" + }, + { + "contract_id": "build_idempotency_key", + "contract_type": "Function", + "file_path": "backend/src/services/maintenance/_orchestrators.py", + "start_line": 30, + "end_line": 44, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns a tuple of (frozenset(str), str|None, str|None) for DB comparison.", + "PRE": "tables is a list of strings. start_time is a datetime or None. end_time is a datetime or None.", + "PURPOSE": "Build idempotency key from (tables, start_time, end_time). Sorted lowercased tables, ISO timestamps.", + "RATIONALE": "message is intentionally excluded from key per spec — different message with same tables/times = same event." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region build_idempotency_key [C:2] [TYPE Function]\n# @BRIEF Build idempotency key from (tables, start_time, end_time). Sorted lowercased tables, ISO timestamps.\n# @PRE tables is a list of strings. start_time is a datetime or None. end_time is a datetime or None.\n# @POST Returns a tuple of (frozenset(str), str|None, str|None) for DB comparison.\n# @RATIONALE message is intentionally excluded from key per spec — different message with same tables/times = same event.\ndef build_idempotency_key(\n tables: list[str],\n start_time: datetime | None,\n end_time: datetime | None,\n) -> tuple[frozenset[str], str | None, str | None]:\n sorted_tables = sorted(t.strip().lower() for t in tables if t.strip())\n start_key = start_time.isoformat() if start_time else None\n end_key = end_time.isoformat() if end_time else None\n return (frozenset(sorted_tables), start_key, end_key)\n# #endregion build_idempotency_key\n" + }, { "contract_id": "mapping_service", "contract_type": "Module", @@ -51274,7 +53706,7 @@ "contract_type": "Module", "file_path": "backend/src/services/resource_service.py", "start_line": 1, - "end_line": 484, + "end_line": 518, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -51314,14 +53746,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ResourceServiceModule [C:5] [TYPE Module] [SEMANTICS resource, git, task, status, superset]\n# @BRIEF Shared service for fetching resource data with Git status and task status\n# @LAYER: Service\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskManagerPackage]\n# @RELATION DEPENDS_ON -> [TaskManagerModels]\n# @RELATION DEPENDS_ON -> [GitService]\n# @INVARIANT: All resources include metadata about their current state\n# @SIDE_EFFECT: Queries multiple backends for status\n# @DATA_CONTRACT: ResourceQuery -> ResourceStatusSummary\n\nfrom datetime import UTC, datetime\nfrom typing import Any\n\nfrom ..core.logger import belief_scope, logger\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager.models import Task\nfrom ..services.git_service import GitService\n\n\n# #region ResourceService [C:3] [TYPE Class]\n# @BRIEF Provides centralized access to resource data with enhanced metadata\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [GitService]\nclass ResourceService:\n\n # region ResourceService_init [TYPE Function]\n # @PURPOSE: Initialize the resource service with dependencies\n # @PRE: None\n # @POST: ResourceService is ready to fetch resources\n def __init__(self):\n with belief_scope(\"ResourceService.__init__\"):\n self.git_service = GitService()\n logger.reason(\"Initialized ResourceService\", extra={\"src\": \"ResourceService\"})\n # endregion ResourceService_init\n\n # region get_dashboards_with_status [TYPE Function]\n # @PURPOSE: Fetch dashboards from environment with Git status and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of dashboards with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Dashboards with git_status and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummary]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_dashboards_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n dashboards = client.get_dashboards_summary(require_slug=require_slug)\n\n # Enhance each dashboard with Git status and task status\n result = []\n for dashboard in dashboards:\n # dashboard is already a dict, no need to call .dict()\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get('id')\n\n # Git status can be skipped for list endpoints and loaded lazily on UI side.\n if include_git_status:\n git_status = self._get_git_status_for_dashboard(dashboard_id)\n dashboard_dict['git_status'] = git_status\n else:\n dashboard_dict['git_status'] = None\n\n # Show status of the latest LLM validation for this dashboard.\n last_task = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n dashboard_dict['last_task'] = last_task\n\n result.append(dashboard_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} dashboards with status\")\n return result\n # endregion get_dashboards_with_status\n\n # region get_dashboards_page_with_status [TYPE Function]\n # @PURPOSE: Fetch one dashboard page from environment and enrich only that page with status metadata.\n # @PRE: env is valid; page >= 1; page_size > 0.\n # @POST: Returns page items plus total counters without scanning all pages locally.\n # @PARAM: env (Environment) - Source environment.\n # @PARAM: tasks (Optional[List[Task]]) - Tasks for latest LLM status.\n # @PARAM: page (int) - 1-based page number.\n # @PARAM: page_size (int) - Page size.\n # @RETURN: Dict[str, Any] - {\"dashboards\": List[Dict], \"total\": int, \"total_pages\": int}\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummaryPage]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_page_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n page: int = 1,\n page_size: int = 10,\n search: str | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> dict[str, Any]:\n with belief_scope(\n \"get_dashboards_page_with_status\",\n f\"env={env.id}, page={page}, page_size={page_size}, search={search}\",\n ):\n client = SupersetClient(env)\n total, dashboards_page = client.get_dashboards_summary_page(\n page=page,\n page_size=page_size,\n search=search,\n require_slug=require_slug,\n )\n\n result = []\n for dashboard in dashboards_page:\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get(\"id\")\n\n if include_git_status:\n dashboard_dict[\"git_status\"] = self._get_git_status_for_dashboard(dashboard_id)\n else:\n dashboard_dict[\"git_status\"] = None\n\n dashboard_dict[\"last_task\"] = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n result.append(dashboard_dict)\n\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n logger.info(\n \"[ResourceService][Coherence:OK] Fetched dashboards page %s/%s (%s items, total=%s)\",\n page,\n total_pages,\n len(result),\n total,\n )\n return {\n \"dashboards\": result,\n \"total\": total,\n \"total_pages\": total_pages,\n }\n # endregion get_dashboards_page_with_status\n\n # region _get_last_llm_task_for_dashboard [TYPE Function]\n # @PURPOSE: Get most recent LLM validation task for a dashboard in an environment\n # @PRE: dashboard_id is a valid integer identifier\n # @POST: Returns the newest llm_dashboard_validation task summary or None\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @PARAM: env_id (Optional[str]) - Environment ID to match task params\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n # @RELATION: CALLS ->[_normalize_validation_status]\n # @RELATION: CALLS ->[_normalize_task_status]\n def _get_last_llm_task_for_dashboard(\n self,\n dashboard_id: int,\n env_id: str | None,\n tasks: list[Task] | None = None,\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n dashboard_id_str = str(dashboard_id)\n matched_tasks = []\n\n for task in tasks:\n if getattr(task, \"plugin_id\", None) != \"llm_dashboard_validation\":\n continue\n\n params = getattr(task, \"params\", {}) or {}\n if str(params.get(\"dashboard_id\")) != dashboard_id_str:\n continue\n\n if env_id is not None:\n task_env = params.get(\"environment_id\") or params.get(\"env\")\n if str(task_env) != str(env_id):\n continue\n\n matched_tasks.append(task)\n\n if not matched_tasks:\n return None\n\n def _task_time(task_obj: Any) -> datetime:\n raw_time = (\n getattr(task_obj, \"started_at\", None)\n or getattr(task_obj, \"finished_at\", None)\n or getattr(task_obj, \"created_at\", None)\n )\n return self._normalize_datetime_for_compare(raw_time)\n\n projected_tasks = []\n for task in matched_tasks:\n raw_result = getattr(task, \"result\", None)\n validation_status = None\n if isinstance(raw_result, dict):\n validation_status = self._normalize_validation_status(raw_result.get(\"status\"))\n projected_tasks.append(\n (\n task,\n validation_status,\n _task_time(task),\n )\n )\n\n projected_tasks.sort(key=lambda item: item[2], reverse=True)\n latest_task, latest_validation_status, _ = projected_tasks[0]\n decisive_task = next(\n (\n item for item in projected_tasks\n if item[1] in {\"PASS\", \"WARN\", \"FAIL\"}\n ),\n None,\n )\n validation_status = latest_validation_status\n if validation_status == \"UNKNOWN\" and decisive_task is not None:\n validation_status = decisive_task[1]\n\n return {\n \"task_id\": str(getattr(latest_task, \"id\", \"\")),\n \"status\": self._normalize_task_status(getattr(latest_task, \"status\", \"\")),\n \"validation_status\": validation_status,\n }\n # endregion _get_last_llm_task_for_dashboard\n\n # region _normalize_task_status [TYPE Function]\n # @PURPOSE: Normalize task status to stable uppercase values for UI/API projections\n # @PRE: raw_status can be enum or string\n # @POST: Returns uppercase status without enum class prefix\n # @PARAM: raw_status (Any) - Raw task status object/value\n # @RETURN: str - Normalized status token\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_task_status(self, raw_status: Any) -> str:\n if raw_status is None:\n return \"\"\n value = getattr(raw_status, \"value\", raw_status)\n status_text = str(value).strip()\n if \".\" in status_text:\n status_text = status_text.split(\".\")[-1]\n return status_text.upper()\n # endregion _normalize_task_status\n\n # region _normalize_validation_status [TYPE Function]\n # @PURPOSE: Normalize LLM validation status to PASS/FAIL/WARN/UNKNOWN\n # @PRE: raw_status can be any scalar type\n # @POST: Returns normalized validation status token or None\n # @PARAM: raw_status (Any) - Raw validation status from task result\n # @RETURN: Optional[str] - PASS|FAIL|WARN|UNKNOWN\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_validation_status(self, raw_status: Any) -> str | None:\n if raw_status is None:\n return None\n status_text = str(raw_status).strip().upper()\n if status_text in {\"PASS\", \"FAIL\", \"WARN\"}:\n return status_text\n return \"UNKNOWN\"\n # endregion _normalize_validation_status\n\n # region _normalize_datetime_for_compare [TYPE Function]\n # @PURPOSE: Normalize datetime values to UTC-aware values for safe comparisons.\n # @PRE: value may be datetime or any scalar.\n # @POST: Returns UTC-aware datetime; non-datetime values map to minimal UTC datetime.\n # @PARAM: value (Any) - Candidate datetime-like value.\n # @RETURN: datetime - UTC-aware comparable datetime.\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n # @RELATION: USED_BY ->[_get_last_task_for_resource]\n def _normalize_datetime_for_compare(self, value: Any) -> datetime:\n if isinstance(value, datetime):\n if value.tzinfo is None:\n return value.replace(tzinfo=UTC)\n return value.astimezone(UTC)\n return datetime.min.replace(tzinfo=UTC)\n # endregion _normalize_datetime_for_compare\n\n # region get_datasets_with_status [TYPE Function]\n # @PURPOSE: Fetch datasets from environment with mapping progress and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of datasets with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Datasets with mapped_fields and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDatasetsSummary]\n # @RELATION: CALLS ->[_get_last_task_for_resource]\n async def get_datasets_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_datasets_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n datasets = client.get_datasets_summary()\n\n # Enhance each dataset with task status\n result = []\n for dataset in datasets:\n # dataset is already a dict, no need to call .dict()\n dataset_dict = dataset\n dataset_id = dataset_dict.get('id')\n\n # Get last task status\n last_task = self._get_last_task_for_resource(\n f\"dataset-{dataset_id}\",\n tasks\n )\n dataset_dict['last_task'] = last_task\n\n result.append(dataset_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} datasets with status\")\n return result\n # endregion get_datasets_with_status\n\n # region get_activity_summary [TYPE Function]\n # @PURPOSE: Get summary of active and recent tasks for the activity indicator\n # @PRE: tasks is a list of Task objects\n # @POST: Returns summary with active_count and recent_tasks\n # @PARAM: tasks (List[Task]) - List of tasks to summarize\n # @RETURN: Dict - Activity summary\n # @RELATION: CALLS ->[_extract_resource_name_from_task]\n # @RELATION: CALLS ->[_extract_resource_type_from_task]\n def get_activity_summary(self, tasks: list[Task]) -> dict[str, Any]:\n with belief_scope(\"get_activity_summary\"):\n # Count active (RUNNING, WAITING_INPUT) tasks\n active_tasks = [\n t for t in tasks\n if t.status in ['RUNNING', 'WAITING_INPUT']\n ]\n\n # Get recent tasks (last 5)\n recent_tasks = sorted(\n tasks,\n key=lambda t: t.created_at,\n reverse=True\n )[:5]\n\n # Format recent tasks for frontend\n recent_tasks_formatted = []\n for task in recent_tasks:\n resource_name = self._extract_resource_name_from_task(task)\n recent_tasks_formatted.append({\n 'task_id': str(task.id),\n 'resource_name': resource_name,\n 'resource_type': self._extract_resource_type_from_task(task),\n 'status': task.status,\n 'started_at': task.created_at.isoformat() if task.created_at else None\n })\n\n return {\n 'active_count': len(active_tasks),\n 'recent_tasks': recent_tasks_formatted\n }\n # endregion get_activity_summary\n\n # region _get_git_status_for_dashboard [TYPE Function]\n # @PURPOSE: Get Git sync status for a dashboard\n # @PRE: dashboard_id is a valid integer\n # @POST: Returns git status or None if no repo exists\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @RETURN: Optional[Dict] - Git status with branch and sync_status\n # @RELATION: CALLS ->[get_repo]\n def _get_git_status_for_dashboard(self, dashboard_id: int) -> dict[str, Any] | None:\n try:\n repo = self.git_service.get_repo(dashboard_id)\n if not repo:\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n\n # Check if there are uncommitted changes\n try:\n # Get current branch\n branch = repo.active_branch.name\n\n # Check for uncommitted changes\n is_dirty = repo.is_dirty()\n has_changes_for_commit = repo.is_dirty(untracked_files=True)\n\n # Check for unpushed commits\n unpushed = len(list(repo.iter_commits(f'{branch}@{{u}}..{branch}'))) if '@{u}' in str(repo.refs) else 0\n\n if is_dirty or unpushed > 0:\n sync_status = 'DIFF'\n else:\n sync_status = 'OK'\n\n return {\n 'branch': branch,\n 'sync_status': sync_status,\n 'has_repo': True,\n 'has_changes_for_commit': has_changes_for_commit\n }\n except Exception:\n logger.warning(f\"[ResourceService][Warning] Failed to get git status for dashboard {dashboard_id}\")\n return {\n 'branch': None,\n 'sync_status': 'ERROR',\n 'has_repo': True,\n 'has_changes_for_commit': False\n }\n except Exception:\n # No repo exists for this dashboard\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n # endregion _get_git_status_for_dashboard\n\n # region _get_last_task_for_resource [TYPE Function]\n # @PURPOSE: Get the most recent task for a specific resource\n # @PRE: resource_id is a valid string\n # @POST: Returns task summary or None if no tasks found\n # @PARAM: resource_id (str) - The resource identifier (e.g., \"dashboard-123\")\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n def _get_last_task_for_resource(\n self,\n resource_id: str,\n tasks: list[Task] | None = None\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n # Filter tasks for this resource\n resource_tasks = []\n for task in tasks:\n params = task.params or {}\n if params.get('resource_id') == resource_id:\n resource_tasks.append(task)\n\n if not resource_tasks:\n return None\n\n # Get most recent task with timezone-safe comparison.\n last_task = max(\n resource_tasks,\n key=lambda t: self._normalize_datetime_for_compare(getattr(t, \"created_at\", None)),\n )\n\n return {\n 'task_id': str(last_task.id),\n 'status': last_task.status\n }\n # endregion _get_last_task_for_resource\n\n # region _extract_resource_name_from_task [TYPE Function]\n # @PURPOSE: Extract resource name from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource name or task ID\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource name or fallback\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_name_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_name', f\"Task {task.id}\")\n # endregion _extract_resource_name_from_task\n\n # region _extract_resource_type_from_task [TYPE Function]\n # @PURPOSE: Extract resource type from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource type or 'unknown'\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource type\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_type_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_type', 'unknown')\n # endregion _extract_resource_type_from_task\n# #endregion ResourceService\n# #endregion ResourceServiceModule\n" + "body": "# #region ResourceServiceModule [C:5] [TYPE Module] [SEMANTICS resource, git, task, status, superset]\n# @BRIEF Shared service for fetching resource data with Git status and task status\n# @LAYER: Service\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [TaskManagerPackage]\n# @RELATION DEPENDS_ON -> [TaskManagerModels]\n# @RELATION DEPENDS_ON -> [GitService]\n# @INVARIANT: All resources include metadata about their current state\n# @SIDE_EFFECT: Queries multiple backends for status\n# @DATA_CONTRACT: ResourceQuery -> ResourceStatusSummary\n\nimport asyncio\nfrom datetime import UTC, datetime\nfrom typing import Any\n\nfrom ..core.logger import belief_scope, logger\nfrom ..core.superset_client import SupersetClient\nfrom ..core.task_manager.models import Task\nfrom ..services.git_service import GitService\n\n\n# #region ResourceService [C:3] [TYPE Class]\n# @BRIEF Provides centralized access to resource data with enhanced metadata\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [GitService]\nclass ResourceService:\n\n # region ResourceService_init [TYPE Function]\n # @PURPOSE: Initialize the resource service with dependencies\n # @PRE: None\n # @POST: ResourceService is ready to fetch resources\n def __init__(self):\n with belief_scope(\"ResourceService.__init__\"):\n self.git_service = GitService()\n logger.reason(\"Initialized ResourceService\", extra={\"src\": \"ResourceService\"})\n # endregion ResourceService_init\n\n # region get_dashboards_with_status [TYPE Function]\n # @PURPOSE: Fetch dashboards from environment with Git status and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of dashboards with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Dashboards with git_status and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummary]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_dashboards_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n dashboards = client.get_dashboards_summary(require_slug=require_slug)\n\n # Enhance each dashboard with Git status and task status\n result = []\n for dashboard in dashboards:\n # dashboard is already a dict, no need to call .dict()\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get('id')\n\n # Git status can be skipped for list endpoints and loaded lazily on UI side.\n if include_git_status:\n git_status = self._get_git_status_for_dashboard(dashboard_id)\n dashboard_dict['git_status'] = git_status\n else:\n dashboard_dict['git_status'] = None\n\n # Show status of the latest LLM validation for this dashboard.\n last_task = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n dashboard_dict['last_task'] = last_task\n\n result.append(dashboard_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} dashboards with status\")\n return result\n # endregion get_dashboards_with_status\n\n # region get_dashboards_page_with_status [TYPE Function]\n # @PURPOSE: Fetch one dashboard page from environment and enrich only that page with status metadata.\n # @PRE: env is valid; page >= 1; page_size > 0.\n # @POST: Returns page items plus total counters without scanning all pages locally.\n # @PARAM: env (Environment) - Source environment.\n # @PARAM: tasks (Optional[List[Task]]) - Tasks for latest LLM status.\n # @PARAM: page (int) - 1-based page number.\n # @PARAM: page_size (int) - Page size.\n # @RETURN: Dict[str, Any] - {\"dashboards\": List[Dict], \"total\": int, \"total_pages\": int}\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummaryPage]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_page_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n page: int = 1,\n page_size: int = 10,\n search: str | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> dict[str, Any]:\n with belief_scope(\n \"get_dashboards_page_with_status\",\n f\"env={env.id}, page={page}, page_size={page_size}, search={search}\",\n ):\n client = SupersetClient(env)\n total, dashboards_page = client.get_dashboards_summary_page(\n page=page,\n page_size=page_size,\n search=search,\n require_slug=require_slug,\n )\n\n result = []\n for dashboard in dashboards_page:\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get(\"id\")\n\n if include_git_status:\n dashboard_dict[\"git_status\"] = self._get_git_status_for_dashboard(dashboard_id)\n else:\n dashboard_dict[\"git_status\"] = None\n\n dashboard_dict[\"last_task\"] = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n result.append(dashboard_dict)\n\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n logger.info(\n \"[ResourceService][Coherence:OK] Fetched dashboards page %s/%s (%s items, total=%s)\",\n page,\n total_pages,\n len(result),\n total,\n )\n return {\n \"dashboards\": result,\n \"total\": total,\n \"total_pages\": total_pages,\n }\n # endregion get_dashboards_page_with_status\n\n # region _get_last_llm_task_for_dashboard [TYPE Function]\n # @PURPOSE: Get most recent LLM validation task for a dashboard in an environment\n # @PRE: dashboard_id is a valid integer identifier\n # @POST: Returns the newest llm_dashboard_validation task summary or None\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @PARAM: env_id (Optional[str]) - Environment ID to match task params\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n # @RELATION: CALLS ->[_normalize_validation_status]\n # @RELATION: CALLS ->[_normalize_task_status]\n def _get_last_llm_task_for_dashboard(\n self,\n dashboard_id: int,\n env_id: str | None,\n tasks: list[Task] | None = None,\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n dashboard_id_str = str(dashboard_id)\n matched_tasks = []\n\n for task in tasks:\n if getattr(task, \"plugin_id\", None) != \"llm_dashboard_validation\":\n continue\n\n params = getattr(task, \"params\", {}) or {}\n if str(params.get(\"dashboard_id\")) != dashboard_id_str:\n continue\n\n if env_id is not None:\n task_env = params.get(\"environment_id\") or params.get(\"env\")\n if str(task_env) != str(env_id):\n continue\n\n matched_tasks.append(task)\n\n if not matched_tasks:\n return None\n\n def _task_time(task_obj: Any) -> datetime:\n raw_time = (\n getattr(task_obj, \"started_at\", None)\n or getattr(task_obj, \"finished_at\", None)\n or getattr(task_obj, \"created_at\", None)\n )\n return self._normalize_datetime_for_compare(raw_time)\n\n projected_tasks = []\n for task in matched_tasks:\n raw_result = getattr(task, \"result\", None)\n validation_status = None\n if isinstance(raw_result, dict):\n validation_status = self._normalize_validation_status(raw_result.get(\"status\"))\n projected_tasks.append(\n (\n task,\n validation_status,\n _task_time(task),\n )\n )\n\n projected_tasks.sort(key=lambda item: item[2], reverse=True)\n latest_task, latest_validation_status, _ = projected_tasks[0]\n decisive_task = next(\n (\n item for item in projected_tasks\n if item[1] in {\"PASS\", \"WARN\", \"FAIL\"}\n ),\n None,\n )\n validation_status = latest_validation_status\n if validation_status == \"UNKNOWN\" and decisive_task is not None:\n validation_status = decisive_task[1]\n\n return {\n \"task_id\": str(getattr(latest_task, \"id\", \"\")),\n \"status\": self._normalize_task_status(getattr(latest_task, \"status\", \"\")),\n \"validation_status\": validation_status,\n }\n # endregion _get_last_llm_task_for_dashboard\n\n # region _normalize_task_status [TYPE Function]\n # @PURPOSE: Normalize task status to stable uppercase values for UI/API projections\n # @PRE: raw_status can be enum or string\n # @POST: Returns uppercase status without enum class prefix\n # @PARAM: raw_status (Any) - Raw task status object/value\n # @RETURN: str - Normalized status token\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_task_status(self, raw_status: Any) -> str:\n if raw_status is None:\n return \"\"\n value = getattr(raw_status, \"value\", raw_status)\n status_text = str(value).strip()\n if \".\" in status_text:\n status_text = status_text.split(\".\")[-1]\n return status_text.upper()\n # endregion _normalize_task_status\n\n # region _normalize_validation_status [TYPE Function]\n # @PURPOSE: Normalize LLM validation status to PASS/FAIL/WARN/UNKNOWN\n # @PRE: raw_status can be any scalar type\n # @POST: Returns normalized validation status token or None\n # @PARAM: raw_status (Any) - Raw validation status from task result\n # @RETURN: Optional[str] - PASS|FAIL|WARN|UNKNOWN\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_validation_status(self, raw_status: Any) -> str | None:\n if raw_status is None:\n return None\n status_text = str(raw_status).strip().upper()\n if status_text in {\"PASS\", \"FAIL\", \"WARN\"}:\n return status_text\n return \"UNKNOWN\"\n # endregion _normalize_validation_status\n\n # region _normalize_datetime_for_compare [TYPE Function]\n # @PURPOSE: Normalize datetime values to UTC-aware values for safe comparisons.\n # @PRE: value may be datetime or any scalar.\n # @POST: Returns UTC-aware datetime; non-datetime values map to minimal UTC datetime.\n # @PARAM: value (Any) - Candidate datetime-like value.\n # @RETURN: datetime - UTC-aware comparable datetime.\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n # @RELATION: USED_BY ->[_get_last_task_for_resource]\n def _normalize_datetime_for_compare(self, value: Any) -> datetime:\n if isinstance(value, datetime):\n if value.tzinfo is None:\n return value.replace(tzinfo=UTC)\n return value.astimezone(UTC)\n return datetime.min.replace(tzinfo=UTC)\n # endregion _normalize_datetime_for_compare\n\n # region get_datasets_with_status [TYPE Function]\n # @PURPOSE: Fetch datasets from environment with mapping progress and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of datasets with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Datasets with mapped_fields, last_task and linked_dashboard_count fields\n # @RELATION: CALLS -> [SupersetClientGetDatasetsSummary]\n # @RELATION: CALLS -> [SupersetClientGetDatasetLinkedDashboardCount]\n # @RELATION: CALLS ->[_get_last_task_for_resource]\n # @RATIONALE linked_dashboard_count was missing — get_datasets_summary() only returns id/table_name/schema/database\n # StatsBar showed linked_count=0 because the field was never populated in list endpoint.\n # Fix: fetch /dataset/{id}/related_objects for each dataset concurrently (semaphore=3, timeout=10s).\n # @REJECTED N+1 blocking calls rejected — would timeout at 26×1s. Semaphore + asyncio.to_thread + timeout prevents overload.\n async def get_datasets_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_datasets_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n datasets = client.get_datasets_summary()\n\n # Enhance each dataset with task status and linked dashboard count\n sem = asyncio.Semaphore(3) # limit concurrent Superset calls\n\n async def fetch_linked_count(ds_id: int) -> int:\n async with sem:\n try:\n return await asyncio.wait_for(\n asyncio.to_thread(\n client.get_dataset_linked_dashboard_count, ds_id\n ),\n timeout=10.0,\n )\n except (asyncio.TimeoutError, Exception):\n logger.warning(\n f\"[get_datasets_with_status][Warning] \"\n f\"Failed to fetch linked dashboard count for dataset {ds_id}\"\n )\n return 0\n\n result = []\n linked_tasks = []\n for dataset in datasets:\n dataset_dict = dataset\n dataset_id = dataset_dict.get('id')\n\n # Get last task status\n last_task = self._get_last_task_for_resource(\n f\"dataset-{dataset_id}\",\n tasks\n )\n dataset_dict['last_task'] = last_task\n\n result.append(dataset_dict)\n linked_tasks.append(fetch_linked_count(dataset_id))\n\n # Fetch linked dashboard counts concurrently — FR-022\n if linked_tasks:\n linked_counts = await asyncio.gather(*linked_tasks)\n for ds, count in zip(result, linked_counts):\n ds['linked_dashboard_count'] = count\n\n logger.info(\n f\"[ResourceService][Coherence:OK] \"\n f\"Fetched {len(result)} datasets with status and linked counts\"\n )\n return result\n # endregion get_datasets_with_status\n\n # region get_activity_summary [TYPE Function]\n # @PURPOSE: Get summary of active and recent tasks for the activity indicator\n # @PRE: tasks is a list of Task objects\n # @POST: Returns summary with active_count and recent_tasks\n # @PARAM: tasks (List[Task]) - List of tasks to summarize\n # @RETURN: Dict - Activity summary\n # @RELATION: CALLS ->[_extract_resource_name_from_task]\n # @RELATION: CALLS ->[_extract_resource_type_from_task]\n def get_activity_summary(self, tasks: list[Task]) -> dict[str, Any]:\n with belief_scope(\"get_activity_summary\"):\n # Count active (RUNNING, WAITING_INPUT) tasks\n active_tasks = [\n t for t in tasks\n if t.status in ['RUNNING', 'WAITING_INPUT']\n ]\n\n # Get recent tasks (last 5)\n recent_tasks = sorted(\n tasks,\n key=lambda t: t.created_at,\n reverse=True\n )[:5]\n\n # Format recent tasks for frontend\n recent_tasks_formatted = []\n for task in recent_tasks:\n resource_name = self._extract_resource_name_from_task(task)\n recent_tasks_formatted.append({\n 'task_id': str(task.id),\n 'resource_name': resource_name,\n 'resource_type': self._extract_resource_type_from_task(task),\n 'status': task.status,\n 'started_at': task.created_at.isoformat() if task.created_at else None\n })\n\n return {\n 'active_count': len(active_tasks),\n 'recent_tasks': recent_tasks_formatted\n }\n # endregion get_activity_summary\n\n # region _get_git_status_for_dashboard [TYPE Function]\n # @PURPOSE: Get Git sync status for a dashboard\n # @PRE: dashboard_id is a valid integer\n # @POST: Returns git status or None if no repo exists\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @RETURN: Optional[Dict] - Git status with branch and sync_status\n # @RELATION: CALLS ->[get_repo]\n def _get_git_status_for_dashboard(self, dashboard_id: int) -> dict[str, Any] | None:\n try:\n repo = self.git_service.get_repo(dashboard_id)\n if not repo:\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n\n # Check if there are uncommitted changes\n try:\n # Get current branch\n branch = repo.active_branch.name\n\n # Check for uncommitted changes\n is_dirty = repo.is_dirty()\n has_changes_for_commit = repo.is_dirty(untracked_files=True)\n\n # Check for unpushed commits\n unpushed = len(list(repo.iter_commits(f'{branch}@{{u}}..{branch}'))) if '@{u}' in str(repo.refs) else 0\n\n if is_dirty or unpushed > 0:\n sync_status = 'DIFF'\n else:\n sync_status = 'OK'\n\n return {\n 'branch': branch,\n 'sync_status': sync_status,\n 'has_repo': True,\n 'has_changes_for_commit': has_changes_for_commit\n }\n except Exception:\n logger.warning(f\"[ResourceService][Warning] Failed to get git status for dashboard {dashboard_id}\")\n return {\n 'branch': None,\n 'sync_status': 'ERROR',\n 'has_repo': True,\n 'has_changes_for_commit': False\n }\n except Exception:\n # No repo exists for this dashboard\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n # endregion _get_git_status_for_dashboard\n\n # region _get_last_task_for_resource [TYPE Function]\n # @PURPOSE: Get the most recent task for a specific resource\n # @PRE: resource_id is a valid string\n # @POST: Returns task summary or None if no tasks found\n # @PARAM: resource_id (str) - The resource identifier (e.g., \"dashboard-123\")\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n def _get_last_task_for_resource(\n self,\n resource_id: str,\n tasks: list[Task] | None = None\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n # Filter tasks for this resource\n resource_tasks = []\n for task in tasks:\n params = task.params or {}\n if params.get('resource_id') == resource_id:\n resource_tasks.append(task)\n\n if not resource_tasks:\n return None\n\n # Get most recent task with timezone-safe comparison.\n last_task = max(\n resource_tasks,\n key=lambda t: self._normalize_datetime_for_compare(getattr(t, \"created_at\", None)),\n )\n\n return {\n 'task_id': str(last_task.id),\n 'status': last_task.status\n }\n # endregion _get_last_task_for_resource\n\n # region _extract_resource_name_from_task [TYPE Function]\n # @PURPOSE: Extract resource name from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource name or task ID\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource name or fallback\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_name_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_name', f\"Task {task.id}\")\n # endregion _extract_resource_name_from_task\n\n # region _extract_resource_type_from_task [TYPE Function]\n # @PURPOSE: Extract resource type from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource type or 'unknown'\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource type\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_type_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_type', 'unknown')\n # endregion _extract_resource_type_from_task\n# #endregion ResourceService\n# #endregion ResourceServiceModule\n" }, { "contract_id": "ResourceService", "contract_type": "Class", "file_path": "backend/src/services/resource_service.py", - "start_line": 21, - "end_line": 483, + "start_line": 22, + "end_line": 517, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -51345,7 +53777,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region ResourceService [C:3] [TYPE Class]\n# @BRIEF Provides centralized access to resource data with enhanced metadata\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [GitService]\nclass ResourceService:\n\n # region ResourceService_init [TYPE Function]\n # @PURPOSE: Initialize the resource service with dependencies\n # @PRE: None\n # @POST: ResourceService is ready to fetch resources\n def __init__(self):\n with belief_scope(\"ResourceService.__init__\"):\n self.git_service = GitService()\n logger.reason(\"Initialized ResourceService\", extra={\"src\": \"ResourceService\"})\n # endregion ResourceService_init\n\n # region get_dashboards_with_status [TYPE Function]\n # @PURPOSE: Fetch dashboards from environment with Git status and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of dashboards with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Dashboards with git_status and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummary]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_dashboards_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n dashboards = client.get_dashboards_summary(require_slug=require_slug)\n\n # Enhance each dashboard with Git status and task status\n result = []\n for dashboard in dashboards:\n # dashboard is already a dict, no need to call .dict()\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get('id')\n\n # Git status can be skipped for list endpoints and loaded lazily on UI side.\n if include_git_status:\n git_status = self._get_git_status_for_dashboard(dashboard_id)\n dashboard_dict['git_status'] = git_status\n else:\n dashboard_dict['git_status'] = None\n\n # Show status of the latest LLM validation for this dashboard.\n last_task = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n dashboard_dict['last_task'] = last_task\n\n result.append(dashboard_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} dashboards with status\")\n return result\n # endregion get_dashboards_with_status\n\n # region get_dashboards_page_with_status [TYPE Function]\n # @PURPOSE: Fetch one dashboard page from environment and enrich only that page with status metadata.\n # @PRE: env is valid; page >= 1; page_size > 0.\n # @POST: Returns page items plus total counters without scanning all pages locally.\n # @PARAM: env (Environment) - Source environment.\n # @PARAM: tasks (Optional[List[Task]]) - Tasks for latest LLM status.\n # @PARAM: page (int) - 1-based page number.\n # @PARAM: page_size (int) - Page size.\n # @RETURN: Dict[str, Any] - {\"dashboards\": List[Dict], \"total\": int, \"total_pages\": int}\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummaryPage]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_page_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n page: int = 1,\n page_size: int = 10,\n search: str | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> dict[str, Any]:\n with belief_scope(\n \"get_dashboards_page_with_status\",\n f\"env={env.id}, page={page}, page_size={page_size}, search={search}\",\n ):\n client = SupersetClient(env)\n total, dashboards_page = client.get_dashboards_summary_page(\n page=page,\n page_size=page_size,\n search=search,\n require_slug=require_slug,\n )\n\n result = []\n for dashboard in dashboards_page:\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get(\"id\")\n\n if include_git_status:\n dashboard_dict[\"git_status\"] = self._get_git_status_for_dashboard(dashboard_id)\n else:\n dashboard_dict[\"git_status\"] = None\n\n dashboard_dict[\"last_task\"] = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n result.append(dashboard_dict)\n\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n logger.info(\n \"[ResourceService][Coherence:OK] Fetched dashboards page %s/%s (%s items, total=%s)\",\n page,\n total_pages,\n len(result),\n total,\n )\n return {\n \"dashboards\": result,\n \"total\": total,\n \"total_pages\": total_pages,\n }\n # endregion get_dashboards_page_with_status\n\n # region _get_last_llm_task_for_dashboard [TYPE Function]\n # @PURPOSE: Get most recent LLM validation task for a dashboard in an environment\n # @PRE: dashboard_id is a valid integer identifier\n # @POST: Returns the newest llm_dashboard_validation task summary or None\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @PARAM: env_id (Optional[str]) - Environment ID to match task params\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n # @RELATION: CALLS ->[_normalize_validation_status]\n # @RELATION: CALLS ->[_normalize_task_status]\n def _get_last_llm_task_for_dashboard(\n self,\n dashboard_id: int,\n env_id: str | None,\n tasks: list[Task] | None = None,\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n dashboard_id_str = str(dashboard_id)\n matched_tasks = []\n\n for task in tasks:\n if getattr(task, \"plugin_id\", None) != \"llm_dashboard_validation\":\n continue\n\n params = getattr(task, \"params\", {}) or {}\n if str(params.get(\"dashboard_id\")) != dashboard_id_str:\n continue\n\n if env_id is not None:\n task_env = params.get(\"environment_id\") or params.get(\"env\")\n if str(task_env) != str(env_id):\n continue\n\n matched_tasks.append(task)\n\n if not matched_tasks:\n return None\n\n def _task_time(task_obj: Any) -> datetime:\n raw_time = (\n getattr(task_obj, \"started_at\", None)\n or getattr(task_obj, \"finished_at\", None)\n or getattr(task_obj, \"created_at\", None)\n )\n return self._normalize_datetime_for_compare(raw_time)\n\n projected_tasks = []\n for task in matched_tasks:\n raw_result = getattr(task, \"result\", None)\n validation_status = None\n if isinstance(raw_result, dict):\n validation_status = self._normalize_validation_status(raw_result.get(\"status\"))\n projected_tasks.append(\n (\n task,\n validation_status,\n _task_time(task),\n )\n )\n\n projected_tasks.sort(key=lambda item: item[2], reverse=True)\n latest_task, latest_validation_status, _ = projected_tasks[0]\n decisive_task = next(\n (\n item for item in projected_tasks\n if item[1] in {\"PASS\", \"WARN\", \"FAIL\"}\n ),\n None,\n )\n validation_status = latest_validation_status\n if validation_status == \"UNKNOWN\" and decisive_task is not None:\n validation_status = decisive_task[1]\n\n return {\n \"task_id\": str(getattr(latest_task, \"id\", \"\")),\n \"status\": self._normalize_task_status(getattr(latest_task, \"status\", \"\")),\n \"validation_status\": validation_status,\n }\n # endregion _get_last_llm_task_for_dashboard\n\n # region _normalize_task_status [TYPE Function]\n # @PURPOSE: Normalize task status to stable uppercase values for UI/API projections\n # @PRE: raw_status can be enum or string\n # @POST: Returns uppercase status without enum class prefix\n # @PARAM: raw_status (Any) - Raw task status object/value\n # @RETURN: str - Normalized status token\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_task_status(self, raw_status: Any) -> str:\n if raw_status is None:\n return \"\"\n value = getattr(raw_status, \"value\", raw_status)\n status_text = str(value).strip()\n if \".\" in status_text:\n status_text = status_text.split(\".\")[-1]\n return status_text.upper()\n # endregion _normalize_task_status\n\n # region _normalize_validation_status [TYPE Function]\n # @PURPOSE: Normalize LLM validation status to PASS/FAIL/WARN/UNKNOWN\n # @PRE: raw_status can be any scalar type\n # @POST: Returns normalized validation status token or None\n # @PARAM: raw_status (Any) - Raw validation status from task result\n # @RETURN: Optional[str] - PASS|FAIL|WARN|UNKNOWN\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_validation_status(self, raw_status: Any) -> str | None:\n if raw_status is None:\n return None\n status_text = str(raw_status).strip().upper()\n if status_text in {\"PASS\", \"FAIL\", \"WARN\"}:\n return status_text\n return \"UNKNOWN\"\n # endregion _normalize_validation_status\n\n # region _normalize_datetime_for_compare [TYPE Function]\n # @PURPOSE: Normalize datetime values to UTC-aware values for safe comparisons.\n # @PRE: value may be datetime or any scalar.\n # @POST: Returns UTC-aware datetime; non-datetime values map to minimal UTC datetime.\n # @PARAM: value (Any) - Candidate datetime-like value.\n # @RETURN: datetime - UTC-aware comparable datetime.\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n # @RELATION: USED_BY ->[_get_last_task_for_resource]\n def _normalize_datetime_for_compare(self, value: Any) -> datetime:\n if isinstance(value, datetime):\n if value.tzinfo is None:\n return value.replace(tzinfo=UTC)\n return value.astimezone(UTC)\n return datetime.min.replace(tzinfo=UTC)\n # endregion _normalize_datetime_for_compare\n\n # region get_datasets_with_status [TYPE Function]\n # @PURPOSE: Fetch datasets from environment with mapping progress and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of datasets with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Datasets with mapped_fields and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDatasetsSummary]\n # @RELATION: CALLS ->[_get_last_task_for_resource]\n async def get_datasets_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_datasets_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n datasets = client.get_datasets_summary()\n\n # Enhance each dataset with task status\n result = []\n for dataset in datasets:\n # dataset is already a dict, no need to call .dict()\n dataset_dict = dataset\n dataset_id = dataset_dict.get('id')\n\n # Get last task status\n last_task = self._get_last_task_for_resource(\n f\"dataset-{dataset_id}\",\n tasks\n )\n dataset_dict['last_task'] = last_task\n\n result.append(dataset_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} datasets with status\")\n return result\n # endregion get_datasets_with_status\n\n # region get_activity_summary [TYPE Function]\n # @PURPOSE: Get summary of active and recent tasks for the activity indicator\n # @PRE: tasks is a list of Task objects\n # @POST: Returns summary with active_count and recent_tasks\n # @PARAM: tasks (List[Task]) - List of tasks to summarize\n # @RETURN: Dict - Activity summary\n # @RELATION: CALLS ->[_extract_resource_name_from_task]\n # @RELATION: CALLS ->[_extract_resource_type_from_task]\n def get_activity_summary(self, tasks: list[Task]) -> dict[str, Any]:\n with belief_scope(\"get_activity_summary\"):\n # Count active (RUNNING, WAITING_INPUT) tasks\n active_tasks = [\n t for t in tasks\n if t.status in ['RUNNING', 'WAITING_INPUT']\n ]\n\n # Get recent tasks (last 5)\n recent_tasks = sorted(\n tasks,\n key=lambda t: t.created_at,\n reverse=True\n )[:5]\n\n # Format recent tasks for frontend\n recent_tasks_formatted = []\n for task in recent_tasks:\n resource_name = self._extract_resource_name_from_task(task)\n recent_tasks_formatted.append({\n 'task_id': str(task.id),\n 'resource_name': resource_name,\n 'resource_type': self._extract_resource_type_from_task(task),\n 'status': task.status,\n 'started_at': task.created_at.isoformat() if task.created_at else None\n })\n\n return {\n 'active_count': len(active_tasks),\n 'recent_tasks': recent_tasks_formatted\n }\n # endregion get_activity_summary\n\n # region _get_git_status_for_dashboard [TYPE Function]\n # @PURPOSE: Get Git sync status for a dashboard\n # @PRE: dashboard_id is a valid integer\n # @POST: Returns git status or None if no repo exists\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @RETURN: Optional[Dict] - Git status with branch and sync_status\n # @RELATION: CALLS ->[get_repo]\n def _get_git_status_for_dashboard(self, dashboard_id: int) -> dict[str, Any] | None:\n try:\n repo = self.git_service.get_repo(dashboard_id)\n if not repo:\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n\n # Check if there are uncommitted changes\n try:\n # Get current branch\n branch = repo.active_branch.name\n\n # Check for uncommitted changes\n is_dirty = repo.is_dirty()\n has_changes_for_commit = repo.is_dirty(untracked_files=True)\n\n # Check for unpushed commits\n unpushed = len(list(repo.iter_commits(f'{branch}@{{u}}..{branch}'))) if '@{u}' in str(repo.refs) else 0\n\n if is_dirty or unpushed > 0:\n sync_status = 'DIFF'\n else:\n sync_status = 'OK'\n\n return {\n 'branch': branch,\n 'sync_status': sync_status,\n 'has_repo': True,\n 'has_changes_for_commit': has_changes_for_commit\n }\n except Exception:\n logger.warning(f\"[ResourceService][Warning] Failed to get git status for dashboard {dashboard_id}\")\n return {\n 'branch': None,\n 'sync_status': 'ERROR',\n 'has_repo': True,\n 'has_changes_for_commit': False\n }\n except Exception:\n # No repo exists for this dashboard\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n # endregion _get_git_status_for_dashboard\n\n # region _get_last_task_for_resource [TYPE Function]\n # @PURPOSE: Get the most recent task for a specific resource\n # @PRE: resource_id is a valid string\n # @POST: Returns task summary or None if no tasks found\n # @PARAM: resource_id (str) - The resource identifier (e.g., \"dashboard-123\")\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n def _get_last_task_for_resource(\n self,\n resource_id: str,\n tasks: list[Task] | None = None\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n # Filter tasks for this resource\n resource_tasks = []\n for task in tasks:\n params = task.params or {}\n if params.get('resource_id') == resource_id:\n resource_tasks.append(task)\n\n if not resource_tasks:\n return None\n\n # Get most recent task with timezone-safe comparison.\n last_task = max(\n resource_tasks,\n key=lambda t: self._normalize_datetime_for_compare(getattr(t, \"created_at\", None)),\n )\n\n return {\n 'task_id': str(last_task.id),\n 'status': last_task.status\n }\n # endregion _get_last_task_for_resource\n\n # region _extract_resource_name_from_task [TYPE Function]\n # @PURPOSE: Extract resource name from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource name or task ID\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource name or fallback\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_name_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_name', f\"Task {task.id}\")\n # endregion _extract_resource_name_from_task\n\n # region _extract_resource_type_from_task [TYPE Function]\n # @PURPOSE: Extract resource type from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource type or 'unknown'\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource type\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_type_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_type', 'unknown')\n # endregion _extract_resource_type_from_task\n# #endregion ResourceService\n" + "body": "# #region ResourceService [C:3] [TYPE Class]\n# @BRIEF Provides centralized access to resource data with enhanced metadata\n# @RELATION DEPENDS_ON -> [SupersetClient]\n# @RELATION DEPENDS_ON -> [GitService]\nclass ResourceService:\n\n # region ResourceService_init [TYPE Function]\n # @PURPOSE: Initialize the resource service with dependencies\n # @PRE: None\n # @POST: ResourceService is ready to fetch resources\n def __init__(self):\n with belief_scope(\"ResourceService.__init__\"):\n self.git_service = GitService()\n logger.reason(\"Initialized ResourceService\", extra={\"src\": \"ResourceService\"})\n # endregion ResourceService_init\n\n # region get_dashboards_with_status [TYPE Function]\n # @PURPOSE: Fetch dashboards from environment with Git status and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of dashboards with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Dashboards with git_status and last_task fields\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummary]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_dashboards_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n dashboards = client.get_dashboards_summary(require_slug=require_slug)\n\n # Enhance each dashboard with Git status and task status\n result = []\n for dashboard in dashboards:\n # dashboard is already a dict, no need to call .dict()\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get('id')\n\n # Git status can be skipped for list endpoints and loaded lazily on UI side.\n if include_git_status:\n git_status = self._get_git_status_for_dashboard(dashboard_id)\n dashboard_dict['git_status'] = git_status\n else:\n dashboard_dict['git_status'] = None\n\n # Show status of the latest LLM validation for this dashboard.\n last_task = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n dashboard_dict['last_task'] = last_task\n\n result.append(dashboard_dict)\n\n logger.info(f\"[ResourceService][Coherence:OK] Fetched {len(result)} dashboards with status\")\n return result\n # endregion get_dashboards_with_status\n\n # region get_dashboards_page_with_status [TYPE Function]\n # @PURPOSE: Fetch one dashboard page from environment and enrich only that page with status metadata.\n # @PRE: env is valid; page >= 1; page_size > 0.\n # @POST: Returns page items plus total counters without scanning all pages locally.\n # @PARAM: env (Environment) - Source environment.\n # @PARAM: tasks (Optional[List[Task]]) - Tasks for latest LLM status.\n # @PARAM: page (int) - 1-based page number.\n # @PARAM: page_size (int) - Page size.\n # @RETURN: Dict[str, Any] - {\"dashboards\": List[Dict], \"total\": int, \"total_pages\": int}\n # @RELATION: CALLS -> [SupersetClientGetDashboardsSummaryPage]\n # @RELATION: CALLS ->[_get_git_status_for_dashboard]\n # @RELATION: CALLS ->[_get_last_llm_task_for_dashboard]\n async def get_dashboards_page_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None,\n page: int = 1,\n page_size: int = 10,\n search: str | None = None,\n include_git_status: bool = True,\n require_slug: bool = False,\n ) -> dict[str, Any]:\n with belief_scope(\n \"get_dashboards_page_with_status\",\n f\"env={env.id}, page={page}, page_size={page_size}, search={search}\",\n ):\n client = SupersetClient(env)\n total, dashboards_page = client.get_dashboards_summary_page(\n page=page,\n page_size=page_size,\n search=search,\n require_slug=require_slug,\n )\n\n result = []\n for dashboard in dashboards_page:\n dashboard_dict = dashboard\n dashboard_id = dashboard_dict.get(\"id\")\n\n if include_git_status:\n dashboard_dict[\"git_status\"] = self._get_git_status_for_dashboard(dashboard_id)\n else:\n dashboard_dict[\"git_status\"] = None\n\n dashboard_dict[\"last_task\"] = self._get_last_llm_task_for_dashboard(\n dashboard_id,\n env.id,\n tasks,\n )\n result.append(dashboard_dict)\n\n total_pages = (total + page_size - 1) // page_size if total > 0 else 1\n logger.info(\n \"[ResourceService][Coherence:OK] Fetched dashboards page %s/%s (%s items, total=%s)\",\n page,\n total_pages,\n len(result),\n total,\n )\n return {\n \"dashboards\": result,\n \"total\": total,\n \"total_pages\": total_pages,\n }\n # endregion get_dashboards_page_with_status\n\n # region _get_last_llm_task_for_dashboard [TYPE Function]\n # @PURPOSE: Get most recent LLM validation task for a dashboard in an environment\n # @PRE: dashboard_id is a valid integer identifier\n # @POST: Returns the newest llm_dashboard_validation task summary or None\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @PARAM: env_id (Optional[str]) - Environment ID to match task params\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n # @RELATION: CALLS ->[_normalize_validation_status]\n # @RELATION: CALLS ->[_normalize_task_status]\n def _get_last_llm_task_for_dashboard(\n self,\n dashboard_id: int,\n env_id: str | None,\n tasks: list[Task] | None = None,\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n dashboard_id_str = str(dashboard_id)\n matched_tasks = []\n\n for task in tasks:\n if getattr(task, \"plugin_id\", None) != \"llm_dashboard_validation\":\n continue\n\n params = getattr(task, \"params\", {}) or {}\n if str(params.get(\"dashboard_id\")) != dashboard_id_str:\n continue\n\n if env_id is not None:\n task_env = params.get(\"environment_id\") or params.get(\"env\")\n if str(task_env) != str(env_id):\n continue\n\n matched_tasks.append(task)\n\n if not matched_tasks:\n return None\n\n def _task_time(task_obj: Any) -> datetime:\n raw_time = (\n getattr(task_obj, \"started_at\", None)\n or getattr(task_obj, \"finished_at\", None)\n or getattr(task_obj, \"created_at\", None)\n )\n return self._normalize_datetime_for_compare(raw_time)\n\n projected_tasks = []\n for task in matched_tasks:\n raw_result = getattr(task, \"result\", None)\n validation_status = None\n if isinstance(raw_result, dict):\n validation_status = self._normalize_validation_status(raw_result.get(\"status\"))\n projected_tasks.append(\n (\n task,\n validation_status,\n _task_time(task),\n )\n )\n\n projected_tasks.sort(key=lambda item: item[2], reverse=True)\n latest_task, latest_validation_status, _ = projected_tasks[0]\n decisive_task = next(\n (\n item for item in projected_tasks\n if item[1] in {\"PASS\", \"WARN\", \"FAIL\"}\n ),\n None,\n )\n validation_status = latest_validation_status\n if validation_status == \"UNKNOWN\" and decisive_task is not None:\n validation_status = decisive_task[1]\n\n return {\n \"task_id\": str(getattr(latest_task, \"id\", \"\")),\n \"status\": self._normalize_task_status(getattr(latest_task, \"status\", \"\")),\n \"validation_status\": validation_status,\n }\n # endregion _get_last_llm_task_for_dashboard\n\n # region _normalize_task_status [TYPE Function]\n # @PURPOSE: Normalize task status to stable uppercase values for UI/API projections\n # @PRE: raw_status can be enum or string\n # @POST: Returns uppercase status without enum class prefix\n # @PARAM: raw_status (Any) - Raw task status object/value\n # @RETURN: str - Normalized status token\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_task_status(self, raw_status: Any) -> str:\n if raw_status is None:\n return \"\"\n value = getattr(raw_status, \"value\", raw_status)\n status_text = str(value).strip()\n if \".\" in status_text:\n status_text = status_text.split(\".\")[-1]\n return status_text.upper()\n # endregion _normalize_task_status\n\n # region _normalize_validation_status [TYPE Function]\n # @PURPOSE: Normalize LLM validation status to PASS/FAIL/WARN/UNKNOWN\n # @PRE: raw_status can be any scalar type\n # @POST: Returns normalized validation status token or None\n # @PARAM: raw_status (Any) - Raw validation status from task result\n # @RETURN: Optional[str] - PASS|FAIL|WARN|UNKNOWN\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n def _normalize_validation_status(self, raw_status: Any) -> str | None:\n if raw_status is None:\n return None\n status_text = str(raw_status).strip().upper()\n if status_text in {\"PASS\", \"FAIL\", \"WARN\"}:\n return status_text\n return \"UNKNOWN\"\n # endregion _normalize_validation_status\n\n # region _normalize_datetime_for_compare [TYPE Function]\n # @PURPOSE: Normalize datetime values to UTC-aware values for safe comparisons.\n # @PRE: value may be datetime or any scalar.\n # @POST: Returns UTC-aware datetime; non-datetime values map to minimal UTC datetime.\n # @PARAM: value (Any) - Candidate datetime-like value.\n # @RETURN: datetime - UTC-aware comparable datetime.\n # @RELATION: USED_BY ->[_get_last_llm_task_for_dashboard]\n # @RELATION: USED_BY ->[_get_last_task_for_resource]\n def _normalize_datetime_for_compare(self, value: Any) -> datetime:\n if isinstance(value, datetime):\n if value.tzinfo is None:\n return value.replace(tzinfo=UTC)\n return value.astimezone(UTC)\n return datetime.min.replace(tzinfo=UTC)\n # endregion _normalize_datetime_for_compare\n\n # region get_datasets_with_status [TYPE Function]\n # @PURPOSE: Fetch datasets from environment with mapping progress and last task status\n # @PRE: env is a valid Environment object\n # @POST: Returns list of datasets with enhanced metadata\n # @PARAM: env (Environment) - The environment to fetch from\n # @PARAM: tasks (List[Task]) - List of tasks to check for status\n # @RETURN: List[Dict] - Datasets with mapped_fields, last_task and linked_dashboard_count fields\n # @RELATION: CALLS -> [SupersetClientGetDatasetsSummary]\n # @RELATION: CALLS -> [SupersetClientGetDatasetLinkedDashboardCount]\n # @RELATION: CALLS ->[_get_last_task_for_resource]\n # @RATIONALE linked_dashboard_count was missing — get_datasets_summary() only returns id/table_name/schema/database\n # StatsBar showed linked_count=0 because the field was never populated in list endpoint.\n # Fix: fetch /dataset/{id}/related_objects for each dataset concurrently (semaphore=3, timeout=10s).\n # @REJECTED N+1 blocking calls rejected — would timeout at 26×1s. Semaphore + asyncio.to_thread + timeout prevents overload.\n async def get_datasets_with_status(\n self,\n env: Any,\n tasks: list[Task] | None = None\n ) -> list[dict[str, Any]]:\n with belief_scope(\"get_datasets_with_status\", f\"env={env.id}\"):\n client = SupersetClient(env)\n datasets = client.get_datasets_summary()\n\n # Enhance each dataset with task status and linked dashboard count\n sem = asyncio.Semaphore(3) # limit concurrent Superset calls\n\n async def fetch_linked_count(ds_id: int) -> int:\n async with sem:\n try:\n return await asyncio.wait_for(\n asyncio.to_thread(\n client.get_dataset_linked_dashboard_count, ds_id\n ),\n timeout=10.0,\n )\n except (asyncio.TimeoutError, Exception):\n logger.warning(\n f\"[get_datasets_with_status][Warning] \"\n f\"Failed to fetch linked dashboard count for dataset {ds_id}\"\n )\n return 0\n\n result = []\n linked_tasks = []\n for dataset in datasets:\n dataset_dict = dataset\n dataset_id = dataset_dict.get('id')\n\n # Get last task status\n last_task = self._get_last_task_for_resource(\n f\"dataset-{dataset_id}\",\n tasks\n )\n dataset_dict['last_task'] = last_task\n\n result.append(dataset_dict)\n linked_tasks.append(fetch_linked_count(dataset_id))\n\n # Fetch linked dashboard counts concurrently — FR-022\n if linked_tasks:\n linked_counts = await asyncio.gather(*linked_tasks)\n for ds, count in zip(result, linked_counts):\n ds['linked_dashboard_count'] = count\n\n logger.info(\n f\"[ResourceService][Coherence:OK] \"\n f\"Fetched {len(result)} datasets with status and linked counts\"\n )\n return result\n # endregion get_datasets_with_status\n\n # region get_activity_summary [TYPE Function]\n # @PURPOSE: Get summary of active and recent tasks for the activity indicator\n # @PRE: tasks is a list of Task objects\n # @POST: Returns summary with active_count and recent_tasks\n # @PARAM: tasks (List[Task]) - List of tasks to summarize\n # @RETURN: Dict - Activity summary\n # @RELATION: CALLS ->[_extract_resource_name_from_task]\n # @RELATION: CALLS ->[_extract_resource_type_from_task]\n def get_activity_summary(self, tasks: list[Task]) -> dict[str, Any]:\n with belief_scope(\"get_activity_summary\"):\n # Count active (RUNNING, WAITING_INPUT) tasks\n active_tasks = [\n t for t in tasks\n if t.status in ['RUNNING', 'WAITING_INPUT']\n ]\n\n # Get recent tasks (last 5)\n recent_tasks = sorted(\n tasks,\n key=lambda t: t.created_at,\n reverse=True\n )[:5]\n\n # Format recent tasks for frontend\n recent_tasks_formatted = []\n for task in recent_tasks:\n resource_name = self._extract_resource_name_from_task(task)\n recent_tasks_formatted.append({\n 'task_id': str(task.id),\n 'resource_name': resource_name,\n 'resource_type': self._extract_resource_type_from_task(task),\n 'status': task.status,\n 'started_at': task.created_at.isoformat() if task.created_at else None\n })\n\n return {\n 'active_count': len(active_tasks),\n 'recent_tasks': recent_tasks_formatted\n }\n # endregion get_activity_summary\n\n # region _get_git_status_for_dashboard [TYPE Function]\n # @PURPOSE: Get Git sync status for a dashboard\n # @PRE: dashboard_id is a valid integer\n # @POST: Returns git status or None if no repo exists\n # @PARAM: dashboard_id (int) - The dashboard ID\n # @RETURN: Optional[Dict] - Git status with branch and sync_status\n # @RELATION: CALLS ->[get_repo]\n def _get_git_status_for_dashboard(self, dashboard_id: int) -> dict[str, Any] | None:\n try:\n repo = self.git_service.get_repo(dashboard_id)\n if not repo:\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n\n # Check if there are uncommitted changes\n try:\n # Get current branch\n branch = repo.active_branch.name\n\n # Check for uncommitted changes\n is_dirty = repo.is_dirty()\n has_changes_for_commit = repo.is_dirty(untracked_files=True)\n\n # Check for unpushed commits\n unpushed = len(list(repo.iter_commits(f'{branch}@{{u}}..{branch}'))) if '@{u}' in str(repo.refs) else 0\n\n if is_dirty or unpushed > 0:\n sync_status = 'DIFF'\n else:\n sync_status = 'OK'\n\n return {\n 'branch': branch,\n 'sync_status': sync_status,\n 'has_repo': True,\n 'has_changes_for_commit': has_changes_for_commit\n }\n except Exception:\n logger.warning(f\"[ResourceService][Warning] Failed to get git status for dashboard {dashboard_id}\")\n return {\n 'branch': None,\n 'sync_status': 'ERROR',\n 'has_repo': True,\n 'has_changes_for_commit': False\n }\n except Exception:\n # No repo exists for this dashboard\n return {\n 'branch': None,\n 'sync_status': 'NO_REPO',\n 'has_repo': False,\n 'has_changes_for_commit': False\n }\n # endregion _get_git_status_for_dashboard\n\n # region _get_last_task_for_resource [TYPE Function]\n # @PURPOSE: Get the most recent task for a specific resource\n # @PRE: resource_id is a valid string\n # @POST: Returns task summary or None if no tasks found\n # @PARAM: resource_id (str) - The resource identifier (e.g., \"dashboard-123\")\n # @PARAM: tasks (Optional[List[Task]]) - List of tasks to search\n # @RETURN: Optional[Dict] - Task summary with task_id and status\n # @RELATION: CALLS ->[_normalize_datetime_for_compare]\n def _get_last_task_for_resource(\n self,\n resource_id: str,\n tasks: list[Task] | None = None\n ) -> dict[str, Any] | None:\n if not tasks:\n return None\n\n # Filter tasks for this resource\n resource_tasks = []\n for task in tasks:\n params = task.params or {}\n if params.get('resource_id') == resource_id:\n resource_tasks.append(task)\n\n if not resource_tasks:\n return None\n\n # Get most recent task with timezone-safe comparison.\n last_task = max(\n resource_tasks,\n key=lambda t: self._normalize_datetime_for_compare(getattr(t, \"created_at\", None)),\n )\n\n return {\n 'task_id': str(last_task.id),\n 'status': last_task.status\n }\n # endregion _get_last_task_for_resource\n\n # region _extract_resource_name_from_task [TYPE Function]\n # @PURPOSE: Extract resource name from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource name or task ID\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource name or fallback\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_name_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_name', f\"Task {task.id}\")\n # endregion _extract_resource_name_from_task\n\n # region _extract_resource_type_from_task [TYPE Function]\n # @PURPOSE: Extract resource type from task params\n # @PRE: task is a valid Task object\n # @POST: Returns resource type or 'unknown'\n # @PARAM: task (Task) - The task to extract from\n # @RETURN: str - Resource type\n # @RELATION: USED_BY ->[get_activity_summary]\n def _extract_resource_type_from_task(self, task: Task) -> str:\n params = task.params or {}\n return params.get('resource_type', 'unknown')\n # endregion _extract_resource_type_from_task\n# #endregion ResourceService\n" }, { "contract_id": "security_badge_service", @@ -51454,6 +53886,139 @@ "tier_source": "AutoCalculated", "body": " # #region _format_permission_key [C:1] [TYPE Function]\n # @BRIEF Convert normalized permission pair to compact UI key.\n def _format_permission_key(self, resource: str, action: str) -> str:\n normalized_resource = sanitize_text(resource) or \"\"\n normalized_action = str(action or \"\").strip().upper()\n if normalized_action == \"READ\":\n return normalized_resource\n return f\"{normalized_resource}:{normalized_action.lower()}\"\n # #endregion _format_permission_key\n" }, + { + "contract_id": "SqlTableExtractorModule", + "contract_type": "Module", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 1, + "end_line": 226, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Three-phase SQL+Jinja table name extractor for virtual datasets as per FR-003." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region SqlTableExtractorModule [C:2] [TYPE Module] [SEMANTICS sql, jinja, table, extraction, parsing]\n# @BRIEF Three-phase SQL+Jinja table name extractor for virtual datasets as per FR-003.\n# Phase 1: Detect Jinja spans vs SQL spans\n# Phase 2: In Jinja spans, extract \"schema.table\" from string values\n# Phase 3: In SQL spans, regex pattern + sqlparse filter to reject string literal false positives\n# @LAYER Service\n# @RELATION DEPENDS_ON -> [re, sqlparse]\n# @INVARIANT Only exact schema.table matches (case-insensitive); unqualified references are NOT matched.\n# @INVARIANT Returns a set[str] of fully-qualified table names (lowercased for case-insensitive matching).\n\nimport re\nfrom typing import Iterable\n\nimport sqlparse\nfrom sqlparse.sql import Identifier, Parenthesis, Token, TokenList\nfrom sqlparse.tokens import Literal, Name, Punctuation, Whitespace\n\n# ── Phase 1: Jinja span detection ───────────────────────────\n\n# Minimal Jinja token detection: {% ... %}, {{ ... }}, {# ... #}\n_JINJA_BLOCK_RE = re.compile(r\"{%-?\\s*.*?\\s*-?%}\", re.DOTALL)\n_JINJA_EXPR_RE = re.compile(r\"{{-?\\s*.*?\\s*-?}}\", re.DOTALL)\n_JINJA_COMMENT_RE = re.compile(r\"{#.*?#}\", re.DOTALL)\n\n# ── Phase 3: schema.table regex (case-insensitive) ───────────\n_SCHEMA_TABLE_RE = re.compile(\n r\"\"\"\n (? list[tuple[str, str]]:\n \"\"\"Split raw SQL+Jinja text into alternating Jinja and SQL spans.\n\n Phase 1 detects Jinja blocks ({%%}, {{}}, {##}) and returns the\n remaining text as SQL spans.\n \"\"\"\n if not raw_sql or not raw_sql.strip():\n return [(\"sql\", raw_sql or \"\")]\n\n spans: list[tuple[str, str]] = []\n # Collect all Jinja match positions\n jinja_matches: list[tuple[int, int]] = []\n for pattern in (_JINJA_BLOCK_RE, _JINJA_EXPR_RE, _JINJA_COMMENT_RE):\n for m in pattern.finditer(raw_sql):\n jinja_matches.append((m.start(), m.end()))\n\n # Merge overlapping Jinja spans\n if jinja_matches:\n jinja_matches.sort()\n merged: list[tuple[int, int]] = [jinja_matches[0]]\n for start, end in jinja_matches[1:]:\n if start <= merged[-1][1]:\n merged[-1] = (merged[-1][0], max(merged[-1][1], end))\n else:\n merged.append((start, end))\n\n # Build alternating sql/jinja spans\n cursor = 0\n for start, end in merged:\n if cursor < start:\n sql_chunk = raw_sql[cursor:start].strip()\n if sql_chunk:\n spans.append((\"sql\", sql_chunk))\n jinja_chunk = raw_sql[start:end].strip()\n if jinja_chunk:\n spans.append((\"jinja\", jinja_chunk))\n cursor = end\n if cursor < len(raw_sql):\n remaining = raw_sql[cursor:].strip()\n if remaining:\n spans.append((\"sql\", remaining))\n else:\n spans.append((\"sql\", raw_sql.strip()))\n\n return spans\n# #endregion detect_jinja_spans\n\n\n# #region extract_tables_from_jinja [C:2] [TYPE Function]\n# @BRIEF Phase 2: Extract \"schema.table\" references from Jinja string values.\n# Looks for patterns like \"raw.sales\" inside Jinja text.\n# @PRE jinja_text is a string from a Jinja span.\n# @POST Returns a set of lowercased schema.table strings.\ndef extract_tables_from_jinja(jinja_text: str) -> set[str]:\n \"\"\"Extract ``schema.table`` references from within Jinja template blocks.\n\n Looks for double-quoted or single-quoted string values that match\n the ``schema.table`` pattern, e.g. ``\"raw.sales\"`` or ``'raw.inventory'``.\n \"\"\"\n tables: set[str] = set()\n # Match string values: \"schema.table\" or 'schema.table'\n string_pattern = re.compile(\n r\"\"\"[\"']([a-zA-Z_][\\w]*\\.[a-zA-Z_][\\w]*)[\"']\"\"\"\n )\n for m in string_pattern.finditer(jinja_text):\n tables.add(m.group(1).lower())\n return tables\n# #endregion extract_tables_from_jinja\n\n\n# #region is_string_literal [C:1] [TYPE Function]\n# @BRIEF Check if a sqlparse Token is a string literal (not a schema.table identifier).\n# @PRE token is a sqlparse Token.\n# @POST Returns True if the token is a string/Single/Literal.String.\ndef is_string_literal(token: Token) -> bool:\n \"\"\"Return True if token is a string literal type in sqlparse.\"\"\"\n return token.ttype is Literal.String.Single or token.ttype is Literal.String\n# #endregion is_string_literal\n\n\n# #region extract_tables_from_sql_span [C:2] [TYPE Function]\n# @BRIEF Phase 3: Extract schema.table references from SQL text using regex + sqlparse filtering.\n# Uses regex to find all schema.table candidates, then sqlparse to filter out\n# false positives inside string literals.\n# @PRE sql_text is a string from a SQL span (non-Jinja).\n# @POST Returns a set of lowercased schema.table strings.\ndef extract_tables_from_sql_span(sql_text: str) -> set[str]:\n \"\"\"Extract ``schema.table`` references from plain SQL text.\n\n Uses regex to find all ``schema.table`` candidates, then sqlparse\n to reject matches that fall inside string literals.\n \"\"\"\n tables: set[str] = set()\n raw_matches = _SCHEMA_TABLE_RE.findall(sql_text)\n if not raw_matches:\n return tables\n\n # Use sqlparse to identify string literal positions\n parsed = sqlparse.parse(sql_text)\n string_literal_ranges: list[tuple[int, int]] = []\n\n def walk_tokens(tokens: Iterable[Token], base_offset: int = 0) -> None:\n offset = base_offset\n for token in tokens:\n if isinstance(token, TokenList):\n walk_tokens(token.flatten(), offset)\n else:\n ttype = token.ttype\n val = token.value\n if is_string_literal(token):\n string_literal_ranges.append(\n (offset, offset + len(val))\n )\n offset += len(val)\n\n for stmt in parsed:\n if stmt is None:\n continue\n walk_tokens(stmt.flatten(), base_offset=0)\n\n def is_in_string(pos: int) -> bool:\n for s_start, s_end in string_literal_ranges:\n if s_start <= pos <= s_end:\n return True\n return False\n\n # Re-scan with full match positions to filter\n for m in _SCHEMA_TABLE_RE.finditer(sql_text):\n if not is_in_string(m.start()):\n # Extract schema and table from match groups\n schema = m.group(2) or m.group(1) or \"\"\n table = m.group(3) or \"\"\n # Filter out column aliases (single-char schemas like \"a.id\", \"o.id\")\n if len(schema) < 2 and schema.isalpha() and schema.islower():\n continue\n if schema and table:\n tables.add(f\"{schema.lower()}.{table.lower()}\")\n\n return tables\n# #endregion extract_tables_from_sql_span\n\n\n# #region extract_tables_from_sql [C:2] [TYPE Function]\n# @BRIEF Three-phase entry point: extract all schema.table references from raw SQL+Jinja text.\n# @PRE raw_sql is a string (possibly empty).\n# @POST Returns a set of lowercased fully-qualified table names (schema.table format).\n# @RELATION CALLS -> [detect_jinja_spans]\n# @RELATION CALLS -> [extract_tables_from_jinja]\n# @RELATION CALLS -> [extract_tables_from_sql_span]\ndef extract_tables_from_sql(raw_sql: str) -> set[str]:\n \"\"\"Extract all ``schema.table`` references from raw SQL + Jinja text.\n\n Three-phase approach per FR-003:\n 1. Detect Jinja spans vs SQL spans\n 2. In Jinja spans, extract ``schema.table`` from quoted string values\n 3. In SQL spans, regex + sqlparse filter to reject string literal false positives\n\n Returns a set of lowercased ``schema.table`` strings for case-insensitive matching.\n\n Example:\n >>> extract_tables_from_sql(\"SELECT * FROM raw.sales JOIN raw.inventory ON ...\")\n {'raw.sales', 'raw.inventory'}\n \"\"\"\n if not raw_sql or not raw_sql.strip():\n return set()\n\n all_tables: set[str] = set()\n spans = detect_jinja_spans(raw_sql)\n\n for span_type, text in spans:\n if span_type == \"jinja\":\n all_tables.update(extract_tables_from_jinja(text))\n else:\n all_tables.update(extract_tables_from_sql_span(text))\n\n return all_tables\n# #endregion extract_tables_from_sql\n\n# #endregion SqlTableExtractorModule\n" + }, + { + "contract_id": "detect_jinja_spans", + "contract_type": "Function", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 43, + "end_line": 93, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns a list of (span_type: str, text: str) tuples.", + "PRE": "raw_sql is a string (possibly empty).", + "PURPOSE": "Phase 1: Split raw SQL text into Jinja spans and SQL spans." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region detect_jinja_spans [C:2] [TYPE Function]\n# @BRIEF Phase 1: Split raw SQL text into Jinja spans and SQL spans.\n# @PRE raw_sql is a string (possibly empty).\n# @POST Returns a list of (span_type: str, text: str) tuples.\n# span_type is \"jinja\" or \"sql\".\ndef detect_jinja_spans(raw_sql: str) -> list[tuple[str, str]]:\n \"\"\"Split raw SQL+Jinja text into alternating Jinja and SQL spans.\n\n Phase 1 detects Jinja blocks ({%%}, {{}}, {##}) and returns the\n remaining text as SQL spans.\n \"\"\"\n if not raw_sql or not raw_sql.strip():\n return [(\"sql\", raw_sql or \"\")]\n\n spans: list[tuple[str, str]] = []\n # Collect all Jinja match positions\n jinja_matches: list[tuple[int, int]] = []\n for pattern in (_JINJA_BLOCK_RE, _JINJA_EXPR_RE, _JINJA_COMMENT_RE):\n for m in pattern.finditer(raw_sql):\n jinja_matches.append((m.start(), m.end()))\n\n # Merge overlapping Jinja spans\n if jinja_matches:\n jinja_matches.sort()\n merged: list[tuple[int, int]] = [jinja_matches[0]]\n for start, end in jinja_matches[1:]:\n if start <= merged[-1][1]:\n merged[-1] = (merged[-1][0], max(merged[-1][1], end))\n else:\n merged.append((start, end))\n\n # Build alternating sql/jinja spans\n cursor = 0\n for start, end in merged:\n if cursor < start:\n sql_chunk = raw_sql[cursor:start].strip()\n if sql_chunk:\n spans.append((\"sql\", sql_chunk))\n jinja_chunk = raw_sql[start:end].strip()\n if jinja_chunk:\n spans.append((\"jinja\", jinja_chunk))\n cursor = end\n if cursor < len(raw_sql):\n remaining = raw_sql[cursor:].strip()\n if remaining:\n spans.append((\"sql\", remaining))\n else:\n spans.append((\"sql\", raw_sql.strip()))\n\n return spans\n# #endregion detect_jinja_spans\n" + }, + { + "contract_id": "extract_tables_from_jinja", + "contract_type": "Function", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 96, + "end_line": 115, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Phase 2: Extract \"schema.table\" references from Jinja string values." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region extract_tables_from_jinja [C:2] [TYPE Function]\n# @BRIEF Phase 2: Extract \"schema.table\" references from Jinja string values.\n# Looks for patterns like \"raw.sales\" inside Jinja text.\n# @PRE jinja_text is a string from a Jinja span.\n# @POST Returns a set of lowercased schema.table strings.\ndef extract_tables_from_jinja(jinja_text: str) -> set[str]:\n \"\"\"Extract ``schema.table`` references from within Jinja template blocks.\n\n Looks for double-quoted or single-quoted string values that match\n the ``schema.table`` pattern, e.g. ``\"raw.sales\"`` or ``'raw.inventory'``.\n \"\"\"\n tables: set[str] = set()\n # Match string values: \"schema.table\" or 'schema.table'\n string_pattern = re.compile(\n r\"\"\"[\"']([a-zA-Z_][\\w]*\\.[a-zA-Z_][\\w]*)[\"']\"\"\"\n )\n for m in string_pattern.finditer(jinja_text):\n tables.add(m.group(1).lower())\n return tables\n# #endregion extract_tables_from_jinja\n" + }, + { + "contract_id": "is_string_literal", + "contract_type": "Function", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 118, + "end_line": 125, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "POST": "Returns True if the token is a string/Single/Literal.String.", + "PRE": "token is a sqlparse Token.", + "PURPOSE": "Check if a sqlparse Token is a string literal (not a schema.table identifier)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region is_string_literal [C:1] [TYPE Function]\n# @BRIEF Check if a sqlparse Token is a string literal (not a schema.table identifier).\n# @PRE token is a sqlparse Token.\n# @POST Returns True if the token is a string/Single/Literal.String.\ndef is_string_literal(token: Token) -> bool:\n \"\"\"Return True if token is a string literal type in sqlparse.\"\"\"\n return token.ttype is Literal.String.Single or token.ttype is Literal.String\n# #endregion is_string_literal\n" + }, + { + "contract_id": "extract_tables_from_sql_span", + "contract_type": "Function", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 128, + "end_line": 187, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Phase 3: Extract schema.table references from SQL text using regex + sqlparse filtering." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region extract_tables_from_sql_span [C:2] [TYPE Function]\n# @BRIEF Phase 3: Extract schema.table references from SQL text using regex + sqlparse filtering.\n# Uses regex to find all schema.table candidates, then sqlparse to filter out\n# false positives inside string literals.\n# @PRE sql_text is a string from a SQL span (non-Jinja).\n# @POST Returns a set of lowercased schema.table strings.\ndef extract_tables_from_sql_span(sql_text: str) -> set[str]:\n \"\"\"Extract ``schema.table`` references from plain SQL text.\n\n Uses regex to find all ``schema.table`` candidates, then sqlparse\n to reject matches that fall inside string literals.\n \"\"\"\n tables: set[str] = set()\n raw_matches = _SCHEMA_TABLE_RE.findall(sql_text)\n if not raw_matches:\n return tables\n\n # Use sqlparse to identify string literal positions\n parsed = sqlparse.parse(sql_text)\n string_literal_ranges: list[tuple[int, int]] = []\n\n def walk_tokens(tokens: Iterable[Token], base_offset: int = 0) -> None:\n offset = base_offset\n for token in tokens:\n if isinstance(token, TokenList):\n walk_tokens(token.flatten(), offset)\n else:\n ttype = token.ttype\n val = token.value\n if is_string_literal(token):\n string_literal_ranges.append(\n (offset, offset + len(val))\n )\n offset += len(val)\n\n for stmt in parsed:\n if stmt is None:\n continue\n walk_tokens(stmt.flatten(), base_offset=0)\n\n def is_in_string(pos: int) -> bool:\n for s_start, s_end in string_literal_ranges:\n if s_start <= pos <= s_end:\n return True\n return False\n\n # Re-scan with full match positions to filter\n for m in _SCHEMA_TABLE_RE.finditer(sql_text):\n if not is_in_string(m.start()):\n # Extract schema and table from match groups\n schema = m.group(2) or m.group(1) or \"\"\n table = m.group(3) or \"\"\n # Filter out column aliases (single-char schemas like \"a.id\", \"o.id\")\n if len(schema) < 2 and schema.isalpha() and schema.islower():\n continue\n if schema and table:\n tables.add(f\"{schema.lower()}.{table.lower()}\")\n\n return tables\n# #endregion extract_tables_from_sql_span\n" + }, + { + "contract_id": "extract_tables_from_sql", + "contract_type": "Function", + "file_path": "backend/src/services/sql_table_extractor.py", + "start_line": 190, + "end_line": 224, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "POST": "Returns a set of lowercased fully-qualified table names (schema.table format).", + "PRE": "raw_sql is a string (possibly empty).", + "PURPOSE": "Three-phase entry point: extract all schema.table references from raw SQL+Jinja text." + }, + "relations": [ + { + "source_id": "extract_tables_from_sql", + "relation_type": "CALLS", + "target_id": "detect_jinja_spans", + "target_ref": "[detect_jinja_spans]" + }, + { + "source_id": "extract_tables_from_sql", + "relation_type": "CALLS", + "target_id": "extract_tables_from_jinja", + "target_ref": "[extract_tables_from_jinja]" + }, + { + "source_id": "extract_tables_from_sql", + "relation_type": "CALLS", + "target_id": "extract_tables_from_sql_span", + "target_ref": "[extract_tables_from_sql_span]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region extract_tables_from_sql [C:2] [TYPE Function]\n# @BRIEF Three-phase entry point: extract all schema.table references from raw SQL+Jinja text.\n# @PRE raw_sql is a string (possibly empty).\n# @POST Returns a set of lowercased fully-qualified table names (schema.table format).\n# @RELATION CALLS -> [detect_jinja_spans]\n# @RELATION CALLS -> [extract_tables_from_jinja]\n# @RELATION CALLS -> [extract_tables_from_sql_span]\ndef extract_tables_from_sql(raw_sql: str) -> set[str]:\n \"\"\"Extract all ``schema.table`` references from raw SQL + Jinja text.\n\n Three-phase approach per FR-003:\n 1. Detect Jinja spans vs SQL spans\n 2. In Jinja spans, extract ``schema.table`` from quoted string values\n 3. In SQL spans, regex + sqlparse filter to reject string literal false positives\n\n Returns a set of lowercased ``schema.table`` strings for case-insensitive matching.\n\n Example:\n >>> extract_tables_from_sql(\"SELECT * FROM raw.sales JOIN raw.inventory ON ...\")\n {'raw.sales', 'raw.inventory'}\n \"\"\"\n if not raw_sql or not raw_sql.strip():\n return set()\n\n all_tables: set[str] = set()\n spans = detect_jinja_spans(raw_sql)\n\n for span_type, text in spans:\n if span_type == \"jinja\":\n all_tables.update(extract_tables_from_jinja(text))\n else:\n all_tables.update(extract_tables_from_sql_span(text))\n\n return all_tables\n# #endregion extract_tables_from_sql\n" + }, { "contract_id": "superset_lookup_service", "contract_type": "Module", @@ -51536,7 +54101,7 @@ "contract_type": "Module", "file_path": "backend/src/services/validation_run_service.py", "start_line": 1, - "end_line": 135, + "end_line": 140, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -51548,7 +54113,7 @@ "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" + "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 # Match both spawned task_id (TaskRecord) and policy_id (ValidationPolicy.id)\n # because the frontend sends the validation policy UUID, but ValidationRecord.task_id\n # stores the spawned task UUID. Fall back to policy_id for the common case.\n query = query.filter(\n (ValidationRecord.task_id == task_id) | (ValidationRecord.policy_id == task_id)\n )\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", @@ -56100,6 +58665,686 @@ "tier_source": "AutoCalculated", "body": "# [DEF:test_sql_lab_launch_falls_back_to_legacy_execute_endpoint:Function]\n# @PURPOSE: Confirms SQL Lab launch falls back from modern to legacy execute endpoint and preserves canonical session reference extraction.\n# @RELATION: [DEPENDS_ON] ->[SupersetCompilationAdapter]\ndef test_sql_lab_launch_falls_back_to_legacy_execute_endpoint():\n adapter, client = make_adapter()\n client.get_dataset.return_value = {\n \"result\": {\n \"id\": 55,\n \"schema\": \"public\",\n \"database\": {\"id\": 9},\n }\n }\n client.network.request.side_effect = [\n RuntimeError(\"sqllab execute unavailable\"),\n {\"result\": {\"id\": \"query-123\"}},\n ]\n payload = SqlLabLaunchPayload(\n session_id=\"sess-3\",\n dataset_id=55,\n preview_id=\"preview-9\",\n compiled_sql=\"SELECT * FROM sales\",\n template_params={\"limit\": 10},\n )\n\n sql_lab_ref = adapter.create_sql_lab_session(payload)\n\n assert sql_lab_ref == \"query-123\"\n assert client.network.request.call_count == 2\n # @FRAGILE: Positional call assertion — ordering changes will break this test without indicating a real regression. Prefer content-based assertion.\n first_call = client.network.request.call_args_list[0].kwargs\n # @FRAGILE: Positional call assertion — ordering changes will break this test without indicating a real regression. Prefer content-based assertion.\n second_call = client.network.request.call_args_list[1].kwargs\n assert first_call[\"endpoint\"] == \"/sqllab/execute/\"\n assert second_call[\"endpoint\"] == \"/sql_lab/execute/\"\n\n\n# [/DEF:test_sql_lab_launch_falls_back_to_legacy_execute_endpoint:Function]\n" }, + { + "contract_id": "TestAPIKeyAuth", + "contract_type": "Module", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 1, + "end_line": 255, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Contract tests for API key authentication — valid key, invalid, revoked, expired, missing permission," + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region TestAPIKeyAuth [C:3] [TYPE Module] [SEMANTICS test, api_key, auth, dependency]\n# @BRIEF Contract tests for API key authentication — valid key, invalid, revoked, expired, missing permission,\n# environment scoping, JWT precedence. Uses TestClient with dependency overrides.\n# @RELATION BINDS_TO -> [APIKeyUtilities]\n# @RELATION BINDS_TO -> [APIKeyModel]\n# @RELATION BINDS_TO -> [MaintenanceRoutesModule]\n# @TEST_CONTRACT: get_api_key_principal returns APIKeyPrincipal for valid key, None for no header, 401 for invalid/revoked/expired.\n# @TEST_CONTRACT: require_api_key_or_jwt rejects invalid/revoked/expired keys, checks permissions, enforces environment scope.\n# @TEST_EDGE: missing_header -> returns None\n# @TEST_EDGE: invalid_key -> 401\n# @TEST_EDGE: revoked_key -> 401\n# @TEST_EDGE: expired_key -> 401\n# @TEST_EDGE: missing_permission -> 403\n# @TEST_EDGE: environment_scope_mismatch -> 400\n# @TEST_EDGE: jwt_precedence -> JWT takes precedence over API key\nfrom datetime import datetime, timezone, timedelta\nfrom unittest.mock import AsyncMock, MagicMock, patch\n\nimport pytest\nfrom fastapi import HTTPException, status\nfrom fastapi.testclient import TestClient\n\n\n# ── Fixtures ──────────────────────────────────────────────────\n\n\n@pytest.fixture\ndef db_session():\n \"\"\"Create an in-memory SQLite session with the api_keys table.\"\"\"\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n yield session\n session.close()\n\n\n@pytest.fixture\ndef valid_api_key(db_session):\n \"\"\"Create a valid API key and return its raw value, prefix, and database row.\"\"\"\n from src.core.auth.api_key import generate_api_key\n from src.models.api_key import APIKey\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Test Key\",\n permissions=[\"maintenance:start\", \"maintenance:end\"],\n active=True,\n )\n db_session.add(api_key)\n db_session.commit()\n return raw, api_key\n\n\n@pytest.fixture\ndef client():\n \"\"\"Create a TestClient.\"\"\"\n from src.app import app\n\n return TestClient(app)\n\n\n@pytest.fixture\ndef mock_db():\n \"\"\"Patch get_db dependency with in-memory SQLite session (same pattern as test_maintenance_api).\"\"\"\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n from src.dependencies import get_db\n from src.app import app\n\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n\n # Add default maintenance settings (needed by /api/maintenance endpoints)\n from src.models.maintenance import MaintenanceSettings, DashboardScope\n\n settings = MaintenanceSettings(\n id=\"default\",\n target_environment_id=\"test-env\",\n display_timezone=\"UTC\",\n banner_template=\"Test: {message} ({start_time}-{end_time})\",\n dashboard_scope=DashboardScope.PUBLISHED_ONLY,\n excluded_dashboard_ids=[],\n forced_dashboard_ids=[],\n )\n session.add(settings)\n session.commit()\n\n def _get_db_override():\n db = Session()\n try:\n yield db\n finally:\n db.close()\n\n app.dependency_overrides[get_db] = _get_db_override\n yield session\n app.dependency_overrides.pop(get_db, None)\n session.close()\n\n\n@pytest.fixture\ndef mock_task_manager():\n \"\"\"Patch get_task_manager to return a mock.\"\"\"\n from src.dependencies import get_task_manager\n from src.app import app\n\n mock_tm = MagicMock()\n mock_task = MagicMock()\n mock_task.id = \"test-task-id-123\"\n mock_tm.create_task = AsyncMock(return_value=mock_task)\n\n app.dependency_overrides[get_task_manager] = lambda: mock_tm\n yield mock_tm\n app.dependency_overrides.pop(get_task_manager, None)\n\n\n# ── Tests for get_api_key_principal ───────────────────────────\n\nclass TestGetApiKeyPrincipal:\n \"\"\"Contract tests for get_api_key_principal dependency.\"\"\"\n\n # #region test_no_header_returns_none [C:2] [TYPE Function]\n # @BRIEF No X-API-Key header → returns None.\n @pytest.mark.asyncio\n async def test_no_header_returns_none(self):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n # Mock a request without the header\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = None\n mock_db = MagicMock()\n\n result = await get_api_key_principal(mock_request, mock_db)\n assert result is None\n\n # #endregion test_no_header_returns_none\n\n # #region test_valid_key_returns_principal [C:2] [TYPE Function]\n # @BRIEF Valid API key → returns APIKeyPrincipal with correct fields.\n @pytest.mark.asyncio\n async def test_valid_key_returns_principal(self, db_session, valid_api_key):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n raw_key, api_key_row = valid_api_key\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw_key\n\n result = await get_api_key_principal(mock_request, db_session)\n assert result is not None\n assert result.name == \"Test Key\"\n assert result.api_key_id == api_key_row.id\n assert result.environment_id is None\n assert \"maintenance:start\" in result.permissions\n\n # #endregion test_valid_key_returns_principal\n\n # #region test_invalid_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Invalid API key → 401.\n @pytest.mark.asyncio\n async def test_invalid_key_raises_401(self, db_session):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = \"ssk_invalid_key_that_does_not_exist\"\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_invalid_key_raises_401\n\n # #region test_revoked_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Revoked (active=False) API key → 401.\n @pytest.mark.asyncio\n async def test_revoked_key_raises_401(self, db_session):\n from src.core.auth.api_key import generate_api_key\n from src.dependencies import get_api_key_principal\n from src.models.api_key import APIKey\n from fastapi import Request\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Revoked Key\",\n permissions=[\"maintenance:start\"],\n active=False, # revoked\n )\n db_session.add(api_key)\n db_session.commit()\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_revoked_key_raises_401\n\n # #region test_expired_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Expired API key → 401.\n @pytest.mark.asyncio\n async def test_expired_key_raises_401(self, db_session):\n from src.core.auth.api_key import generate_api_key\n from src.dependencies import get_api_key_principal\n from src.models.api_key import APIKey\n from fastapi import Request\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Expired Key\",\n permissions=[\"maintenance:start\"],\n active=True,\n expires_at=datetime.now(timezone.utc) - timedelta(hours=1), # expired\n )\n db_session.add(api_key)\n db_session.commit()\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_expired_key_raises_401\n\n\n# #endregion TestAPIKeyAuth\n" + }, + { + "contract_id": "test_no_header_returns_none", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 142, + "end_line": 157, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "No X-API-Key header → returns None." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_no_header_returns_none [C:2] [TYPE Function]\n # @BRIEF No X-API-Key header → returns None.\n @pytest.mark.asyncio\n async def test_no_header_returns_none(self):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n # Mock a request without the header\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = None\n mock_db = MagicMock()\n\n result = await get_api_key_principal(mock_request, mock_db)\n assert result is None\n\n # #endregion test_no_header_returns_none\n" + }, + { + "contract_id": "test_valid_key_returns_principal", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 159, + "end_line": 177, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Valid API key → returns APIKeyPrincipal with correct fields." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_valid_key_returns_principal [C:2] [TYPE Function]\n # @BRIEF Valid API key → returns APIKeyPrincipal with correct fields.\n @pytest.mark.asyncio\n async def test_valid_key_returns_principal(self, db_session, valid_api_key):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n raw_key, api_key_row = valid_api_key\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw_key\n\n result = await get_api_key_principal(mock_request, db_session)\n assert result is not None\n assert result.name == \"Test Key\"\n assert result.api_key_id == api_key_row.id\n assert result.environment_id is None\n assert \"maintenance:start\" in result.permissions\n\n # #endregion test_valid_key_returns_principal\n" + }, + { + "contract_id": "test_invalid_key_raises_401", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 179, + "end_line": 193, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Invalid API key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_invalid_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Invalid API key → 401.\n @pytest.mark.asyncio\n async def test_invalid_key_raises_401(self, db_session):\n from src.dependencies import get_api_key_principal\n from fastapi import Request\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = \"ssk_invalid_key_that_does_not_exist\"\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_invalid_key_raises_401\n" + }, + { + "contract_id": "test_revoked_key_raises_401", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 195, + "end_line": 222, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Revoked (active=False) API key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_revoked_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Revoked (active=False) API key → 401.\n @pytest.mark.asyncio\n async def test_revoked_key_raises_401(self, db_session):\n from src.core.auth.api_key import generate_api_key\n from src.dependencies import get_api_key_principal\n from src.models.api_key import APIKey\n from fastapi import Request\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Revoked Key\",\n permissions=[\"maintenance:start\"],\n active=False, # revoked\n )\n db_session.add(api_key)\n db_session.commit()\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_revoked_key_raises_401\n" + }, + { + "contract_id": "test_expired_key_raises_401", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 224, + "end_line": 252, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Expired API key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_expired_key_raises_401 [C:2] [TYPE Function]\n # @BRIEF Expired API key → 401.\n @pytest.mark.asyncio\n async def test_expired_key_raises_401(self, db_session):\n from src.core.auth.api_key import generate_api_key\n from src.dependencies import get_api_key_principal\n from src.models.api_key import APIKey\n from fastapi import Request\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Expired Key\",\n permissions=[\"maintenance:start\"],\n active=True,\n expires_at=datetime.now(timezone.utc) - timedelta(hours=1), # expired\n )\n db_session.add(api_key)\n db_session.commit()\n\n mock_request = MagicMock(spec=Request)\n mock_request.headers.get.return_value = raw\n\n with pytest.raises(HTTPException) as exc:\n await get_api_key_principal(mock_request, db_session)\n assert exc.value.status_code == 401\n\n # #endregion test_expired_key_raises_401\n" + }, + { + "contract_id": "test_api_key_auth_valid", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 291, + "end_line": 306, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Valid API key with matching permission → 202." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_valid [C:2] [TYPE Function]\n # @BRIEF Valid API key with matching permission → 202.\n def test_api_key_auth_valid(self, client, mock_db, mock_task_manager):\n raw_key = self._create_api_key(mock_db, permissions=[\"maintenance:start\"])\n\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\"X-API-Key\": raw_key},\n )\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n assert data[\"status\"] == \"pending\"\n\n # #endregion test_api_key_auth_valid\n" + }, + { + "contract_id": "test_api_key_auth_wrong_permission", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 308, + "end_line": 323, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "API key lacks required permission → 403." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_wrong_permission [C:2] [TYPE Function]\n # @BRIEF API key lacks required permission → 403.\n def test_api_key_auth_wrong_permission(self, client, mock_db, mock_task_manager):\n # Key has 'maintenance:end' only, not 'maintenance:start'\n raw_key = self._create_api_key(mock_db, permissions=[\"maintenance:end\"])\n\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\"X-API-Key\": raw_key},\n )\n assert response.status_code == 403\n data = response.json()\n assert \"detail\" in data\n\n # #endregion test_api_key_auth_wrong_permission\n" + }, + { + "contract_id": "test_api_key_auth_revoked", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 325, + "end_line": 350, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Revoked API key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_revoked [C:2] [TYPE Function]\n # @BRIEF Revoked API key → 401.\n def test_api_key_auth_revoked(self, client, mock_db, mock_task_manager):\n from src.core.auth.api_key import generate_api_key\n from src.models.api_key import APIKey\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Revoked Key\",\n permissions=[\"maintenance:start\"],\n active=False,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\"X-API-Key\": raw},\n )\n assert response.status_code == 401\n assert \"revoked\" in response.json().get(\"detail\", \"\").lower()\n\n # #endregion test_api_key_auth_revoked\n" + }, + { + "contract_id": "test_api_key_auth_expired", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 352, + "end_line": 378, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Expired API key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_expired [C:2] [TYPE Function]\n # @BRIEF Expired API key → 401.\n def test_api_key_auth_expired(self, client, mock_db, mock_task_manager):\n from src.core.auth.api_key import generate_api_key\n from src.models.api_key import APIKey\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Expired Key\",\n permissions=[\"maintenance:start\"],\n active=True,\n expires_at=datetime.now(timezone.utc) - timedelta(hours=1),\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\"X-API-Key\": raw},\n )\n assert response.status_code == 401\n assert \"expired\" in response.json().get(\"detail\", \"\").lower()\n\n # #endregion test_api_key_auth_expired\n" + }, + { + "contract_id": "test_api_key_auth_invalid", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 380, + "end_line": 391, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Non-existent key → 401." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_invalid [C:2] [TYPE Function]\n # @BRIEF Non-existent key → 401.\n def test_api_key_auth_invalid(self, client, mock_db, mock_task_manager):\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\"X-API-Key\": \"ssk_invalid_nonexistent_key\"},\n )\n assert response.status_code == 401\n assert \"invalid\" in response.json().get(\"detail\", \"\").lower()\n\n # #endregion test_api_key_auth_invalid\n" + }, + { + "contract_id": "test_api_key_auth_environment_scope", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 393, + "end_line": 415, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Key scoped to ss-dev, request for ss-prod → 400." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_environment_scope [C:2] [TYPE Function]\n # @BRIEF Key scoped to ss-dev, request for ss-prod → 400.\n def test_api_key_auth_environment_scope(self, client, mock_db, mock_task_manager):\n raw_key = self._create_api_key(\n mock_db,\n environment_id=\"ss-dev\",\n permissions=[\"maintenance:start\"],\n )\n\n payload = dict(self.START_PAYLOAD)\n payload[\"environment_id\"] = \"ss-prod\" # Mismatch!\n\n response = client.post(\n self.API_START_URL,\n json=payload,\n headers={\"X-API-Key\": raw_key},\n )\n assert response.status_code == 400\n data = response.json()\n assert \"restricted\" in data.get(\"detail\", \"\").lower()\n assert \"ss-dev\" in data.get(\"detail\", \"\")\n\n # #endregion test_api_key_auth_environment_scope\n" + }, + { + "contract_id": "test_api_key_auth_environment_scope_ok", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 417, + "end_line": 438, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Key scoped to ss-dev, request for ss-dev → 202." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_api_key_auth_environment_scope_ok [C:2] [TYPE Function]\n # @BRIEF Key scoped to ss-dev, request for ss-dev → 202.\n def test_api_key_auth_environment_scope_ok(self, client, mock_db, mock_task_manager):\n raw_key = self._create_api_key(\n mock_db,\n environment_id=\"ss-dev\",\n permissions=[\"maintenance:start\"],\n )\n\n payload = dict(self.START_PAYLOAD)\n payload[\"environment_id\"] = \"ss-dev\" # Match!\n\n response = client.post(\n self.API_START_URL,\n json=payload,\n headers={\"X-API-Key\": raw_key},\n )\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n\n # #endregion test_api_key_auth_environment_scope_ok\n" + }, + { + "contract_id": "test_jwt_precedence", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_auth.py", + "start_line": 440, + "end_line": 497, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Both valid API key + valid JWT → JWT takes precedence." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_jwt_precedence [C:2] [TYPE Function]\n # @BRIEF Both valid API key + valid JWT → JWT takes precedence.\n def test_jwt_precedence(self, client, mock_db, mock_task_manager):\n from src.core.auth.jwt import create_access_token\n from src.models.auth import User, Role\n from src.dependencies import get_auth_db\n from src.app import app\n\n raw_key = self._create_api_key(\n mock_db,\n environment_id=\"ss-dev\",\n permissions=[\"maintenance:start\"],\n )\n\n # Create a JWT user with Admin role (full access)\n role = Role(name=\"Admin\", description=\"Admin role\")\n mock_db.add(role)\n mock_db.commit()\n\n user = User(\n username=\"jwt-user\",\n password_hash=\"nohash\",\n auth_source=\"LOCAL\",\n is_active=True,\n )\n user.roles.append(role)\n mock_db.add(user)\n mock_db.commit()\n\n # Create a valid JWT token\n token = create_access_token(data={\"sub\": \"jwt-user\"})\n\n # Override get_auth_db to use our mock_db for auth queries too\n # The auth DB and main DB are separate in production, but for tests\n # we use the same in-memory DB\n\n def _get_auth_db_override():\n yield mock_db\n\n app.dependency_overrides[get_auth_db] = _get_auth_db_override\n\n # Send request with BOTH X-API-Key and Authorization: Bearer\n response = client.post(\n self.API_START_URL,\n json=self.START_PAYLOAD,\n headers={\n \"X-API-Key\": raw_key,\n \"Authorization\": f\"Bearer {token}\",\n },\n )\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n\n # Cleanup\n app.dependency_overrides.pop(get_auth_db, None)\n\n # #endregion test_jwt_precedence\n" + }, + { + "contract_id": "TestAPIKeyModel", + "contract_type": "Module", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 1, + "end_line": 122, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Contract tests for the APIKey SQLAlchemy model — creation, hash storage, and field constraints.", + "TEST_CONTRACT": "APIKey model stores SHA-256 hash and prefix; raw key never persisted.", + "TEST_EDGE": "active defaults to True" + }, + "relations": [ + { + "source_id": "TestAPIKeyModel", + "relation_type": "BINDS_TO", + "target_id": "APIKeyModel", + "target_ref": "[APIKeyModel]" + } + ], + "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 C2", + "detail": { + "actual_complexity": 2, + "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 C2", + "detail": { + "actual_complexity": 2, + "contract_type": "Module" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region TestAPIKeyModel [C:2] [TYPE Module] [SEMANTICS test, api_key, model]\n# @BRIEF Contract tests for the APIKey SQLAlchemy model — creation, hash storage, and field constraints.\n# @RELATION BINDS_TO -> [APIKeyModel]\n# @TEST_CONTRACT: APIKey model stores SHA-256 hash and prefix; raw key never persisted.\n# @TEST_EDGE: key_hash is unique and indexed\n# @TEST_EDGE: prefix is exactly 11 chars (\"ssk_\" + 7)\n# @TEST_EDGE: active defaults to True\nimport pytest\nfrom datetime import datetime, timezone\n\n\n# #region clean_db [C:1] [TYPE Fixture]\n# @BRIEF In-memory SQLite fixture for APIKey model tests.\n@pytest.fixture\ndef clean_db():\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n yield session\n session.close()\n# #endregion clean_db\n\n\nclass TestAPIKeyModel:\n \"\"\"Verify APIKey model fields and constraints.\"\"\"\n\n # #region test_create_api_key [C:2] [TYPE Function]\n # @BRIEF Create APIKey with required fields and verify defaults.\n def test_create_api_key(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"a\" * 64,\n prefix=\"ssk_abc1234\",\n name=\"Test Key\",\n permissions=[\"maintenance:start\"],\n )\n clean_db.add(api_key)\n clean_db.commit()\n clean_db.refresh(api_key)\n\n assert api_key.id is not None\n assert api_key.key_hash == \"a\" * 64\n assert api_key.prefix == \"ssk_abc1234\"\n assert api_key.name == \"Test Key\"\n assert api_key.permissions == [\"maintenance:start\"]\n assert api_key.active is True\n assert api_key.created_at is not None\n assert api_key.environment_id is None\n assert api_key.expires_at is None\n assert api_key.last_used_at is None\n # #endregion test_create_api_key\n\n # #region test_key_hash_unique [C:2] [TYPE Function]\n # @BRIEF key_hash is unique — duplicate raises IntegrityError.\n def test_key_hash_unique(self, clean_db):\n from sqlalchemy.exc import IntegrityError\n from src.models.api_key import APIKey\n\n clean_db.add(APIKey(\n key_hash=\"b\" * 64,\n prefix=\"ssk_xyz7890\",\n name=\"Key 1\",\n permissions=[\"maintenance:start\"],\n ))\n clean_db.commit()\n\n with pytest.raises(IntegrityError):\n clean_db.add(APIKey(\n key_hash=\"b\" * 64, # Same hash\n prefix=\"ssk_def5678\",\n name=\"Key 2\",\n permissions=[\"maintenance:end\"],\n ))\n clean_db.commit()\n # #endregion test_key_hash_unique\n\n # #region test_prefix_length [C:2] [TYPE Function]\n # @BRIEF prefix is exactly 11 characters.\n def test_prefix_length(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"c\" * 64,\n prefix=\"ssk_short1\", # 10 chars — should be ok in SQL\n name=\"Short Prefix\",\n permissions=[\"maintenance:start\"],\n )\n clean_db.add(api_key)\n clean_db.commit()\n # The DB allows any prefix length; the app layer enforces 11 chars\n # via generate_api_key. Model just stores what it's given.\n assert len(api_key.prefix) <= 11\n # #endregion test_prefix_length\n\n # #region test_active_default_true [C:2] [TYPE Function]\n # @BRIEF active column defaults to True.\n def test_active_default_true(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"d\" * 64,\n prefix=\"ssk_def1234\",\n name=\"Default Active\",\n permissions=[],\n )\n clean_db.add(api_key)\n clean_db.commit()\n\n assert api_key.active is True\n # #endregion test_active_default_true\n# #endregion TestAPIKeyModel\n" + }, + { + "contract_id": "clean_db", + "contract_type": "Fixture", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 12, + "end_line": 31, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1, + "PURPOSE": "In-memory SQLite fixture for APIKey model tests." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'Fixture'", + "detail": { + "actual_type": "Fixture", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'Fixture' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Fixture" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'Fixture'", + "detail": { + "actual_type": "Fixture", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'Fixture' at C1", + "detail": { + "actual_complexity": 1, + "contract_type": "Fixture" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region clean_db [C:1] [TYPE Fixture]\n# @BRIEF In-memory SQLite fixture for APIKey model tests.\n@pytest.fixture\ndef clean_db():\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n yield session\n session.close()\n# #endregion clean_db\n" + }, + { + "contract_id": "test_create_api_key", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 37, + "end_line": 62, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Create APIKey with required fields and verify defaults." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_create_api_key [C:2] [TYPE Function]\n # @BRIEF Create APIKey with required fields and verify defaults.\n def test_create_api_key(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"a\" * 64,\n prefix=\"ssk_abc1234\",\n name=\"Test Key\",\n permissions=[\"maintenance:start\"],\n )\n clean_db.add(api_key)\n clean_db.commit()\n clean_db.refresh(api_key)\n\n assert api_key.id is not None\n assert api_key.key_hash == \"a\" * 64\n assert api_key.prefix == \"ssk_abc1234\"\n assert api_key.name == \"Test Key\"\n assert api_key.permissions == [\"maintenance:start\"]\n assert api_key.active is True\n assert api_key.created_at is not None\n assert api_key.environment_id is None\n assert api_key.expires_at is None\n assert api_key.last_used_at is None\n # #endregion test_create_api_key\n" + }, + { + "contract_id": "test_key_hash_unique", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 64, + "end_line": 86, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "key_hash is unique — duplicate raises IntegrityError." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_key_hash_unique [C:2] [TYPE Function]\n # @BRIEF key_hash is unique — duplicate raises IntegrityError.\n def test_key_hash_unique(self, clean_db):\n from sqlalchemy.exc import IntegrityError\n from src.models.api_key import APIKey\n\n clean_db.add(APIKey(\n key_hash=\"b\" * 64,\n prefix=\"ssk_xyz7890\",\n name=\"Key 1\",\n permissions=[\"maintenance:start\"],\n ))\n clean_db.commit()\n\n with pytest.raises(IntegrityError):\n clean_db.add(APIKey(\n key_hash=\"b\" * 64, # Same hash\n prefix=\"ssk_def5678\",\n name=\"Key 2\",\n permissions=[\"maintenance:end\"],\n ))\n clean_db.commit()\n # #endregion test_key_hash_unique\n" + }, + { + "contract_id": "test_prefix_length", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 88, + "end_line": 104, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "prefix is exactly 11 characters." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_prefix_length [C:2] [TYPE Function]\n # @BRIEF prefix is exactly 11 characters.\n def test_prefix_length(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"c\" * 64,\n prefix=\"ssk_short1\", # 10 chars — should be ok in SQL\n name=\"Short Prefix\",\n permissions=[\"maintenance:start\"],\n )\n clean_db.add(api_key)\n clean_db.commit()\n # The DB allows any prefix length; the app layer enforces 11 chars\n # via generate_api_key. Model just stores what it's given.\n assert len(api_key.prefix) <= 11\n # #endregion test_prefix_length\n" + }, + { + "contract_id": "test_active_default_true", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_model.py", + "start_line": 106, + "end_line": 121, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "active column defaults to True." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_active_default_true [C:2] [TYPE Function]\n # @BRIEF active column defaults to True.\n def test_active_default_true(self, clean_db):\n from src.models.api_key import APIKey\n\n api_key = APIKey(\n key_hash=\"d\" * 64,\n prefix=\"ssk_def1234\",\n name=\"Default Active\",\n permissions=[],\n )\n clean_db.add(api_key)\n clean_db.commit()\n\n assert api_key.active is True\n # #endregion test_active_default_true\n" + }, + { + "contract_id": "TestAPIKeyRoutes", + "contract_type": "Module", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 1, + "end_line": 258, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Contract tests for admin API key CRUD endpoints — list, create (raw key present), revoke, idempotent revoke.", + "TEST_CONTRACT": "DELETE /api/admin/api-keys/{id} -> 200 with status=revoked", + "TEST_EDGE": "missing_permissions -> 422" + }, + "relations": [ + { + "source_id": "TestAPIKeyRoutes", + "relation_type": "BINDS_TO", + "target_id": "AdminApiKeyRoutes", + "target_ref": "[AdminApiKeyRoutes]" + } + ], + "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" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region TestAPIKeyRoutes [C:3] [TYPE Module] [SEMANTICS test, api_key, routes, crud]\n# @BRIEF Contract tests for admin API key CRUD endpoints — list, create (raw key present), revoke, idempotent revoke.\n# @RELATION BINDS_TO -> [AdminApiKeyRoutes]\n# @TEST_CONTRACT: GET /api/admin/api-keys -> list of keys without raw_key or key_hash\n# @TEST_CONTRACT: POST /api/admin/api-keys -> 201 with raw_key in response\n# @TEST_CONTRACT: DELETE /api/admin/api-keys/{id} -> 200 with status=revoked\n# @TEST_EDGE: revoked_key_delete -> 404\n# @TEST_EDGE: missing_name -> 422\n# @TEST_EDGE: missing_permissions -> 422\nimport json\nimport sys\nfrom datetime import datetime, timezone, timedelta\nfrom unittest.mock import MagicMock, patch\n\nimport pytest\nfrom fastapi import status\nfrom fastapi.testclient import TestClient\n\n# Patch GitService at module level to prevent /app/storage/repositories error\n_mock_git_svc_cls = MagicMock()\n_mock_git_svc_cls.return_value = MagicMock()\nsys.modules['src.services.git._base'] = MagicMock(GitService=_mock_git_svc_cls)\nsys.modules['src.services.git_service'] = MagicMock(GitService=_mock_git_svc_cls)\n\n\n# ── Fixtures ──────────────────────────────────────────────────\n\n@pytest.fixture\ndef client():\n \"\"\"Create a TestClient with all dependencies mocked.\"\"\"\n from src.app import app\n return TestClient(app)\n\n\ndef _mock_admin_auth():\n \"\"\"Apply dependency overrides for admin authentication.\"\"\"\n from src.dependencies import get_current_user\n from src.app import app\n\n mock_role = MagicMock()\n mock_role.name = \"Admin\"\n mock_role.permissions = []\n\n mock_user = MagicMock()\n mock_user.username = \"test-admin\"\n mock_user.roles = [mock_role]\n\n async def _mock_get_current_user():\n return mock_user\n\n app.dependency_overrides[get_current_user] = _mock_get_current_user\n\n\ndef _clear_overrides():\n from src.app import app\n app.dependency_overrides = {}\n\n\n@pytest.fixture(autouse=True)\ndef auth_mock():\n _mock_admin_auth()\n yield\n _clear_overrides()\n\n\n@pytest.fixture\ndef mock_db():\n \"\"\"Patch get_db dependency with in-memory SQLite session.\"\"\"\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n from src.dependencies import get_db\n from src.app import app\n\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n\n def _get_db_override():\n db = Session()\n try:\n yield db\n finally:\n db.close()\n\n app.dependency_overrides[get_db] = _get_db_override\n yield session\n app.dependency_overrides.pop(get_db, None)\n session.close()\n\n\n# ── Tests ─────────────────────────────────────────────────────\n\nclass TestListApiKeys:\n \"\"\"Contract tests for GET /api/admin/api-keys.\"\"\"\n\n # #region test_list_empty [C:2] [TYPE Function]\n # @BRIEF No keys → returns empty list.\n def test_list_empty(self, client, mock_db):\n response = client.get(\"/api/admin/api-keys/\")\n assert response.status_code == 200\n data = response.json()\n assert isinstance(data, list)\n assert len(data) == 0\n # #endregion test_list_empty\n\n # #region test_list_with_keys [C:2] [TYPE Function]\n # @BRIEF Keys exist → returns list without raw_key or key_hash fields.\n def test_list_with_keys(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n # Create a key\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Test Key\",\n permissions=[\"maintenance:start\", \"maintenance:end\"],\n active=True,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.get(\"/api/admin/api-keys/\")\n assert response.status_code == 200\n data = response.json()\n assert len(data) == 1\n assert data[0][\"name\"] == \"Test Key\"\n assert data[0][\"prefix\"] == prefix\n assert \"raw_key\" not in data[0]\n assert \"key_hash\" not in data[0]\n # #endregion test_list_with_keys\n\n\nclass TestCreateApiKey:\n \"\"\"Contract tests for POST /api/admin/api-keys.\"\"\"\n\n # #region test_create_valid [C:2] [TYPE Function]\n # @BRIEF Valid request → 201 with raw_key, prefix, id.\n def test_create_valid(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"name\": \"CI/CD Pipeline\",\n \"permissions\": [\"maintenance:start\", \"maintenance:end\"],\n \"environment_id\": \"prod-env-1\",\n },\n )\n assert response.status_code == 201\n data = response.json()\n assert \"id\" in data\n assert \"raw_key\" in data\n assert data[\"raw_key\"].startswith(\"ssk_\")\n assert data[\"prefix\"] == data[\"raw_key\"][:11]\n assert data[\"name\"] == \"CI/CD Pipeline\"\n assert data[\"permissions\"] == [\"maintenance:start\", \"maintenance:end\"]\n assert data[\"active\"] is True\n assert data[\"environment_id\"] == \"prod-env-1\"\n # Verify raw key is NOT in DB\n from src.models.api_key import APIKey\n db_key = mock_db.query(APIKey).filter(APIKey.id == data[\"id\"]).first()\n assert db_key is not None\n assert db_key.key_hash != data[\"raw_key\"]\n assert db_key.prefix == data[\"prefix\"]\n # #endregion test_create_valid\n\n # #region test_create_missing_name [C:2] [TYPE Function]\n # @BRIEF Missing name → 400 or 422.\n def test_create_missing_name(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"permissions\": [\"maintenance:start\"],\n },\n )\n assert response.status_code in (400, 422)\n # #endregion test_create_missing_name\n\n # #region test_create_empty_permissions [C:2] [TYPE Function]\n # @BRIEF Empty permissions → 400 or 422.\n def test_create_empty_permissions(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"name\": \"No Perms\",\n \"permissions\": [],\n },\n )\n assert response.status_code in (400, 422)\n # #endregion test_create_empty_permissions\n\n\nclass TestRevokeApiKey:\n \"\"\"Contract tests for DELETE /api/admin/api-keys/{id}.\"\"\"\n\n # #region test_revoke_valid [C:2] [TYPE Function]\n # @BRIEF Revoke existing active key → 200 with status=revoked.\n def test_revoke_valid(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"To Revoke\",\n permissions=[\"maintenance:start\"],\n active=True,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.delete(f\"/api/admin/api-keys/{api_key.id}\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"id\"] == api_key.id\n assert data[\"status\"] == \"revoked\"\n\n # Verify DB\n mock_db.refresh(api_key)\n assert api_key.active is False\n # #endregion test_revoke_valid\n\n # #region test_revoke_already_revoked [C:2] [TYPE Function]\n # @BRIEF Revoke already revoked key → 404.\n def test_revoke_already_revoked(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Already Revoked\",\n permissions=[\"maintenance:start\"],\n active=False, # already revoked\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.delete(f\"/api/admin/api-keys/{api_key.id}\")\n assert response.status_code == 404\n # #endregion test_revoke_already_revoked\n\n # #region test_revoke_not_found [C:2] [TYPE Function]\n # @BRIEF Revoke non-existent key → 404.\n def test_revoke_not_found(self, client, mock_db):\n response = client.delete(\"/api/admin/api-keys/nonexistent-id\")\n assert response.status_code == 404\n # #endregion test_revoke_not_found\n# #endregion TestAPIKeyRoutes\n" + }, + { + "contract_id": "test_list_empty", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 103, + "end_line": 111, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "No keys → returns empty list." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_list_empty [C:2] [TYPE Function]\n # @BRIEF No keys → returns empty list.\n def test_list_empty(self, client, mock_db):\n response = client.get(\"/api/admin/api-keys/\")\n assert response.status_code == 200\n data = response.json()\n assert isinstance(data, list)\n assert len(data) == 0\n # #endregion test_list_empty\n" + }, + { + "contract_id": "test_list_with_keys", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 113, + "end_line": 139, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Keys exist → returns list without raw_key or key_hash fields." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_list_with_keys [C:2] [TYPE Function]\n # @BRIEF Keys exist → returns list without raw_key or key_hash fields.\n def test_list_with_keys(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n # Create a key\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Test Key\",\n permissions=[\"maintenance:start\", \"maintenance:end\"],\n active=True,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.get(\"/api/admin/api-keys/\")\n assert response.status_code == 200\n data = response.json()\n assert len(data) == 1\n assert data[0][\"name\"] == \"Test Key\"\n assert data[0][\"prefix\"] == prefix\n assert \"raw_key\" not in data[0]\n assert \"key_hash\" not in data[0]\n # #endregion test_list_with_keys\n" + }, + { + "contract_id": "test_create_valid", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 145, + "end_line": 172, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Valid request → 201 with raw_key, prefix, id." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_create_valid [C:2] [TYPE Function]\n # @BRIEF Valid request → 201 with raw_key, prefix, id.\n def test_create_valid(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"name\": \"CI/CD Pipeline\",\n \"permissions\": [\"maintenance:start\", \"maintenance:end\"],\n \"environment_id\": \"prod-env-1\",\n },\n )\n assert response.status_code == 201\n data = response.json()\n assert \"id\" in data\n assert \"raw_key\" in data\n assert data[\"raw_key\"].startswith(\"ssk_\")\n assert data[\"prefix\"] == data[\"raw_key\"][:11]\n assert data[\"name\"] == \"CI/CD Pipeline\"\n assert data[\"permissions\"] == [\"maintenance:start\", \"maintenance:end\"]\n assert data[\"active\"] is True\n assert data[\"environment_id\"] == \"prod-env-1\"\n # Verify raw key is NOT in DB\n from src.models.api_key import APIKey\n db_key = mock_db.query(APIKey).filter(APIKey.id == data[\"id\"]).first()\n assert db_key is not None\n assert db_key.key_hash != data[\"raw_key\"]\n assert db_key.prefix == data[\"prefix\"]\n # #endregion test_create_valid\n" + }, + { + "contract_id": "test_create_missing_name", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 174, + "end_line": 184, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Missing name → 400 or 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_create_missing_name [C:2] [TYPE Function]\n # @BRIEF Missing name → 400 or 422.\n def test_create_missing_name(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"permissions\": [\"maintenance:start\"],\n },\n )\n assert response.status_code in (400, 422)\n # #endregion test_create_missing_name\n" + }, + { + "contract_id": "test_create_empty_permissions", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 186, + "end_line": 197, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Empty permissions → 400 or 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_create_empty_permissions [C:2] [TYPE Function]\n # @BRIEF Empty permissions → 400 or 422.\n def test_create_empty_permissions(self, client, mock_db):\n response = client.post(\n \"/api/admin/api-keys/\",\n json={\n \"name\": \"No Perms\",\n \"permissions\": [],\n },\n )\n assert response.status_code in (400, 422)\n # #endregion test_create_empty_permissions\n" + }, + { + "contract_id": "test_revoke_valid", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 203, + "end_line": 229, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Revoke existing active key → 200 with status=revoked." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_revoke_valid [C:2] [TYPE Function]\n # @BRIEF Revoke existing active key → 200 with status=revoked.\n def test_revoke_valid(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"To Revoke\",\n permissions=[\"maintenance:start\"],\n active=True,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.delete(f\"/api/admin/api-keys/{api_key.id}\")\n assert response.status_code == 200\n data = response.json()\n assert data[\"id\"] == api_key.id\n assert data[\"status\"] == \"revoked\"\n\n # Verify DB\n mock_db.refresh(api_key)\n assert api_key.active is False\n # #endregion test_revoke_valid\n" + }, + { + "contract_id": "test_revoke_already_revoked", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 231, + "end_line": 250, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Revoke already revoked key → 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_revoke_already_revoked [C:2] [TYPE Function]\n # @BRIEF Revoke already revoked key → 404.\n def test_revoke_already_revoked(self, client, mock_db):\n from src.models.api_key import APIKey\n from src.core.auth.api_key import generate_api_key\n\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Already Revoked\",\n permissions=[\"maintenance:start\"],\n active=False, # already revoked\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n response = client.delete(f\"/api/admin/api-keys/{api_key.id}\")\n assert response.status_code == 404\n # #endregion test_revoke_already_revoked\n" + }, + { + "contract_id": "test_revoke_not_found", + "contract_type": "Function", + "file_path": "backend/tests/test_api_key_routes.py", + "start_line": 252, + "end_line": 257, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Revoke non-existent key → 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_revoke_not_found [C:2] [TYPE Function]\n # @BRIEF Revoke non-existent key → 404.\n def test_revoke_not_found(self, client, mock_db):\n response = client.delete(\"/api/admin/api-keys/nonexistent-id\")\n assert response.status_code == 404\n # #endregion test_revoke_not_found\n" + }, { "contract_id": "TestAuth", "contract_type": "Module", @@ -56610,7 +59855,7 @@ "contract_type": "Module", "file_path": "backend/tests/test_core_scheduler.py", "start_line": 1, - "end_line": 175, + "end_line": 518, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -56652,14 +59897,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "# #region TestCoreScheduler [C:3] [TYPE Module] [SEMANTICS test, scheduler, apscheduler, load, reload]\n# @BRIEF Verify SchedulerService load_schedules and translation job add/remove contracts.\n# @RELATION BINDS_TO -> [SchedulerService]\n# @TEST_EDGE: load_schedules_reloads — jobs survive remove_all_jobs when re-registered from DB\n# @TEST_EDGE: add_remove_translation_job — job correctly registered and removed from APScheduler\n# @TEST_INVARIANT: translation_jobs_persist_across_reload -> VERIFIED_BY: [test_load_schedules_reloads_translation_schedules]\n\nimport sys\nfrom pathlib import Path\n\nsys.path.insert(0, str(Path(__file__).parent.parent / \"src\"))\n\nfrom unittest.mock import MagicMock, patch\n\nfrom apscheduler.schedulers.background import BackgroundScheduler\n\n# ---------------------------------------------------------------------------\n# Helpers — fresh scheduler & mock config\n# ---------------------------------------------------------------------------\n\ndef _make_mock_config_manager(backup_env_id=\"env1\", backup_cron=\"0 3 * * *\"):\n \"\"\"Build a mock ConfigManager returning a single backup-enabled environment.\"\"\"\n mgr = MagicMock()\n mock_env = MagicMock()\n mock_env.id = backup_env_id\n mock_env.backup_schedule = MagicMock()\n mock_env.backup_schedule.enabled = True\n mock_env.backup_schedule.cron_expression = backup_cron\n mock_config = MagicMock()\n mock_config.environments = [mock_env]\n mgr.get_config.return_value = mock_config\n return mgr\n\n\ndef _make_mock_task_manager():\n \"\"\"Build a mock TaskManager returning no active tasks.\"\"\"\n tm = MagicMock()\n tm.get_tasks.return_value = []\n return tm\n\n\n# ---------------------------------------------------------------------------\n# Fixture helpers — start/stop a real BackgroundScheduler\n# ---------------------------------------------------------------------------\n\ndef _start_scheduler():\n \"\"\"Create and start a BackgroundScheduler. Returns the scheduler instance.\"\"\"\n sched = BackgroundScheduler()\n sched.start()\n return sched\n\n\ndef _stop_scheduler(sched):\n \"\"\"Shutdown a BackgroundScheduler if running.\"\"\"\n if sched.running:\n sched.shutdown(wait=False)\n\n\n# #region test_load_schedules_reloads_translation_schedules [C:1] [TYPE Function]\ndef test_load_schedules_reloads_translation_schedules():\n \"\"\"Verify load_schedules re-registers translation jobs after remove_all_jobs.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a translation job (simulates what happens before reload)\n svc.add_translation_job(\n schedule_id=\"sched-1\",\n job_id=\"job-1\",\n cron_expression=\"0 2 * * *\",\n )\n\n # Verify it exists BEFORE reload\n job_before = sched.get_job(\"translate_sched-1\")\n assert job_before is not None, \"Translation job should exist before reload\"\n\n # Mock the DB query that load_schedules uses internally\n mock_schedule = MagicMock()\n mock_schedule.id = \"sched-1\"\n mock_schedule.job_id = \"job-1\"\n mock_schedule.cron_expression = \"0 2 * * *\"\n mock_schedule.timezone = \"UTC\"\n mock_schedule.execution_mode = \"full\"\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.all.return_value = [mock_schedule]\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.load_schedules()\n\n # After reload, the translation job should STILL exist\n job_after = sched.get_job(\"translate_sched-1\")\n assert job_after is not None, (\n \"Translation job should survive load_schedules (re-registered from DB)\"\n )\n\n # Backup job should also exist (added from config)\n backup_job = sched.get_job(\"backup_env1\")\n assert backup_job is not None, \"Backup job should be registered by load_schedules\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_load_schedules_reloads_translation_schedules\n\n\n# #region test_add_and_remove_translation_job [C:1] [TYPE Function]\ndef test_add_and_remove_translation_job():\n \"\"\"Verify add_translation_job registers and remove_translation_job removes.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should NOT exist before add\n assert sched.get_job(\"translate_sched-x\") is None\n\n svc.add_translation_job(\n schedule_id=\"sched-x\",\n job_id=\"job-x\",\n cron_expression=\"*/5 * * * *\",\n )\n\n # Should exist after add\n job = sched.get_job(\"translate_sched-x\")\n assert job is not None, \"Translation job should be registered after add\"\n assert job.id == \"translate_sched-x\"\n\n svc.remove_translation_job(\"sched-x\")\n\n # Should NOT exist after remove\n assert sched.get_job(\"translate_sched-x\") is None, (\n \"Translation job should be removed after remove_translation_job\"\n )\n finally:\n _stop_scheduler(sched)\n# #endregion test_add_and_remove_translation_job\n\n\n# #region test_remove_nonexistent_translation_job_no_error [C:1] [TYPE Function]\ndef test_remove_nonexistent_translation_job_no_error():\n \"\"\"Verify remove_translation_job handles non-existent job silently.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should not raise — silent ignore\n svc.remove_translation_job(\"nonexistent-sched\")\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_nonexistent_translation_job_no_error\n\n\n# #endregion TestCoreScheduler\n" + "body": "# #region TestCoreScheduler [C:3] [TYPE Module] [SEMANTICS test, scheduler, apscheduler, load, reload]\n# @BRIEF Verify SchedulerService load_schedules and translation job add/remove contracts.\n# @RELATION BINDS_TO -> [SchedulerService]\n# @TEST_EDGE: load_schedules_reloads — jobs survive remove_all_jobs when re-registered from DB\n# @TEST_EDGE: add_remove_translation_job — job correctly registered and removed from APScheduler\n# @TEST_INVARIANT: translation_jobs_persist_across_reload -> VERIFIED_BY: [test_load_schedules_reloads_translation_schedules]\n\nimport asyncio\nfrom datetime import time\nfrom pathlib import Path\nimport sys\n\nsys.path.insert(0, str(Path(__file__).parent.parent / \"src\"))\n\nfrom unittest.mock import MagicMock, patch\n\nfrom apscheduler.schedulers.background import BackgroundScheduler\n\n# ---------------------------------------------------------------------------\n# Helpers — fresh scheduler & mock config\n# ---------------------------------------------------------------------------\n\ndef _make_mock_config_manager(backup_env_id=\"env1\", backup_cron=\"0 3 * * *\"):\n \"\"\"Build a mock ConfigManager returning a single backup-enabled environment.\"\"\"\n mgr = MagicMock()\n mock_env = MagicMock()\n mock_env.id = backup_env_id\n mock_env.backup_schedule = MagicMock()\n mock_env.backup_schedule.enabled = True\n mock_env.backup_schedule.cron_expression = backup_cron\n mock_config = MagicMock()\n mock_config.environments = [mock_env]\n mgr.get_config.return_value = mock_config\n return mgr\n\n\ndef _make_mock_task_manager():\n \"\"\"Build a mock TaskManager returning no active tasks.\"\"\"\n tm = MagicMock()\n tm.get_tasks.return_value = []\n return tm\n\n\n# ---------------------------------------------------------------------------\n# Fixture helpers — start/stop a real BackgroundScheduler\n# ---------------------------------------------------------------------------\n\ndef _start_scheduler():\n \"\"\"Create and start a BackgroundScheduler. Returns the scheduler instance.\"\"\"\n sched = BackgroundScheduler()\n sched.start()\n return sched\n\n\ndef _stop_scheduler(sched):\n \"\"\"Shutdown a BackgroundScheduler if running.\"\"\"\n if sched.running:\n sched.shutdown(wait=False)\n\n\n# #region test_load_schedules_reloads_translation_schedules [C:1] [TYPE Function]\ndef test_load_schedules_reloads_translation_schedules():\n \"\"\"Verify load_schedules re-registers translation jobs after remove_all_jobs.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a translation job (simulates what happens before reload)\n svc.add_translation_job(\n schedule_id=\"sched-1\",\n job_id=\"job-1\",\n cron_expression=\"0 2 * * *\",\n )\n\n # Verify it exists BEFORE reload\n job_before = sched.get_job(\"translate_sched-1\")\n assert job_before is not None, \"Translation job should exist before reload\"\n\n # Mock the DB query that load_schedules uses internally\n mock_schedule = MagicMock()\n mock_schedule.id = \"sched-1\"\n mock_schedule.job_id = \"job-1\"\n mock_schedule.cron_expression = \"0 2 * * *\"\n mock_schedule.timezone = \"UTC\"\n mock_schedule.execution_mode = \"full\"\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.all.return_value = [mock_schedule]\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.load_schedules()\n\n # After reload, the translation job should STILL exist\n job_after = sched.get_job(\"translate_sched-1\")\n assert job_after is not None, (\n \"Translation job should survive load_schedules (re-registered from DB)\"\n )\n\n # Backup job should also exist (added from config)\n backup_job = sched.get_job(\"backup_env1\")\n assert backup_job is not None, \"Backup job should be registered by load_schedules\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_load_schedules_reloads_translation_schedules\n\n\n# #region test_add_and_remove_translation_job [C:1] [TYPE Function]\ndef test_add_and_remove_translation_job():\n \"\"\"Verify add_translation_job registers and remove_translation_job removes.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should NOT exist before add\n assert sched.get_job(\"translate_sched-x\") is None\n\n svc.add_translation_job(\n schedule_id=\"sched-x\",\n job_id=\"job-x\",\n cron_expression=\"*/5 * * * *\",\n )\n\n # Should exist after add\n job = sched.get_job(\"translate_sched-x\")\n assert job is not None, \"Translation job should be registered after add\"\n assert job.id == \"translate_sched-x\"\n\n svc.remove_translation_job(\"sched-x\")\n\n # Should NOT exist after remove\n assert sched.get_job(\"translate_sched-x\") is None, (\n \"Translation job should be removed after remove_translation_job\"\n )\n finally:\n _stop_scheduler(sched)\n# #endregion test_add_and_remove_translation_job\n\n\n# #region test_remove_nonexistent_translation_job_no_error [C:1] [TYPE Function]\ndef test_remove_nonexistent_translation_job_no_error():\n \"\"\"Verify remove_translation_job handles non-existent job silently.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should not raise — silent ignore\n svc.remove_translation_job(\"nonexistent-sched\")\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_nonexistent_translation_job_no_error\n\n\n# #region test_add_validation_job [C:1] [TYPE Function]\ndef test_add_validation_job():\n \"\"\"Verify add_validation_job registers an APScheduler job.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n assert sched.get_job(\"validation_pol-1\") is None\n\n svc.add_validation_job(\n policy_id=\"pol-1\",\n cron_expression=\"30 10 * * 0,2,4\", # 10:30 Mon, Wed, Fri\n app_timezone=\"Europe/Moscow\",\n )\n\n job = sched.get_job(\"validation_pol-1\")\n assert job is not None, \"Validation job should be registered after add\"\n assert job.id == \"validation_pol-1\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_add_validation_job\n\n\n# #region test_load_schedules_loads_validation_policies [C:1] [TYPE Function]\ndef test_load_schedules_loads_validation_policies():\n \"\"\"Verify load_schedules re-registers validation jobs from DB.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n # Add app_timezone to config so cron gets a timezone\n cfg.get_config.return_value.settings.app_timezone = \"Europe/Moscow\"\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a validation job (to test it survives reload)\n svc.add_validation_job(\n policy_id=\"pol-1\",\n cron_expression=\"0 10 * * 1,3,5\",\n )\n assert sched.get_job(\"validation_pol-1\") is not None\n\n # Mock DB to return an active ValidationPolicy with schedule_days\n mock_policy = MagicMock()\n mock_policy.id = \"pol-1\"\n mock_policy.schedule_days = [0, 2, 4] # Mon, Wed, Fri\n mock_policy.window_start = time(10, 30)\n mock_policy.window_end = time(11, 0)\n\n mock_db = MagicMock()\n # First query is for TranslationSchedule (empty), second is ValidationPolicy\n mock_db.query.side_effect = [\n MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[])))),\n MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[mock_policy])))),\n ]\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.load_schedules()\n\n # Validation job should still exist after reload\n job = sched.get_job(\"validation_pol-1\")\n assert job is not None, \"Validation job should survive load_schedules\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_load_schedules_loads_validation_policies\n\n\n# #region test_trigger_validation_creates_tasks [C:1] [TYPE Function]\ndef test_trigger_validation_creates_tasks():\n \"\"\"Verify _trigger_validation creates TaskManager tasks for each dashboard.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n # Mock the ValidationPolicy DB query\n mock_policy = MagicMock()\n mock_policy.id = \"pol-1\"\n mock_policy.is_active = True\n mock_policy.dashboard_ids = [\"dash-1\", \"dash-2\"]\n mock_policy.environment_id = \"ss-dev\"\n mock_policy.provider_id = \"prov-1\"\n mock_policy.window_start = time(10, 0)\n mock_policy.window_end = time(10, 30)\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n # Patch asyncio.run_coroutine_threadsafe to call the function synchronously\n # so we can verify the mock was called\n captured_calls = []\n\n def fake_run_coro(_coro_or_fn, _loop):\n captured_calls.append(1)\n return MagicMock()\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db), \\\n patch(\"src.core.scheduler.asyncio.run_coroutine_threadsafe\", side_effect=fake_run_coro):\n svc._trigger_validation(\"pol-1\")\n\n # Should have submitted 2 coroutines via run_coroutine_threadsafe (one per dashboard)\n assert len(captured_calls) == 2, (\n f\"Expected 2 task submissions via run_coroutine_threadsafe, got {len(captured_calls)}\"\n )\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_creates_tasks\n\n\n# #region test_trigger_validation_skips_missing_policy [C:1] [TYPE Function]\ndef test_trigger_validation_skips_missing_policy():\n \"\"\"Verify _trigger_validation does not fail when policy is missing.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n # Mock DB to return None (policy not found)\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = None\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n # Should not raise\n svc._trigger_validation(\"nonexistent-policy\")\n\n # create_task should not have been called\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_missing_policy\n\n\n# #region test_trigger_validation_skips_inactive_policy [C:1] [TYPE Function]\ndef test_trigger_validation_skips_inactive_policy():\n \"\"\"Verify _trigger_validation skips an inactive policy.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n mock_policy = MagicMock()\n mock_policy.id = \"pol-inactive\"\n mock_policy.is_active = False\n mock_policy.dashboard_ids = [\"dash-1\"]\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc._trigger_validation(\"pol-inactive\")\n\n # create_task should not have been called for inactive policy\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_inactive_policy\n\n\n# #region test_trigger_validation_skips_no_dashboards [C:1] [TYPE Function]\ndef test_trigger_validation_skips_no_dashboards():\n \"\"\"Verify _trigger_validation skips a policy with no dashboards.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n mock_policy = MagicMock()\n mock_policy.id = \"pol-empty\"\n mock_policy.is_active = True\n mock_policy.dashboard_ids = []\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc._trigger_validation(\"pol-empty\")\n\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_no_dashboards\n\n\n# #region test_remove_validation_job [C:1] [TYPE Function]\ndef test_remove_validation_job():\n \"\"\"Verify remove_validation_job removes an existing job.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n svc.add_validation_job(\"pol-remove\", cron_expression=\"0 10 * * 1\")\n assert sched.get_job(\"validation_pol-remove\") is not None\n\n svc.remove_validation_job(\"pol-remove\")\n assert sched.get_job(\"validation_pol-remove\") is None\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_validation_job\n\n\n# #region test_remove_nonexistent_validation_job [C:1] [TYPE Function]\ndef test_remove_nonexistent_validation_job():\n \"\"\"Verify remove_validation_job handles non-existent job silently.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should not raise\n svc.remove_validation_job(\"nonexistent-pol\")\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_nonexistent_validation_job\n\n\n# #region test_reload_validation_policy_adds_job [C:1] [TYPE Function]\ndef test_reload_validation_policy_adds_job():\n \"\"\"Verify reload_validation_policy registers a job for an active policy with schedule.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Mock DB to return an active policy with schedule_days\n mock_policy = MagicMock()\n mock_policy.id = \"pol-reload\"\n mock_policy.is_active = True\n mock_policy.schedule_days = [0, 2, 4]\n mock_policy.window_start = time(10, 30)\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.reload_validation_policy(\"pol-reload\")\n\n job = sched.get_job(\"validation_pol-reload\")\n assert job is not None, \"Job should be registered after reload\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_reload_validation_policy_adds_job\n\n\n# #region test_reload_validation_policy_removes_job_when_policy_gone [C:1] [TYPE Function]\ndef test_reload_validation_policy_removes_job_when_policy_gone():\n \"\"\"Verify reload_validation_policy removes job when policy is missing or inactive.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a job\n svc.add_validation_job(\"pol-gone\", cron_expression=\"0 10 * * 1\")\n assert sched.get_job(\"validation_pol-gone\") is not None\n\n # Mock DB to return None (policy not found)\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = None\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.reload_validation_policy(\"pol-gone\")\n\n # Job should have been removed\n assert sched.get_job(\"validation_pol-gone\") is None\n finally:\n _stop_scheduler(sched)\n# #endregion test_reload_validation_policy_removes_job_when_policy_gone\n# #endregion TestCoreScheduler\n" }, { "contract_id": "test_load_schedules_reloads_translation_schedules", "contract_type": "Function", "file_path": "backend/tests/test_core_scheduler.py", - "start_line": 59, - "end_line": 110, + "start_line": 61, + "end_line": 112, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -56675,8 +59920,8 @@ "contract_id": "test_add_and_remove_translation_job", "contract_type": "Function", "file_path": "backend/tests/test_core_scheduler.py", - "start_line": 113, - "end_line": 150, + "start_line": 115, + "end_line": 152, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -56692,8 +59937,8 @@ "contract_id": "test_remove_nonexistent_translation_job_no_error", "contract_type": "Function", "file_path": "backend/tests/test_core_scheduler.py", - "start_line": 153, - "end_line": 172, + "start_line": 155, + "end_line": 174, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -56705,6 +59950,176 @@ "tier_source": "AutoCalculated", "body": "# #region test_remove_nonexistent_translation_job_no_error [C:1] [TYPE Function]\ndef test_remove_nonexistent_translation_job_no_error():\n \"\"\"Verify remove_translation_job handles non-existent job silently.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should not raise — silent ignore\n svc.remove_translation_job(\"nonexistent-sched\")\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_nonexistent_translation_job_no_error\n" }, + { + "contract_id": "test_add_validation_job", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 177, + "end_line": 205, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_add_validation_job [C:1] [TYPE Function]\ndef test_add_validation_job():\n \"\"\"Verify add_validation_job registers an APScheduler job.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n assert sched.get_job(\"validation_pol-1\") is None\n\n svc.add_validation_job(\n policy_id=\"pol-1\",\n cron_expression=\"30 10 * * 0,2,4\", # 10:30 Mon, Wed, Fri\n app_timezone=\"Europe/Moscow\",\n )\n\n job = sched.get_job(\"validation_pol-1\")\n assert job is not None, \"Validation job should be registered after add\"\n assert job.id == \"validation_pol-1\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_add_validation_job\n" + }, + { + "contract_id": "test_load_schedules_loads_validation_policies", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 208, + "end_line": 254, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_load_schedules_loads_validation_policies [C:1] [TYPE Function]\ndef test_load_schedules_loads_validation_policies():\n \"\"\"Verify load_schedules re-registers validation jobs from DB.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n # Add app_timezone to config so cron gets a timezone\n cfg.get_config.return_value.settings.app_timezone = \"Europe/Moscow\"\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a validation job (to test it survives reload)\n svc.add_validation_job(\n policy_id=\"pol-1\",\n cron_expression=\"0 10 * * 1,3,5\",\n )\n assert sched.get_job(\"validation_pol-1\") is not None\n\n # Mock DB to return an active ValidationPolicy with schedule_days\n mock_policy = MagicMock()\n mock_policy.id = \"pol-1\"\n mock_policy.schedule_days = [0, 2, 4] # Mon, Wed, Fri\n mock_policy.window_start = time(10, 30)\n mock_policy.window_end = time(11, 0)\n\n mock_db = MagicMock()\n # First query is for TranslationSchedule (empty), second is ValidationPolicy\n mock_db.query.side_effect = [\n MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[])))),\n MagicMock(filter=MagicMock(return_value=MagicMock(all=MagicMock(return_value=[mock_policy])))),\n ]\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.load_schedules()\n\n # Validation job should still exist after reload\n job = sched.get_job(\"validation_pol-1\")\n assert job is not None, \"Validation job should survive load_schedules\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_load_schedules_loads_validation_policies\n" + }, + { + "contract_id": "test_trigger_validation_creates_tasks", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 257, + "end_line": 304, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_validation_creates_tasks [C:1] [TYPE Function]\ndef test_trigger_validation_creates_tasks():\n \"\"\"Verify _trigger_validation creates TaskManager tasks for each dashboard.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n # Mock the ValidationPolicy DB query\n mock_policy = MagicMock()\n mock_policy.id = \"pol-1\"\n mock_policy.is_active = True\n mock_policy.dashboard_ids = [\"dash-1\", \"dash-2\"]\n mock_policy.environment_id = \"ss-dev\"\n mock_policy.provider_id = \"prov-1\"\n mock_policy.window_start = time(10, 0)\n mock_policy.window_end = time(10, 30)\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n # Patch asyncio.run_coroutine_threadsafe to call the function synchronously\n # so we can verify the mock was called\n captured_calls = []\n\n def fake_run_coro(_coro_or_fn, _loop):\n captured_calls.append(1)\n return MagicMock()\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db), \\\n patch(\"src.core.scheduler.asyncio.run_coroutine_threadsafe\", side_effect=fake_run_coro):\n svc._trigger_validation(\"pol-1\")\n\n # Should have submitted 2 coroutines via run_coroutine_threadsafe (one per dashboard)\n assert len(captured_calls) == 2, (\n f\"Expected 2 task submissions via run_coroutine_threadsafe, got {len(captured_calls)}\"\n )\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_creates_tasks\n" + }, + { + "contract_id": "test_trigger_validation_skips_missing_policy", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 307, + "end_line": 335, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_validation_skips_missing_policy [C:1] [TYPE Function]\ndef test_trigger_validation_skips_missing_policy():\n \"\"\"Verify _trigger_validation does not fail when policy is missing.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n # Mock DB to return None (policy not found)\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = None\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n # Should not raise\n svc._trigger_validation(\"nonexistent-policy\")\n\n # create_task should not have been called\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_missing_policy\n" + }, + { + "contract_id": "test_trigger_validation_skips_inactive_policy", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 338, + "end_line": 369, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_validation_skips_inactive_policy [C:1] [TYPE Function]\ndef test_trigger_validation_skips_inactive_policy():\n \"\"\"Verify _trigger_validation skips an inactive policy.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n mock_policy = MagicMock()\n mock_policy.id = \"pol-inactive\"\n mock_policy.is_active = False\n mock_policy.dashboard_ids = [\"dash-1\"]\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc._trigger_validation(\"pol-inactive\")\n\n # create_task should not have been called for inactive policy\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_inactive_policy\n" + }, + { + "contract_id": "test_trigger_validation_skips_no_dashboards", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 372, + "end_line": 402, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_trigger_validation_skips_no_dashboards [C:1] [TYPE Function]\ndef test_trigger_validation_skips_no_dashboards():\n \"\"\"Verify _trigger_validation skips a policy with no dashboards.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n svc.loop = asyncio.new_event_loop()\n\n mock_policy = MagicMock()\n mock_policy.id = \"pol-empty\"\n mock_policy.is_active = True\n mock_policy.dashboard_ids = []\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc._trigger_validation(\"pol-empty\")\n\n assert tm.create_task.call_count == 0\n finally:\n _stop_scheduler(sched)\n# #endregion test_trigger_validation_skips_no_dashboards\n" + }, + { + "contract_id": "test_remove_validation_job", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 405, + "end_line": 427, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_remove_validation_job [C:1] [TYPE Function]\ndef test_remove_validation_job():\n \"\"\"Verify remove_validation_job removes an existing job.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n svc.add_validation_job(\"pol-remove\", cron_expression=\"0 10 * * 1\")\n assert sched.get_job(\"validation_pol-remove\") is not None\n\n svc.remove_validation_job(\"pol-remove\")\n assert sched.get_job(\"validation_pol-remove\") is None\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_validation_job\n" + }, + { + "contract_id": "test_remove_nonexistent_validation_job", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 430, + "end_line": 449, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_remove_nonexistent_validation_job [C:1] [TYPE Function]\ndef test_remove_nonexistent_validation_job():\n \"\"\"Verify remove_validation_job handles non-existent job silently.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Should not raise\n svc.remove_validation_job(\"nonexistent-pol\")\n finally:\n _stop_scheduler(sched)\n# #endregion test_remove_nonexistent_validation_job\n" + }, + { + "contract_id": "test_reload_validation_policy_adds_job", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 452, + "end_line": 484, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_reload_validation_policy_adds_job [C:1] [TYPE Function]\ndef test_reload_validation_policy_adds_job():\n \"\"\"Verify reload_validation_policy registers a job for an active policy with schedule.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Mock DB to return an active policy with schedule_days\n mock_policy = MagicMock()\n mock_policy.id = \"pol-reload\"\n mock_policy.is_active = True\n mock_policy.schedule_days = [0, 2, 4]\n mock_policy.window_start = time(10, 30)\n\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = mock_policy\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.reload_validation_policy(\"pol-reload\")\n\n job = sched.get_job(\"validation_pol-reload\")\n assert job is not None, \"Job should be registered after reload\"\n finally:\n _stop_scheduler(sched)\n# #endregion test_reload_validation_policy_adds_job\n" + }, + { + "contract_id": "test_reload_validation_policy_removes_job_when_policy_gone", + "contract_type": "Function", + "file_path": "backend/tests/test_core_scheduler.py", + "start_line": 487, + "end_line": 517, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_reload_validation_policy_removes_job_when_policy_gone [C:1] [TYPE Function]\ndef test_reload_validation_policy_removes_job_when_policy_gone():\n \"\"\"Verify reload_validation_policy removes job when policy is missing or inactive.\"\"\"\n from src.core.scheduler import SchedulerService\n\n sched = _start_scheduler()\n try:\n cfg = _make_mock_config_manager()\n tm = _make_mock_task_manager()\n\n svc = SchedulerService.__new__(SchedulerService)\n svc.task_manager = tm\n svc.config_manager = cfg\n svc.scheduler = sched\n\n # Pre-register a job\n svc.add_validation_job(\"pol-gone\", cron_expression=\"0 10 * * 1\")\n assert sched.get_job(\"validation_pol-gone\") is not None\n\n # Mock DB to return None (policy not found)\n mock_db = MagicMock()\n mock_db.query.return_value.filter.return_value.first.return_value = None\n\n with patch(\"src.core.scheduler.SessionLocal\", return_value=mock_db):\n svc.reload_validation_policy(\"pol-gone\")\n\n # Job should have been removed\n assert sched.get_job(\"validation_pol-gone\") is None\n finally:\n _stop_scheduler(sched)\n# #endregion test_reload_validation_policy_removes_job_when_policy_gone\n" + }, { "contract_id": "TestDashboardsApi", "contract_type": "Module", @@ -57187,6 +60602,168 @@ "tier_source": "AutoCalculated", "body": " # #region test_deprecation_comment_exists [C:2] [TYPE Function]\n # @BRIEF The source module documents the @DEPRECATED rationale in the region header.\n def test_deprecation_comment_exists(self):\n \"\"\"Verify the source file documents the is_multimodal_model deprecation.\n\n The @DEPRECATED tag is in the region header (line 127), not in the function body.\n inspect.getsource(function) only returns the body (lines 137-167).\n \"\"\"\n module_path = Path(__file__).parent.parent / \"src\" / \"services\" / \"llm_prompt_templates.py\"\n source = module_path.read_text(encoding=\"utf-8\")\n assert \"DEPRECATED\" in source, \"Source must document @DEPRECATED status\"\n assert \"is_multimodal_model is deprecated\" in source.lower() or \"deprecated\" in source.lower()\n # #endregion test_deprecation_comment_exists\n" }, + { + "contract_id": "test_layout_utils", + "contract_type": "TestModule", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 1, + "end_line": 55, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Contract tests for layout utility functions — _estimate_markdown_height." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_layout_utils [C:3] [TYPE TestModule] [SEMANTICS test, layout, superset, height, estimation]\n# @BRIEF Contract tests for layout utility functions — _estimate_markdown_height.\n# Verifies the height estimation formula: empty → 19, short text → computed,\n# padding accounted for, and long text capped at 200.\n# @LAYER Test\n# @RELATION BINDS_TO -> [LayoutUtils]\n# @TEST_CONTRACT: _estimate_markdown_height(str) -> int in [19, 200]\n# @TEST_EDGE: empty_content -> returns minimum height (19)\n# @TEST_EDGE: html_only_content -> returns minimum height (19)\n# @TEST_EDGE: content_with_padding -> padding:12 correctly increases height\n# @TEST_EDGE: very_long_content -> capped at maximum height (200)\nimport pytest\n\nfrom src.core.superset_client._layout_utils import _estimate_markdown_height\n\n\nclass TestEstimateMarkdownHeight:\n \"\"\"Tests for _estimate_markdown_height pure function.\"\"\"\n\n # #region test_empty_content [C:2] [TYPE Function]\n # @BRIEF Empty string returns minimum height 19.\n def test_empty_content(self):\n assert _estimate_markdown_height(\"\") == 19\n # #endregion test_empty_content\n\n # #region test_single_line_text [C:2] [TYPE Function]\n # @BRIEF Short text without padding returns expected computed height.\n # 200 chars → 200//40+1 = 6 lines → 6*22 = 132px → 40+132 = 172px → 172//8 = 21\n def test_single_line_text(self):\n text = \"A\" * 200\n assert _estimate_markdown_height(text) == 21\n # #endregion test_single_line_text\n\n # #region test_content_with_padding [C:2] [TYPE Function]\n # @BRIEF Content with padding:12 — 24px added to content height.\n # 200 chars + padding:12 → 6*22 + 24 = 156 → 40+156 = 196 → 196//8 = 24\n def test_content_with_padding(self):\n content = '
' + \"A\" * 200 + \"
\"\n assert _estimate_markdown_height(content) == 24\n # #endregion test_content_with_padding\n\n # #region test_very_long_content [C:2] [TYPE Function]\n # @BRIEF Very long content (3000 chars) capped at max height 200.\n def test_very_long_content(self):\n text = \"A\" * 3000\n assert _estimate_markdown_height(text) == 200\n # #endregion test_very_long_content\n\n # #region test_html_only_content [C:2] [TYPE Function]\n # @BRIEF HTML-only content (no visible text) returns minimum height 19.\n def test_html_only_content(self):\n content = \"

\"\n assert _estimate_markdown_height(content) == 19\n # #endregion test_html_only_content\n# #endregion test_layout_utils\n" + }, + { + "contract_id": "test_empty_content", + "contract_type": "Function", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 20, + "end_line": 24, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Empty string returns minimum height 19." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_empty_content [C:2] [TYPE Function]\n # @BRIEF Empty string returns minimum height 19.\n def test_empty_content(self):\n assert _estimate_markdown_height(\"\") == 19\n # #endregion test_empty_content\n" + }, + { + "contract_id": "test_single_line_text", + "contract_type": "Function", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 26, + "end_line": 32, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Short text without padding returns expected computed height." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_single_line_text [C:2] [TYPE Function]\n # @BRIEF Short text without padding returns expected computed height.\n # 200 chars → 200//40+1 = 6 lines → 6*22 = 132px → 40+132 = 172px → 172//8 = 21\n def test_single_line_text(self):\n text = \"A\" * 200\n assert _estimate_markdown_height(text) == 21\n # #endregion test_single_line_text\n" + }, + { + "contract_id": "test_content_with_padding", + "contract_type": "Function", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 34, + "end_line": 40, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Content with padding:12 — 24px added to content height." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_content_with_padding [C:2] [TYPE Function]\n # @BRIEF Content with padding:12 — 24px added to content height.\n # 200 chars + padding:12 → 6*22 + 24 = 156 → 40+156 = 196 → 196//8 = 24\n def test_content_with_padding(self):\n content = '
' + \"A\" * 200 + \"
\"\n assert _estimate_markdown_height(content) == 24\n # #endregion test_content_with_padding\n" + }, + { + "contract_id": "test_very_long_content", + "contract_type": "Function", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 42, + "end_line": 47, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Very long content (3000 chars) capped at max height 200." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_very_long_content [C:2] [TYPE Function]\n # @BRIEF Very long content (3000 chars) capped at max height 200.\n def test_very_long_content(self):\n text = \"A\" * 3000\n assert _estimate_markdown_height(text) == 200\n # #endregion test_very_long_content\n" + }, + { + "contract_id": "test_html_only_content", + "contract_type": "Function", + "file_path": "backend/tests/test_layout_utils.py", + "start_line": 49, + "end_line": 54, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "HTML-only content (no visible text) returns minimum height 19." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_html_only_content [C:2] [TYPE Function]\n # @BRIEF HTML-only content (no visible text) returns minimum height 19.\n def test_html_only_content(self):\n content = \"

\"\n assert _estimate_markdown_height(content) == 19\n # #endregion test_html_only_content\n" + }, { "contract_id": "test_log_persistence", "contract_type": "Module", @@ -58012,6 +61589,906 @@ "tier_source": "AutoCalculated", "body": " # #region test_plugin_loader_logger_calls_exist [C:2] [TYPE Function]\n # @BRIEF plugin_loader.py references logger.error/warning/info in its code.\n def test_plugin_loader_logger_calls_exist(self):\n code = self.PLUGIN_LOADER_PATH.read_text(encoding=\"utf-8\")\n tree = ast.parse(code, filename=str(self.PLUGIN_LOADER_PATH))\n\n logger_calls = []\n for node in ast.walk(tree):\n if (isinstance(node, ast.Call)\n and isinstance(node.func, ast.Attribute)\n and isinstance(node.func.value, ast.Name)\n and \"logger\" in node.func.value.id.lower()):\n logger_calls.append((node.lineno, node.func.attr))\n\n error_levels = {\"error\", \"warning\", \"info\", \"debug\", \"reason\", \"reflect\", \"explore\"}\n matching = [call for call in logger_calls if call[1] in error_levels]\n assert len(matching) >= 4, (\n f\"plugin_loader.py has only {len(matching)} logger.error/warning/info calls \"\n f\"(expected at least 4 for the 4 replaced print() statements): {matching}\"\n )\n # #endregion test_plugin_loader_logger_calls_exist\n" }, + { + "contract_id": "test_maintenance_api", + "contract_type": "TestModule", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 1, + "end_line": 474, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Contract tests for Maintenance Banner API endpoints — T016, T025." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_maintenance_api [C:3] [TYPE TestModule] [SEMANTICS test, maintenance, api, fastapi, pytest]\n# @BRIEF Contract tests for Maintenance Banner API endpoints — T016, T025.\n# Tests POST /start, POST /{id}/end, POST /end-all, GET /events, GET /dashboard-banners,\n# GET /settings, PUT /settings.\n# @LAYER Test\n# @RELATION BINDS_TO -> [MaintenanceRoutesModule]\n# @TEST_CONTRACT: POST /api/maintenance/start -> 202 {task_id, maintenance_id, status}\n# @TEST_CONTRACT: POST /api/maintenance/{id}/end -> 202 {task_id, status}\n# @TEST_CONTRACT: POST /api/maintenance/end-all -> 202 {task_id, status}\n# @TEST_EDGE: missing_tables -> 422 validation error\n# @TEST_EDGE: end_time_before_start_time -> 400 validation error\n# @TEST_EDGE: non_existent_event_end -> 404 not found\nimport json\nimport os\nimport uuid\nfrom datetime import datetime, timezone, timedelta\nfrom typing import Any\nfrom unittest.mock import AsyncMock, MagicMock, patch, PropertyMock\n\nimport pytest\nfrom fastapi import status\n\n# Patch GitService at module level to prevent /app/storage/repositories error\n# This patches the base module BEFORE any imports can reach it\nimport sys\nfrom unittest.mock import MagicMock\n\n_mock_git_svc_cls = MagicMock()\n_mock_git_svc_cls.return_value = MagicMock()\nsys.modules['src.services.git._base'] = MagicMock(GitService=_mock_git_svc_cls)\nsys.modules['src.services.git_service'] = MagicMock(GitService=_mock_git_svc_cls)\n\n\n# ── Fixtures ──────────────────────────────────────────────────\n\n@pytest.fixture\ndef client():\n \"\"\"Create a TestClient with all dependencies mocked.\"\"\"\n from fastapi.testclient import TestClient\n from src.app import app\n return TestClient(app)\n\n\n@pytest.fixture(autouse=True)\ndef auth_mock(client, mock_db):\n \"\"\"Create a valid API key with maintenance permissions and mock JWT user.\"\"\"\n from src.core.auth.api_key import generate_api_key\n from src.models.api_key import APIKey\n from src.dependencies import get_current_user\n from src.app import app\n\n # Create API key for mutation endpoints\n raw, prefix, key_hash = generate_api_key()\n api_key = APIKey(\n key_hash=key_hash,\n prefix=prefix,\n name=\"Test API Key\",\n permissions=[\"maintenance:start\", \"maintenance:end\", \"maintenance:end_all\"],\n active=True,\n )\n mock_db.add(api_key)\n mock_db.commit()\n\n client.headers.update({\"X-API-Key\": raw})\n\n # Mock JWT user for read-only endpoints\n mock_role = MagicMock()\n mock_role.name = \"Admin\"\n mock_role.permissions = []\n\n mock_user = MagicMock()\n mock_user.username = \"test-admin\"\n mock_user.roles = [mock_role]\n\n async def _mock_get_current_user():\n return mock_user\n\n app.dependency_overrides[get_current_user] = _mock_get_current_user\n\n yield\n\n client.headers.pop(\"X-API-Key\", None)\n app.dependency_overrides = {}\n\n\n@pytest.fixture\ndef mock_db():\n \"\"\"Patch get_db dependency to return a clean in-memory session.\n \n Uses StaticPool so all Session() instances share the same connection,\n preventing SQLite threading issues where each :memory: connection\n creates a separate database.\n Creates all tables on the shared Base.metadata.\n \"\"\"\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker, Session as SASession\n from sqlalchemy.pool import StaticPool\n from src.models.mapping import Base\n from src.dependencies import get_db\n from src.models.maintenance import MaintenanceSettings, DashboardScope\n\n # StaticPool ensures all sessions share the same in-memory connection\n engine = create_engine(\n \"sqlite:///:memory:\",\n poolclass=StaticPool,\n connect_args={\"check_same_thread\": False},\n echo=False,\n )\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n\n # Create default settings\n settings = MaintenanceSettings(\n id=\"default\",\n target_environment_id=\"test-env\",\n display_timezone=\"UTC\",\n banner_template=\"Test: {message} ({start_time}-{end_time})\",\n dashboard_scope=DashboardScope.PUBLISHED_ONLY,\n excluded_dashboard_ids=[],\n forced_dashboard_ids=[],\n )\n session.add(settings)\n session.commit()\n\n def _get_db_override():\n db = Session()\n try:\n yield db\n finally:\n db.close()\n\n from src.app import app\n app.dependency_overrides[get_db] = _get_db_override\n yield session\n app.dependency_overrides.pop(get_db, None)\n session.close()\n\n\n@pytest.fixture\ndef mock_task_manager():\n \"\"\"Patch get_task_manager to return a mock.\"\"\"\n from src.dependencies import get_task_manager\n\n mock_tm = MagicMock()\n mock_task = MagicMock()\n mock_task.id = \"test-task-id-123\"\n mock_tm.create_task = AsyncMock(return_value=mock_task)\n\n from src.app import app\n app.dependency_overrides[get_task_manager] = lambda: mock_tm\n yield mock_tm\n app.dependency_overrides.pop(get_task_manager, None)\n\n\n# ── T016: POST /api/maintenance/start ─────────────────────────\n\nclass TestStartEndpoint:\n \"\"\"Contract tests for POST /api/maintenance/start.\"\"\"\n\n # #region test_start_returns_202 [C:2] [TYPE Function]\n # @BRIEF Valid request returns 202 with task_id and maintenance_id.\n def test_start_returns_202(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"message\": \"Test maintenance\",\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n assert \"maintenance_id\" in data\n assert data[\"status\"] == \"pending\"\n # #endregion test_start_returns_202\n\n # #region test_start_missing_tables [C:2] [TYPE Function]\n # @BRIEF Missing tables field returns 422.\n def test_start_missing_tables(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n },\n )\n assert response.status_code == 422\n # #endregion test_start_missing_tables\n\n # #region test_start_end_time_before_start [C:2] [TYPE Function]\n # @BRIEF end_time before start_time returns 400.\n def test_start_end_time_before_start(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 400\n # #endregion test_start_end_time_before_start\n\n # #region test_start_too_many_tables [C:2] [TYPE Function]\n # @BRIEF More than 100 tables returns 422 (Pydantic validation).\n def test_start_too_many_tables(self, client, mock_db, mock_task_manager):\n tables = [f\"raw.table{i}\" for i in range(101)]\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": tables,\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 422\n # #endregion test_start_too_many_tables\n\n # #region test_start_idempotency [C:2] [TYPE Function]\n # @BRIEF Same (tables, start, end) returns already_active.\n def test_start_idempotency(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n payload = {\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"environment_id\": \"test-env\",\n }\n\n # First call creates event\n response1 = client.post(\"/api/maintenance/start\", json=payload)\n assert response1.status_code == 202\n\n # Manually set event to ACTIVE so idempotency check finds it\n maintenance_id = response1.json()[\"maintenance_id\"]\n event = mock_db.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == maintenance_id\n ).first()\n if event:\n event.status = MaintenanceEventStatus.ACTIVE\n mock_db.commit()\n\n # Second call with same params — idempotent\n response2 = client.post(\"/api/maintenance/start\", json=payload)\n assert response2.status_code == 202\n data = response2.json()\n # Should have maintenance_id and status\n assert data.get(\"maintenance_id\") or data.get(\"status\")\n # #endregion test_start_idempotency\n\n\n# ── T025: POST /api/maintenance/{id}/end ──────────────────────\n\nclass TestEndEndpoint:\n \"\"\"Contract tests for POST /api/maintenance/{id}/end.\"\"\"\n\n # #region test_end_returns_202 [C:2] [TYPE Function]\n # @BRIEF Valid maintenance_id returns 202.\n def test_end_returns_202(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.post(f\"/api/maintenance/{event.id}/end\")\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n # #endregion test_end_returns_202\n\n # #region test_end_not_found [C:2] [TYPE Function]\n # @BRIEF Non-existent maintenance_id returns 404.\n def test_end_not_found(self, client, mock_db, mock_task_manager):\n response = client.post(\"/api/maintenance/nonexistent-id/end\")\n assert response.status_code == 404\n # #endregion test_end_not_found\n\n\n# ── POST /api/maintenance/end-all ─────────────────────────────\n\nclass TestEndAllEndpoint:\n \"\"\"Contract tests for POST /api/maintenance/end-all.\"\"\"\n\n # #region test_end_all_returns_202 [C:2] [TYPE Function]\n # @BRIEF end-all returns 202.\n def test_end_all_returns_202(self, client, mock_db, mock_task_manager):\n response = client.post(\"/api/maintenance/end-all\")\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n assert data[\"status\"] == \"pending\"\n # #endregion test_end_all_returns_202\n\n\n# ── GET /api/maintenance/events ───────────────────────────────\n\nclass TestEventsEndpoint:\n \"\"\"Contract tests for GET /api/maintenance/events.\"\"\"\n\n # #region test_list_events [C:2] [TYPE Function]\n # @BRIEF Returns active and completed events.\n def test_list_events(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n active = MaintenanceEvent(\n tables=[\"raw.active\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(active)\n\n completed = MaintenanceEvent(\n tables=[\"raw.done\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.COMPLETED,\n environment_id=\"test-env\",\n )\n mock_db.add(completed)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n data = response.json()\n assert \"active\" in data\n assert \"completed\" in data\n # #endregion test_list_events\n\n # #region test_expired_event_auto_ends [C:2] [TYPE Function]\n # @BRIEF Event past end_time with ACTIVE status → create_task called with auto-end params.\n def test_expired_event_auto_ends(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) - timedelta(hours=2),\n end_time=datetime.now(timezone.utc) - timedelta(hours=1),\n message=\"Expired maintenance\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_called_once_with(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": event.id,\n \"environment_id\": \"test-env\",\n \"user\": \"system\",\n },\n )\n # #endregion test_expired_event_auto_ends\n\n # #region test_future_end_time_skipped [C:2] [TYPE Function]\n # @BRIEF Event with future end_time → no task created, skipped by < now filter.\n def test_future_end_time_skipped(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) + timedelta(hours=1),\n end_time=datetime.now(timezone.utc) + timedelta(hours=3),\n message=\"Future maintenance\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_not_called()\n # #endregion test_future_end_time_skipped\n\n # #region test_no_end_time_skipped [C:2] [TYPE Function]\n # @BRIEF Event with end_time=None → no task created, skipped by isnot(None) filter.\n def test_no_end_time_skipped(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) - timedelta(hours=2),\n end_time=None,\n message=\"No end time\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_not_called()\n # #endregion test_no_end_time_skipped\n\n\n# ── GET /api/maintenance/dashboard-banners ────────────────────\n\nclass TestDashboardBannersEndpoint:\n \"\"\"Contract tests for GET /api/maintenance/dashboard-banners.\"\"\"\n\n # #region test_list_banners [C:2] [TYPE Function]\n # @BRIEF Returns list of active banners.\n def test_list_banners(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import (\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n )\n\n banner = MaintenanceDashboardBanner(\n environment_id=\"test-env\",\n dashboard_id=101,\n chart_id=12345,\n banner_text=\"Test\",\n status=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n mock_db.add(banner)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/dashboard-banners\")\n assert response.status_code == 200\n data = response.json()\n assert isinstance(data, list)\n # #endregion test_list_banners\n\n\n# ── GET /api/maintenance/settings ─────────────────────────────\n\nclass TestSettingsEndpoint:\n \"\"\"Contract tests for GET/PUT /api/maintenance/settings.\"\"\"\n\n # #region test_get_settings [C:2] [TYPE Function]\n # @BRIEF GET returns settings.\n def test_get_settings(self, client, mock_db, mock_task_manager):\n response = client.get(\"/api/maintenance/settings\")\n assert response.status_code == 200\n data = response.json()\n assert \"target_environment_id\" in data\n assert data[\"target_environment_id\"] == \"test-env\"\n # #endregion test_get_settings\n\n # #region test_put_settings [C:2] [TYPE Function]\n # @BRIEF PUT updates settings.\n def test_put_settings(self, client, mock_db, mock_task_manager):\n response = client.put(\n \"/api/maintenance/settings\",\n json={\"display_timezone\": \"Europe/Moscow\"},\n )\n assert response.status_code == 200\n data = response.json()\n assert data[\"display_timezone\"] == \"Europe/Moscow\"\n # #endregion test_put_settings\n# #endregion test_maintenance_api\n" + }, + { + "contract_id": "test_start_returns_202", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 161, + "end_line": 179, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Valid request returns 202 with task_id and maintenance_id." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_start_returns_202 [C:2] [TYPE Function]\n # @BRIEF Valid request returns 202 with task_id and maintenance_id.\n def test_start_returns_202(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"message\": \"Test maintenance\",\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n assert \"maintenance_id\" in data\n assert data[\"status\"] == \"pending\"\n # #endregion test_start_returns_202\n" + }, + { + "contract_id": "test_start_missing_tables", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 181, + "end_line": 191, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Missing tables field returns 422." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_start_missing_tables [C:2] [TYPE Function]\n # @BRIEF Missing tables field returns 422.\n def test_start_missing_tables(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n },\n )\n assert response.status_code == 422\n # #endregion test_start_missing_tables\n" + }, + { + "contract_id": "test_start_end_time_before_start", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 193, + "end_line": 206, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "end_time before start_time returns 400." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_start_end_time_before_start [C:2] [TYPE Function]\n # @BRIEF end_time before start_time returns 400.\n def test_start_end_time_before_start(self, client, mock_db, mock_task_manager):\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 400\n # #endregion test_start_end_time_before_start\n" + }, + { + "contract_id": "test_start_too_many_tables", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 208, + "end_line": 221, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "More than 100 tables returns 422 (Pydantic validation)." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_start_too_many_tables [C:2] [TYPE Function]\n # @BRIEF More than 100 tables returns 422 (Pydantic validation).\n def test_start_too_many_tables(self, client, mock_db, mock_task_manager):\n tables = [f\"raw.table{i}\" for i in range(101)]\n response = client.post(\n \"/api/maintenance/start\",\n json={\n \"tables\": tables,\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"environment_id\": \"test-env\",\n },\n )\n assert response.status_code == 422\n # #endregion test_start_too_many_tables\n" + }, + { + "contract_id": "test_start_idempotency", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 223, + "end_line": 254, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Same (tables, start, end) returns already_active." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_start_idempotency [C:2] [TYPE Function]\n # @BRIEF Same (tables, start, end) returns already_active.\n def test_start_idempotency(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n payload = {\n \"tables\": [\"raw.sales\"],\n \"start_time\": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),\n \"end_time\": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),\n \"environment_id\": \"test-env\",\n }\n\n # First call creates event\n response1 = client.post(\"/api/maintenance/start\", json=payload)\n assert response1.status_code == 202\n\n # Manually set event to ACTIVE so idempotency check finds it\n maintenance_id = response1.json()[\"maintenance_id\"]\n event = mock_db.query(MaintenanceEvent).filter(\n MaintenanceEvent.id == maintenance_id\n ).first()\n if event:\n event.status = MaintenanceEventStatus.ACTIVE\n mock_db.commit()\n\n # Second call with same params — idempotent\n response2 = client.post(\"/api/maintenance/start\", json=payload)\n assert response2.status_code == 202\n data = response2.json()\n # Should have maintenance_id and status\n assert data.get(\"maintenance_id\") or data.get(\"status\")\n # #endregion test_start_idempotency\n" + }, + { + "contract_id": "test_end_returns_202", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 262, + "end_line": 280, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Valid maintenance_id returns 202." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_end_returns_202 [C:2] [TYPE Function]\n # @BRIEF Valid maintenance_id returns 202.\n def test_end_returns_202(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.post(f\"/api/maintenance/{event.id}/end\")\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n # #endregion test_end_returns_202\n" + }, + { + "contract_id": "test_end_not_found", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 282, + "end_line": 287, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Non-existent maintenance_id returns 404." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_end_not_found [C:2] [TYPE Function]\n # @BRIEF Non-existent maintenance_id returns 404.\n def test_end_not_found(self, client, mock_db, mock_task_manager):\n response = client.post(\"/api/maintenance/nonexistent-id/end\")\n assert response.status_code == 404\n # #endregion test_end_not_found\n" + }, + { + "contract_id": "test_end_all_returns_202", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 295, + "end_line": 303, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "end-all returns 202." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_end_all_returns_202 [C:2] [TYPE Function]\n # @BRIEF end-all returns 202.\n def test_end_all_returns_202(self, client, mock_db, mock_task_manager):\n response = client.post(\"/api/maintenance/end-all\")\n assert response.status_code == 202\n data = response.json()\n assert \"task_id\" in data\n assert data[\"status\"] == \"pending\"\n # #endregion test_end_all_returns_202\n" + }, + { + "contract_id": "test_list_events", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 311, + "end_line": 338, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Returns active and completed events." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_list_events [C:2] [TYPE Function]\n # @BRIEF Returns active and completed events.\n def test_list_events(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n\n active = MaintenanceEvent(\n tables=[\"raw.active\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(active)\n\n completed = MaintenanceEvent(\n tables=[\"raw.done\"],\n start_time=datetime.now(timezone.utc),\n status=MaintenanceEventStatus.COMPLETED,\n environment_id=\"test-env\",\n )\n mock_db.add(completed)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n data = response.json()\n assert \"active\" in data\n assert \"completed\" in data\n # #endregion test_list_events\n" + }, + { + "contract_id": "test_expired_event_auto_ends", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 340, + "end_line": 369, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Event past end_time with ACTIVE status → create_task called with auto-end params." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_expired_event_auto_ends [C:2] [TYPE Function]\n # @BRIEF Event past end_time with ACTIVE status → create_task called with auto-end params.\n def test_expired_event_auto_ends(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) - timedelta(hours=2),\n end_time=datetime.now(timezone.utc) - timedelta(hours=1),\n message=\"Expired maintenance\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_called_once_with(\n plugin_id=\"maintenance_banner_apply\",\n params={\n \"operation\": \"end\",\n \"event_id\": event.id,\n \"environment_id\": \"test-env\",\n \"user\": \"system\",\n },\n )\n # #endregion test_expired_event_auto_ends\n" + }, + { + "contract_id": "test_future_end_time_skipped", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 371, + "end_line": 392, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Event with future end_time → no task created, skipped by < now filter." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_future_end_time_skipped [C:2] [TYPE Function]\n # @BRIEF Event with future end_time → no task created, skipped by < now filter.\n def test_future_end_time_skipped(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) + timedelta(hours=1),\n end_time=datetime.now(timezone.utc) + timedelta(hours=3),\n message=\"Future maintenance\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_not_called()\n # #endregion test_future_end_time_skipped\n" + }, + { + "contract_id": "test_no_end_time_skipped", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 394, + "end_line": 415, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Event with end_time=None → no task created, skipped by isnot(None) filter." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_no_end_time_skipped [C:2] [TYPE Function]\n # @BRIEF Event with end_time=None → no task created, skipped by isnot(None) filter.\n def test_no_end_time_skipped(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus\n from datetime import timedelta\n\n event = MaintenanceEvent(\n tables=[\"raw.sales\"],\n start_time=datetime.now(timezone.utc) - timedelta(hours=2),\n end_time=None,\n message=\"No end time\",\n status=MaintenanceEventStatus.ACTIVE,\n environment_id=\"test-env\",\n )\n mock_db.add(event)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/events\")\n assert response.status_code == 200\n\n mock_task_manager.create_task.assert_not_called()\n # #endregion test_no_end_time_skipped\n" + }, + { + "contract_id": "test_list_banners", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 423, + "end_line": 445, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Returns list of active banners." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_list_banners [C:2] [TYPE Function]\n # @BRIEF Returns list of active banners.\n def test_list_banners(self, client, mock_db, mock_task_manager):\n from src.models.maintenance import (\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n )\n\n banner = MaintenanceDashboardBanner(\n environment_id=\"test-env\",\n dashboard_id=101,\n chart_id=12345,\n banner_text=\"Test\",\n status=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n mock_db.add(banner)\n mock_db.commit()\n\n response = client.get(\"/api/maintenance/dashboard-banners\")\n assert response.status_code == 200\n data = response.json()\n assert isinstance(data, list)\n # #endregion test_list_banners\n" + }, + { + "contract_id": "test_get_settings", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 453, + "end_line": 461, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "GET returns settings." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_get_settings [C:2] [TYPE Function]\n # @BRIEF GET returns settings.\n def test_get_settings(self, client, mock_db, mock_task_manager):\n response = client.get(\"/api/maintenance/settings\")\n assert response.status_code == 200\n data = response.json()\n assert \"target_environment_id\" in data\n assert data[\"target_environment_id\"] == \"test-env\"\n # #endregion test_get_settings\n" + }, + { + "contract_id": "test_put_settings", + "contract_type": "Function", + "file_path": "backend/tests/test_maintenance_api.py", + "start_line": 463, + "end_line": 473, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "PUT updates settings." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " # #region test_put_settings [C:2] [TYPE Function]\n # @BRIEF PUT updates settings.\n def test_put_settings(self, client, mock_db, mock_task_manager):\n response = client.put(\n \"/api/maintenance/settings\",\n json={\"display_timezone\": \"Europe/Moscow\"},\n )\n assert response.status_code == 200\n data = response.json()\n assert data[\"display_timezone\"] == \"Europe/Moscow\"\n # #endregion test_put_settings\n" + }, + { + "contract_id": "test_maintenance_service", + "contract_type": "TestModule", + "file_path": "backend/tests/test_maintenance_service.py", + "start_line": 1, + "end_line": 622, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Integration tests for MaintenanceService — T018, T026, T026a." + }, + "relations": [], + "schema_warnings": [ + { + "code": "tag_not_for_contract_type", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "COMPLEXITY", + "message": "@COMPLEXITY is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "PURPOSE", + "message": "@PURPOSE is not allowed for contract type 'TestModule'", + "detail": { + "actual_type": "TestModule", + "allowed_types": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "PURPOSE", + "message": "@PURPOSE is forbidden for contract type 'TestModule' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "TestModule" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "# #region test_maintenance_service [C:3] [TYPE TestModule] [SEMANTICS test, maintenance, service, pytest, integration]\n# @BRIEF Integration tests for MaintenanceService — T018, T026, T026a.\n# Tests the C3/C4 orchestrators: start_maintenance, end_maintenance, end_all_maintenance,\n# and helpers: find_affected_dashboards, ensure_banner_chart, build_banner_text, rebuild_banner.\n# @LAYER Test\n# @RELATION BINDS_TO -> [MaintenanceServiceModule]\n# @TEST_CONTRACT: start_maintenance(str, Session, SupersetClient) -> dict\n# @TEST_CONTRACT: end_maintenance(str, Session, SupersetClient) -> dict\n# @TEST_CONTRACT: end_all_maintenance(Session, SupersetClient) -> dict\n# @TEST_EDGE: event_not_found -> returns failed status with error message\n# @TEST_EDGE: no_matching_dashboards -> returns \"no_match\" status\n# @TEST_EDGE: superset_api_failure -> returns partial/failed with error details\nimport uuid\nfrom datetime import datetime, timezone\nfrom typing import Any, cast\nfrom unittest.mock import MagicMock, patch, PropertyMock\n\nimport pytest\n\nfrom src.models.maintenance import (\n DashboardScope,\n MaintenanceDashboardBanner,\n MaintenanceDashboardBannerStatus,\n MaintenanceDashboardState,\n MaintenanceDashboardStateStatus,\n MaintenanceEvent,\n MaintenanceEventStatus,\n MaintenanceSettings,\n)\nfrom src.services.maintenance import (\n build_banner_text,\n build_idempotency_key,\n end_all_maintenance,\n end_maintenance,\n ensure_banner_chart,\n find_affected_dashboards,\n rebuild_banner,\n start_maintenance,\n)\n\n\n# ── Fixtures ──────────────────────────────────────────────────\n\n@pytest.fixture\ndef mock_superset():\n \"\"\"Create a mock SupersetClient for testing.\"\"\"\n client = MagicMock()\n # Default: no datasets\n client.get_datasets.return_value = (0, [])\n client.get_dashboards.return_value = (0, [])\n client.get_dataset_detail.return_value = {\"linked_dashboards\": []}\n client.create_markdown_chart.return_value = 12345\n client.get_chart.return_value = {\"id\": 12345, \"result\": {\"viz_type\": \"markdown\"}}\n client.update_banner_on_dashboard.return_value = {\"result\": \"ok\"}\n client.update_dashboard_layout.return_value = {\"result\": \"ok\"}\n client.remove_chart_from_layout.return_value = {\"result\": \"ok\"}\n client.delete_chart.return_value = {\"result\": \"ok\"}\n return client\n\n\n@pytest.fixture\ndef db_session():\n \"\"\"Create an in-memory SQLite session with tables.\"\"\"\n from sqlalchemy import create_engine\n from sqlalchemy.orm import sessionmaker\n from src.models.mapping import Base\n\n engine = create_engine(\"sqlite:///:memory:\", echo=False)\n Base.metadata.create_all(engine)\n Session = sessionmaker(bind=engine)\n session = Session()\n\n # Create default settings\n settings = MaintenanceSettings(\n id=\"default\",\n target_environment_id=\"test-env\",\n display_timezone=\"UTC\",\n banner_template=\"Maintenance: {message} ({start_time} - {end_time})\",\n dashboard_scope=DashboardScope.PUBLISHED_ONLY,\n excluded_dashboard_ids=[],\n forced_dashboard_ids=[],\n )\n session.add(settings)\n session.commit()\n return session\n\n\n@pytest.fixture\ndef pending_event(db_session):\n \"\"\"Create a PENDING maintenance event in the DB.\"\"\"\n event = MaintenanceEvent(\n tables=[\"raw.sales\", \"raw.inventory\"],\n start_time=datetime.now(timezone.utc),\n end_time=datetime.now(timezone.utc),\n message=\"Test maintenance\",\n status=MaintenanceEventStatus.PENDING,\n environment_id=\"test-env\",\n )\n db_session.add(event)\n db_session.commit()\n return event\n\n\n# ── T017: build_idempotency_key tests ─────────────────────────\n\nclass TestBuildIdempotencyKey:\n \"\"\"Tests for build_idempotency_key helper.\"\"\"\n\n # #region test_basic_key [C:2] [TYPE Function]\n # @BRIEF Basic idempotency key with tables and times.\n def test_basic_key(self):\n tables = [\"raw.sales\", \"RAW.INVENTORY\"]\n start = datetime(2026, 5, 21, 22, 0, 0, tzinfo=timezone.utc)\n end = datetime(2026, 5, 22, 2, 0, 0, tzinfo=timezone.utc)\n key = build_idempotency_key(tables, start, end)\n assert key[0] == frozenset({\"raw.inventory\", \"raw.sales\"})\n assert key[1] == \"2026-05-21T22:00:00+00:00\"\n assert key[2] == \"2026-05-22T02:00:00+00:00\"\n # #endregion test_basic_key\n\n # #region test_key_without_end_time [C:2] [TYPE Function]\n # @BRIEF Idempotency key with None end_time.\n def test_key_without_end_time(self):\n tables = [\"raw.sales\"]\n start = datetime(2026, 5, 21, 22, 0, 0, tzinfo=timezone.utc)\n key = build_idempotency_key(tables, start, None)\n assert key[0] == frozenset({\"raw.sales\"})\n assert key[1] == \"2026-05-21T22:00:00+00:00\"\n assert key[2] is None\n # #endregion test_key_without_end_time\n\n # #region test_key_table_sorting [C:2] [TYPE Function]\n # @BRIEF Tables are sorted alphabetically in frozenset.\n def test_key_table_sorting(self):\n key1 = build_idempotency_key([\"z.table\", \"a.table\"], None, None)\n key2 = build_idempotency_key([\"a.table\", \"z.table\"], None, None)\n assert key1 == key2\n # #endregion test_key_table_sorting\n\n\n# ── T019: find_affected_dashboards tests ──────────────────────\n\nclass TestFindAffectedDashboards:\n \"\"\"Tests for find_affected_dashboards.\"\"\"\n\n # #region test_empty_tables [C:2] [TYPE Function]\n # @BRIEF Empty tables list returns empty.\n def test_empty_tables(self, mock_superset):\n result = find_affected_dashboards([], mock_superset)\n assert result == []\n # #endregion test_empty_tables\n\n # #region test_table_based_match [C:2] [TYPE Function]\n # @BRIEF Table-based dataset matching.\n def test_table_based_match(self, mock_superset):\n mock_superset.get_datasets.return_value = (2, [\n {\"id\": 1, \"schema\": \"raw\", \"table_name\": \"sales\", \"sql\": None},\n {\"id\": 2, \"schema\": \"raw\", \"table_name\": \"inventory\", \"sql\": None},\n ])\n mock_superset.get_dataset_detail.side_effect = [\n {\"linked_dashboards\": [{\"id\": 101}]},\n {\"linked_dashboards\": [{\"id\": 102}]},\n ]\n\n result = find_affected_dashboards([\"raw.sales\"], mock_superset)\n assert 101 in result\n assert 102 not in result\n # #endregion test_table_based_match\n\n # #region test_virtual_dataset_match [C:2] [TYPE Function]\n # @BRIEF Virtual SQL dataset matching via SqlTableExtractor.\n def test_virtual_dataset_match(self, mock_superset):\n mock_superset.get_datasets.return_value = (1, [\n {\n \"id\": 1,\n \"schema\": \"raw\",\n \"table_name\": \"sales_view\",\n \"sql\": \"SELECT * FROM raw.sales\",\n \"is_sqllab_view\": True,\n },\n ])\n mock_superset.get_dataset_detail.return_value = {\n \"linked_dashboards\": [{\"id\": 101}],\n }\n\n result = find_affected_dashboards([\"raw.sales\"], mock_superset)\n assert 101 in result\n # #endregion test_virtual_dataset_match\n\n # #region test_case_insensitive_matching [C:2] [TYPE Function]\n # @BRIEF Matching is case-insensitive.\n def test_case_insensitive_matching(self, mock_superset):\n mock_superset.get_datasets.return_value = (1, [\n {\"id\": 1, \"schema\": \"RAW\", \"table_name\": \"SALES\", \"sql\": None},\n ])\n mock_superset.get_dataset_detail.return_value = {\n \"linked_dashboards\": [{\"id\": 101}],\n }\n\n result = find_affected_dashboards([\"raw.sales\"], mock_superset)\n assert 101 in result\n # #endregion test_case_insensitive_matching\n\n # #region test_superset_api_failure [C:2] [TYPE Function]\n # @BRIEF Superset API failure propagates.\n def test_superset_api_failure(self, mock_superset):\n mock_superset.get_datasets.side_effect = Exception(\"Superset API error\")\n with pytest.raises(Exception, match=\"Superset API error\"):\n find_affected_dashboards([\"raw.sales\"], mock_superset)\n # #endregion test_superset_api_failure\n\n\n# ── T019a: ensure_banner_chart tests ──────────────────────────\n\nclass TestEnsureBannerChart:\n \"\"\"Tests for ensure_banner_chart.\"\"\"\n\n # #region test_creates_new_banner [C:2] [TYPE Function]\n # @BRIEF No existing banner — creates new chart and banner row.\n def test_creates_new_banner(self, mock_superset, db_session):\n banner = ensure_banner_chart(\n 101, \"test-env\", mock_superset, db_session\n )\n assert banner.dashboard_id == 101\n assert banner.chart_id == 12345\n assert banner.status == MaintenanceDashboardBannerStatus.ACTIVE\n mock_superset.create_markdown_chart.assert_called_once_with(101, \"*Maintenance banner placeholder*\")\n mock_superset.update_dashboard_layout.assert_called_once_with(101, 12345)\n # #endregion test_creates_new_banner\n\n # #region test_returns_existing_banner [C:2] [TYPE Function]\n # @BRIEF Existing active banner — returns it.\n def test_returns_existing_banner(self, mock_superset, db_session):\n existing = MaintenanceDashboardBanner(\n environment_id=\"test-env\",\n dashboard_id=101,\n chart_id=999,\n banner_text=\"Existing\",\n status=MaintenanceDashboardBannerStatus.ACTIVE,\n )\n db_session.add(existing)\n db_session.commit()\n\n banner = ensure_banner_chart(\n 101, \"test-env\", mock_superset, db_session\n )\n assert banner.id == existing.id\n assert banner.chart_id == 999\n mock_superset.create_markdown_chart.assert_not_called()\n # #endregion test_returns_existing_banner\n\n # #region test_chart_creation_failure [C:2] [TYPE Function]\n # @BRIEF Chart creation failure propagates.\n def test_chart_creation_failure(self, mock_superset, db_session):\n mock_superset.create_markdown_chart.side_effect = Exception(\"Chart error\")\n with pytest.raises(Exception, match=\"Chart error\"):\n ensure_banner_chart(101, \"test-env\", mock_superset, db_session)\n # #endregion test_chart_creation_failure\n\n\n# ── T020: build_banner_text tests ─────────────────────────────\n\nclass TestBuildBannerText:\n \"\"\"Tests for build_banner_text.\"\"\"\n\n # #region test_single_event [C:2] [TYPE Function]\n # @BRIEF Single event — direct substitution.\n def test_single_event(self):\n events = [\n {\"start_time\": \"2026-05-21T22:00:00+00:00\",\n \"end_time\": \"2026-05-22T02:00:00+00:00\",\n \"message\": \"Updating tables\"}\n ]\n template = \"Banner: {message} ({start_time} - {end_time})\"\n result = build_banner_text(events, template)\n assert \"Updating tables\" in result\n assert \"2026-05-21 22:00\" in result\n assert \"2026-05-22 02:00\" in result\n # #endregion test_single_event\n\n # #region test_multiple_events [C:2] [TYPE Function]\n # @BRIEF Multiple events — combined message.\n def test_multiple_events(self):\n events = [\n {\"start_time\": \"2026-05-21T22:00:00+00:00\",\n \"end_time\": \"2026-05-22T02:00:00+00:00\",\n \"message\": \"Event 1\"},\n {\"start_time\": \"2026-05-23T22:00:00+00:00\",\n \"end_time\": \"2026-05-24T02:00:00+00:00\",\n \"message\": \"Event 2\"},\n ]\n template = \"Banner: {message} ({start_time} - {end_time})\"\n result = build_banner_text(events, template)\n assert \"Event 1\" in result\n assert \"Event 2\" in result\n # #endregion test_multiple_events\n\n # #region test_empty_events [C:2] [TYPE Function]\n # @BRIEF Empty events list returns empty string.\n def test_empty_events(self):\n result = build_banner_text([], \"Template: {message}\")\n assert result == \"\"\n # #endregion test_empty_events\n\n # #region test_missing_variables [C:2] [TYPE Function]\n # @BRIEF Missing variables replaced with empty string.\n def test_missing_variables(self):\n events = [{\"start_time\": None, \"end_time\": None, \"message\": \"Hi\"}]\n template = \"Start: {start_time} - End: {end_time} - Msg: {message}\"\n result = build_banner_text(events, template)\n assert \"уточняется\" in result\n assert \"Hi\" in result\n # #endregion test_missing_variables\n\n # #region test_html_escaping [C:2] [TYPE Function]\n # @BRIEF Message is HTML-escaped.\n def test_html_escaping(self):\n events = [{\n \"start_time\": \"2026-05-21T22:00:00+00:00\",\n \"end_time\": \"2026-05-22T02:00:00+00:00\",\n \"message\": \"\",\n }]\n template = \"{message}\"\n result = build_banner_text(events, template)\n assert \"\",\n }]\n template = \"{message}\"\n result = build_banner_text(events, template)\n assert \"\n\n
\n
\n

\n {$t.tasks?.recent }\n

\n
\n
\n \n \n
\n \n
\n \n {$t.common?.refresh }\n \n
\n
\n \n {#if loading && tasks.length === 0}\n
{$t.tasks?.loading }
\n {:else if error}\n
{error}
\n {:else if tasks.length === 0}\n
{$t.tasks?.no_tasks }
\n {:else}\n
    \n {#each tasks as task}\n
  • \n \n
  • \n {/each}\n
\n {/if}\n
\n\n" + "body": "\n\n\n\n\n\n
\n
\n

\n {$t.tasks?.recent }\n

\n
\n
\n \n \n
\n \n
\n \n {$t.common?.refresh }\n \n
\n
\n \n {#if loading && tasks.length === 0}\n
{$t.tasks?.loading }
\n {:else if error}\n
{error}
\n {:else if tasks.length === 0}\n
{$t.tasks?.no_tasks }
\n {:else}\n
    \n {#each tasks as task}\n
  • \n \n
  • \n {/each}\n
\n {/if}\n
\n\n" }, { "contract_id": "getStatusColor:Function", "contract_type": "Function", "file_path": "frontend/src/components/TaskHistory.svelte", - "start_line": 86, - "end_line": 100, + "start_line": 90, + "end_line": 104, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -64917,8 +70487,8 @@ "contract_id": "onDestroy:Function", "contract_type": "Function", "file_path": "frontend/src/components/TaskHistory.svelte", - "start_line": 112, - "end_line": 119, + "start_line": 116, + "end_line": 123, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -66280,7 +71850,7 @@ "contract_type": "Component", "file_path": "frontend/src/components/llm/ProviderConfig.svelte", "start_line": 1, - "end_line": 593, + "end_line": 592, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -66323,7 +71893,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n
\n
\n

{$t.llm.providers_title}

\n {\n resetForm();\n showForm = true;\n }}\n >\n {$t.llm.add_provider}\n \n
\n\n {#if showForm}\n \n
\n

\n {editingProvider ? $t.llm.edit_provider : $t.llm.new_provider}\n

\n\n
\n
\n {$t.llm.name}\n \n
\n\n
\n {$t.llm.type}\n updateBaseUrlForType(formData.provider_type)}\n class=\"mt-1 block w-full border rounded-md p-2\"\n >\n \n \n \n \n \n
\n\n
\n {$t.llm.base_url}\n
\n \n \n {isLoadingModels ? \"...\" : \"↻\"}\n \n
\n
\n\n
\n {$t.llm.api_key}\n {#if editingProvider && formData.api_key && isMaskedKey(formData.api_key)}\n
\n \n {formData.api_key}\n \n { formData.api_key = \"\"; }}\n >\n {$t.llm?.change_key || \"Change\"}\n \n
\n

\n {$t.llm?.key_masked_hint || \"Masked for security. Click \\\"Change\\\" to enter a new key.\"}\n

\n {:else}\n \n {/if}\n
\n\n
\n {$t.llm.default_model}\n\n {#if isLoadingModels}\n
\n \n {$t.llm.loading_models}\n
\n {:else if modelsLoadError}\n
{modelsLoadError}
\n {/if}\n\n {#if availableModels.length > 0 && !isLoadingModels}\n \n {#each availableModels as model}\n \n {/each}\n \n
\n {($t.llm.models_loaded || \"{count} models loaded\").replace(\"{count}\", availableModels.length)}\n
\n {:else}\n \n {/if}\n
\n\n
\n \n {$t.llm.active}\n
\n\n
\n \n \n {$t.llm.multimodal_checkbox}\n \n
\n
\n\n {#if testStatus.message}\n \n {testStatus.message}\n
\n {/if}\n\n
\n {\n showForm = false;\n }}\n >\n {$t.llm.cancel}\n \n \n {isTesting ? $t.llm.testing : $t.llm.test}\n \n \n {$t.llm.save}\n \n
\n
\n \n {/if}\n\n
\n {#each providers as provider}\n \n
\n
\n {provider.name}\n \n {provider.is_active ? $t.llm.active : \"Inactive\"}\n \n \n {provider.is_multimodal\n ? ($t.llm?.multimodal )\n : ($t.llm?.text_only )}\n \n
\n
\n {provider.provider_type} • {provider.default_model}\n
\n
\n
\n handleEdit(provider)}\n >\n {$t.common.edit}\n \n handleDelete(provider)}\n disabled={deletingProviderIds.has(provider.id)}\n >\n {#if deletingProviderIds.has(provider.id)}\n ...\n {:else}\n {$t.common.delete}\n {/if}\n \n toggleActive(provider)}\n disabled={togglingProviderIds.has(provider.id) || deletingProviderIds.has(provider.id)}\n >\n {#if togglingProviderIds.has(provider.id)}\n ...\n {:else}\n {provider.is_active ? \"Deactivate\" : \"Activate\"}\n {/if}\n \n
\n
\n {:else}\n \n {$t.llm.no_providers}\n \n {/each}\n \n\n\n\n" + "body": "\n\n\n\n\n\n\n
\n
\n

{$t.llm.providers_title}

\n {\n resetForm();\n showForm = true;\n }}\n >\n {$t.llm.add_provider}\n \n
\n\n {#if showForm}\n \n
\n

\n {editingProvider ? $t.llm.edit_provider : $t.llm.new_provider}\n

\n\n
\n
\n {$t.llm.name}\n \n
\n\n
\n {$t.llm.type}\n updateBaseUrlForType(formData.provider_type)}\n class=\"mt-1 block w-full border rounded-md p-2\"\n >\n \n \n \n \n \n
\n\n
\n {$t.llm.base_url}\n
\n \n \n {isLoadingModels ? \"...\" : \"↻\"}\n \n
\n
\n\n
\n {$t.llm.api_key}\n {#if editingProvider && formData.api_key && isMaskedKey(formData.api_key)}\n
\n \n {formData.api_key}\n \n { formData.api_key = \"\"; }}\n >\n {$t.llm?.change_key || \"Change\"}\n \n
\n

\n {$t.llm?.key_masked_hint || \"Masked for security. Click \\\"Change\\\" to enter a new key.\"}\n

\n {:else}\n \n {/if}\n
\n\n
\n {$t.llm.default_model}\n\n {#if isLoadingModels}\n
\n \n {$t.llm.loading_models}\n
\n {:else if modelsLoadError}\n
{modelsLoadError}
\n {/if}\n\n {#if availableModels.length > 0 && !isLoadingModels}\n \n {#each availableModels as model}\n \n {/each}\n \n
\n {($t.llm.models_loaded || \"{count} models loaded\").replace(\"{count}\", availableModels.length)}\n
\n {:else}\n \n {/if}\n
\n\n
\n \n {$t.llm.active}\n
\n\n
\n \n \n {$t.llm.multimodal_checkbox}\n \n
\n
\n\n {#if testStatus.message}\n \n {testStatus.message}\n
\n {/if}\n\n
\n {\n showForm = false;\n }}\n >\n {$t.llm.cancel}\n \n \n {isTesting ? $t.llm.testing : $t.llm.test}\n \n \n {$t.llm.save}\n \n
\n
\n \n {/if}\n\n
\n {#each providers as provider}\n \n
\n
\n {provider.name}\n \n {provider.is_active ? $t.llm.active : \"Inactive\"}\n \n \n {provider.is_multimodal\n ? ($t.llm?.multimodal )\n : ($t.llm?.text_only )}\n \n
\n
\n {provider.provider_type} • {provider.default_model}\n
\n
\n
\n handleEdit(provider)}\n >\n {$t.common.edit}\n \n handleDelete(provider)}\n disabled={deletingProviderIds.has(provider.id)}\n >\n {#if deletingProviderIds.has(provider.id)}\n ...\n {:else}\n {$t.common.delete}\n {/if}\n \n toggleActive(provider)}\n disabled={togglingProviderIds.has(provider.id) || deletingProviderIds.has(provider.id)}\n >\n {#if togglingProviderIds.has(provider.id)}\n ...\n {:else}\n {provider.is_active ? \"Deactivate\" : \"Activate\"}\n {/if}\n \n
\n
\n {:else}\n \n {$t.llm.no_providers}\n \n {/each}\n \n\n\n\n" }, { "contract_id": "ValidationReport", @@ -67200,7 +72770,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.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" + "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';\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 const protocol = typeof window !== 'undefined' && window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n const host = typeof window !== 'undefined' ? window.location.host : 'localhost:8000';\n return `${protocol}//${host}/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 // ── API Key Management ────────────────────────────────────\n listApiKeys: () => fetchApi('/admin/api-keys/'),\n createApiKey: (payload) => postApi('/admin/api-keys/', payload, { suppressToast: true }),\n revokeApiKey: (keyId) => requestApi(`/admin/api-keys/${keyId}`, 'DELETE'),\n};\n// #endregion ApiModule\n" }, { "contract_id": "ReportsApiTest", @@ -67802,6 +73372,156 @@ "tier_source": "AutoCalculated", "body": "// #region normalizeDatasetReviewDetail:Function [TYPE Function]\n// @PURPOSE: Normalize refreshed session-detail DTOs into the legacy route-friendly workspace shape.\n// @PRE: detail may already be legacy-flat or refreshed with nested session/session_version fields.\n// @POST: Returns a shape with flattened summary fields plus refreshed collections and version metadata.\nexport function normalizeDatasetReviewDetail(detail) {\n if (!detail) {\n return null;\n }\n\n if (!detail.session && detail.session_id) {\n return detail;\n }\n\n const summary = detail.session || {};\n const preview = detail.preview || null;\n\n return {\n ...summary,\n session_version:\n detail.session_version ?? summary.session_version ?? summary.version ?? null,\n version: detail.session_version ?? summary.session_version ?? summary.version ?? null,\n profile: detail.profile || null,\n findings: detail.findings || [],\n semantic_sources: detail.semantic_sources || [],\n semantic_fields: detail.semantic_fields || [],\n imported_filters: detail.filters || detail.imported_filters || [],\n template_variables: detail.template_variables || [],\n execution_mappings: detail.mappings || detail.execution_mappings || [],\n clarification: detail.clarification || null,\n clarification_sessions: detail.clarification\n ? [detail.clarification.clarification_session].filter(Boolean)\n : detail.clarification_sessions || [],\n previews: preview ? [preview] : detail.previews || [],\n preview,\n latest_run_context: detail.latest_run_context || null,\n };\n}\n// #endregion normalizeDatasetReviewDetail:Function\n" }, + { + "contract_id": "MaintenanceApi", + "contract_type": "Module", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 1, + "end_line": 69, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "LAYER": "Frontend", + "PURPOSE": "API client for Maintenance Banner endpoints. Uses requestApi for all calls." + }, + "relations": [ + { + "source_id": "MaintenanceApi", + "relation_type": "DEPENDS_ON", + "target_id": "requestApi", + "target_ref": "[requestApi]" + } + ], + "schema_warnings": [ + { + "code": "invalid_enum_value", + "tag": "LAYER", + "message": "@LAYER value 'Frontend' is not in allowed enum", + "detail": { + "allowed": [ + "Core", + "Domain", + "API", + "UI", + "Service", + "Infrastructure", + "Plugin", + "Tests" + ], + "value": "Frontend" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region MaintenanceApi [C:2] [TYPE Module] [SEMANTICS api, maintenance, rest, client]\n// @BRIEF API client for Maintenance Banner endpoints. Uses requestApi for all calls.\n// @LAYER Frontend\n// @RELATION DEPENDS_ON -> [requestApi]\n// @ADR-0007: Uses $effect(() => subscribe(...)) pattern, NOT fromStore + $derived.\n\nimport { requestApi } from \"$lib/api.js\";\n\nconst BASE = \"/maintenance\";\n\n/**\n * Start a maintenance event.\n * @param {object} params - { tables, start_time, end_time?, message? }\n * @returns {Promise} { task_id, maintenance_id, status }\n */\nexport async function startMaintenance(params) {\n return requestApi(`${BASE}/start`, \"POST\", params);\n}\n\n/**\n * End a specific maintenance event.\n * @param {string} maintenanceId\n * @returns {Promise} { task_id, status }\n */\nexport async function endMaintenance(maintenanceId) {\n return requestApi(`${BASE}/${maintenanceId}/end`, \"POST\");\n}\n\n/**\n * End all active maintenance events.\n * @returns {Promise} { task_id, status }\n */\nexport async function endAllMaintenance() {\n return requestApi(`${BASE}/end-all`, \"POST\");\n}\n\n/**\n * Get current settings.\n * @returns {Promise} MaintenanceSettingsResponse\n */\nexport async function getSettings() {\n return requestApi(`${BASE}/settings`, \"GET\");\n}\n\n/**\n * Update settings.\n * @param {object} settings\n * @returns {Promise} Updated MaintenanceSettingsResponse\n */\nexport async function updateSettings(settings) {\n return requestApi(`${BASE}/settings`, \"PUT\", settings);\n}\n\n/**\n * List events.\n * @returns {Promise} { active: [...], completed: [...] }\n */\nexport async function listEvents() {\n return requestApi(`${BASE}/events`, \"GET\");\n}\n\n/**\n * List dashboard banner states.\n * @returns {Promise} Array of { dashboard_id, active, events, start_time, end_time }\n */\nexport async function listDashboardBanners() {\n return requestApi(`${BASE}/dashboard-banners`, \"GET\");\n}\n// #endregion MaintenanceApi\n" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::startMaintenance", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 11, + "end_line": 16, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * Start a maintenance event.\n * @param {object} params - { tables, start_time, end_time?, message? }\n * @returns {Promise} { task_id, maintenance_id, status }\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::endMaintenance", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 20, + "end_line": 25, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * End a specific maintenance event.\n * @param {string} maintenanceId\n * @returns {Promise} { task_id, status }\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::endAllMaintenance", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 29, + "end_line": 33, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * End all active maintenance events.\n * @returns {Promise} { task_id, status }\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::getSettings", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 37, + "end_line": 41, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * Get current settings.\n * @returns {Promise} MaintenanceSettingsResponse\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::updateSettings", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 45, + "end_line": 50, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * Update settings.\n * @param {object} settings\n * @returns {Promise} Updated MaintenanceSettingsResponse\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::listEvents", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 54, + "end_line": 58, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * List events.\n * @returns {Promise} { active: [...], completed: [...] }\n */" + }, + { + "contract_id": "frontend/src/lib/api/maintenance.js::listDashboardBanners", + "contract_type": "Function", + "file_path": "frontend/src/lib/api/maintenance.js", + "start_line": 62, + "end_line": 66, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * List dashboard banner states.\n * @returns {Promise} Array of { dashboard_id, active, events, start_time, end_time }\n */" + }, { "contract_id": "ReportsApi", "contract_type": "Module", @@ -70988,6 +76708,74 @@ "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 Schedule Days\n
\n {#each days as day}\n \n {/each}\n
\n
\n
\n\n \n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n\n {#if formData.dashboard_ids.length > 0}\n
\n

\n 💡 System will automatically distribute {formData.dashboard_ids.length} checks within this {Math.floor(windowDurationMinutes() / 60)}h {windowDurationMinutes() % 60}m window.\n

\n {#if isWindowTooSmall}\n

\n ⚠️ Window might be too narrow for {formData.dashboard_ids.length} dashboards.\n

\n {/if}\n
\n {/if}\n\n
\n \n \n
\n\n
\n \n \n
\n
\n
\n\n
\n \n \n
\n
\n\n" }, + { + "contract_id": "ScheduleAtAGlance", + "contract_type": "Component", + "file_path": "frontend/src/lib/components/health/ScheduleAtAGlance.svelte", + "start_line": 1, + "end_line": 407, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "PURPOSE": "Compact weekly schedule widget showing active validation tasks with day grid, time windows, and cross-referenced health status.", + "TYPE": "{{ healthItems: Array<{task_id?: string, status: string}>, selectedEnvId?: string, appTimezone?: string }}", + "UX_FEEDBACK": "Click on policy row navigates to validation task edit page", + "UX_REACTIVITY": "Props -> healthItems, selectedEnvId. LocalState -> tasks, loading, error", + "UX_STATE": "Error -> Compact error banner with retry", + "UX_TEST": "Ready -> {mock: fetchTasks returns 1 task, expected: grid + policy list + nextUpcoming}" + }, + "relations": [ + { + "source_id": "ScheduleAtAGlance", + "relation_type": "CALLS", + "target_id": "ValidationApi.fetchTasks", + "target_ref": "[ValidationApi.fetchTasks]" + }, + { + "source_id": "ScheduleAtAGlance", + "relation_type": "DEPENDS_ON", + "target_id": "HealthCenterPage", + "target_ref": "[HealthCenterPage]" + }, + { + "source_id": "ScheduleAtAGlance", + "relation_type": "DEPENDS_ON", + "target_id": "i18n", + "target_ref": "[i18n]" + } + ], + "schema_warnings": [ + { + "code": "invalid_enum_value", + "tag": "TYPE", + "message": "@TYPE value '{{ healthItems: Array<{task_id?: string, status: string}>, selectedEnvId?: string, appTimezone?: string }}' is not in allowed enum", + "detail": { + "allowed": [ + "Module", + "Function", + "Class", + "Component", + "Block", + "ADR", + "Tombstone", + "Skill", + "Agent" + ], + "value": "{{ healthItems: Array<{task_id?: string, status: string}>, selectedEnvId?: string, appTimezone?: string }}" + } + }, + { + "code": "unknown_tag", + "tag": "UX_TEST", + "message": "@UX_TEST is not defined in axiom_config.yaml tags", + "detail": null + } + ], + "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 {$t.health?.schedule_title || 'Schedule'}\n

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

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

\n

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

\n
\n\n \n {:else}\n
\n
\n \n
\n
\n {#each DAY_SHORT as dayLabel, idx (idx)}\n {@const active = isDayActive(idx)}\n {@const dayTasks = getTasksForDay(idx)}\n t.id === hoveredTaskId) ? 'ring-2 ring-blue-300' : 'opacity-60') : ''}\"\n title={active ? `${dayTasks.length} task(s) on ${DAY_SHORT[idx]}` : ''}\n >\n \n {$t.validation?.[`days_${dayLabel}`] || dayLabel.toUpperCase()}\n \n {#if active}\n {#each dayTasks.slice(0, 2) as task (task.id)}\n {@const tc = getTaskColor(task)}\n \n {/each}\n {#if dayTasks.length > 2}\n +{dayTasks.length - 2}\n {/if}\n {/if}\n
\n {/each}\n
\n\n \n
\n \n \n \n {#if scheduledTasks.length === 1}\n {formatTimeRange(scheduledTasks[0].window_start, scheduledTasks[0].window_end)}\n {:else}\n {$t.health?.schedule_multi_time || 'Multiple windows'}\n {/if}\n ·\n {appTimezone}\n
\n
\n\n \n
\n
\n {#each scheduledTasks as task (task.id)}\n {@const status = getTaskStatus(task.id)}\n {@const tc = status ? getStatusStyle(status) : null}\n handleTaskClick(task.id)}\n onmouseenter={() => (hoveredTaskId = task.id)}\n onmouseleave={() => (hoveredTaskId = null)}\n class=\"w-full text-left flex items-center gap-3 px-3 py-2 rounded-lg border border-transparent hover:border-gray-200 hover:bg-gray-50 transition-all cursor-pointer group\"\n >\n \n \n\n \n
\n
\n {task.name}\n {#if task.environment_id}\n \n {task.environment_id}\n \n {/if}\n
\n
\n \n \n {#each DAY_SHORT as dayLabel, idx (idx)}\n {#if taskRunsOnDay(task, idx)}\n \n {$t.validation?.[`days_${dayLabel}`] || dayLabel.slice(0, 2).toUpperCase()}\n \n {:else}\n \n {dayLabel.slice(0, 1).toUpperCase()}\n \n {/if}\n {/each}\n \n ·\n {formatTimeRange(task.window_start, task.window_end)}\n ·\n \n {Array.isArray(task.dashboard_ids) ? task.dashboard_ids.length : 0} {$t.health?.schedule_dashboards || 'dashboards'}\n \n
\n
\n\n \n \n \n \n \n {/each}\n
\n\n \n {#if nextUpcoming}\n
\n
\n \n \n \n {$t.health?.schedule_next || 'Next'}:\n {nextUpcoming.task.name}\n ·\n \n {formatNextDay(nextUpcoming.dayIdx)} {nextUpcoming.timeStr?.slice(0, 5)} {appTimezone}\n \n
\n
\n {/if}\n
\n
\n \n {/if}\n\n\n" + }, { "contract_id": "Sidebar", "contract_type": "Component", @@ -71546,7 +77334,7 @@ "contract_type": "Function", "file_path": "frontend/src/lib/components/layout/sidebarNavigation.js", "start_line": 1, - "end_line": 217, + "end_line": 229, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -71601,7 +77389,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: \"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" + "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 id: \"maintenance\",\n label: nav.maintenance || \"Maintenance\",\n icon: \"activity\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/maintenance\",\n requiredPermission: \"maintenance:write\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.maintenance || \"Maintenance\", path: \"/maintenance\", requiredPermission: \"maintenance:write\", 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", @@ -71642,7 +77430,7 @@ "contract_type": "Function", "file_path": "frontend/src/lib/components/layout/sidebarNavigation.js", "start_line": 32, - "end_line": 209, + "end_line": 221, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -71654,7 +77442,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: \"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" + "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 id: \"maintenance\",\n label: nav.maintenance || \"Maintenance\",\n icon: \"activity\",\n tone: \"from-orange-100 to-orange-200 text-orange-700 ring-orange-200\",\n path: \"/maintenance\",\n requiredPermission: \"maintenance:write\",\n requiredAction: \"READ\",\n subItems: [\n { label: nav.maintenance || \"Maintenance\", path: \"/maintenance\", requiredPermission: \"maintenance:write\", 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", @@ -72214,6 +78002,71 @@ "tier_source": "AutoCalculated", "body": "// #region getReportTypeProfile:Function [TYPE Function]\n// @PURPOSE: Resolve visual profile by task type with guaranteed fallback.\n// @PRE: taskType may be known/unknown/empty.\n// @POST: Returns one profile object.\n//\n// @TEST_CONTRACT: GetReportTypeProfileModel ->\n// {\n// required_fields: {taskType: string},\n// invariants: [\n// \"Returns correct profile for known taskType\",\n// \"Returns 'unknown' profile for invalid or missing taskType\"\n// ]\n// }\n// @TEST_FIXTURE: valid_type -> {\"taskType\": \"migration\"}\n// @TEST_EDGE: invalid_type -> {\"taskType\": \"invalid\"}\n// @TEST_INVARIANT: fallbacks_to_unknown -> verifies: [invalid_type]\nexport function getReportTypeProfile(taskType) {\n const key = typeof taskType === 'string' ? taskType : 'unknown';\n console.log(\"[reports][ui][getReportTypeProfile][STATE:START]\");\n console.log(\"[reports][ui][getReportTypeProfile] Resolved type '\" + taskType + \"' to profile '\" + key + \"'\");\n return REPORT_TYPE_PROFILES[key] || REPORT_TYPE_PROFILES.unknown;\n}\n// #endregion getReportTypeProfile:Function\n" }, + { + "contract_id": "ApiKeysTab", + "contract_type": "Component", + "file_path": "frontend/src/lib/components/settings/ApiKeysTab.svelte", + "start_line": 1, + "end_line": 407, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "UI", + "PURPOSE": "API Key management tab — list, generate (one-time reveal), and revoke API keys.", + "UX_FEEDBACK": "Toast on generate success/error, revoke success/error", + "UX_REACTIVITY": "Props -> $props(), LocalState -> $state(keys, isLoading, error)", + "UX_RECOVERY": "Retry button on load error", + "UX_STATE": "Revealing -> Warning panel with raw key and copy button" + }, + "relations": [ + { + "source_id": "ApiKeysTab", + "relation_type": "DEPENDS_ON", + "target_id": "ApiModule", + "target_ref": "[ApiModule]" + }, + { + "source_id": "ApiKeysTab", + "relation_type": "DEPENDS_ON", + "target_id": "I18nModule", + "target_ref": "[I18nModule]" + }, + { + "source_id": "ApiKeysTab", + "relation_type": "DEPENDS_ON", + "target_id": "ToastsModule", + "target_ref": "[ToastsModule]" + } + ], + "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
\n \n
\n
\n

{$t.api_keys?.title || 'API Keys'}

\n

\n {$t.api_keys?.description || 'Manage API keys for service-to-service authentication.'}\n

\n
\n { showGenerateForm = !showGenerateForm; }}\n disabled={isLoading}\n >\n {$t.api_keys?.generate?.title || 'Generate New API Key'}\n \n
\n\n \n {#if showGenerateForm}\n
\n

{$t.api_keys?.generate?.title || 'Generate New API Key'}

\n\n \n
\n \n \n
\n\n \n
\n \n \n \n {#each environments as env (env.id)}\n \n {/each}\n \n
\n\n \n
\n \n
\n {#each AVAILABLE_PERMISSIONS as perm}\n \n {/each}\n
\n
\n\n \n
\n \n \n
\n\n \n
\n \n {#if isGenerating}\n \n \n \n \n {/if}\n {$t.api_keys?.generate?.generate || 'Generate Key'}\n \n \n {$t.api_keys?.generate?.cancel || 'Cancel'}\n \n
\n
\n {/if}\n\n \n {#if revealedKey}\n
\n
\n ⚠️\n
\n

\n {$t.api_keys?.reveal?.warning || 'This is the ONLY time the key will be shown. Copy it now.'}\n

\n
{revealedKey.raw_key}
\n
\n
\n
\n copyToClipboard(revealedKey.raw_key)}\n >\n {$t.api_keys?.reveal?.copy || 'Copy to Clipboard'}\n \n \n {$t.api_keys?.reveal?.dismiss || 'Dismiss'}\n \n
\n
\n {/if}\n\n \n {#if error}\n
\n {error}\n \n Retry\n \n
\n {:else if isLoading}\n \n
\n {#each [1, 2, 3] as _}\n
\n {/each}\n
\n {:else if keys.length === 0}\n \n
\n {$t.api_keys?.empty || 'No API keys configured.'}\n
\n {:else}\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n {#each keys as key (key.id)}\n \n \n \n \n \n \n \n \n {/each}\n \n
\n {$t.api_keys?.table?.name || 'Name'}\n \n {$t.api_keys?.table?.prefix || 'Prefix'}\n \n {$t.api_keys?.table?.environment || 'Environment'}\n \n {$t.api_keys?.table?.permissions || 'Permissions'}\n \n {$t.api_keys?.table?.status || 'Status'}\n \n {$t.api_keys?.table?.actions || 'Actions'}\n
{key.name}{key.prefix}...{key.environment_id || '—'}\n
\n {#each key.permissions as perm}\n {perm}\n {/each}\n
\n
\n \n \n {key.active\n ? ($t.api_keys?.status?.active || 'Active')\n : ($t.api_keys?.status?.revoked || 'Revoked')}\n \n \n {#if key.active}\n confirmRevoke(key)}\n disabled={revokingId === key.id}\n >\n {#if revokingId === key.id}\n Revoking...\n {:else}\n ✕ {$t.api_keys?.revoke?.revoke || 'Revoke'}\n {/if}\n \n {:else}\n \n {/if}\n
\n
\n {/if}\n
\n\n" + }, { "contract_id": "BulkCorrectionSidebar", "contract_type": "Component", @@ -72420,7 +78273,7 @@ "contract_type": "Component", "file_path": "frontend/src/lib/components/translate/ScheduleConfig.svelte", "start_line": 1, - "end_line": 286, + "end_line": 296, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -72462,7 +78315,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t
\n\t\t

{$t.translate?.schedule?.title || 'Schedule Configuration'}

\n\t\t{#if !isLoading && scheduleExists}\n\t\t\t\n\t\t\t\t\n\t\t\t\t{isEnabled ? ($t.translate?.schedule?.enabled || 'Enabled') : ($t.translate?.schedule?.disabled || 'Disabled')}\n\t\t\t\n\t\t{/if}\n\t
\n\n\t{#if isLoading}\n\t\t
\n\n\t{:else if uxState === 'idle'}\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t

{$t.translate?.schedule?.no_schedule || 'No schedule configured'}

\n\t\t\t

{$t.translate?.schedule?.no_schedule_hint || 'Set up a recurring schedule for automatic translations'}

\n\t\t\t\n\t\t
\n\n\t{:else if uxState === 'editing' || uxState === 'enabled' || uxState === 'disabled'}\n\t\t
\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\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\t

\n\t\t\t\t\t{getCronDescription(cronExpression)}\n\t\t\t\t

\n\t\t\t
\n\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t{#each commonTimezones as tz}\n\t\t\t\t\t\t\n\t\t\t\t\t{/each}\n\t\t\t\t\n\t\t\t
\n\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t\n\t\t\t{#if nextExecutions.length > 0}\n\t\t\t\t
\n\t\t\t\t\t

{$t.translate?.schedule?.next_executions || 'Next Executions'}

\n\t\t\t\t\t{#each nextExecutions as dt, i}\n\t\t\t\t\t\t

{i + 1}. {new Date(dt).toLocaleString()}

\n\t\t\t\t\t{/each}\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t\n\t\t\t{#if uxState === 'no_prior_run_warning'}\n\t\t\t\t
\n\t\t\t\t\t

\n\t\t\t\t\t\t⚠ {$t.translate?.schedule?.no_prior_run_warning || 'No prior successful manual run. Schedule may run with default settings. Consider running manually first.'}\n\t\t\t\t\t

\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t\n\t\t\t
\n\t\t\t\t{#if scheduleExists}\n\t\t\t\t\t\n\t\t\t\t{:else}\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\t\t\t\t
\n\t\t\t\t\t{#if scheduleExists && (uxState === 'enabled' || uxState === 'disabled')}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t\t{#if uxState === 'editing'}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t{/if}\n
\n\n" + "body": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t
\n\t\t

{$t.translate?.schedule?.title || 'Schedule Configuration'}

\n\t\t{#if !isLoading && scheduleExists}\n\t\t\t\n\t\t\t\t\n\t\t\t\t{isEnabled ? ($t.translate?.schedule?.enabled || 'Enabled') : ($t.translate?.schedule?.disabled || 'Disabled')}\n\t\t\t\n\t\t{/if}\n\t
\n\n\t{#if isLoading}\n\t\t
\n\n\t{:else if uxState === 'idle'}\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t

{$t.translate?.schedule?.no_schedule || 'No schedule configured'}

\n\t\t\t

{$t.translate?.schedule?.no_schedule_hint || 'Set up a recurring schedule for automatic translations'}

\n\t\t\t\n\t\t
\n\n\t{:else if uxState === 'editing' || uxState === 'enabled' || uxState === 'disabled'}\n\t\t
\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\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\t

\n\t\t\t\t\t{getCronDescription(cronExpression)}\n\t\t\t\t

\n\t\t\t
\n\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t{#each commonTimezones as tz}\n\t\t\t\t\t\t\n\t\t\t\t\t{/each}\n\t\t\t\t\n\t\t\t
\n\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t\n\t\t\t{#if nextExecutions.length > 0}\n\t\t\t\t
\n\t\t\t\t\t

{$t.translate?.schedule?.next_executions || 'Next Executions'}

\n\t\t\t\t\t{#each nextExecutions as dt, i}\n\t\t\t\t\t\t

{i + 1}. {new Date(dt).toLocaleString()}

\n\t\t\t\t\t{/each}\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t\n\t\t\t{#if uxState === 'no_prior_run_warning'}\n\t\t\t\t
\n\t\t\t\t\t

\n\t\t\t\t\t\t⚠ {$t.translate?.schedule?.no_prior_run_warning || 'No prior successful manual run. Schedule may run with default settings. Consider running manually first.'}\n\t\t\t\t\t

\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t\n\t\t\t
\n\t\t\t\t{#if scheduleExists}\n\t\t\t\t\t\n\t\t\t\t{:else}\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\t\t\t\t
\n\t\t\t\t\t{#if scheduleExists && (uxState === 'enabled' || uxState === 'disabled')}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t\t{#if uxState === 'editing'}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t{/if}\n
\n\n" }, { "contract_id": "TargetSchemaHint", @@ -73373,7 +79226,7 @@ "contract_type": "Module", "file_path": "frontend/src/lib/i18n/index.ts", "start_line": 1, - "end_line": 179, + "end_line": 191, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -73397,14 +79250,14 @@ "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 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" + "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 enApiKeys from './locales/en/api-keys.json';\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';\nimport enMaintenance from './locales/en/maintenance.json';\nimport enConnections from './locales/en/connections.json';\n\nimport ruApiKeys from './locales/ru/api-keys.json';\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';\nimport ruMaintenance from './locales/ru/maintenance.json';\nimport ruConnections from './locales/ru/connections.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tapi_keys: enApiKeys,\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\tmaintenance: enMaintenance,\n\tconnections: enConnections,\n};\n\nconst ru = {\n\tapi_keys: ruApiKeys,\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\tmaintenance: ruMaintenance,\n\tconnections: ruConnections,\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", "contract_type": "Function", "file_path": "frontend/src/lib/i18n/index.ts", "start_line": 6, - "end_line": 178, + "end_line": 190, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -73476,14 +79329,14 @@ ], "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 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" + "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 enApiKeys from './locales/en/api-keys.json';\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';\nimport enMaintenance from './locales/en/maintenance.json';\nimport enConnections from './locales/en/connections.json';\n\nimport ruApiKeys from './locales/ru/api-keys.json';\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';\nimport ruMaintenance from './locales/ru/maintenance.json';\nimport ruConnections from './locales/ru/connections.json';\n\n// Merge domain objects into locale dictionaries\nconst en = {\n\tapi_keys: enApiKeys,\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\tmaintenance: enMaintenance,\n\tconnections: enConnections,\n};\n\nconst ru = {\n\tapi_keys: ruApiKeys,\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\tmaintenance: ruMaintenance,\n\tconnections: ruConnections,\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", "contract_type": "Function", "file_path": "frontend/src/lib/i18n/index.ts", - "start_line": 129, - "end_line": 139, + "start_line": 141, + "end_line": 151, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -73500,8 +79353,8 @@ "contract_id": "t:Store", "contract_type": "Function", "file_path": "frontend/src/lib/i18n/index.ts", - "start_line": 141, - "end_line": 150, + "start_line": 153, + "end_line": 162, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -73524,8 +79377,8 @@ "contract_id": "_:Function", "contract_type": "Function", "file_path": "frontend/src/lib/i18n/index.ts", - "start_line": 152, - "end_line": 176, + "start_line": 164, + "end_line": 188, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -73556,8 +79409,8 @@ "contract_id": "frontend/src/lib/i18n/index.ts::_", "contract_type": "Function", "file_path": "frontend/src/lib/i18n/index.ts", - "start_line": 153, - "end_line": 158, + "start_line": 165, + "end_line": 170, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -76136,6 +81989,297 @@ "tier_source": "AutoCalculated", "body": " /**\n * Refresh health summary from API\n * @param {string|null} environmentId - Optional environment filter\n */" }, + { + "contract_id": "MaintenanceStore", + "contract_type": "Module", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 1, + "end_line": 180, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "Frontend", + "PURPOSE": "Svelte 5 (Runes) store for maintenance banner state. Auto-polls events every 30s via interval.", + "RETURNS": "{object} Maintenance store with runes state and methods.", + "UI_STATE": "Error -> error state populated with message", + "UX_REACTIVITY": "$state for events/settings/banners. Manual setInterval for polling.", + "UX_RECOVERY": "Error toast on failure. Retry via loadEvents/loadSettings." + }, + "relations": [ + { + "source_id": "MaintenanceStore", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceApi", + "target_ref": "[MaintenanceApi]" + }, + { + "source_id": "MaintenanceStore", + "relation_type": "DEPENDS_ON", + "target_id": "addToast", + "target_ref": "[addToast]" + } + ], + "schema_warnings": [ + { + "code": "invalid_enum_value", + "tag": "LAYER", + "message": "@LAYER value 'Frontend' is not in allowed enum", + "detail": { + "allowed": [ + "Core", + "Domain", + "API", + "UI", + "Service", + "Infrastructure", + "Plugin", + "Tests" + ], + "value": "Frontend" + } + }, + { + "code": "unknown_tag", + "tag": "RETURNS", + "message": "@RETURNS is not defined in axiom_config.yaml tags", + "detail": null + }, + { + "code": "unknown_tag", + "tag": "UI_STATE", + "message": "@UI_STATE is not defined in axiom_config.yaml tags", + "detail": null + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_REACTIVITY", + "message": "@UX_REACTIVITY is not allowed for contract type 'Module'", + "detail": { + "actual_type": "Module", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_REACTIVITY", + "message": "@UX_REACTIVITY is forbidden for contract type 'Module' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Module" + } + }, + { + "code": "tag_not_for_contract_type", + "tag": "UX_RECOVERY", + "message": "@UX_RECOVERY is not allowed for contract type 'Module'", + "detail": { + "actual_type": "Module", + "allowed_types": [ + "Component" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "UX_RECOVERY", + "message": "@UX_RECOVERY is forbidden for contract type 'Module' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Module" + } + } + ], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region MaintenanceStore [C:3] [TYPE Module] [SEMANTICS store, maintenance, svelte, runes]\n// @BRIEF Svelte 5 (Runes) store for maintenance banner state. Auto-polls events every 30s via interval.\n// @LAYER Frontend\n// @RELATION DEPENDS_ON -> [MaintenanceApi]\n// @RELATION DEPENDS_ON -> [addToast]\n// @UI_STATE Idle -> events loaded, settings loaded, banners loaded\n// @UI_STATE Loading -> isLoading = true during fetches\n// @UI_STATE Error -> error state populated with message\n// @ADR-0007: Uses $effect(() => subscribe(...)) pattern, NOT fromStore + $derived.\n// @UX_REACTIVITY $state for events/settings/banners. Manual setInterval for polling.\n// @UX_RECOVERY Error toast on failure. Retry via loadEvents/loadSettings.\n\nimport { addToast } from \"$lib/toasts.js\";\nimport * as maintenanceApi from \"$lib/api/maintenance.js\";\n\nconst POLL_INTERVAL_MS = 30000;\n\n/**\n * @returns {object} Maintenance store with runes state and methods.\n */\nexport function createMaintenanceStore() {\n // #region MaintenanceStore.state [C:1] [TYPE Block]\n let activeEvents = $state([]);\n let completedEvents = $state([]);\n let settings = $state(null);\n let dashboardBanners = $state([]);\n let isLoading = $state(false);\n let error = $state(null);\n let _pollInterval = null;\n // #endregion MaintenanceStore.state\n\n // #region MaintenanceStore.methods [C:2] [TYPE Block]\n\n /**\n * Load events from API.\n */\n async function loadEvents() {\n isLoading = true;\n error = null;\n try {\n const data = await maintenanceApi.listEvents();\n activeEvents = data.active || [];\n completedEvents = data.completed || [];\n } catch (e) {\n const msg = e?.message || \"Failed to load events\";\n error = msg;\n console.error(\"[MaintenanceStore] loadEvents error:\", msg);\n } finally {\n isLoading = false;\n }\n }\n\n /**\n * Load dashboard banner states.\n */\n async function loadDashboardBanners() {\n try {\n const data = await maintenanceApi.listDashboardBanners();\n dashboardBanners = Array.isArray(data) ? data : [];\n } catch (e) {\n console.error(\"[MaintenanceStore] loadDashboardBanners error:\", e?.message);\n dashboardBanners = [];\n }\n }\n\n /**\n * Load settings from API.\n */\n async function loadSettings() {\n try {\n settings = await maintenanceApi.getSettings();\n } catch (e) {\n console.error(\"[MaintenanceStore] loadSettings error:\", e?.message);\n }\n }\n\n /**\n * End a specific maintenance event.\n * @param {string} maintenanceId\n */\n async function endEvent(maintenanceId) {\n try {\n const data = await maintenanceApi.endMaintenance(maintenanceId);\n if (data?.task_id) {\n addToast(\"Removal task started\", \"info\");\n }\n await loadEvents();\n } catch (e) {\n const msg = e?.message || \"Failed to end maintenance event\";\n addToast(msg, \"error\");\n throw e;\n }\n }\n\n /**\n * End all active maintenance events.\n */\n async function endAllEvents() {\n try {\n const data = await maintenanceApi.endAllMaintenance();\n if (data?.task_id) {\n addToast(\"Bulk removal task started\", \"info\");\n }\n await loadEvents();\n } catch (e) {\n const msg = e?.message || \"Failed to end all events\";\n addToast(msg, \"error\");\n throw e;\n }\n }\n\n /**\n * Update settings.\n * @param {object} newSettings\n */\n async function updateSettings(newSettings) {\n isLoading = true;\n try {\n settings = await maintenanceApi.updateSettings(newSettings);\n addToast(\"Settings saved\", \"success\");\n } catch (e) {\n const msg = e?.message || \"Failed to update settings\";\n addToast(msg, \"error\");\n throw e;\n } finally {\n isLoading = false;\n }\n }\n\n /**\n * Initialize the store: load all data once and start polling.\n */\n async function init() {\n await Promise.all([loadEvents(), loadSettings(), loadDashboardBanners()]);\n startPolling();\n }\n\n /**\n * Start auto-polling for events every 30s.\n */\n function startPolling() {\n if (_pollInterval) return;\n _pollInterval = setInterval(async () => {\n await loadEvents();\n }, POLL_INTERVAL_MS);\n }\n\n /**\n * Stop auto-polling.\n */\n function stopPolling() {\n if (_pollInterval) {\n clearInterval(_pollInterval);\n _pollInterval = null;\n }\n }\n\n // #endregion MaintenanceStore.methods\n\n return {\n get activeEvents() { return activeEvents; },\n get completedEvents() { return completedEvents; },\n get settings() { return settings; },\n get dashboardBanners() { return dashboardBanners; },\n get isLoading() { return isLoading; },\n get error() { return error; },\n loadEvents,\n loadSettings,\n loadDashboardBanners,\n endEvent,\n endAllEvents,\n updateSettings,\n init,\n startPolling,\n stopPolling,\n };\n}\n\nexport const maintenanceStore = createMaintenanceStore();\n// #endregion MaintenanceStore\n" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::createMaintenanceStore", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 18, + "end_line": 21, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": "/**\n * @returns {object} Maintenance store with runes state and methods.\n */" + }, + { + "contract_id": "MaintenanceStore.state", + "contract_type": "Block", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 22, + "end_line": 30, + "tier": "TIER_1", + "complexity": 1, + "metadata": { + "COMPLEXITY": 1 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " // #region MaintenanceStore.state [C:1] [TYPE Block]\n let activeEvents = $state([]);\n let completedEvents = $state([]);\n let settings = $state(null);\n let dashboardBanners = $state([]);\n let isLoading = $state(false);\n let error = $state(null);\n let _pollInterval = null;\n // #endregion MaintenanceStore.state\n" + }, + { + "contract_id": "MaintenanceStore.methods", + "contract_type": "Block", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 32, + "end_line": 158, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2 + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": " // #region MaintenanceStore.methods [C:2] [TYPE Block]\n\n /**\n * Load events from API.\n */\n async function loadEvents() {\n isLoading = true;\n error = null;\n try {\n const data = await maintenanceApi.listEvents();\n activeEvents = data.active || [];\n completedEvents = data.completed || [];\n } catch (e) {\n const msg = e?.message || \"Failed to load events\";\n error = msg;\n console.error(\"[MaintenanceStore] loadEvents error:\", msg);\n } finally {\n isLoading = false;\n }\n }\n\n /**\n * Load dashboard banner states.\n */\n async function loadDashboardBanners() {\n try {\n const data = await maintenanceApi.listDashboardBanners();\n dashboardBanners = Array.isArray(data) ? data : [];\n } catch (e) {\n console.error(\"[MaintenanceStore] loadDashboardBanners error:\", e?.message);\n dashboardBanners = [];\n }\n }\n\n /**\n * Load settings from API.\n */\n async function loadSettings() {\n try {\n settings = await maintenanceApi.getSettings();\n } catch (e) {\n console.error(\"[MaintenanceStore] loadSettings error:\", e?.message);\n }\n }\n\n /**\n * End a specific maintenance event.\n * @param {string} maintenanceId\n */\n async function endEvent(maintenanceId) {\n try {\n const data = await maintenanceApi.endMaintenance(maintenanceId);\n if (data?.task_id) {\n addToast(\"Removal task started\", \"info\");\n }\n await loadEvents();\n } catch (e) {\n const msg = e?.message || \"Failed to end maintenance event\";\n addToast(msg, \"error\");\n throw e;\n }\n }\n\n /**\n * End all active maintenance events.\n */\n async function endAllEvents() {\n try {\n const data = await maintenanceApi.endAllMaintenance();\n if (data?.task_id) {\n addToast(\"Bulk removal task started\", \"info\");\n }\n await loadEvents();\n } catch (e) {\n const msg = e?.message || \"Failed to end all events\";\n addToast(msg, \"error\");\n throw e;\n }\n }\n\n /**\n * Update settings.\n * @param {object} newSettings\n */\n async function updateSettings(newSettings) {\n isLoading = true;\n try {\n settings = await maintenanceApi.updateSettings(newSettings);\n addToast(\"Settings saved\", \"success\");\n } catch (e) {\n const msg = e?.message || \"Failed to update settings\";\n addToast(msg, \"error\");\n throw e;\n } finally {\n isLoading = false;\n }\n }\n\n /**\n * Initialize the store: load all data once and start polling.\n */\n async function init() {\n await Promise.all([loadEvents(), loadSettings(), loadDashboardBanners()]);\n startPolling();\n }\n\n /**\n * Start auto-polling for events every 30s.\n */\n function startPolling() {\n if (_pollInterval) return;\n _pollInterval = setInterval(async () => {\n await loadEvents();\n }, POLL_INTERVAL_MS);\n }\n\n /**\n * Stop auto-polling.\n */\n function stopPolling() {\n if (_pollInterval) {\n clearInterval(_pollInterval);\n _pollInterval = null;\n }\n }\n\n // #endregion MaintenanceStore.methods\n" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::loadEvents", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 34, + "end_line": 37, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Load events from API.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::loadDashboardBanners", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 53, + "end_line": 56, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Load dashboard banner states.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::loadSettings", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 66, + "end_line": 69, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Load settings from API.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::endEvent", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 77, + "end_line": 81, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * End a specific maintenance event.\n * @param {string} maintenanceId\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::endAllEvents", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 95, + "end_line": 98, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * End all active maintenance events.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::updateSettings", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 112, + "end_line": 116, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Update settings.\n * @param {object} newSettings\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::init", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 130, + "end_line": 133, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Initialize the store: load all data once and start polling.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::startPolling", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 138, + "end_line": 141, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Start auto-polling for events every 30s.\n */" + }, + { + "contract_id": "frontend/src/lib/stores/maintenance.svelte.js::stopPolling", + "contract_type": "Function", + "file_path": "frontend/src/lib/stores/maintenance.svelte.js", + "start_line": 148, + "end_line": 151, + "tier": "TIER_1", + "complexity": 1, + "metadata": {}, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "jsdoc", + "tier_source": "AutoCalculated", + "body": " /**\n * Stop auto-polling.\n */" + }, { "contract_id": "SidebarStore", "contract_type": "Store", @@ -79217,8 +85361,8 @@ "contract_id": "DashboardHub.normalizeTaskStatus:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 192, - "end_line": 205, + "start_line": 197, + "end_line": 210, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79236,8 +85380,8 @@ "contract_id": "DashboardHub.normalizeValidationStatus:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 207, - "end_line": 222, + "start_line": 212, + "end_line": 227, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79255,8 +85399,8 @@ "contract_id": "DashboardHub.getValidationBadgeClass:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 224, - "end_line": 238, + "start_line": 229, + "end_line": 243, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79274,8 +85418,8 @@ "contract_id": "DashboardHub.getValidationLabel:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 240, - "end_line": 253, + "start_line": 245, + "end_line": 258, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79293,8 +85437,8 @@ "contract_id": "DashboardHub.normalizeOwners:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 255, - "end_line": 291, + "start_line": 260, + "end_line": 296, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79312,8 +85456,8 @@ "contract_id": "DashboardHub.loadDashboards:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 293, - "end_line": 495, + "start_line": 298, + "end_line": 525, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79347,14 +85491,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region DashboardHub.loadDashboards:Function [TYPE Function]\n /**\n * @PURPOSE: Load full dashboard dataset for current environment and hydrate grid projection.\n * @PRE: selectedEnv is not null.\n * @POST: allDashboards, dashboards, pagination and selection state are synchronized.\n * @UX_STATE: Loading -> true during request lifecycle.\n * @UX_STATE: Error -> `error` populated when request fails.\n */\n async function loadDashboards() {\n if (!selectedEnv) return;\n\n const requestSeq = dashboardsLoadSeq + 1;\n dashboardsLoadSeq = requestSeq;\n isLoading = true;\n error = null;\n try {\n const firstResponse = await api.getDashboards(selectedEnv, {\n page: currentPage,\n page_size: pageSize,\n search: searchQuery.trim() || undefined,\n page_context: \"dashboards_main\",\n apply_profile_default: true,\n override_show_all: profileFilterOverrideShowAll,\n filters: {\n title: Array.from(columnFilters.title),\n git_status: Array.from(columnFilters.git_status),\n llm_status: Array.from(columnFilters.llm_status),\n changed_on: Array.from(columnFilters.changed_on),\n actor: Array.from(columnFilters.actor),\n },\n });\n if (requestSeq !== dashboardsLoadSeq) return;\n\n const rawDashboards = firstResponse?.dashboards || [];\n serverTotal = Number(firstResponse?.total || 0);\n serverTotalPages = Math.max(1, Number(firstResponse?.total_pages || 1));\n effectiveProfileFilter = firstResponse?.effective_profile_filter || null;\n profileFilterOverrideShowAll = Boolean(\n firstResponse?.effective_profile_filter?.override_show_all,\n );\n\n gitResolvedIds = new Set();\n gitLoadingIds = new Set();\n\n allDashboards = rawDashboards.map((d) => {\n const owners = normalizeOwners(d.owners);\n const hasGitStatus = !!d.git_status;\n return {\n id: d.id,\n title: d.title,\n slug: d.slug,\n changedOn: d.last_modified || null,\n changedOnLabel: formatDate(d.last_modified),\n owners,\n actorLabel: owners.length > 0 ? owners.join(\", \") : \"-\",\n git: hasGitStatus\n ? {\n status: d.git_status?.sync_status?.toLowerCase() || \"no_repo\",\n branch: d.git_status?.branch || null,\n hasRepo: d.git_status?.has_repo === true,\n hasChangesForCommit:\n d.git_status?.has_changes_for_commit === true,\n }\n : {\n status: \"pending\",\n branch: null,\n hasRepo: null,\n hasChangesForCommit: false,\n },\n lastTask: d.last_task\n ? {\n status: normalizeTaskStatus(d.last_task.status),\n validationStatus: normalizeValidationStatus(\n d.last_task.validation_status,\n ),\n id: d.last_task.task_id,\n }\n : null,\n actions: [\"migrate\", \"backup\"],\n };\n });\n\n selectedIds = new Set(\n Array.from(selectedIds).filter((id) =>\n allDashboards.some((dashboard) => dashboard.id === id),\n ),\n );\n applyGridTransforms();\n updateSelectionState();\n } catch (err) {\n if (requestSeq !== dashboardsLoadSeq) return;\n error = err.message || $t.dashboard?.load_failed;\n console.error(\n \"[DashboardHub][COHERENCE:FAILED] Load dashboards Error:\",\n err,\n );\n } finally {\n if (requestSeq === dashboardsLoadSeq) {\n isLoading = false;\n }\n }\n }\n\n // Handle search input\n function handleSearch(event) {\n debouncedSearch(event.target.value);\n }\n\n // Handle page change\n function handlePageChange(page) {\n if (page === currentPage) return;\n currentPage = page;\n void loadDashboards();\n }\n\n // Handle page size change\n function handlePageSizeChange(event) {\n pageSize = parseInt(event.target.value);\n currentPage = 1;\n void loadDashboards();\n }\n\n // #region DashboardHub.handleTemporaryShowAll:Function [TYPE Function]\n /**\n * @PURPOSE: Temporarily disable profile-default dashboard filter for current page context.\n * @PRE: Dashboards list is loaded in dashboards_main context.\n * @POST: Next request is sent with override_show_all=true.\n */\n function handleTemporaryShowAll() {\n if (profileFilterOverrideShowAll) return;\n profileFilterOverrideShowAll = true;\n currentPage = 1;\n void loadDashboards();\n }\n // #endregion DashboardHub.handleTemporaryShowAll:Function\n\n // #region DashboardHub.handleRestoreProfileFilter:Function [TYPE Function]\n /**\n * @PURPOSE: Re-enable persisted profile-default filtering after temporary override.\n * @PRE: Current page is in override mode.\n * @POST: Next request is sent with override_show_all=false.\n */\n function handleRestoreProfileFilter() {\n if (!profileFilterOverrideShowAll) return;\n profileFilterOverrideShowAll = false;\n currentPage = 1;\n void loadDashboards();\n }\n // #endregion DashboardHub.handleRestoreProfileFilter:Function\n\n // Update selection state based on current selection\n function updateSelectionState() {\n const visibleCount = dashboards.length;\n const totalCount = filteredDashboards.length;\n\n isAllSelected = selectedIds.size === totalCount && totalCount > 0;\n isAllVisibleSelected =\n selectedIds.size === visibleCount && visibleCount > 0;\n }\n\n function replaceSelectedIds(nextSelection) {\n selectedIds = nextSelection;\n updateSelectionState();\n }\n\n function clearSelectedIds() {\n replaceSelectedIds(new Set());\n }\n\n // Handle checkbox change for individual dashboard\n function handleCheckboxChange(dashboard, event) {\n const nextSelection = new Set(selectedIds);\n if (event.target.checked) {\n nextSelection.add(dashboard.id);\n } else {\n nextSelection.delete(dashboard.id);\n }\n replaceSelectedIds(nextSelection);\n }\n\n // Handle select all\n function handleSelectAll() {\n if (isAllSelected) {\n clearSelectedIds();\n return;\n }\n const nextSelection = new Set(selectedIds);\n filteredDashboards.forEach((dashboard) => nextSelection.add(dashboard.id));\n replaceSelectedIds(nextSelection);\n }\n\n // Handle select visible\n function handleSelectVisible() {\n const nextSelection = new Set(selectedIds);\n if (isAllVisibleSelected) {\n dashboards.forEach((dashboard) => nextSelection.delete(dashboard.id));\n } else {\n dashboards.forEach((dashboard) => nextSelection.add(dashboard.id));\n }\n replaceSelectedIds(nextSelection);\n }\n\n // #endregion DashboardHub.loadDashboards:Function\n" + "body": " // #region DashboardHub.loadDashboards:Function [TYPE Function]\n /**\n * @PURPOSE: Load full dashboard dataset for current environment and hydrate grid projection.\n * @PRE: selectedEnv is not null.\n * @POST: allDashboards, dashboards, pagination and selection state are synchronized.\n * @UX_STATE: Loading -> true during request lifecycle.\n * @UX_STATE: Error -> `error` populated when request fails.\n */\n async function loadDashboards() {\n if (!selectedEnv) return;\n\n const requestSeq = dashboardsLoadSeq + 1;\n dashboardsLoadSeq = requestSeq;\n isLoading = true;\n error = null;\n try {\n const firstResponse = await api.getDashboards(selectedEnv, {\n page: currentPage,\n page_size: pageSize,\n search: searchQuery.trim() || undefined,\n page_context: \"dashboards_main\",\n apply_profile_default: true,\n override_show_all: profileFilterOverrideShowAll,\n filters: {\n title: Array.from(columnFilters.title),\n git_status: Array.from(columnFilters.git_status),\n llm_status: Array.from(columnFilters.llm_status),\n changed_on: Array.from(columnFilters.changed_on),\n actor: Array.from(columnFilters.actor),\n },\n });\n if (requestSeq !== dashboardsLoadSeq) return;\n\n const rawDashboards = firstResponse?.dashboards || [];\n serverTotal = Number(firstResponse?.total || 0);\n serverTotalPages = Math.max(1, Number(firstResponse?.total_pages || 1));\n effectiveProfileFilter = firstResponse?.effective_profile_filter || null;\n profileFilterOverrideShowAll = Boolean(\n firstResponse?.effective_profile_filter?.override_show_all,\n );\n\n gitResolvedIds = new Set();\n gitLoadingIds = new Set();\n\n allDashboards = rawDashboards.map((d) => {\n const owners = normalizeOwners(d.owners);\n const hasGitStatus = !!d.git_status;\n return {\n id: d.id,\n title: d.title,\n slug: d.slug,\n changedOn: d.last_modified || null,\n changedOnLabel: formatDate(d.last_modified),\n owners,\n actorLabel: owners.length > 0 ? owners.join(\", \") : \"-\",\n git: hasGitStatus\n ? {\n status: d.git_status?.sync_status?.toLowerCase() || \"no_repo\",\n branch: d.git_status?.branch || null,\n hasRepo: d.git_status?.has_repo === true,\n hasChangesForCommit:\n d.git_status?.has_changes_for_commit === true,\n }\n : {\n status: \"pending\",\n branch: null,\n hasRepo: null,\n hasChangesForCommit: false,\n },\n lastTask: d.last_task\n ? {\n status: normalizeTaskStatus(d.last_task.status),\n validationStatus: normalizeValidationStatus(\n d.last_task.validation_status,\n ),\n id: d.last_task.task_id,\n }\n : null,\n actions: [\"migrate\", \"backup\"],\n };\n });\n\n selectedIds = new Set(\n Array.from(selectedIds).filter((id) =>\n allDashboards.some((dashboard) => dashboard.id === id),\n ),\n );\n applyGridTransforms();\n updateSelectionState();\n } catch (err) {\n if (requestSeq !== dashboardsLoadSeq) return;\n error = err.message || $t.dashboard?.load_failed;\n console.error(\n \"[DashboardHub][COHERENCE:FAILED] Load dashboards Error:\",\n err,\n );\n } finally {\n if (requestSeq === dashboardsLoadSeq) {\n isLoading = false;\n }\n }\n }\n\n // Handle search input\n function handleSearch(event) {\n debouncedSearch(event.target.value);\n }\n\n // Load dashboard options for SearchableMultiSelect\n async function loadDashboardSearchOptions(query = '') {\n if (!selectedEnv) return;\n searchableDashboardLoading = true;\n try {\n const response = await api.getDashboards(selectedEnv, {\n search: query || undefined,\n page_size: 100,\n page_context: 'other',\n apply_profile_default: false,\n override_show_all: true,\n });\n searchableDashboardOptions = (response?.dashboards || []).map((d) => ({\n id: d.id,\n name: d.title,\n subtitle: d.slug || '',\n hint: d.last_modified ? formatDate(d.last_modified) : '',\n }));\n } catch {\n searchableDashboardOptions = [];\n } finally {\n searchableDashboardLoading = false;\n }\n }\n\n // Handle page change\n function handlePageChange(page) {\n if (page === currentPage) return;\n currentPage = page;\n void loadDashboards();\n }\n\n // Handle page size change\n function handlePageSizeChange(event) {\n pageSize = parseInt(event.target.value);\n currentPage = 1;\n void loadDashboards();\n }\n\n // #region DashboardHub.handleTemporaryShowAll:Function [TYPE Function]\n /**\n * @PURPOSE: Temporarily disable profile-default dashboard filter for current page context.\n * @PRE: Dashboards list is loaded in dashboards_main context.\n * @POST: Next request is sent with override_show_all=true.\n */\n function handleTemporaryShowAll() {\n if (profileFilterOverrideShowAll) return;\n profileFilterOverrideShowAll = true;\n currentPage = 1;\n void loadDashboards();\n }\n // #endregion DashboardHub.handleTemporaryShowAll:Function\n\n // #region DashboardHub.handleRestoreProfileFilter:Function [TYPE Function]\n /**\n * @PURPOSE: Re-enable persisted profile-default filtering after temporary override.\n * @PRE: Current page is in override mode.\n * @POST: Next request is sent with override_show_all=false.\n */\n function handleRestoreProfileFilter() {\n if (!profileFilterOverrideShowAll) return;\n profileFilterOverrideShowAll = false;\n currentPage = 1;\n void loadDashboards();\n }\n // #endregion DashboardHub.handleRestoreProfileFilter:Function\n\n // Update selection state based on current selection\n function updateSelectionState() {\n const visibleCount = dashboards.length;\n const totalCount = filteredDashboards.length;\n\n isAllSelected = selectedIds.size === totalCount && totalCount > 0;\n isAllVisibleSelected =\n selectedIds.size === visibleCount && visibleCount > 0;\n }\n\n function replaceSelectedIds(nextSelection) {\n selectedIds = nextSelection;\n updateSelectionState();\n }\n\n function clearSelectedIds() {\n replaceSelectedIds(new Set());\n }\n\n // Handle checkbox change for individual dashboard\n function handleCheckboxChange(dashboard, event) {\n const nextSelection = new Set(selectedIds);\n if (event.target.checked) {\n nextSelection.add(dashboard.id);\n } else {\n nextSelection.delete(dashboard.id);\n }\n replaceSelectedIds(nextSelection);\n }\n\n // Handle select all\n function handleSelectAll() {\n if (isAllSelected) {\n clearSelectedIds();\n return;\n }\n const nextSelection = new Set(selectedIds);\n filteredDashboards.forEach((dashboard) => nextSelection.add(dashboard.id));\n replaceSelectedIds(nextSelection);\n }\n\n // Handle select visible\n function handleSelectVisible() {\n const nextSelection = new Set(selectedIds);\n if (isAllVisibleSelected) {\n dashboards.forEach((dashboard) => nextSelection.delete(dashboard.id));\n } else {\n dashboards.forEach((dashboard) => nextSelection.add(dashboard.id));\n }\n replaceSelectedIds(nextSelection);\n }\n\n // #endregion DashboardHub.loadDashboards:Function\n" }, { "contract_id": "DashboardHub.handleTemporaryShowAll:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 415, - "end_line": 427, + "start_line": 445, + "end_line": 457, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79372,8 +85516,8 @@ "contract_id": "DashboardHub.handleRestoreProfileFilter:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 429, - "end_line": 441, + "start_line": 459, + "end_line": 471, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79391,8 +85535,8 @@ "contract_id": "DashboardHub.formatDate:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 497, - "end_line": 510, + "start_line": 527, + "end_line": 540, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79410,8 +85554,8 @@ "contract_id": "DashboardHub.getGitSummaryLabel:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 512, - "end_line": 530, + "start_line": 542, + "end_line": 560, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79429,8 +85573,8 @@ "contract_id": "DashboardHub.getLlmSummaryLabel:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 532, - "end_line": 544, + "start_line": 562, + "end_line": 574, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79448,8 +85592,8 @@ "contract_id": "DashboardHub.getColumnCellValue:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 546, - "end_line": 563, + "start_line": 576, + "end_line": 593, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79467,8 +85611,8 @@ "contract_id": "DashboardHub.getFilterOptions:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 565, - "end_line": 580, + "start_line": 595, + "end_line": 610, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79486,8 +85630,8 @@ "contract_id": "DashboardHub.getVisibleFilterOptions:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 582, - "end_line": 595, + "start_line": 612, + "end_line": 625, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79505,8 +85649,8 @@ "contract_id": "DashboardHub.toggleFilterDropdown:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 597, - "end_line": 626, + "start_line": 627, + "end_line": 656, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79524,8 +85668,8 @@ "contract_id": "DashboardHub.toggleFilterValue:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 628, - "end_line": 646, + "start_line": 658, + "end_line": 676, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79543,8 +85687,8 @@ "contract_id": "DashboardHub.clearColumnFilter:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 648, - "end_line": 660, + "start_line": 678, + "end_line": 690, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79562,8 +85706,8 @@ "contract_id": "DashboardHub.selectAllColumnFilterValues:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 662, - "end_line": 677, + "start_line": 692, + "end_line": 707, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79581,8 +85725,8 @@ "contract_id": "DashboardHub.updateColumnFilterSearch:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 679, - "end_line": 689, + "start_line": 709, + "end_line": 719, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79600,8 +85744,8 @@ "contract_id": "DashboardHub.hasColumnFilter:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 691, - "end_line": 701, + "start_line": 721, + "end_line": 731, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79619,8 +85763,8 @@ "contract_id": "DashboardHub.doesDashboardPassColumnFilters:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 703, - "end_line": 720, + "start_line": 733, + "end_line": 750, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79638,8 +85782,8 @@ "contract_id": "DashboardHub.getSortValue:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 722, - "end_line": 740, + "start_line": 752, + "end_line": 770, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79657,8 +85801,8 @@ "contract_id": "DashboardHub.handleSort:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 742, - "end_line": 759, + "start_line": 772, + "end_line": 789, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79676,8 +85820,8 @@ "contract_id": "DashboardHub.getSortIndicator:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 761, - "end_line": 772, + "start_line": 791, + "end_line": 802, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79695,8 +85839,8 @@ "contract_id": "DashboardHub.applyGridTransforms:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/+page.svelte", - "start_line": 774, - "end_line": 801, + "start_line": 804, + "end_line": 835, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -79730,7 +85874,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region DashboardHub.applyGridTransforms:Function [TYPE Function]\n /**\n * @PURPOSE: Apply search + column filters + sort + pagination to grid data.\n * @PRE: allDashboards is current source collection.\n * @POST: filteredDashboards/dashboards/total/totalPages are synchronized.\n * @UX_STATE: Loaded -> visible rows reflect all active controls deterministically.\n */\n function applyGridTransforms() {\n const nextFiltered = allDashboards\n // Search and column filters are server-side.\n .filter(() => true);\n\n nextFiltered.sort((a, b) => {\n const aValue = getSortValue(a, sortColumn);\n const bValue = getSortValue(b, sortColumn);\n if (aValue < bValue) return sortDirection === \"asc\" ? -1 : 1;\n if (aValue > bValue) return sortDirection === \"asc\" ? 1 : -1;\n return 0;\n });\n\n filteredDashboards = nextFiltered;\n dashboards = filteredDashboards;\n total = serverTotal;\n totalPages = serverTotalPages;\n updateSelectionState();\n void hydrateVisibleGitStatusesBatch();\n }\n // #endregion DashboardHub.applyGridTransforms:Function\n" + "body": " // #region DashboardHub.applyGridTransforms:Function [TYPE Function]\n /**\n * @PURPOSE: Apply search + column filters + sort + pagination to grid data.\n * @PRE: allDashboards is current source collection.\n * @POST: filteredDashboards/dashboards/total/totalPages are synchronized.\n * @UX_STATE: Loaded -> visible rows reflect all active controls deterministically.\n */\n function applyGridTransforms() {\n let nextFiltered = allDashboards;\n // Client-side multi-select filter (SearchableMultiSelect)\n if (filterDashboardIds.length > 0) {\n nextFiltered = nextFiltered.filter((d) =>\n filterDashboardIds.includes(d.id),\n );\n }\n\n nextFiltered.sort((a, b) => {\n const aValue = getSortValue(a, sortColumn);\n const bValue = getSortValue(b, sortColumn);\n if (aValue < bValue) return sortDirection === \"asc\" ? -1 : 1;\n if (aValue > bValue) return sortDirection === \"asc\" ? 1 : -1;\n return 0;\n });\n\n filteredDashboards = nextFiltered;\n dashboards = filteredDashboards;\n total = serverTotal;\n totalPages = serverTotalPages;\n updateSelectionState();\n void hydrateVisibleGitStatusesBatch();\n }\n // #endregion DashboardHub.applyGridTransforms:Function\n" }, { "contract_id": "DashboardHeader", @@ -79886,7 +86030,7 @@ "contract_type": "Page", "file_path": "frontend/src/routes/dashboards/health/+page.svelte", "start_line": 1, - "end_line": 229, + "end_line": 243, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -79902,6 +86046,12 @@ "target_id": "HealthMatrix", "target_ref": "[HealthMatrix]" }, + { + "source_id": "HealthCenterPage", + "relation_type": "DEPENDS_ON", + "target_id": "ScheduleAtAGlance", + "target_ref": "[ScheduleAtAGlance]" + }, { "source_id": "HealthCenterPage", "relation_type": "CALLS", @@ -80035,14 +86185,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n
\n
\n
\n

{$t.health?.title}

\n

{$t.health?.subtitle}

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

{$t.health?.validation_details}

\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n {#if loading}\n {#each Array(3) as _}\n \n \n \n \n \n \n \n \n {/each}\n {:else if healthData.items.length === 0}\n \n \n \n {:else}\n {#each healthData.items as item}\n \n \n \n \n \n \n \n \n {/each}\n {/if}\n \n
{$t.health?.table_dashboard}{$t.health?.table_environment}{$t.health?.table_status}{$t.health?.table_last_check}{$t.health?.table_summary}\n {$t.common?.actions}\n
\n {$t.health?.no_records}\n
\n \n {item.dashboard_slug || item.dashboard_id}\n \n \n {item.environment_id}\n \n \n {item.status}\n \n \n {formatDistanceToNow(new Date(item.last_check), { addSuffix: true })}\n \n {item.summary || '-'}\n \n {#if item.task_id}\n {$t.health?.view_report}\n {/if}\n handleDeleteReport(item)}\n disabled={deletingReportIds.has(item.record_id)}\n >\n {deletingReportIds.has(item.record_id) ? '...' : $t.common?.delete}\n \n
\n
\n
\n
\n\n" + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n

{$t.health?.title}

\n

{$t.health?.subtitle}

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

{$t.health?.validation_details}

\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n {#if loading}\n {#each Array(3) as _, i (i)}\n \n \n \n \n \n \n \n \n {/each}\n {:else if healthData.items.length === 0}\n \n \n \n {:else}\n {#each healthData.items as item (item.record_id || item.dashboard_id)}\n \n \n \n \n \n \n \n \n {/each}\n {/if}\n \n
{$t.health?.table_dashboard}{$t.health?.table_environment}{$t.health?.table_status}{$t.health?.table_last_check}{$t.health?.table_summary}\n {$t.common?.actions}\n
\n {$t.health?.no_records}\n
\n \n \n {item.dashboard_slug || item.dashboard_id}\n \n \n {item.environment_id}\n \n \n {item.status}\n \n \n {formatDistanceToNow(new Date(item.last_check), { addSuffix: true })}\n \n {item.summary || '-'}\n \n {#if item.task_id}\n \n {$t.health?.view_report}\n {/if}\n handleDeleteReport(item)}\n disabled={deletingReportIds.has(item.record_id)}\n >\n {deletingReportIds.has(item.record_id) ? '...' : $t.common?.delete}\n \n
\n
\n
\n
\n\n" }, { "contract_id": "loadData:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/health/+page.svelte", - "start_line": 31, - "end_line": 58, + "start_line": 35, + "end_line": 64, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -80055,14 +86205,14 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region loadData:Function [TYPE Function]\n // @PURPOSE: Load health summary rows and environment options for the current filter.\n // @PRE: Page is mounted or environment selection changed.\n // @POST: `healthData` and `environments` reflect latest backend response.\n // @SIDE_EFFECT: Calls backend API endpoints for health summary and environments.\n async function loadData() {\n loading = true;\n error = null;\n try {\n const summaryPromise = selectedEnvId\n ? getHealthSummary(selectedEnvId)\n : healthStore.refresh();\n const [summary, envs] = await Promise.all([\n summaryPromise,\n getEnvironments()\n ]);\n healthData = summary;\n environments = envs;\n if (!selectedEnvId && envs.length > 0) {\n // selectedEnvId = envs[0].id; // Optional: default to first env\n }\n } catch (e) {\n error = e.message;\n } finally {\n loading = false;\n }\n }\n // #endregion loadData:Function\n" + "body": " // #region loadData:Function [TYPE Function]\n // @PURPOSE: Load health summary rows and environment options for the current filter.\n // @PRE: Page is mounted or environment selection changed.\n // @POST: `healthData` and `environments` reflect latest backend response.\n // @SIDE_EFFECT: Calls backend API endpoints for health summary and environments.\n async function loadData() {\n loading = true;\n error = null;\n try {\n const summaryPromise = selectedEnvId\n ? getHealthSummary(selectedEnvId)\n : healthStore.refresh();\n const [summary, envs, consolidated] = await Promise.all([\n summaryPromise,\n getEnvironments(),\n getConsolidatedSettings().catch(() => ({ app_timezone: 'Europe/Moscow' }))\n ]);\n healthData = summary;\n environments = envs;\n appTimezone = consolidated.app_timezone || 'Europe/Moscow';\n if (!selectedEnvId && envs.length > 0) {\n // selectedEnvId = envs[0].id; // Optional: default to first env\n }\n } catch (e) {\n error = e.message;\n } finally {\n loading = false;\n }\n }\n // #endregion loadData:Function\n" }, { "contract_id": "handleEnvChange:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/health/+page.svelte", - "start_line": 64, - "end_line": 72, + "start_line": 70, + "end_line": 78, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -80080,8 +86230,8 @@ "contract_id": "handleDeleteReport:Function", "contract_type": "Function", "file_path": "frontend/src/routes/dashboards/health/+page.svelte", - "start_line": 74, - "end_line": 100, + "start_line": 80, + "end_line": 104, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -80094,7 +86244,7 @@ "schema_warnings": [], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": " // #region handleDeleteReport:Function [TYPE Function]\n // @PURPOSE: Delete one health report row with confirmation and optimistic button lock.\n // @PRE: item contains `record_id` from health summary payload.\n // @POST: Row is removed from backend and page data is reloaded on success.\n // @SIDE_EFFECT: Calls DELETE health API and emits toast notifications.\n async function handleDeleteReport(item) {\n if (!item?.record_id || deletingReportIds.has(item.record_id)) return;\n if (!confirm($t.health?.delete_confirm.replace('{slug}', item.dashboard_slug || item.dashboard_id))) return;\n\n deletingReportIds.add(item.record_id);\n deletingReportIds = new Set(deletingReportIds);\n\n try {\n await requestApi(`/health/summary/${item.record_id}`, 'DELETE');\n addToast($t.health?.delete_success.replace('{slug}', item.dashboard_slug || item.dashboard_id), 'success');\n await loadData();\n } catch (e) {\n addToast(\n $t.health?.delete_failed.replace('{error}', e?.message || $t.common?.error),\n 'error',\n );\n } finally {\n deletingReportIds.delete(item.record_id);\n deletingReportIds = new Set(deletingReportIds);\n }\n }\n // #endregion handleDeleteReport:Function\n" + "body": " // #region handleDeleteReport:Function [TYPE Function]\n // @PURPOSE: Delete one health report row with confirmation and optimistic button lock.\n // @PRE: item contains `record_id` from health summary payload.\n // @POST: Row is removed from backend and page data is reloaded on success.\n // @SIDE_EFFECT: Calls DELETE health API and emits toast notifications.\n async function handleDeleteReport(item) {\n if (!item?.record_id || deletingReportIds.has(item.record_id)) return;\n if (!confirm($t.health?.delete_confirm.replace('{slug}', item.dashboard_slug || item.dashboard_id))) return;\n\n deletingReportIds.add(item.record_id);\n\n try {\n await requestApi(`/health/summary/${item.record_id}`, 'DELETE');\n addToast($t.health?.delete_success.replace('{slug}', item.dashboard_slug || item.dashboard_id), 'success');\n await loadData();\n } catch (e) {\n addToast(\n $t.health?.delete_failed.replace('{error}', e?.message || $t.common?.error),\n 'error',\n );\n } finally {\n deletingReportIds.delete(item.record_id);\n }\n }\n // #endregion handleDeleteReport:Function\n" }, { "contract_id": "HealthPageIntegrationTest:Module", @@ -80173,7 +86323,7 @@ "contract_type": "Page", "file_path": "frontend/src/routes/datasets/+page.svelte", "start_line": 1, - "end_line": 407, + "end_line": 467, "tier": "TIER_3", "complexity": 5, "metadata": { @@ -80210,7 +86360,7 @@ ], "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" + "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 \n {$t.datasets?.source_type ?? 'Тип источника'}\n \n \n { if (mapSourceType === 'sqllab' && mapDatabases.length === 0 && selectedEnv) { api.getEnvironmentDatabases(selectedEnv).then(dbs => mapDatabases = dbs ?? []).catch(() => {}); } }}\n >\n \n \n \n {#if mapSourceType === \"sqllab\"}\n \n \n \n \n \n \n {#each mapDatabases as db (db.id)}\n \n {/each}\n \n \n \n \n \n \n
\n {$t.datasets?.sql_templates ?? 'Шаблоны'}:\n { mapSqlQuery = \"SELECT c.column_name, c.data_type, pgd.description\\nFROM information_schema.columns c\\nLEFT JOIN pg_catalog.pg_description pgd ON pgd.objsubid = c.ordinal_position\\n AND pgd.objoid = (SELECT attrelid FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = c.table_name) AND attname = c.column_name)\\nWHERE c.table_schema = 'public'\\n AND c.table_name = 'your_table_name'\\nORDER BY c.ordinal_position;\" }}\n >information_schema\n { mapSqlQuery = \"SELECT column_name, description AS verbose_name\\nFROM my_column_mappings\\nWHERE table_name = 'your_table_name'\\nORDER BY column_name;\" }}\n >{$t.datasets?.sql_template_custom ?? 'Кастомная таблица'}\n { mapSqlQuery = \"\"; }}\n >{$t.datasets?.sql_template_clear ?? 'Очистить'}\n
\n \n {:else}\n \n \n \n \n mapFileData = e.target.files}\n />\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 {$t.datasets?.select_llm_provider ?? 'LLM-провайдер'}\n \n \n \n
\n \n \n
\n
\n
\n {/if}\n\n\n" }, { "contract_id": "ColumnsTable", @@ -80268,13 +86418,14 @@ "contract_type": "Component", "file_path": "frontend/src/routes/datasets/DatasetList.svelte", "start_line": 1, - "end_line": 168, + "end_line": 190, "tier": "TIER_2", "complexity": 4, "metadata": { "COMPLEXITY": 4, - "LAYER": "UI", "PURPOSE": "Renders paginated dataset cards with mapping progress bars, checkboxes, and quick actions.", + "RATIONALE": "Action buttons switched from bg-primary solid to border-outline style, card padding reduced from p-3 to p-2.5, row gap from gap-3 to gap-2.5 — fixes \"huge buttons\" visual complaint.", + "REJECTED": "Solid blue action buttons rejected — too visually heavy on each card line.", "UX_REACTIVITY": "Props -> datasets, selectedIds, isLoading, error, total, page, totalPages, pageSize, onselect, onaction, onpagechange, onsearch, oncheckbox", "UX_STATE": "Empty -> \"No datasets found\" after search/filter." }, @@ -80286,33 +86437,10 @@ "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" - } - } - ], + "schema_warnings": [], "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" + "body": "\n\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 _, _i (_i)}\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 (dataset.id)}\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 >\n \n \n \n \n \n \n \n \n { e.stopPropagation(); onaction?.(dataset, 'generate_docs'); }}\n >\n \n \n \n \n \n \n \n \n \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", @@ -80426,16 +86554,16 @@ "contract_type": "Component", "file_path": "frontend/src/routes/datasets/StatsBar.svelte", "start_line": 1, - "end_line": 51, + "end_line": 49, "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." + "PURPOSE": "Compact filter pills showing aggregate counts (All, Without mapping, Mapped, Linked).", + "RATIONALE": "Converted from card tiles (p-3, text-2xl) to compact pills (rounded-full px-3 py-1 text-sm) to fix oversized buttons complaint.", + "REJECTED": "Card-tile filter buttons rejected — were too visually heavy at 12px padding + 24px font, dominating the page top.", + "UX_REACTIVITY": "Events -> onfilter(filterKey) emitted on pill click", + "UX_STATE": "Filtered -> selected pill has filled background; parent reloads with filter param." }, "relations": [ { @@ -80445,52 +86573,10 @@ "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 }}" - } - } - ], + "schema_warnings": [], "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" + "body": "\n\n\n\n\n\n\n\n\n\n\n\n
\n {#each tiles as tile (tile.key)}\n {#if isLoading}\n
\n {:else}\n handleTileClick(tile.key)}\n aria-pressed={activeFilter === tile.key}\n title={$t.datasets?.[tile.key === 'all' ? 'filter_all_tip' : tile.key === 'unmapped' ? 'filter_unmapped_tip' : tile.key === 'mapped' ? 'filter_mapped_tip' : 'filter_linked_tip']}\n >\n {$t.datasets?.[tile.label] ?? tile.label}\n {tile.getCount(stats)}\n \n {/if}\n {/each}\n
\n\n" }, { "contract_id": "DatasetReviewWorkspaceEntry", @@ -81800,6 +87886,210 @@ "tier_source": "AutoCalculated", "body": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n

{$t.auth?.login }

\n\n {#if error}\n
\n {error}\n
\n {/if}\n\n
{ event.preventDefault(); handleLogin(); }} class=\"space-y-4\">\n
\n \n \n
\n\n
\n \n \n
\n\n \n {loading ? ($t.auth?.logging_in ) : ($t.auth?.login )}\n \n \n\n
\n
\n
\n
\n
\n
\n {$t.auth?.or_continue_with }\n
\n
\n\n
\n \n {$t.auth?.corporate_sso }\n \n
\n
\n
\n\n\n" }, + { + "contract_id": "MaintenanceBannerPage", + "contract_type": "Page", + "file_path": "frontend/src/routes/maintenance/+page.svelte", + "start_line": 1, + "end_line": 81, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "LAYER": "Page", + "PURPOSE": "Maintenance Banners management page. Composes SettingsPanel and EventsTable from store.", + "UX_FEEDBACK": "Toast via addToast() from $lib/toasts.js", + "UX_RECOVERY": "Refresh via maintenanceStore.loadEvents().", + "UX_STATE": "Error -> Error toast shown." + }, + "relations": [ + { + "source_id": "MaintenanceBannerPage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceStore", + "target_ref": "[MaintenanceStore]" + }, + { + "source_id": "MaintenanceBannerPage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceSettingsPanel", + "target_ref": "[MaintenanceSettingsPanel]" + }, + { + "source_id": "MaintenanceBannerPage", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceEventsTable", + "target_ref": "[MaintenanceEventsTable]" + } + ], + "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": "LAYER", + "message": "@LAYER is not allowed for contract type 'Page'", + "detail": { + "actual_type": "Page", + "allowed_types": [ + "Module", + "Skill", + "Agent" + ] + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "LAYER", + "message": "@LAYER is forbidden for contract type 'Page' at C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "invalid_enum_value", + "tag": "LAYER", + "message": "@LAYER value 'Page' is not in allowed enum", + "detail": { + "allowed": [ + "Core", + "Domain", + "API", + "UI", + "Service", + "Infrastructure", + "Plugin", + "Tests" + ], + "value": "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": "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 C3", + "detail": { + "actual_complexity": 3, + "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 C3", + "detail": { + "actual_complexity": 3, + "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 C3", + "detail": { + "actual_complexity": 3, + "contract_type": "Page" + } + }, + { + "code": "tag_forbidden_by_complexity", + "tag": "RELATION", + "message": "@RELATION 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 \n
\n

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

\n maintenanceStore.loadEvents()}\n disabled={pageLoading}\n class=\"inline-flex items-center justify-center rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50\"\n >\n {$t.common?.refresh || \"Refresh\"}\n \n
\n\n {#if pageLoading}\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n {#each [1, 2, 3] as _, i (i)}\n
\n {/each}\n
\n
\n {:else}\n \n maintenanceStore.loadEvents()} />\n\n \n \n\n \n \n {/if}\n
\n\n" + }, { "contract_id": "ReactiveDashboardFetch:Block", "contract_type": "Function", @@ -83530,7 +89820,7 @@ "contract_type": "Page", "file_path": "frontend/src/routes/settings/+page.svelte", "start_line": 1, - "end_line": 274, + "end_line": 290, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -83938,7 +90228,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 {$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" + "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 handleTabChange(\"system\")}\n >\n {$t.settings?.system || \"System\"}\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 {:else if activeTab === \"system\"}\n \n {/if}\n
\n {/if}\n\n\n" }, { "contract_id": "frontend/src/routes/settings/+page.ts::load", @@ -83960,7 +90250,7 @@ "contract_type": "Component", "file_path": "frontend/src/routes/settings/FeaturesSettings.svelte", "start_line": 1, - "end_line": 65, + "end_line": 72, "tier": "TIER_1", "complexity": 2, "metadata": { @@ -83997,14 +90287,14 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n
\n

\n {$t.settings?.features || \"Features\"}\n

\n

\n {$t.settings?.features_description || \"Enable or disable top-level application features.\"}\n

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

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

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

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

\n
\n \n
\n
\n\n
\n \n {$t.settings?.save_features || $t.settings?.save_logging || \"Save\"}\n \n
\n
\n
\n\n" + "body": "\n\n\n\n\n\n\n
\n

\n {$t.settings?.features || \"Features\"}\n

\n

\n {$t.settings?.features_description || \"Enable or disable top-level application features.\"}\n

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

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

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

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

\n
\n \n
\n
\n\n
\n \n {$t.settings?.save_features || $t.settings?.save_logging || \"Save\"}\n \n
\n
\n
\n\n" }, { "contract_id": "LlmSettings", "contract_type": "Component", "file_path": "frontend/src/routes/settings/LlmSettings.svelte", "start_line": 1, - "end_line": 225, + "end_line": 250, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -84056,7 +90346,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n\n
\n

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

\n

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

\n\n \n\n
\n

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

\n

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

\n\n
\n
\n \n {$t.settings?.llm_chatbot_provider}\n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n\n
\n \n {$t.settings?.llm_chatbot_model}\n \n \n
\n
\n
\n\n
\n

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

\n

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

\n\n
\n
\n \n {$t.settings?.llm_binding_dashboard_validation}\n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n {#if !isDashboardValidationBindingValid(settings)}\n

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

\n {/if}\n
\n\n
\n \n {$t.settings?.llm_binding_documentation}\n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n\n
\n \n {$t.settings?.llm_binding_git_commit}\n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n
\n
\n\n
\n

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

\n

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

\n\n
\n
\n \n {$t.settings?.llm_prompt_documentation}\n \n \n
\n\n
\n \n {$t.settings?.llm_prompt_dashboard_validation}\n \n \n
\n\n
\n \n {$t.settings?.llm_prompt_git_commit}\n \n \n
\n
\n\n
\n \n {$t.settings?.save_llm_prompts}\n \n
\n
\n
\n\n" + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n

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

\n

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

\n\n \n\n
\n

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

\n

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

\n\n
\n
\n \n \n {$t.settings?.llm_chatbot_provider}\n \n \n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n\n
\n \n \n {$t.settings?.llm_chatbot_model}\n \n \n \n \n
\n
\n
\n\n
\n

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

\n

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

\n\n
\n
\n \n \n {$t.settings?.llm_binding_dashboard_validation}\n \n \n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n {#if !isDashboardValidationBindingValid(settings)}\n

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

\n {/if}\n
\n\n
\n \n \n {$t.settings?.llm_binding_documentation}\n \n \n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n\n
\n \n \n {$t.settings?.llm_binding_git_commit}\n \n \n \n \n \n {#each settings.llm_providers || [] as provider}\n \n {/each}\n \n
\n
\n
\n\n
\n

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

\n

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

\n\n
\n
\n \n \n {$t.settings?.llm_prompt_documentation}\n \n \n \n \n
\n\n
\n \n \n {$t.settings?.llm_prompt_dashboard_validation}\n \n \n \n \n
\n\n
\n \n \n {$t.settings?.llm_prompt_git_commit}\n \n \n \n \n
\n
\n\n
\n \n {$t.settings?.save_llm_prompts}\n \n
\n
\n
\n\n" }, { "contract_id": "LoggingSettings", @@ -84169,7 +90459,7 @@ "contract_type": "Component", "file_path": "frontend/src/routes/settings/MigrationSettings.svelte", "start_line": 1, - "end_line": 139, + "end_line": 144, "tier": "TIER_2", "complexity": 3, "metadata": { @@ -84215,7 +90505,7 @@ ], "anchor_syntax": "region", "tier_source": "AutoCalculated", - "body": "\n\n\n\n\n\n\n\n\n\n\n
\n

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

\n

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

\n\n \n
\n

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

\n
\n
\n {$t.tasks?.cron_label}\n \n

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

\n
\n \n {isSavingMigration ? $t.settings?.saving : $t.common?.save}\n \n \n {#if isSyncing}\n \n {$t.settings?.syncing}\n {:else}\n \n {$t.settings?.sync_now}\n {/if}\n \n
\n
\n\n \n
\n\n" + "body": "\n\n\n\n\n\n\n\n\n\n\n
\n

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

\n

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

\n\n \n
\n

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

\n
\n
\n \n {$t.tasks?.cron_label}\n \n \n \n

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

\n
\n \n {isSavingMigration ? $t.settings?.saving : $t.common?.save}\n \n \n {#if isSyncing}\n \n {$t.settings?.syncing}\n {:else}\n \n {$t.settings?.sync_now}\n {/if}\n \n
\n
\n\n \n
\n\n" }, { "contract_id": "StorageSettings", @@ -84261,6 +90551,26 @@ "tier_source": "AutoCalculated", "body": "\n\n\n\n\n\n\n
\n

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

\n

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

\n\n
\n
\n
\n {$t.storage?.root}\n \n
\n
\n {$t.storage?.backups}\n \n
\n
\n {$t.storage?.repositories}\n \n
\n
\n\n
\n onSave()}\n class=\"bg-primary text-white px-4 py-2 rounded hover:bg-primary-hover\"\n >\n {$t.settings?.save_storage_config}\n \n
\n
\n
\n\n" }, + { + "contract_id": "SystemSettings", + "contract_type": "Component", + "file_path": "frontend/src/routes/settings/SystemSettings.svelte", + "start_line": 1, + "end_line": 93, + "tier": "TIER_2", + "complexity": 3, + "metadata": { + "COMPLEXITY": 3, + "POST": "User can select the application timezone and manage API keys.", + "PRE": "settings object is provided with app_timezone field.", + "PURPOSE": "System settings tab: timezone configuration and API key management." + }, + "relations": [], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "\n\n\n\n\n\n
\n \n
\n

{$t.settings?.system || \"System\"}

\n

{$t.settings?.system_description || \"Application-wide system settings including timezone.\"}

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

\n {$t.settings?.app_timezone_hint || \"All schedule times and timestamps will be displayed and executed in this timezone.\"}\n

\n \n {#each COMMON_TIMEZONES as tz (tz.value)}\n \n {/each}\n \n
\n\n \n
\n \n \n \n {settings.app_timezone}:\n \n {new Date().toLocaleString($locale === 'en' ? 'en-US' : 'ru-RU', { timeZone: settings.app_timezone || 'Europe/Moscow' })}\n \n
\n
\n\n
\n \n {$t.settings?.save_system || $t.settings?.save_logging || \"Save\"}\n \n
\n
\n
\n\n \n
\n \n
\n
\n\n" + }, { "contract_id": "SettingsPageUxTest:Module", "contract_type": "Function", @@ -84494,8 +90804,8 @@ "contract_id": "loadConfigs:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 57, - "end_line": 70, + "start_line": 58, + "end_line": 71, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84513,8 +90823,8 @@ "contract_id": "handleTest:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 74, - "end_line": 102, + "start_line": 75, + "end_line": 103, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84532,8 +90842,8 @@ "contract_id": "handleSave:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 104, - "end_line": 138, + "start_line": 105, + "end_line": 139, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84551,8 +90861,8 @@ "contract_id": "handleEdit:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 140, - "end_line": 160, + "start_line": 141, + "end_line": 161, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84577,8 +90887,8 @@ "contract_id": "resetForm:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 162, - "end_line": 178, + "start_line": 163, + "end_line": 179, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84594,8 +90904,8 @@ "contract_id": "loadGiteaRepos:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 202, - "end_line": 225, + "start_line": 203, + "end_line": 226, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84613,8 +90923,8 @@ "contract_id": "handleCreateGiteaRepo:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 227, - "end_line": 256, + "start_line": 228, + "end_line": 257, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84632,8 +90942,8 @@ "contract_id": "handleDeleteGiteaRepo:Function", "contract_type": "Function", "file_path": "frontend/src/routes/settings/git/+page.svelte", - "start_line": 258, - "end_line": 291, + "start_line": 259, + "end_line": 292, "tier": "TIER_1", "complexity": 1, "metadata": { @@ -84725,8 +91035,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": 41, - "end_line": 45, + "start_line": 42, + "end_line": 46, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84740,8 +91050,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": 51, - "end_line": 55, + "start_line": 52, + "end_line": 56, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84755,8 +91065,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": 63, - "end_line": 67, + "start_line": 64, + "end_line": 68, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84770,8 +91080,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": 77, - "end_line": 81, + "start_line": 78, + "end_line": 82, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84785,8 +91095,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": 98, - "end_line": 106, + "start_line": 99, + "end_line": 107, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84800,8 +91110,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": 114, - "end_line": 117, + "start_line": 115, + "end_line": 118, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84815,8 +91125,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": 127, - "end_line": 132, + "start_line": 128, + "end_line": 133, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -84830,8 +91140,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": 145, - "end_line": 149, + "start_line": 146, + "end_line": 150, "tier": "TIER_1", "complexity": 1, "metadata": {}, @@ -86409,7 +92719,7 @@ "contract_type": "Page", "file_path": "frontend/src/routes/validation/[id]/+page.svelte", "start_line": 1, - "end_line": 699, + "end_line": 722, "tier": "TIER_2", "complexity": 4, "metadata": { @@ -86634,7 +92944,7 @@ ], "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" + "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'}: {task?.created_at ? new Date(task.created_at).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 { dashboardIds = []; 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 ({ id: String(d.id), name: d.title || d.dashboard_title || d.name || String(d.id), subtitle: d.schema || '' }))}\n bind:selected={dashboardIds}\n placeholder={$t.validation?.dashboard || 'Select dashboard...'}\n selectAllLabel={$t.dashboard?.select_all || 'Select All'}\n clearLabel=\"Clear\"\n emptyMessage=\"No dashboards found\"\n disabled={!environmentId}\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 multimodalProviders 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 \n

\n \n \n \n {$t.validation?.schedule_timezone_hint || 'All times in'} {appTimezone}\n

\n
\n {/if}\n
\n\n \n
\n \n
\n
\n\n \n {:else if activeTab === 'history'}\n
\n \n
\n \n \n \n
\n

{$t.validation?.history_info_title || 'About run history'}

\n

{$t.validation?.history_info_desc || 'This tab shows validation runs for this specific task. Runs appear after you click \"Run Now\" or when the scheduled task executes. Each run captures a dashboard screenshot and sends it to the LLM provider for analysis.'}

\n
\n
\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

{$t.validation?.run_history_empty_hint || 'Click \"Run Now\" above to start a validation run. The result will appear here once analysis completes.'}

\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", @@ -89060,6 +95370,62 @@ "tier_source": "AutoCalculated", "body": "/**\n * @PURPOSE: TypeScript interfaces for Dashboard entities\n * @LAYER: Domain\n */" }, + { + "contract_id": "MaintenanceStoreTests", + "contract_type": "Module", + "file_path": "frontend/tests/maintenance-store.test.ts", + "start_line": 1, + "end_line": 174, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Unit tests for MaintenanceStore runes-based store." + }, + "relations": [ + { + "source_id": "MaintenanceStoreTests", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceStore", + "target_ref": "[MaintenanceStore]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region MaintenanceStoreTests [C:2] [TYPE Module] [SEMANTICS test, store, maintenance]\n// @BRIEF Unit tests for MaintenanceStore runes-based store.\n// @RELATION DEPENDS_ON -> [MaintenanceStore]\n\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\n\n// Use vi.hoisted to create mock functions before the mock factories\nconst { mockListEvents, mockGetSettings, mockUpdateSettings, mockEndMaintenance, mockEndAllMaintenance, mockListDashboardBanners } = vi.hoisted(() => ({\n mockListEvents: vi.fn(),\n mockGetSettings: vi.fn(),\n mockUpdateSettings: vi.fn(),\n mockEndMaintenance: vi.fn(),\n mockEndAllMaintenance: vi.fn(),\n mockListDashboardBanners: vi.fn(),\n}));\n\n// Mock toasts\nvi.mock('$lib/toasts.js', () => ({\n addToast: vi.fn()\n}));\n\n// Mock i18n\nvi.mock('$lib/i18n', () => ({\n t: { maintenance: {} }\n}));\n\nvi.mock('$lib/api/maintenance.js', () => ({\n listEvents: mockListEvents,\n getSettings: mockGetSettings,\n updateSettings: mockUpdateSettings,\n endMaintenance: mockEndMaintenance,\n endAllMaintenance: mockEndAllMaintenance,\n listDashboardBanners: mockListDashboardBanners,\n}));\n\nimport { createMaintenanceStore } from '$lib/stores/maintenance.svelte.js';\n\ndescribe('MaintenanceStore', () => {\n let store;\n\n beforeEach(() => {\n vi.clearAllMocks();\n mockListEvents.mockResolvedValue({ active: [], completed: [] });\n mockGetSettings.mockResolvedValue({\n target_environment_id: 'prod',\n display_timezone: 'UTC',\n banner_template: 'test template',\n dashboard_scope: 'published_only',\n excluded_dashboard_ids: [],\n forced_dashboard_ids: [],\n updated_at: null\n });\n mockListDashboardBanners.mockResolvedValue([]);\n store = createMaintenanceStore();\n });\n\n it('initializes with empty state', () => {\n expect(store.activeEvents).toEqual([]);\n expect(store.completedEvents).toEqual([]);\n expect(store.settings).toBeNull();\n expect(store.dashboardBanners).toEqual([]);\n expect(store.isLoading).toBe(false);\n expect(store.error).toBeNull();\n });\n\n it('loadEvents calls API and updates state', async () => {\n mockListEvents.mockResolvedValue({\n active: [{ id: 'ev-1', tables: ['raw.sales'], status: 'active' }],\n completed: [{ id: 'ev-2', tables: ['raw.inventory'], status: 'completed' }]\n });\n\n await store.loadEvents();\n\n expect(mockListEvents).toHaveBeenCalledTimes(1);\n expect(store.activeEvents).toHaveLength(1);\n expect(store.activeEvents[0].id).toBe('ev-1');\n expect(store.completedEvents).toHaveLength(1);\n expect(store.completedEvents[0].id).toBe('ev-2');\n });\n\n it('loadEvents sets error on API failure', async () => {\n mockListEvents.mockRejectedValue(new Error('Network error'));\n\n await store.loadEvents();\n\n expect(store.error).toBeTruthy();\n expect(store.activeEvents).toEqual([]);\n });\n\n it('loadSettings calls API and updates settings', async () => {\n const testSettings = {\n target_environment_id: 'staging',\n display_timezone: 'Europe/Moscow',\n banner_template: 'custom template',\n dashboard_scope: 'all',\n excluded_dashboard_ids: [1, 2],\n forced_dashboard_ids: [3],\n updated_at: null\n };\n mockGetSettings.mockResolvedValue(testSettings);\n\n await store.loadSettings();\n\n expect(store.settings).toEqual(testSettings);\n });\n\n it('loadSettings does not throw on API failure', async () => {\n mockGetSettings.mockRejectedValue(new Error('API error'));\n\n await expect(store.loadSettings()).resolves.not.toThrow();\n expect(store.settings).toBeNull();\n });\n\n it('loadDashboardBanners updates state', async () => {\n const banners = [\n { dashboard_id: 42, active: true, events: ['ev-1'], start_time: '2026-05-21T22:00:00Z', end_time: null },\n { dashboard_id: 57, active: false, events: [], start_time: null, end_time: null }\n ];\n mockListDashboardBanners.mockResolvedValue(banners);\n\n await store.loadDashboardBanners();\n\n expect(mockListDashboardBanners).toHaveBeenCalledTimes(1);\n expect(store.dashboardBanners).toHaveLength(2);\n });\n\n it('loadDashboardBanners handles non-array response', async () => {\n mockListDashboardBanners.mockResolvedValue(null);\n\n await store.loadDashboardBanners();\n\n expect(store.dashboardBanners).toEqual([]);\n });\n\n it('endEvent calls API and refreshes events', async () => {\n mockEndMaintenance.mockResolvedValue({ task_id: 'task-1', status: 'pending' });\n mockListEvents.mockResolvedValue({ active: [], completed: [] });\n\n await store.endEvent('ev-1');\n\n expect(mockEndMaintenance).toHaveBeenCalledWith('ev-1');\n expect(mockListEvents).toHaveBeenCalled();\n });\n\n it('endAllEvents calls API and refreshes events', async () => {\n mockEndAllMaintenance.mockResolvedValue({ task_id: 'task-bulk', status: 'pending' });\n mockListEvents.mockResolvedValue({ active: [], completed: [] });\n\n await store.endAllEvents();\n\n expect(mockEndAllMaintenance).toHaveBeenCalled();\n expect(mockListEvents).toHaveBeenCalled();\n });\n\n it('updateSettings calls API and updates settings', async () => {\n const newSettings = { dashboard_scope: 'all' };\n mockUpdateSettings.mockResolvedValue({\n ...newSettings,\n target_environment_id: 'prod',\n display_timezone: 'UTC',\n banner_template: 'test',\n excluded_dashboard_ids: [],\n forced_dashboard_ids: [],\n updated_at: '2026-05-22T10:00:00Z'\n });\n\n await store.updateSettings(newSettings);\n\n expect(mockUpdateSettings).toHaveBeenCalledWith(newSettings);\n expect(store.settings).toBeTruthy();\n expect(store.settings.dashboard_scope).toBe('all');\n });\n});\n// #endregion MaintenanceStoreTests\n" + }, + { + "contract_id": "MaintenanceComponentTests", + "contract_type": "Module", + "file_path": "frontend/tests/maintenance.test.ts", + "start_line": 1, + "end_line": 189, + "tier": "TIER_1", + "complexity": 2, + "metadata": { + "COMPLEXITY": 2, + "PURPOSE": "Component tests for MaintenanceEventsTable and DashboardMaintenanceBadge." + }, + "relations": [ + { + "source_id": "MaintenanceComponentTests", + "relation_type": "DEPENDS_ON", + "target_id": "MaintenanceEventsTable", + "target_ref": "[MaintenanceEventsTable]" + }, + { + "source_id": "MaintenanceComponentTests", + "relation_type": "DEPENDS_ON", + "target_id": "DashboardMaintenanceBadge", + "target_ref": "[DashboardMaintenanceBadge]" + } + ], + "schema_warnings": [], + "anchor_syntax": "region", + "tier_source": "AutoCalculated", + "body": "// #region MaintenanceComponentTests [C:2] [TYPE Module] [SEMANTICS test, component, maintenance, events-table, badge]\n// @BRIEF Component tests for MaintenanceEventsTable and DashboardMaintenanceBadge.\n// @RELATION DEPENDS_ON -> [MaintenanceEventsTable]\n// @RELATION DEPENDS_ON -> [DashboardMaintenanceBadge]\n\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\n\n// Create mutable mock data using vi.hoisted\nconst { mockStoreState, mockStore } = vi.hoisted(() => {\n const sharedState = {\n activeEvents: [],\n completedEvents: [],\n settings: null,\n dashboardBanners: [],\n isLoading: false,\n error: null,\n };\n\n const store = {\n get activeEvents() { return sharedState.activeEvents; },\n get completedEvents() { return sharedState.completedEvents; },\n get settings() { return sharedState.settings; },\n get dashboardBanners() { return sharedState.dashboardBanners; },\n get isLoading() { return sharedState.isLoading; },\n get error() { return sharedState.error; },\n loadEvents: vi.fn(),\n loadSettings: vi.fn(),\n loadDashboardBanners: vi.fn(),\n endEvent: vi.fn(),\n endAllEvents: vi.fn(),\n updateSettings: vi.fn(),\n init: vi.fn(),\n startPolling: vi.fn(),\n stopPolling: vi.fn(),\n };\n\n return { mockStoreState: sharedState, mockStore: store };\n});\n\nfunction resetMockStore() {\n mockStoreState.activeEvents = [];\n mockStoreState.completedEvents = [];\n mockStoreState.settings = null;\n mockStoreState.dashboardBanners = [];\n mockStoreState.isLoading = false;\n mockStoreState.error = null;\n}\n\n// Mock toasts\nvi.mock('$lib/toasts.js', () => ({\n addToast: vi.fn()\n}));\n\n// Mock i18n — $t is a derived store, needs subscribe method for Svelte $ prefix\nvi.mock('$lib/i18n', () => {\n const subscribers = new Set();\n const tData = {\n maintenance: {\n active_events: 'Active Events',\n completed_events: 'Completed Events',\n no_active_events: 'No active maintenance events',\n no_completed_events: 'No completed maintenance events',\n remove_banners: 'Remove',\n remove_all: 'Remove All',\n maintenance_badge: 'Maintenance',\n maintenance_tooltip: 'Maintenance active: {start} — {end}',\n event_id: 'Event ID',\n tables: 'Tables',\n affected_dashboards: 'Dashboards',\n start_time: 'Start Time',\n end_time: 'End Time',\n status: 'Status',\n actions: 'Actions',\n },\n common: {}\n };\n return {\n t: {\n subscribe(run) {\n subscribers.add(run);\n run(tData);\n return () => subscribers.delete(run);\n }\n },\n _: (key) => key,\n };\n});\n\nvi.mock('$lib/stores/maintenance.svelte.js', () => ({\n maintenanceStore: mockStore,\n createMaintenanceStore: () => mockStore,\n}));\n\n// Mock the API module\nvi.mock('$lib/api.js', () => ({\n api: {\n getEnvironments: vi.fn(() => Promise.resolve([])),\n getDashboards: vi.fn(() => Promise.resolve({ dashboards: [] })),\n },\n requestApi: vi.fn(),\n}));\n\n// Mock $app/navigation\nvi.mock('$app/navigation', () => ({\n goto: vi.fn(),\n}));\n\n// Mock $app/stores\nvi.mock('$app/stores', () => ({\n page: { subscribe: vi.fn() },\n navigating: { subscribe: vi.fn() },\n updated: { subscribe: vi.fn() },\n}));\n\nimport { render, screen } from '@testing-library/svelte';\nimport MaintenanceEventsTable from '$lib/components/MaintenanceEventsTable.svelte';\nimport DashboardMaintenanceBadge from '$lib/components/DashboardMaintenanceBadge.svelte';\n\ndescribe('MaintenanceEventsTable', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n resetMockStore();\n });\n\n it('renders empty state when no active events', async () => {\n mockStoreState.activeEvents = [];\n mockStoreState.completedEvents = [];\n render(MaintenanceEventsTable);\n expect(screen.getByText('No active maintenance events')).toBeTruthy();\n });\n\n it('renders active events in the table', async () => {\n mockStoreState.activeEvents = [\n { id: 'ev-1', tables: ['raw.sales'], affected_count: 3, start_time: '2026-05-21T22:00:00Z', end_time: null, status: 'active' }\n ];\n mockStoreState.completedEvents = [];\n render(MaintenanceEventsTable);\n expect(screen.getByText('ev-1')).toBeTruthy();\n });\n\n it('renders Remove All button when events exist', async () => {\n mockStoreState.activeEvents = [\n { id: 'ev-1', tables: ['raw.sales'], affected_count: 3, start_time: '2026-05-21T22:00:00Z', end_time: null, status: 'active' }\n ];\n mockStoreState.completedEvents = [];\n render(MaintenanceEventsTable);\n expect(screen.getByText('Remove All')).toBeTruthy();\n });\n});\n\ndescribe('DashboardMaintenanceBadge', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n resetMockStore();\n });\n\n it('renders nothing when no banner state for dashboard', async () => {\n mockStoreState.dashboardBanners = [];\n const { container } = render(DashboardMaintenanceBadge, {\n props: { dashboardId: 42 }\n });\n const badgeElements = container.querySelectorAll('.bg-orange-100');\n expect(badgeElements.length).toBe(0);\n });\n\n it('renders badge when banner is active for dashboard', async () => {\n mockStoreState.dashboardBanners = [\n { dashboard_id: 42, active: true, events: ['ev-1'], start_time: '2026-05-21T22:00:00Z', end_time: null }\n ];\n const { container } = render(DashboardMaintenanceBadge, {\n props: { dashboardId: 42 }\n });\n const badge = container.querySelector('.bg-orange-100');\n expect(badge).toBeTruthy();\n expect(badge?.textContent).toContain('Maintenance');\n });\n\n it('renders nothing when banner exists but not active for this dashboard', async () => {\n mockStoreState.dashboardBanners = [\n { dashboard_id: 57, active: true, events: ['ev-1'], start_time: '2026-05-21T22:00:00Z', end_time: null }\n ];\n const { container } = render(DashboardMaintenanceBadge, {\n props: { dashboardId: 42 }\n });\n const badge = container.querySelector('.bg-orange-100');\n expect(badge).toBeNull();\n });\n});\n// #endregion MaintenanceComponentTests\n" + }, { "contract_id": "MergeSpec", "contract_type": "Module", @@ -89322,6642 +95688,6718 @@ } ], "file_hashes": { - "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/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/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/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/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/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, - "frontend/src/components/MappingTable.svelte": 17937756426921453860, - "frontend/test-results/translation.e2e.js-Transla-49baf-te-a-translation-job-via-UI-chromium/video.webm": 3868075359950286684, - "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, - "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, - "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/cryptography/hazmat/primitives/asymmetric/types.py": 1343652083039949282, + "venv/lib/python3.13/site-packages/anyio/abc/_eventloop.py": 2023190981288767991, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_validate.py": 2133732492454460539, + "frontend/build/_app/immutable/nodes/34.BvudVJiY.js": 938635370536078571, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/RECORD": 8971487317739420905, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_palettes.py": 13495896173068490516, + "venv/lib/python3.13/site-packages/idna/codec.py": 4260241549062101779, + "venv/lib/python3.13/site-packages/pycparser/ply/ygen.py": 5520340773074632724, + "venv/lib/python3.13/site-packages/greenlet/TUserGreenlet.cpp": 16258622236210473101, + "venv/lib/python3.13/site-packages/h11/_state.py": 11398755254809751139, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_ticks.py": 11649965080303468085, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/WHEEL": 18203500019759199992, + "venv/lib/python3.13/site-packages/pandas/tests/test_expressions.py": 16378925536309828288, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/poolmanager.py": 5071697837617938064, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/validator_creation.py": 2745563768861102999, + "venv/lib/python3.13/site-packages/pillow.libs/libharfbuzz-0692f733.so.0.61230.0": 23110287346167671, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.pyi": 17469792319379909312, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/PIL/_imaging.pyi": 17119084207765761921, + "backend/src/models/dataset_review.py": 5814500849969423218, + "venv/lib/python3.13/site-packages/pydantic/_internal/_known_annotated_metadata.py": 9308620143218174987, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE.PSF": 13208428090829817329, + "venv/lib/python3.13/site-packages/tzlocal/unix.py": 995019116408448073, + "venv/lib/python3.13/site-packages/pandas/tests/apply/conftest.py": 13798335354961261346, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_to_xarray.py": 15341013524814290960, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_common.py": 12064185052519470358, + "venv/lib/python3.13/site-packages/pandas/io/stata.py": 14370692318835340323, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py": 6509914623926583629, + "venv/lib/python3.13/site-packages/PIL/ImageMorph.py": 13861961228125789866, + "venv/lib/python3.13/site-packages/pygments/lexers/sgf.py": 6802546617450210439, + "backend/src/plugins/translate/dictionary_entries.py": 11394786590056973146, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_skew_kurt.py": 15225601437354712351, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.py": 15426828792217499138, + "venv/lib/python3.13/site-packages/keyring/backends/null.py": 12740996416911604870, + "venv/lib/python3.13/site-packages/greenlet/tests/test_leaks.py": 1219835696230215605, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py": 16829312896275893002, + "frontend/build/_app/immutable/chunks/7p8qW0H9.js": 8406910162058460039, + "frontend/build/_app/env.js": 8815854342083926790, + "backend/src/schemas/translate.py": 15939985987703420591, + "venv/lib/python3.13/site-packages/numpy/fft/_helper.py": 15906444100774706395, + "venv/lib/python3.13/site-packages/git/refs/head.py": 16271128287606894569, + "backend/src/models/dataset_review_pkg/__init__.py": 17789694606496652579, + "backend/src/services/clean_release/demo_data_service.py": 1822246829322620623, + "backend/src/services/maintenance/_chart_manager.py": 11268757631496775895, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunclike.pyi": 12215374902556647369, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/constants.pyi": 15633065380510755171, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/random.pyi": 9425735458050148191, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein_py.py": 11350239659973489646, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/ma/core.pyi": 4829891173366130328, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_names.py": 10037208029090713121, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_comparison.py": 5348781442514871089, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_update_delete.py": 1317337950621091021, + "venv/lib/python3.13/site-packages/PIL/BdfFontFile.py": 10811640174253687845, + "venv/lib/python3.13/site-packages/pycparser/ply/yacc.py": 4218889705926129841, + "venv/lib/python3.13/site-packages/pygments/lexers/sophia.py": 15971500155124949058, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi": 13016654355866474644, + "backend/src/plugins/translate/preview_constants.py": 12447768695944862994, + "venv/lib/python3.13/site-packages/pygments/lexers/smithy.py": 10789533877863290582, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_expanding.py": 9047466276603454007, + "venv/lib/python3.13/site-packages/pygments/lexers/_vbscript_builtins.py": 9882134558469491349, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py": 5995058808539530576, + "venv/lib/python3.13/site-packages/PIL/ImImagePlugin.py": 15452956038794399492, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/dotenv.py": 5872848911499749500, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/npyio.pyi": 14147712281086095231, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_numba.py": 8250377774229977284, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_map.py": 1115471561925426082, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/RECORD": 10552906886624188222, + "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.pyi": 11535882608355652318, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_take.py": 3281943380342853080, + "venv/lib/python3.13/site-packages/greenlet/TGreenletGlobals.cpp": 17400526028982558937, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_accuracy.py": 3904008607472505376, + "venv/lib/python3.13/site-packages/pydantic/_internal/_signature.py": 17075003201648027250, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bus_messages.py": 4323093138307306385, + "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimes.py": 10585034798097337148, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_dst.py": 12243642467695371088, + "venv/lib/python3.13/site-packages/h11/_headers.py": 7592730288271984585, + "venv/lib/python3.13/site-packages/_pytest/tmpdir.py": 10834220332037364219, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv": 8620268345075425735, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dtype.py": 5553691086633215767, + "backend/src/core/logger/__tests__/test_logger.py": 11665830455325390168, + "venv/lib/python3.13/site-packages/pillow.libs/libavif-01e67780.so.16.3.0": 13947441788826399574, + "venv/lib/python3.13/site-packages/pyasn1/codec/streaming.py": 13202773554072937140, + "venv/lib/python3.13/site-packages/pandas/_libs/interval.pyi": 15698173755300703836, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_dialect.py": 6294522482440261756, + "venv/lib/python3.13/site-packages/ecdsa/eddsa.py": 15966858338456571506, + "venv/lib/python3.13/site-packages/pandas/_libs/join.cpython-313-x86_64-linux-gnu.so": 2947947484481830203, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.pyf": 4660465266594480405, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.pyi": 9282436354926617898, + "venv/lib/python3.13/site-packages/pandas/io/formats/excel.py": 797619981868084011, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_editable.py": 14352954849821931255, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/client.py": 17305914656270781911, + "venv/lib/python3.13/site-packages/numpy/lib/npyio.py": 6782361985454523908, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/flatiter.py": 3066469329738423021, + "frontend/src/components/llm/ValidationReport.svelte": 11810571826279890996, + "frontend/src/lib/components/dataset-review/SourceIntakePanel.svelte": 13922687579631047714, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_interpolate.py": 7354685880215444946, + "venv/lib/python3.13/site-packages/secretstorage/defines.py": 9590959702075554048, + "venv/lib/python3.13/site-packages/PIL/_imagingcms.pyi": 12476347428820346383, + "venv/lib/python3.13/site-packages/smmap/buf.py": 18231775424238352734, + "venv/lib/python3.13/site-packages/pygments/lexers/vip.py": 11287963054551122004, + "venv/lib/python3.13/site-packages/pip/_internal/cli/parser.py": 1064209424435927674, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/RECORD": 12598309574903741388, + "venv/lib/python3.13/site-packages/pygments/sphinxext.py": 2768161754523156130, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs.py": 15657897994221955882, + "venv/lib/python3.13/site-packages/pydantic/types.py": 785880062468926292, + "venv/lib/python3.13/site-packages/starlette/_utils.py": 8384087194580626069, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_repr.py": 7552782621374439569, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/__init__.py": 9106887608906281686, + "venv/lib/python3.13/site-packages/greenlet/TExceptionState.cpp": 17617354576371846109, + "venv/lib/python3.13/site-packages/_pytest/terminalprogress.py": 5490989904517343259, + "frontend/src/routes/settings/git/+page.svelte": 16236142639181206770, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_round.py": 7912161077874611432, + "venv/lib/python3.13/site-packages/jose/jwt.py": 3405491994268385178, + "venv/lib/python3.13/site-packages/apscheduler/__init__.py": 8652514118183227412, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/METADATA": 3814104793342833872, + "venv/lib/python3.13/site-packages/numpy/_utils/__init__.py": 7731065084036767848, + "venv/lib/python3.13/site-packages/pillow.libs/libpng16-4a38ea05.so.16.53.0": 13136089038268964667, + "venv/lib/python3.13/site-packages/pydantic/deprecated/config.py": 12280996227531856230, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/__init__.py": 1343779312297539596, + "venv/lib/python3.13/site-packages/pandas/_libs/indexing.pyi": 90995502095752726, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/METADATA": 12295263493152296681, + "backend/git_repos/remote/test-repo.git/objects/d8/3fe0db1279ef07c4c4f3de4156a629373b4057": 7507193819578792576, + "venv/lib/python3.13/site-packages/jsonschema/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/introspect.py": 5706729538356302335, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/RECORD": 5612689057373270213, + "venv/lib/python3.13/site-packages/pydantic/_internal/_core_metadata.py": 5704137311404303574, + "venv/lib/python3.13/site-packages/pandas/io/parsers/c_parser_wrapper.py": 5841064965672872661, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_sansio_impl.py": 17221368219485351394, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/WHEEL": 16097436423493754389, + "frontend/playwright-report/trace/uiMode.html": 2646979321132705707, + "venv/lib/python3.13/site-packages/sqlalchemy/future/__init__.py": 17688444679736059779, + "venv/lib/python3.13/site-packages/pip/_internal/utils/egg_link.py": 18211947508793805393, + "frontend/src/routes/datasets/__tests__/ColumnsTable.test.js": 15883951776898228284, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/METADATA": 7727489762869155085, + "frontend/build/_app/immutable/chunks/BWQQsteK.js": 15588475815071543641, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py": 16550134594771291234, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authorization_server.py": 13696038495666024258, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_msvc.h": 2465089365642299646, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexing.py": 9988098331562906950, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numeric.py": 5627177940393829333, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.pyi": 13208953770241664384, + "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.py": 2215312866861772848, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_matmul.py": 9323220618335072725, + "venv/lib/python3.13/site-packages/pydantic/deprecated/decorator.py": 8609500261161560793, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_julian_date.py": 6868080396693831272, + "venv/lib/python3.13/site-packages/pandas/io/json/_json.py": 1393095374713367445, + "venv/lib/python3.13/site-packages/urllib3/http2/connection.py": 1661620860881397554, + "venv/lib/python3.13/site-packages/numpy/tests/test_matlib.py": 14395481530627870882, + "venv/lib/python3.13/site-packages/pygments/lexers/_postgres_builtins.py": 2383906454995727700, + "frontend/src/lib/components/settings/ApiKeysTab.svelte": 17208249963941978218, + "backend/src/api/routes/__tests__/test_dataset_review_api.py": 8023021851133925740, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/__init__.py": 2635182244050911910, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90": 6208802899442270399, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_transform.py": 18159263102656491974, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/utils.py": 617314300548081590, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/METADATA": 13695483537390128881, + "venv/lib/python3.13/site-packages/pydantic/plugin/_loader.py": 792663962985957671, + "venv/lib/python3.13/site-packages/click/__init__.py": 9261629899056870564, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/METADATA": 9458019064618635438, + "venv/lib/python3.13/site-packages/httpcore/_sync/socks_proxy.py": 4418971149260853240, + "frontend/src/components/llm/DocPreview.svelte": 25645090129568414, + "backend/src/api/routes/dataset_review.py": 3689614039699023362, + "venv/lib/python3.13/site-packages/numpy/version.pyi": 5075382895829889457, + "venv/lib/python3.13/site-packages/starlette/routing.py": 16063812008141874150, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_astype.py": 11386658862732393123, + "venv/lib/python3.13/site-packages/anyio/to_thread.py": 12767326212338028587, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/licenses/LICENSE": 7959949171752474553, + "venv/lib/python3.13/site-packages/requests/api.py": 12339139862411341381, + "venv/lib/python3.13/site-packages/pandas/core/window/rolling.py": 6316477981414191778, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tolist.py": 8343058000369672317, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_textreader.py": 388955620768371652, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/idnadata.py": 1169745920682458213, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c": 17333399794446198412, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_arithmetic.py": 15071337112968886738, + "venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py": 10265081145401348863, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapped_collection.py": 11377280960650304531, + "venv/bin/pyrsa-priv2pub": 16766314338551408621, + "frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js": 15091004230843271151, + "venv/lib/python3.13/site-packages/pandas/core/sample.py": 11913688303879867963, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_setops.py": 8622608042929141013, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_csv.py": 6678500392137188521, + "backend/src/core/__tests__/test_config_manager_compat.py": 656412918792001580, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_selectable_constructors.py": 84919308502240880, + "venv/lib/python3.13/site-packages/PIL/PdfImagePlugin.py": 16082854250442815862, + "backend/src/core/database.py": 9415540929365751667, + "backend/src/plugins/translate/__tests__/test_sql_generator.py": 4676288356986389564, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge.py": 11366935134260232329, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_astype.py": 15384141282611151560, + "frontend/build/_app/immutable/chunks/CrLU7zQO.js": 14265962769345069959, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.cpython-313-x86_64-linux-gnu.so": 15960606468596245469, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/WHEEL": 2823347510103459191, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/zookeeper.py": 4318643109309626098, + "venv/lib/python3.13/site-packages/cryptography/x509/__init__.py": 4066756344049307453, + "backend/src/api/routes/assistant/_schemas.py": 4855661257485426649, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_size.py": 14032390806503440750, + "backend/alembic/versions/8dd0a93af539_drop_deprecated_source_language_column_.py": 3574830605384611294, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.pyi": 1826323011169529229, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/measure.py": 18327922742808984428, + "venv/lib/python3.13/site-packages/rsa/pkcs1.py": 2576732594642491910, "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/pluggy-1.6.0.dist-info/WHEEL": 14550174241288068152, + "venv/lib/python3.13/site-packages/sqlalchemy/event/attr.py": 5971663429221923939, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/dax.py": 10868881057512002309, + "venv/lib/python3.13/site-packages/PIL/_avif.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/WHEEL": 7414522633964952515, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/decoder.py": 17559787396729804535, + "venv/lib/python3.13/site-packages/attr/__init__.pyi": 13203080513025719049, + "venv/lib/python3.13/site-packages/yaml/representer.py": 10550136298978225013, + "frontend/src/lib/auth/permissions.js": 12787489292887903923, + "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.py": 16854377502491291093, + "frontend/build/_app/immutable/nodes/35.BdI-3vAH.js": 15152994709151408688, + "backend/src/plugins/llm_analysis/models.py": 3600633137673071517, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/common.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_overlaps.py": 2328652590379935311, + "venv/lib/python3.13/site-packages/PIL/EpsImagePlugin.py": 1824020964179364491, + "backend/src/core/encryption_key.py": 5870186928729062534, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkeyutils-dfe70bd6.so.1.5": 9414227432578104677, + "venv/lib/python3.13/site-packages/websockets/sync/router.py": 10335595955948355382, + "venv/lib/python3.13/site-packages/pydantic_settings/utils.py": 14396350455520958703, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_xs.py": 11073752361562791165, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv": 6674536825156196036, + "venv/lib/python3.13/site-packages/pandas/core/arrays/integer.py": 7775055011080964709, + "venv/lib/python3.13/site-packages/h11/_events.py": 13800479928851716538, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/pydantic/v1/tools.py": 1995883197897112278, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_api.py": 6439927798101672423, + "venv/lib/python3.13/site-packages/numpy/_core/numeric.py": 12261531924304979741, + "venv/lib/python3.13/site-packages/pycparser/_build_tables.py": 569728086093219621, + "venv/lib/python3.13/site-packages/pygments/lexers/modula2.py": 6575895980250662093, + "venv/lib/python3.13/site-packages/pygments/lexers/esoteric.py": 16839499623020685146, + "backend/src/models/mapping.py": 13500075972378889022, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_attr_equal.py": 5612259834202470413, + "venv/lib/python3.13/site-packages/numpy/fft/tests/test_pocketfft.py": 18025182347224285050, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.py": 183817263146423033, + "venv/lib/python3.13/site-packages/dotenv/variables.py": 5438726379749803751, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/RECORD": 6488682447051657004, + "venv/lib/python3.13/site-packages/pygments/lexers/_julia_builtins.py": 8846111188795315103, + "venv/lib/python3.13/site-packages/git/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/METADATA": 1862765380818895200, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/types.py": 16795741817129898714, + "venv/lib/python3.13/site-packages/multipart/multipart.py": 26386459953377432, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/impl.py": 4687705587963980337, + "backend/src/services/reports/type_profiles.py": 8365014439236739390, + "venv/lib/python3.13/site-packages/pandas/_config/display.py": 433650013567734821, + "venv/lib/python3.13/site-packages/gitdb/db/base.py": 3375449584942578385, + "venv/lib/python3.13/site-packages/rapidfuzz/utils.py": 5682627611354455144, + "venv/lib/python3.13/site-packages/gitdb/test/lib.py": 13294941660283059872, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f": 13517753924061311074, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_constructors.py": 13890224577680389718, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_indexing.py": 14717641281147152159, + "venv/lib/python3.13/site-packages/pandas/io/parsers/base_parser.py": 15148258424429418380, + "venv/lib/python3.13/site-packages/fastapi/encoders.py": 1914192268055730299, + "venv/lib/python3.13/site-packages/pydantic/utils.py": 1533455264689378477, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isetitem.py": 14895552405828068177, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_almost_equal.py": 9333355453468475330, + "venv/lib/python3.13/site-packages/pandas/_testing/_warnings.py": 5640964566228306285, + "frontend/build/_app/immutable/chunks/BxfreSRb.js": 7524659291169347564, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ma.pyi": 8186102816080813799, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_numerictypes.py": 8836108334624807647, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/authorization_code.py": 4958605540994687737, + "venv/lib/python3.13/site-packages/authlib/oauth2/auth.py": 8455258275234626534, + "venv/lib/python3.13/site-packages/numpy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/computation/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/eiffel.py": 8964563077187051946, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_duplicated.py": 6659959750254523427, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_first_valid_index.py": 15763400665851423183, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_table.tpl": 8706980975714184465, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/numerictypes.pyi": 15565573472138344755, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/path_registry.py": 8410829659513707067, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_version.py": 10384171076976071398, + "frontend/playwright.config.js": 1601415616693761429, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/resolution.py": 5132658725516243311, + "frontend/src/routes/settings/git/__tests__/git_settings_page.ux.test.js": 5334904955024018051, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/scipy_sparse.py": 2091608752719976909, + "frontend/build/_app/immutable/entry/app.B3VIvO3J.js": 430434855117608941, + "venv/lib/python3.13/site-packages/fastapi/security/oauth2.py": 1925394177931547776, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/cffi/model.py": 13544803366359102016, + "venv/lib/python3.13/site-packages/passlib/tests/__init__.py": 16543763165305017760, + "venv/lib/python3.13/site-packages/PIL/WmfImagePlugin.py": 15685062825106444247, + "backend/src/api/routes/translate/_dictionary_routes.py": 5480137091791704976, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/RECORD": 10036839994791510159, + "frontend/src/lib/components/layout/sidebarNavigation.js": 2017502929479329787, + "venv/lib/python3.13/site-packages/_pytest/nodes.py": 515939386237558331, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_compare.py": 3079569478684646491, + "frontend/src/components/MissingMappingModal.svelte": 11264881226066623003, + "venv/lib/python3.13/site-packages/passlib/tests/test_hosts.py": 8284535274820610802, + "venv/lib/python3.13/site-packages/pip/_internal/utils/temp_dir.py": 8657533190026387896, + "venv/lib/python3.13/site-packages/pandas/tests/test_register_accessor.py": 16661086720613729974, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_is_full.py": 9577318758326279694, + "venv/lib/python3.13/site-packages/charset_normalizer/models.py": 9917300217816275821, + "venv/lib/python3.13/site-packages/pygments/lexers/_mapping.py": 12987629396101138833, + "frontend/src/lib/components/dataset-review/SemanticLayerReview.svelte": 10805621354490209991, + "frontend/build/_app/immutable/chunks/D2LDFDH5.js": 1513005501777757570, + "backend/git_repos/remote/test-repo.git/objects/79/b070ad8af7bbc12169f7660d2a7a72ec7a889a": 8153595714065675791, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/string.tpl": 15796203549130590784, + "venv/lib/python3.13/site-packages/greenlet/greenlet_refs.hpp": 8525862687669040510, + "venv/lib/python3.13/site-packages/pip/_internal/build_env.py": 3614358934066127900, + "venv/lib/python3.13/site-packages/numpy/_typing/_shape.py": 12667553664122376205, + "venv/lib/python3.13/site-packages/jaraco/classes/meta.py": 15930255620248873425, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_riscv_unix.h": 8607317131295864391, + "venv/lib/python3.13/site-packages/pluggy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/resource_protector.py": 4823504113176750140, + "venv/lib/python3.13/site-packages/uvicorn/__init__.py": 11517239807926185665, + "backend/src/scripts/create_admin.py": 7540310914822649547, + "venv/lib/python3.13/site-packages/pip/_internal/models/selection_prefs.py": 14700113736620314923, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filters/__init__.py": 835924536855006596, + "venv/lib/python3.13/site-packages/pip/_internal/commands/show.py": 11839987586497822300, + "venv/lib/python3.13/site-packages/_pytest/subtests.py": 14573790885130724739, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_exceptions.py": 12145393002202744314, + "venv/lib/python3.13/site-packages/pandas/tests/series/__init__.py": 15130871412783076140, + "backend/src/schemas/__init__.py": 8700952869915187087, + "backend/src/services/clean_release/__tests__/test_stages.py": 15353751625742444422, + "backend/tests/test_translate_history.py": 14504549443376034614, + "venv/lib/python3.13/site-packages/pip/_internal/utils/deprecation.py": 7435269308988385470, + "venv/lib/python3.13/site-packages/pip/_internal/commands/hash.py": 11824898770873127699, + "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.py": 13574106461973044500, + "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/pygments/lexers/zig.py": 470431199354307668, + "venv/lib/python3.13/site-packages/pygments/lexers/hare.py": 8693002231020751711, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/conftest.py": 3691712173202219606, + "venv/lib/python3.13/site-packages/urllib3/util/wait.py": 14629837381061032546, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_constructors.py": 17219764538851313252, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_map.py": 4761668276463940924, + "venv/lib/python3.13/site-packages/uvicorn/main.py": 5843333502356171120, + "frontend/src/lib/components/layout/__tests__/test_breadcrumbs.svelte.js": 1250794495161202602, + "venv/lib/python3.13/site-packages/pandas/_libs/index.pyi": 17679349633640606985, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/passlib/tests/tox_support.py": 9200774792427691602, + "frontend/src/lib/components/translate/BulkCorrectionSidebar.svelte": 10114621552038076221, + "venv/lib/python3.13/site-packages/pip/_internal/utils/packaging.py": 15555781487631855604, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/jwt.py": 9642615960197748105, + "venv/lib/python3.13/site-packages/PIL/GbrImagePlugin.py": 7681313333602257802, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/styled.py": 8726407298858811635, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/putmask.py": 10934101690788549526, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py": 8864112842559211971, + "venv/lib/python3.13/site-packages/pip/_internal/operations/freeze.py": 3469845570614985559, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE": 14316979437290727897, + "venv/lib/python3.13/site-packages/charset_normalizer/md.cpython-313-x86_64-linux-gnu.so": 1835299664481804968, + "venv/lib/python3.13/site-packages/pip/_internal/self_outdated_check.py": 991029278889407558, + "venv/lib/python3.13/site-packages/urllib3/util/proxy.py": 17667887856427739069, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath_complex.py": 11732242536199439023, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_version.pyi": 3636944488233043883, + "backend/src/core/utils/network.py": 8313622593956890768, + "venv/lib/python3.13/site-packages/httpcore/py.typed": 15130871412783076140, + "backend/tests/services/clean_release/test_policy_resolution_service.py": 3471271299977247598, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_api.py": 7131036004750554905, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_matplotlib.py": 12775850858284584296, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90": 14624074967635860696, + "venv/lib/python3.13/site-packages/passlib/tests/test_context.py": 15195609282700801214, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_skiprows.py": 8764515842253490735, + "venv/lib/python3.13/site-packages/jsonschema/_typing.py": 13152346021901861822, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_asyncio.py": 2820168745710754136, + "venv/lib/python3.13/site-packages/pip/_internal/commands/inspect.py": 1401259241736437656, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/METADATA": 2624107638694809013, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/unix.py": 13808187640638677050, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_symbolic.py": 8093576026032854125, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_array_ops.py": 6709502157317299163, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply.py": 12349190935180702377, + "venv/lib/python3.13/site-packages/requests/auth.py": 912521029864094489, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_console.py": 11657469008721907972, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/lambdas.py": 13377298868598623228, + "venv/lib/python3.13/site-packages/pycparser/ply/cpp.py": 1665654017894222868, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/conftest.py": 16571782049241458769, + "venv/bin/normalizer": 10972303485259566838, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/__init__.py": 15130871412783076140, + "frontend/src/components/git/__tests__/git_manager.unfinished_merge.integration.test.js": 4508809242640248036, + "backend/tests/core/migration/test_archive_parser.py": 1909788158234142574, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_na_values.py": 13527837495439739279, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_head_tail.py": 13047338070883375426, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py": 7624316342162916928, + "venv/lib/python3.13/site-packages/_yaml/__init__.py": 3395829783751571350, + "venv/lib/python3.13/site-packages/cryptography/__init__.py": 641702726372647770, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/box.py": 14303526978791498662, + "venv/lib/python3.13/site-packages/referencing/tests/test_referencing_suite.py": 8875120876162738440, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/h11/_util.py": 9362339074207904329, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/refresh_token.py": 17927903035152872556, + "venv/lib/python3.13/site-packages/anyio/_core/_testing.py": 14024940365851109155, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/api.py": 12339139862411341381, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_dict.py": 16252265723192124609, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_transpose.py": 1686867045869336370, + "venv/lib/python3.13/site-packages/PIL/features.py": 3481835375516797487, + "venv/lib/python3.13/site-packages/yaml/_yaml.cpython-313-x86_64-linux-gnu.so": 16990140871649227895, + "venv/lib/python3.13/site-packages/pygments/lexers/asm.py": 13861952972248758785, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numba.py": 18148155441554555618, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/conftest.py": 9673372914396625461, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dropna.py": 17272771246760486947, + "venv/lib/python3.13/site-packages/pandas/io/parsers/__init__.py": 11752833703934347122, + "backend/src/core/__tests__/test_native_filters.py": 823253235973274872, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/casting.py": 12226803454582253097, + "frontend/src/lib/utils.js": 5436516952434475239, + "frontend/build/_app/immutable/nodes/19.BtYix_y_.js": 13099146879599461804, + "venv/lib/python3.13/site-packages/pygments/lexers/srcinfo.py": 16466766917840327610, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/char.f90": 12203871998988759364, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/numpy/_core/getlimits.py": 7842717073693731093, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename_axis.py": 13193478481758930128, + "frontend/src/routes/+layout.ts": 8392799000856778740, + "frontend/src/routes/tools/debug/+page.svelte": 8699044541980877686, + "backend/src/api/routes/git/_router.py": 8701683910668868827, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo90.f90": 2435648607844815947, + "venv/lib/python3.13/site-packages/pytest/__main__.py": 8747175113746141224, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reflection.py": 1799734694597531652, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_extension_array_equal.py": 16119106336497630796, + "frontend/build/_app/immutable/chunks/B3miH4jD.js": 11736959945545311440, + "backend/src/plugins/llm_analysis/__tests__/test_screenshot_service.py": 17792688368296989200, + "backend/git_repos/remote/test-repo.git/objects/59/3a37acec7d2bddce10df90ab17bc9ede52e523": 1117161574576783985, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh18335.f90": 1126438609189294255, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/models.py": 15928924478695638423, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.cpython-313-x86_64-linux-gnu.so": 16604252871044637047, + "venv/lib/python3.13/site-packages/passlib/registry.py": 5050675058011850564, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_iter.py": 9232021002336641851, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/visitors.py": 5190923415390076080, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/hstore.py": 9700253004947691961, + "venv/lib/python3.13/site-packages/multipart/exceptions.py": 8580522204565816132, + "venv/lib/python3.13/site-packages/pandas/tests/test_errors.py": 10116716310156374885, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/numpyconfig.h": 13339221870252345205, + "venv/lib/python3.13/site-packages/anyio/py.typed": 15130871412783076140, + "backend/src/models/config.py": 7631082065091961320, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/METADATA": 4868544280955034757, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_compare.py": 171535659467902751, + "venv/lib/python3.13/site-packages/pandas/io/formats/_color_data.py": 15614976586613738953, + "frontend/src/lib/components/reports/__tests__/report_type_profiles.test.js": 498330292141991614, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_value_counts.py": 9352540710376306520, + "backend/src/services/reports/__tests__/test_type_profiles.py": 17262223295445285285, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/WHEEL": 9788895026336324100, + "venv/lib/python3.13/site-packages/attr/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/anyio/abc/_subprocesses.py": 4297459042599291531, + "backend/src/core/__init__.py": 8673978627093182792, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__init__.py": 8811477458865810434, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft_umath.cpython-313-x86_64-linux-gnu.so": 16443444849116065961, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo77.f": 16156304612888138777, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi": 2777456956260371820, + "venv/lib/python3.13/site-packages/_pytest/unittest.py": 10848803633530338204, + "venv/lib/python3.13/site-packages/pandas/util/_tester.py": 1033951890304257539, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/RECORD": 2024211292009381421, + "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/test_rapidfuzz_packaging.py": 5189055608193366093, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_numpy.py": 9663734591667845940, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/base.py": 13269563625127294513, + "venv/lib/python3.13/site-packages/PIL/MspImagePlugin.py": 3034490726971829439, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/operators.py": 5584982192355398255, + "venv/lib/python3.13/site-packages/uvicorn/importer.py": 5449629250971153435, + "venv/lib/python3.13/site-packages/passlib/win32.py": 5311393450489898748, + "venv/lib/python3.13/site-packages/pip/_internal/commands/index.py": 16715578868094112894, + "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.py": 4037074830103951000, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_writers.py": 103545128256076790, + "venv/lib/python3.13/site-packages/pandas/io/excel/_odfreader.py": 2760916559416783928, + "venv/lib/python3.13/site-packages/pygments/lexers/maxima.py": 11824576541091274641, + "venv/lib/python3.13/site-packages/pygments/lexers/verifpal.py": 9190813166686923928, + "venv/lib/python3.13/site-packages/pygments/lexers/iolang.py": 10997512999728724130, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_indexing.py": 11572911419313573163, + "frontend/src/lib/auth/__tests__/permissions.test.js": 13555349356008297952, + "frontend/src/lib/components/reports/__tests__/report_detail.ux.test.js": 11878832350632571462, + "venv/lib/python3.13/site-packages/jeepney/auth.py": 10565040329507087892, + "venv/lib/python3.13/site-packages/pandas/core/indexes/extension.py": 7193879749426425951, + "backend/src/core/plugin_base.py": 11649432288706102843, + "backend/src/core/task_manager/persistence.py": 17734987286155732710, + "venv/lib/python3.13/site-packages/jose/utils.py": 1926138853970725083, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/converter.py": 9041278869295701566, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_chaining_and_caching.py": 11784574265874608859, + "venv/lib/python3.13/site-packages/pip/_internal/commands/wheel.py": 16397273591245583356, + "venv/lib/python3.13/site-packages/cryptography/x509/ocsp.py": 17973800752927680404, + "frontend/build/_app/immutable/chunks/1jzJINoE.js": 5138497638450462989, + "backend/src/core/migration/dry_run_orchestrator.py": 6268210017505159964, + "backend/tests/services/clean_release/test_report_audit_immutability.py": 4097909280121147581, + "backend/git_repos/remote/test-repo.git/config": 14478893374498894766, + "venv/lib/python3.13/site-packages/websockets/asyncio/server.py": 885415484558949506, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/key_set.py": 8485970749081951741, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_cov_corr.py": 13652339565475304679, + "venv/lib/python3.13/site-packages/pygments/formatters/irc.py": 2133711525226123259, + "backend/src/core/auth/__tests__/test_auth.py": 9487323693897023350, + "backend/src/core/superset_client/_datasets_preview_filters.py": 14154361389981199486, + "frontend/build/_app/immutable/nodes/6.DJ9MrKC-.js": 8967503365556189617, + "venv/lib/python3.13/site-packages/pip/_internal/models/pylock.py": 16697828625021519459, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_hour.py": 13754646634123368797, + "venv/bin/pyrsa-encrypt": 5858278204727417482, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_astype.py": 11995587502880659624, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/rec.pyi": 14615751247243515028, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_array_utils.py": 14682148205379122638, + "venv/lib/python3.13/site-packages/numpy/lib/mixins.pyi": 15597536290223628777, + "venv/lib/python3.13/site-packages/numpy/version.py": 1497063540123613501, + "venv/lib/python3.13/site-packages/numpy/fft/__init__.pyi": 10354990065626209946, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_from_scalar.py": 16520136036631155842, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np121.pkl.gz": 4708588000144933291, + "venv/lib/python3.13/site-packages/pip/_internal/utils/compat.py": 1841193561752758336, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_select.py": 7083040959665006634, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/METADATA": 14158024963562115116, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.f": 9330535808093475892, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_util.py": 6573034224727513309, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/checks.pyx": 13187505236986855177, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_indexing.py": 14552860427542050771, + "venv/lib/python3.13/site-packages/numpy/core/multiarray.py": 18368443598659711836, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90": 11945588837236968550, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_astype.py": 4023134352880775277, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_indexing.py": 81180636019259296, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/RECORD": 7320381591791379627, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_diff.py": 7420674239386436885, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_argsort.py": 7320661835159648143, + "venv/lib/python3.13/site-packages/PIL/ImageColor.py": 17058618058554970738, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_serialization.py": 2011519400081029270, + "venv/lib/python3.13/site-packages/yaml/scanner.py": 8554164423030397366, + "venv/lib/python3.13/site-packages/pygments/lexers/email.py": 4355246279485460399, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/requirements.py": 11478648568700804705, + "frontend/build/_app/immutable/nodes/24.lnfcaE4o.js": 4000891976750157851, + "venv/lib/python3.13/site-packages/typing_inspection/introspection.py": 13916695705179237047, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_parser.py": 3540203683732744499, + "venv/lib/python3.13/site-packages/anyio/from_thread.py": 7973678341601453474, + "venv/lib/python3.13/site-packages/apscheduler/events.py": 10748346950729364899, + "frontend/src/components/git/GitWorkspacePanel.svelte": 15810952071932060330, + "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.py": 16856718240972376883, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/color.py": 15062855556511243610, + "backend/src/services/reports/__init__.py": 11818812865847046400, + "backend/src/plugins/translate/preview_review.py": 5584592578627646560, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_concat.py": 10207975532842927134, + "venv/lib/python3.13/site-packages/jeepney/io/__init__.py": 2568357146184259175, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/_cmd.py": 14954780419054588164, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/abstract.py": 14216912708889351810, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_mixed.py": 3476101699679108025, + "venv/lib/python3.13/site-packages/httpcore/_backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/RECORD": 17341460504914308184, + "venv/lib/python3.13/site-packages/uvicorn/middleware/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/webmisc.py": 9530962803076253849, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py": 7906029092844029127, + "backend/src/core/auth/security.py": 8289703096420999159, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/__init__.py": 18019562641348687547, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_missing.py": 3991199131191840903, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pyasn1/type/opentype.py": 340146737126677655, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_html.py": 7947998260347730581, + "venv/lib/python3.13/site-packages/fastapi/logger.py": 11590581556317053213, + "venv/lib/python3.13/site-packages/pyasn1/type/error.py": 1479878696626082697, + "venv/lib/python3.13/site-packages/jose/__init__.py": 15575670403380555945, + "venv/lib/python3.13/site-packages/fastapi/_compat/v2.py": 15078491685917047095, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_compression.py": 8577756801858495168, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_accessor.py": 10074496835594855786, + "venv/lib/python3.13/site-packages/websockets/utils.py": 17624459810483092475, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.cpython-313-x86_64-linux-gnu.so": 6157288238855118017, + "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp_impl.cpython-313-x86_64-linux-gnu.so": 11767771662042404251, + "venv/lib/python3.13/site-packages/pygments/lexers/ampl.py": 4594260378653369985, + "frontend/src/components/git/GitOperationsPanel.svelte": 5140779139910068800, + "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.py": 1590647503660777156, + "backend/src/api/routes/mappings.py": 7071183920129492341, + "venv/lib/python3.13/site-packages/pygments/formatter.py": 11156733836937309465, + "frontend/build/_app/immutable/nodes/16.yCusNoj_.js": 1406373227455087905, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/_core/src/umath/svml/LICENSE": 9584102918819171104, + "backend/src/services/clean_release/exceptions.py": 14631509303697939633, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fft.pyi": 14454280827038327842, + "backend/src/api/routes/__init__.py": 8298072528454936676, + "backend/git_repos/remote/test-repo.git/HEAD": 12394318939628232491, + "venv/lib/python3.13/site-packages/rsa/cli.py": 1753949198467694190, + "venv/lib/python3.13/site-packages/passlib/pwd.py": 14727089240749133060, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_shift.py": 8547819448301023303, + "venv/lib/python3.13/site-packages/numpy/_typing/_nested_sequence.py": 7827259347937485408, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_datetimelike.py": 15246580603900811749, + "venv/lib/python3.13/site-packages/git/__init__.py": 15867730798565725003, + "backend/src/core/__tests__/test_superset_preview_pipeline.py": 5793244881571660499, + "backend/src/plugins/llm_analysis/__tests__/test_service.py": 9850768293526486431, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/__init__.py": 9820770319106921495, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__main__.py": 8412594868333244844, + "venv/lib/python3.13/site-packages/fastapi/param_functions.py": 14585101566697773072, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polyutils.pyi": 3841660741524427413, + "venv/lib/python3.13/site-packages/pygments/lexers/tlb.py": 1169242051301155885, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/__init__.py": 293004106962245584, + "venv/lib/python3.13/site-packages/_pytest/scope.py": 7603155109542903644, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/strings.pyi": 402863478592154500, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dot.py": 16876560325283070437, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_masked.py": 5380551301916549925, + "venv/lib/python3.13/site-packages/pandas/io/json/__init__.py": 12333505155070172626, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/uvicorn/loops/uvloop.py": 5385425357504191161, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_fillna.py": 16297834601116528166, + "frontend/build/_app/immutable/chunks/CHelQZPK.js": 13538277300205681632, + "venv/lib/python3.13/site-packages/pydantic/_internal/_core_utils.py": 13248004771466837645, + "venv/lib/python3.13/site-packages/pydantic_core/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/elm.py": 14683437310498104916, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_character/foo77.f": 4046503346951676582, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_string_array.py": 8260883866404398980, + "backend/src/api/routes/__tests__/test_clean_release_source_policy.py": 15242462571646635922, + "venv/lib/python3.13/site-packages/pillow.libs/liblcms2-cc10e42f.so.2.0.17": 4221600618602131476, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/rethinkdb.py": 16413299263077970925, + "venv/lib/python3.13/site-packages/numpy/_globals.pyi": 12839879732484756979, + "venv/lib/python3.13/site-packages/pandas/core/indexes/frozen.py": 1419685664276640120, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py": 5324490103277723813, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-2.csv": 7063857529719738394, + "venv/lib/python3.13/site-packages/annotated_types/test_cases.py": 5123395674810472016, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/request.py": 10484280068366411541, + "venv/lib/python3.13/site-packages/numpy/_core/function_base.pyi": 8343632640078378312, + "venv/lib/python3.13/site-packages/pandas/tests/config/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_period_index.py": 6634414375581820058, + "venv/lib/python3.13/site-packages/pandas/core/internals/ops.py": 4740509262379451243, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarbuffer.py": 16859789411010045795, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_quarter.py": 11099677280196239755, + "venv/lib/python3.13/site-packages/urllib3/contrib/pyopenssl.py": 11839715589709210412, + "venv/lib/python3.13/site-packages/pygments/lexers/basic.py": 12723021007042054402, + "frontend/static/favicon.png": 16740551781088792605, + "venv/lib/python3.13/site-packages/jeepney/low_level.py": 6546206679858571608, + "frontend/build/_app/immutable/chunks/CyrRIrvE.js": 6233954911328508847, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_parser.py": 8145921552236189367, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/RECORD": 11788532857617688351, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/socks.py": 17581293673028078134, + "backend/src/app.py": 9380595892248657452, + "backend/src/api/routes/assistant/_routes.py": 438564212453429233, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.cpython-313-x86_64-linux-gnu.so": 12776951671822017500, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.pyx": 649821942746469002, + "frontend/src/routes/datasets/review/[id]/__tests__/dataset_review_workspace.ux.test.js": 4105775024258653726, + "backend/src/services/git/__init__.py": 14011752637167919253, + "backend/src/plugins/__init__.py": 17194112070692432889, + "backend/tests/test_models.py": 3998442321184404421, + "venv/lib/python3.13/site-packages/_pytest/fixtures.py": 1442767529726551116, + "venv/lib/python3.13/site-packages/ecdsa/_compat.py": 13034064768731879065, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE": 17675192170670564526, + "venv/lib/python3.13/site-packages/pandas/_libs/tslib.pyi": 16170606956605100142, + "venv/lib/python3.13/site-packages/httpx/_types.py": 12461152436147308761, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertions.py": 5556667947376168765, + "venv/lib/python3.13/site-packages/urllib3/_version.py": 839747992523118887, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler_py.py": 16189204441438239231, + "venv/lib/python3.13/site-packages/pygments/lexers/_scilab_builtins.py": 17453812809700086888, + "backend/src/services/clean_release/__init__.py": 18311663871116449547, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/warnings_and_errors.py": 11172336980866895356, + "venv/lib/python3.13/site-packages/pillow.libs/liblzma-61b1002e.so.5.8.2": 11405063484938458842, + "venv/lib/python3.13/site-packages/websockets/asyncio/compatibility.py": 9716993942839407921, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/_typing.py": 17598638528781632158, + "frontend/src/routes/settings/StorageSettings.svelte": 1953157077500445570, + "backend/src/api/routes/dataset_review_pkg/_dependencies.py": 15939232213193276681, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_parquet.py": 11050150015772440923, + "venv/lib/python3.13/site-packages/pygments/lexers/gdscript.py": 12775803139854052838, + "venv/lib/python3.13/site-packages/sqlalchemy/future/engine.py": 4639404437703898767, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/exc.py": 1448374203226983757, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas_xport.py": 16525568795475918874, + "venv/lib/python3.13/site-packages/pydantic/v1/color.py": 14545509649623975912, + "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.py": 11758491058846790938, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npy": 17303060773267383537, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/versioncontrol.py": 13742159245132241245, + "venv/lib/python3.13/site-packages/pandas/tests/tools/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/chunks/C8K-NfB8.js": 522730246953022577, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/ImageEnhance.py": 3218405223202808764, + "backend/tests/test_constants_audit_fixes.py": 18298690956132739779, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/mypy.py": 823265492261272631, + "venv/lib/python3.13/site-packages/pandas/io/orc.py": 12754290195886557668, + "frontend/build/_app/immutable/chunks/C20922N0.js": 14681700380768364777, + "frontend/tests/maintenance.test.ts": 13103794138601813910, + "venv/lib/python3.13/site-packages/gitdb/pack.py": 7828244200815444166, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/__init__.py": 7316739139609490520, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/cmac.py": 12011944740750051829, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi": 10784666243744187693, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/RECORD": 6349071557579241461, + "venv/lib/python3.13/site-packages/sqlalchemy/event/base.py": 18238453132776154057, + "venv/lib/python3.13/site-packages/pygments/lexers/dotnet.py": 17970884907837213099, + "venv/lib/python3.13/site-packages/pandas/core/ops/common.py": 17314999825118928100, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_missing.py": 1963705411068820866, + "venv/lib/python3.13/site-packages/fastapi/datastructures.py": 727178955746650271, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_frequencies.py": 14039315221824123200, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_comparison.py": 11333735187162513512, + "venv/lib/python3.13/site-packages/pygments/formatters/other.py": 13124903290103898118, + "venv/lib/python3.13/site-packages/pygments/lexers/j.py": 9766594937623918053, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/cache.py": 3177663126928467950, + "venv/lib/python3.13/site-packages/pygments/lexers/bare.py": 18266858932333619451, + "venv/lib/python3.13/site-packages/packaging/_elffile.py": 9546225990833172494, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_ndarray_backed.py": 10097812802469682233, + "venv/lib/python3.13/site-packages/pip/_internal/configuration.py": 2563100675379605810, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv": 4581185622290535488, + "venv/lib/python3.13/site-packages/pandas/util/_test_decorators.py": 17930801441803090445, + "backend/tests/test_translate_scheduler_guard.py": 13396608843530344156, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/WHEEL": 5179340427739743287, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE": 2345070715845618109, + "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.py": 546976622482819095, + "venv/lib/python3.13/site-packages/numpy/_core/_operand_flag_tests.cpython-313-x86_64-linux-gnu.so": 12296711931541109624, + "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.pyi": 15067467792538416274, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd_module.py": 7122050193390298178, + "venv/lib/python3.13/site-packages/pandas/io/excel/_odswriter.py": 17220892094904423676, + "venv/lib/python3.13/site-packages/pandas/core/_numba/extensions.py": 4132402557064663751, + "venv/lib/python3.13/site-packages/pandas/core/computation/parsing.py": 3084943521520476999, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/events.py": 13473858896579666058, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/__init__.py": 15487893533770969571, + "venv/lib/python3.13/site-packages/yaml/cyaml.py": 9157893742065554693, + "venv/lib/python3.13/site-packages/pip/_internal/main.py": 13711402795965346761, + "venv/lib/python3.13/site-packages/passlib/handlers/sun_md5_crypt.py": 1949993216707182407, + "venv/lib/python3.13/site-packages/numpy.libs/libscipy_openblas64_-096271d3.so": 14338208504131470036, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/__init__.py": 6327819603201859020, + "frontend/src/lib/ui/Input.svelte": 8632025378593263475, + "venv/lib/python3.13/site-packages/dotenv/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/assertion.py": 5287436128235488464, + "frontend/src/routes/reports/llm/[taskId]/report_page.contract.test.js": 4825093389030464765, + "venv/lib/python3.13/site-packages/secretstorage/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/repo/fun.py": 9019364012746153312, + "frontend/build/_app/immutable/chunks/Dul6iTE7.js": 10339509389374345579, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__init__.py": 8880435562116660648, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_cpp_avx2.cpython-313-x86_64-linux-gnu.so": 12574929384355254457, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_crackfortran.py": 10278720705326601943, + "venv/lib/python3.13/site-packages/gitdb/base.py": 7927279446353696534, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/requests.py": 6703055041957748929, + "venv/lib/python3.13/site-packages/starlette/middleware/authentication.py": 15211131264936212938, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_info.py": 15151894356374015812, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo77.f": 7353666717928699883, + "venv/lib/python3.13/site-packages/numpy/_core/__init__.pyi": 2783897020308040960, + "venv/lib/python3.13/site-packages/passlib/handlers/fshp.py": 13298827601291507295, + "venv/lib/python3.13/site-packages/pandas/io/excel/_util.py": 6664989864423807444, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/pkg_resources.py": 14271077832999370068, + "venv/lib/python3.13/site-packages/anyio/abc/_testing.py": 16484863782452886547, + "venv/lib/python3.13/site-packages/yaml/dumper.py": 11376022992370902766, + "frontend/src/routes/translate/+page.svelte": 15284819686967093613, + "frontend/build/_app/immutable/nodes/11.AnPCb-Ut.js": 13179973353447891567, + "frontend/tests/maintenance-api.test.ts": 10196278218740408254, + "venv/lib/python3.13/site-packages/more_itertools/more.py": 1631135582441184133, + "backend/src/services/__tests__/test_encryption_manager.py": 5925253324895194576, + "venv/lib/python3.13/site-packages/pandas/tests/internals/test_internals.py": 2049484047553296860, "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_append.py": 9644955836191900614, + "venv/lib/python3.13/site-packages/iniconfig/exceptions.py": 16501270224069836264, + "venv/lib/python3.13/site-packages/numpy/_core/multiarray.py": 4484782354376574355, + "venv/lib/python3.13/site-packages/pandas/api/indexers/__init__.py": 17431573013142626187, + "venv/lib/python3.13/site-packages/PIL/ContainerIO.py": 7551929914241379005, + "venv/lib/python3.13/site-packages/pygments/token.py": 6987328478153445584, + "backend/src/services/git/_merge.py": 3056385620903925104, + "venv/lib/python3.13/site-packages/PIL/_util.py": 17116054813914373606, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/npyio.pyi": 15811156298637131744, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_select_dtypes.py": 3530442956913622572, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_mask.py": 9654897363729130542, + "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.pyi": 84606125837677197, + "venv/lib/python3.13/site-packages/pip/_internal/commands/search.py": 8292218231992728142, + "venv/lib/python3.13/site-packages/pandas/_libs/window/aggregations.pyi": 6072607880689125113, + "venv/lib/python3.13/site-packages/numpy/random/_sfc64.cpython-313-x86_64-linux-gnu.so": 17186695607612591922, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_concat.py": 3788461606817482165, + "venv/lib/python3.13/site-packages/git/objects/submodule/__init__.py": 12958523219496107878, + "frontend/e2e/run-e2e.sh": 8106714116467101372, + "frontend/playwright-report/trace/uiMode.Btcz36p_.css": 7361350017361398233, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/claims.py": 11853156183819186599, + "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.pyi": 9291444594181042963, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_astype.py": 7497268667246913350, + "venv/lib/python3.13/site-packages/git/index/typ.py": 11661540784850363024, + "venv/lib/python3.13/site-packages/pygments/lexers/automation.py": 8021926838024836904, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/dml.py": 6567627855667533645, + "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimelike.py": 4356700619632833878, + "venv/lib/python3.13/site-packages/passlib/utils/__init__.py": 11704122205941631503, + "venv/lib/python3.13/site-packages/numpy/ma/core.py": 338350463523585845, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/tzlocal/windows_tz.py": 11696765495002954868, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/base.py": 14734745827490220667, + "frontend/src/components/EnvSelector.svelte": 3937920133889630193, + "venv/lib/python3.13/site-packages/anyio/_core/_sockets.py": 10525237827959090532, + "venv/lib/python3.13/site-packages/starlette/responses.py": 14081178833432955042, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/util.py": 387985965709546512, + "venv/lib/python3.13/site-packages/pygments/styles/native.py": 4559566444883341527, + "backend/tests/test_core_scheduler.py": 2305397851769292578, + "venv/lib/python3.13/site-packages/rsa/common.py": 10921682819204792805, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token_validator.py": 2932866595454490527, + "venv/lib/python3.13/site-packages/greenlet/greenlet_internal.hpp": 13173115501223013762, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_any_index.py": 10800968419286329268, + "venv/lib/python3.13/site-packages/pandas/_version_meson.py": 4875297137037630519, + "venv/lib/python3.13/site-packages/httpcore/_async/connection.py": 2155744160496556069, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml.py": 6906547816798138000, + "venv/lib/python3.13/site-packages/smmap/test/test_mman.py": 8977119225749253844, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/fft/__init__.py": 9343449448737026658, + "frontend/playwright-report/trace/codeMirrorModule.DYBRYzYX.css": 14866915564324637173, + "venv/lib/python3.13/site-packages/rsa/__init__.py": 14623742580410014505, + "venv/lib/python3.13/site-packages/pandas/_libs/json.cpython-313-x86_64-linux-gnu.so": 2436285663630821963, + "venv/lib/python3.13/site-packages/pygments/lexers/sas.py": 6128008194712914874, + "frontend/src/lib/stores/__tests__/mocks/stores.js": 14098417748659067309, + "frontend/src/services/__tests__/gitService.test.js": 12845562082447336909, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_wrap.py": 17083394123203662880, + "backend/src/services/git/_url.py": 15729080796864187707, + "backend/git_repos/remote/test-repo.git/objects/e9/1109abe29d5228675fecd6fc38a097147c090d": 15716642455993350072, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f90continuation.f90": 17056591497459381871, + "venv/lib/python3.13/site-packages/cffi/vengine_gen.py": 6582900613549620556, + "venv/lib/python3.13/site-packages/more_itertools/__init__.pyi": 16479506520351014608, + "venv/lib/python3.13/site-packages/h11/_connection.py": 6971907312737339559, + "venv/lib/python3.13/site-packages/referencing/_attrs.py": 14434891919747863272, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_find_replace.py": 262184394614748386, + "venv/lib/python3.13/site-packages/_pytest/recwarn.py": 15312759837838083596, + "venv/lib/python3.13/site-packages/pandas/tests/test_algos.py": 11860014896449369497, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/quoted_character/foo.f": 15318083678609435813, + "venv/lib/python3.13/site-packages/smmap/test/test_tutorial.py": 16309370344201290582, + "venv/lib/python3.13/site-packages/numpy/_core/_asarray.py": 3468915833437229425, + "venv/lib/python3.13/site-packages/pandas/_config/localization.py": 11197430792343731762, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_string.py": 15542851215119662814, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_values.py": 8372572954663628844, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/adapters.py": 2224938661429637508, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/sqlalchemy.py": 811968833735951956, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_categorical_equal.py": 7942323667866280872, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_common_basic.py": 1945891789924713537, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/errors.py": 6538052228921426956, + "venv/bin/Activate.ps1": 1196103427939049710, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv": 8929553891827331780, + "venv/lib/python3.13/site-packages/pytest/py.typed": 15130871412783076140, + "frontend/playwright-report/trace/playwright-logo.svg": 4728037962520658573, + "venv/lib/python3.13/site-packages/pygments/lexers/phix.py": 16775285097768256238, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/__init__.py": 15130871412783076140, + "backend/src/services/clean_release/__tests__/test_preparation_service.py": 4765724405964286078, + "backend/src/plugins/translate/metrics.py": 16289306156708185830, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv": 13695545125848146013, + "venv/lib/python3.13/site-packages/authlib/jose/__init__.py": 317573635113539563, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_md4.py": 15270721044910698449, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/SunImagePlugin.py": 7661622930404688367, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE": 12064892310002036996, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/lexers/kuin.py": 2818054539831699366, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/__init__.py": 8093984834068317399, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/errors.py": 2147619440137604907, + "venv/lib/python3.13/site-packages/pandas/core/ops/mask_ops.py": 16152832446926420035, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90": 3911644649277659333, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_subplots.py": 4596089143375088346, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_dtypes.py": 13065857166166716628, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_array_to_datetime.py": 3467480435568672840, + "venv/lib/python3.13/site-packages/PIL/_imagingft.pyi": 1385456134120145584, + "backend/src/services/auth_service.py": 17642785219801916280, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_skew.py": 5276102682005383261, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/RECORD": 18314788057673509075, + "backend/src/services/clean_release/compliance_orchestrator.py": 10585043190405940115, + "venv/lib/python3.13/site-packages/dotenv/version.py": 13508433229287636267, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_unique.py": 3148372351781648868, + "venv/lib/python3.13/site-packages/jose/backends/ecdsa_backend.py": 2684176977865283060, + "venv/lib/python3.13/site-packages/pandas/io/feather_format.py": 13242733585787888812, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategies.py": 15673926142454922581, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/base.py": 7110726987481713080, + "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.pyi": 12052895927933479005, + "venv/lib/python3.13/site-packages/pandas/core/indexes/base.py": 496956059910401121, + "frontend/build/_app/immutable/nodes/32.Cmesu1rv.js": 1679171227981656667, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py": 7019253290755243568, + "backend/src/services/git/_base.py": 3671238045679556094, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/apps.py": 10758062668702044519, + "venv/lib/python3.13/site-packages/pygments/styles/lilypond.py": 12486578704132023691, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/resources.py": 11533706401259147051, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_musllinux.py": 2423350951094915747, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcrypto-2e26a48f.so.3": 3658133521245392852, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/screen.py": 6933591906297023845, + "frontend/playwright-report/trace/uiMode.C2Efnu2P.js": 2717171022864487300, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_argparse.py": 11111699418217357084, + "venv/lib/python3.13/site-packages/httpcore/_exceptions.py": 6716590711697088732, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_amd64_unix.h": 16679226724722970205, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_datetimes.py": 7889573945417063183, + "venv/lib/python3.13/site-packages/attr/_cmp.py": 3297594878548179300, + "venv/lib/python3.13/site-packages/starlette/_exception_handler.py": 9892172656847200124, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/reporter.py": 6510864297510700136, + "venv/lib/python3.13/site-packages/pygments/lexers/yang.py": 7409365668425173823, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/random.pyi": 1808392097712315455, + "frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js": 15198772446275187033, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_csv.py": 571991535656576735, + "venv/lib/python3.13/site-packages/PIL/FitsImagePlugin.py": 618556384932056120, + "backend/src/services/__tests__/test_health_service.py": 17832814613637967046, + "venv/lib/python3.13/site-packages/numpy/_array_api_info.pyi": 13283968924732680159, + "venv/lib/python3.13/site-packages/passlib/handlers/pbkdf2.py": 16686685453577026643, + "venv/lib/python3.13/site-packages/pandas/core/tools/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/integration.py": 3085827906490477329, + "venv/lib/python3.13/site-packages/cffi/error.py": 8147505969912539538, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_index.py": 10971093361190283675, + "venv/lib/python3.13/site-packages/pip/_internal/cli/cmdoptions.py": 12107733000019393631, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/RECORD": 15865206372525596795, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_aix.h": 8706347224105630468, + "venv/lib/python3.13/site-packages/pydantic/v1/schema.py": 10008526732895436361, + "venv/lib/python3.13/site-packages/PIL/__init__.py": 10393984345353752724, "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8693/__init__.py": 11065844267208884531, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/ec_key.py": 5961540064444749833, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_endian.h": 2761502363895204652, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/__init__.py": 11850945878149145990, + "venv/lib/python3.13/site-packages/pygments/lexers/c_cpp.py": 1211842877043321095, + "backend/src/models/dataset_review_pkg/_filter_models.py": 13932350898582638473, + "venv/lib/python3.13/site-packages/pygments/lexers/webidl.py": 8097260111959278117, + "venv/lib/python3.13/site-packages/numpy/_core/_ufunc_config.py": 7365943844063702766, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.BSD": 16833702494864671773, + "venv/lib/python3.13/site-packages/pandas/io/json/_normalize.py": 15938855324762935595, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/__init__.py": 6758781485387665020, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_fillna.py": 7349777469648334282, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/orm.py": 7554417559838785150, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_constructors.pyi": 164538008396001632, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/METADATA": 9041650844081036822, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-1.csv": 16078879475693341404, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/funcfortranname.pyf": 1361426175133186231, + "venv/lib/python3.13/site-packages/pandas/core/indexers/utils.py": 5861072573716897447, + "venv/lib/python3.13/site-packages/python_multipart/__init__.py": 10290895261363712562, + "frontend/build/_app/immutable/chunks/DSxK3NUv.js": 8639953729041066468, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_stat_reductions.py": 11569525436540769152, + "backend/src/models/profile.py": 6081037345174498278, + "venv/lib/python3.13/site-packages/_pytest/stepwise.py": 3527630676691417317, + "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector_cpp.cpython-313-x86_64-linux-gnu.so": 16337157355618216738, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/json_schema_test_suite.py": 6152158310190822762, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test__exceptions.py": 12099001631178696189, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/__init__.py": 10357835306532281617, + "frontend/src/routes/+page.ts": 11160596731849880920, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/scoping.py": 17216492046645992674, + "venv/lib/python3.13/site-packages/pygments/formatters/html.py": 1918541918263449443, + "venv/lib/python3.13/site-packages/websockets/asyncio/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_between_time.py": 14266333058913745751, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_polynomial.py": 3049262771098624825, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/__init__.py": 16416360448593978041, + "venv/lib/python3.13/site-packages/PIL/_avif.cpython-313-x86_64-linux-gnu.so": 5243449968857258659, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_constructors.py": 6727209833819502644, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_reductions.py": 17810094294132819208, + "venv/lib/python3.13/site-packages/sqlalchemy/util/compat.py": 16148553252010089561, + "venv/lib/python3.13/site-packages/pygments/lexers/other.py": 6893672181003034910, + "venv/lib/python3.13/site-packages/pydantic/validate_call_decorator.py": 11130572937843915026, + "venv/lib/python3.13/site-packages/pydantic/plugin/__init__.py": 16803973597469216174, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_legend.py": 13094583566764796297, + "venv/lib/python3.13/site-packages/pandas/io/_util.py": 13608922148814398500, + "venv/lib/python3.13/site-packages/urllib3/response.py": 1987354357306756790, + "frontend/src/routes/datasets/__tests__/inline_edit.test.js": 17712409018171053453, + "backend/src/core/middleware/__init__.py": 13917394130915533209, + "venv/lib/python3.13/site-packages/pygments/lexers/_css_builtins.py": 17478340487186531268, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply.py": 8103417303073393969, + "venv/lib/python3.13/site-packages/h11/_receivebuffer.py": 4631433251046338381, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx": 15936470837420356071, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_where.py": 14167991754625133668, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_replace.py": 18039668944453454689, + "backend/tests/core/migration/test_dry_run_orchestrator.py": 5158126098685923841, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/stride_tricks.pyi": 5844806555773292985, + "backend/git_repos/remote/test-repo.git/objects/71/47ad0836409b35c1650dddf5fa6329ba61a824": 16601919569600972016, + "venv/lib/python3.13/site-packages/passlib/handlers/argon2.py": 835074952952017434, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/rebuild.py": 1813298167468704155, + "venv/bin/py.test": 2593802493707545818, + "venv/lib/python3.13/site-packages/starlette/requests.py": 4582424111350387010, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/RECORD": 3649834117451110628, + "venv/lib/python3.13/site-packages/pandas/_libs/hashtable.cpython-313-x86_64-linux-gnu.so": 16963890771704942465, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_time.py": 10463741033950978270, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/uts46data.py": 1867240043777383728, + "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe_protocol.py": 12857147443873820285, + "venv/lib/python3.13/site-packages/gitdb/utils/encoding.py": 1668793658272579497, + "venv/lib/python3.13/site-packages/numpy/ma/README.rst": 13203411621071845216, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/gcp.py": 12328409672947966867, + "venv/lib/python3.13/site-packages/_pytest/config/findpaths.py": 7867603756389940562, + "venv/lib/python3.13/site-packages/numpy/_core/tests/_locales.py": 18178500267053825979, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_builtin.py": 74545289993348593, + "backend/tests/core/test_git_service_gitea_pr.py": 6098719224379185148, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_arrow_compat.py": 17818294260710640443, + "venv/lib/python3.13/site-packages/pydantic/_internal/_internal_dataclass.py": 13206778611516171760, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth1_session.py": 1911069558956893789, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator": 6616723520993329538, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/memmap.pyi": 2834143910417841603, + "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/scalar/interval/test_interval.py": 2911379732293827726, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_to_pydatetime.py": 1129954411080617001, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/__init__.py": 5896924546560667519, + "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/indexes/base_class/test_pickle.py": 3419420815386925630, + "venv/lib/python3.13/site-packages/keyring/__init__.py": 991260689223167957, + "venv/bin/pip3.13": 13861749540792881808, + "venv/lib/python3.13/site-packages/pydantic_settings/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_string.py": 13234624995755549329, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/WHEEL": 13232065379159720345, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/align.py": 6078666505647454830, + "venv/lib/python3.13/site-packages/PIL/PaletteFile.py": 4104323659569809769, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/METADATA": 11557342107649194148, + "venv/lib/python3.13/site-packages/pip/_internal/utils/unpacking.py": 106471890743211548, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/token.py": 4161760290367932793, + "venv/lib/python3.13/site-packages/pandas/core/ops/array_ops.py": 10061020479033421596, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2py2e.py": 8571347023940385644, + "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/_libs/lib.cpython-313-x86_64-linux-gnu.so": 6452315003728497116, + "frontend/build/_app/immutable/assets/AssistantChatPanel.D4L5jlt0.css": 10724144138366384732, + "venv/lib/python3.13/site-packages/h11/_version.py": 9334144031400715479, + "backend/src/models/dataset_review_pkg/_execution_models.py": 14035769184235191693, + "venv/lib/python3.13/site-packages/jaraco/functools/__init__.py": 15334412919279565528, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/resource_protector.py": 9147671710440653567, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/routes/validation/history/+page.svelte": 3920288174017004134, + "backend/src/services/reports/report_service.py": 17586405613867657190, + "venv/lib/python3.13/site-packages/pip/_internal/commands/download.py": 7533669665002975823, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_level_values.py": 12490886203425393290, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/__init__.py": 14186136918454802843, + "frontend/src/lib/components/ui/SearchableMultiSelect.svelte": 681804602822957470, + "backend/git_repos/remote/test-repo.git/hooks/applypatch-msg.sample": 12627299623252391515, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/compiler.py": 13924519162400330589, + "venv/lib/python3.13/site-packages/apscheduler/executors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/date/__init__.py": 16789767433439616593, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/installed.py": 18153165899841229597, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_reduction.py": 2671872764983553906, + "frontend/build/_app/immutable/nodes/3.DC_u72aE.js": 9573850396512596892, + "frontend/eslint.config.js": 14296985543214702398, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_reductions.py": 633644255158859565, + "venv/lib/python3.13/site-packages/fastapi/background.py": 16533963020573865222, + "venv/lib/python3.13/site-packages/pandas/errors/__init__.py": 13444371880185740908, + "venv/lib/python3.13/site-packages/anyio/_core/_resources.py": 8463932838064724564, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/__init__.py": 12793458753561114666, + "venv/lib/python3.13/site-packages/pip/_internal/cli/progress_bars.py": 7584699216537478969, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_deprecations.py": 14624516389510242394, + "backend/src/models/__init__.py": 13280325675752905975, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/abc.py": 6227782083136374888, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/dtype.pyi": 12178008080078679769, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/provision.py": 9472538482404392519, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_ccalendar.py": 8819357623337533489, + "venv/lib/python3.13/site-packages/requests/structures.py": 2668010839316715865, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py": 17873236864291624476, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/selectable.py": 14646717349365560549, + "venv/lib/python3.13/site-packages/numpy/lib/npyio.pyi": 3212440968296555560, + "venv/lib/python3.13/site-packages/pandas/tests/extension/date/array.py": 18073740473413382768, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/base.py": 16052592982063844259, + "venv/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd": 1476688171642957054, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/_pytest/config/argparsing.py": 11156052029258891503, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/yaml/emitter.py": 6036657460416912844, + "venv/lib/python3.13/site-packages/dateutil/tz/__init__.py": 9617254832690762236, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/RECORD": 7810411361439269754, + "venv/lib/python3.13/site-packages/pygments/lexers/jsx.py": 13855228003748707341, + "frontend/src/lib/components/reports/__tests__/reports_filter_performance.test.js": 10583581505638859039, + "frontend/build/_app/immutable/nodes/37.qmsMPGgB.js": 3325998617833460603, + "backend/src/core/superset_client/_dashboards_list.py": 10999374002470143873, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/__init__.py": 8924316361489544973, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/criterion.py": 2042509334195547606, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.pyi": 9854069702366900663, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_get_numeric_data.py": 5896318696417090902, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_partial.py": 3151286293440416036, + "frontend/src/components/tasks/LogFilterBar.svelte": 5318774167984892372, + "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.py": 15854257948148516490, + "frontend/src/routes/storage/repos/+page.svelte": 3849368960648953479, + "backend/src/models/api_key.py": 4327024700622965951, + "frontend/src/routes/validation/[id]/+page.svelte": 17573557905368368906, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_month.py": 8485374160446988786, + "venv/lib/python3.13/site-packages/httpcore/_async/socks_proxy.py": 9026788710898138090, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_subclassing.py": 17318983445227658412, + "backend/alembic/versions/a5b6c7d8e9f0_set_null_ondelete_for_task_records_env_fk.py": 17528129825127496932, + "docker/backend.Dockerfile": 4384294014726084339, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/revocation.py": 16178499278312777474, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq_py.py": 16054175754674285311, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numeric.pyi": 17005748821769179511, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.py": 6142062990691556076, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_base.py": 16710163879060522196, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/METADATA": 15970460108484113417, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/status.py": 2214590120238144582, + "venv/lib/python3.13/site-packages/pydantic/v1/json.py": 16596969681914729251, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_unittests.py": 18157503533859249155, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_quantile.py": 17110581927381599978, + "venv/lib/python3.13/site-packages/pandas/tests/extension/conftest.py": 16886862391161243448, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/dim2.py": 5767600151459095125, + "venv/lib/python3.13/site-packages/anyio/_core/_synchronization.py": 7050001375718876608, + "venv/lib/python3.13/site-packages/fastapi/openapi/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/io/formats/console.py": 10370334487585281127, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_cython.py": 2933400021016349431, + "venv/lib/python3.13/site-packages/pygments/lexers/capnproto.py": 15713281507099411738, + "venv/lib/python3.13/site-packages/pygments/lexers/bqn.py": 11823648528816858738, + "venv/lib/python3.13/site-packages/psycopg2/tz.py": 9966680685796585198, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/RECORD": 11604408378998955169, + "venv/lib/python3.13/site-packages/numpy/lib/_npyio_impl.pyi": 6576645822227068922, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi": 9294219058621261971, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/RECORD": 9974324769263969827, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_quoted_character.py": 2316632434571797367, + "venv/lib/python3.13/site-packages/httpcore/_backends/base.py": 5491727479625093183, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_struct_accessor.py": 6567451952835390075, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_mips_unix.h": 17373389962405490482, + "venv/lib/python3.13/site-packages/greenlet/TGreenlet.cpp": 4121171004360760212, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.py": 5221550291012182443, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_salsa.py": 1756536674254931838, + "backend/src/api/routes/translate/_helpers.py": 13265933139767815312, + "venv/lib/python3.13/site-packages/pygments/lexers/asn1.py": 15030988816882821134, + "venv/lib/python3.13/site-packages/pandas/io/parsers/arrow_parser_wrapper.py": 11745253171984606573, + "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.py": 11393954913234866059, + "venv/lib/python3.13/site-packages/pip/_internal/__init__.py": 7060345458485901709, + "venv/lib/python3.13/site-packages/passlib/apache.py": 2357244937629445006, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90": 14350239197565389508, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_categorical.py": 9923236395692943732, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/datasource.pyi": 80441145804744162, + "backend/_convert_defs.py": 208535643309836247, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90": 8821492401453445757, + "backend/src/services/llm_provider.py": 18361253887642486050, + "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.pyi": 362674842164060822, + "venv/lib/python3.13/site-packages/pandas/_libs/reshape.cpython-313-x86_64-linux-gnu.so": 10639750501333255943, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_retain_attributes.py": 16210262356844956764, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_to_offset.py": 3929599794655343911, + "venv/lib/python3.13/site-packages/sqlalchemy/event/__init__.py": 16182540084654095394, + "venv/lib/python3.13/site-packages/keyring/compat/__init__.py": 7578020229796085753, + "venv/lib/python3.13/site-packages/pygments/lexers/algebra.py": 9651893228421050246, + "backend/src/core/superset_profile_lookup.py": 5518507735632088337, + "backend/src/api/routes/assistant/_llm_planner_intent.py": 16189718762013093878, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/comparisons.pyi": 9338084426044982038, + "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/ma/testutils.pyi": 3899348061346041413, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/__main__.py": 111505188798650285, + "venv/lib/python3.13/site-packages/numpy/testing/print_coercion_tables.pyi": 3814281717779245045, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_quarter.py": 6795026338946382805, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_misc.py": 8706265665356094801, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_clipboard.py": 12674078499544938252, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/__init__.py": 14481526616887213120, + "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.pyi": 5786150108623563787, + "frontend/src/lib/components/layout/__tests__/test_taskDrawer.svelte.js": 15288009749873977442, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/size/foo.f90": 18067977329435720684, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_downcast.py": 10399746645741452200, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/strategy_options.py": 16342048970907383117, + "venv/lib/python3.13/site-packages/numpy/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/cffi/commontypes.py": 11198107299826138465, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937_regressions.py": 8981142329261965538, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90": 10939657740734987454, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/provider.py": 16463243654123731993, + "backend/src/api/routes/git/_environment_routes.py": 1034235394475003092, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libk5crypto-b1f99d5c.so.3.1": 10669523137596317954, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadbconnector.py": 14865906347579451546, + "backend/src/api/routes/dataset_review_pkg/_routes.py": 11040245149296528009, + "venv/lib/python3.13/site-packages/pydantic_settings/main.py": 17272314000918984790, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/RECORD": 17594742868855466393, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/context.py": 1041624619197012753, + "venv/lib/python3.13/site-packages/pygments/formatters/groff.py": 6480830447984073574, + "venv/lib/python3.13/site-packages/pygments/styles/igor.py": 2291640843781128270, + "backend/src/services/clean_release/candidate_service.py": 8516915994721977806, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_format.py": 1947585389944838076, + "backend/src/services/dataset_review/repositories/session_repository.py": 4058785536575367912, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nbit_base_example.pyi": 8571452382806614924, + "frontend/src/services/git-utils.js": 12982149055119314642, + "venv/lib/python3.13/site-packages/pandas/_libs/pandas_parser.cpython-313-x86_64-linux-gnu.so": 18056339336364727359, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/bazaar.py": 5630511062945201327, + "venv/lib/python3.13/site-packages/pluggy/_manager.py": 18202550145040079612, + "venv/lib/python3.13/site-packages/greenlet/greenlet.h": 16216120538647882082, + "venv/lib/python3.13/site-packages/_pytest/pytester_assertions.py": 1899505062406979663, + "venv/lib/python3.13/site-packages/passlib/crypto/_md4.py": 379335134151814809, + "venv/lib/python3.13/site-packages/pydantic_core/core_schema.py": 8106298745123589494, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/pysqlcipher.py": 11225173272050906977, + "venv/lib/python3.13/site-packages/pygments/lexers/_stata_builtins.py": 18053452765493556047, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_index.py": 10837492069089787028, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/resource_protector.py": 17080006010679257864, + "frontend/build/_app/immutable/chunks/Ck4a7ANl.js": 3561562300210641559, + "backend/git_repos/remote/test-repo.git/objects/38/0395343915d386a8d58774cc6c6677205065e8": 5481382229802988191, + "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.cpython-313-x86_64-linux-gnu.so": 9380059465932560412, + "venv/lib/python3.13/site-packages/numpy/_globals.py": 8736093011628027941, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_function_base.pyi": 2792940598392356268, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_series.py": 2980850649986213051, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/wheel.py": 828222664427570058, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_header.py": 3564391095263545879, + "venv/lib/python3.13/site-packages/greenlet/tests/test_gc.py": 6383305344377882524, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-1.csv": 9129730764673472086, + "venv/lib/python3.13/site-packages/referencing/jsonschema.py": 14596871117484757502, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hiworld.f90": 6321872653169140461, + "venv/lib/python3.13/site-packages/pandas/core/sparse/api.py": 9094651265692218821, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/result.py": 8306497889916212025, + "venv/lib/python3.13/site-packages/pygments/lexers/bibtex.py": 14652372822443154388, + "frontend/e2e/run-enterprise-clean-e2e.sh": 11626901202531925046, + "venv/lib/python3.13/site-packages/pip/_internal/exceptions.py": 2252826732781519645, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_regression.py": 16293647824734937323, + "backend/src/api/routes/translate/_metrics_routes.py": 13468336445030118059, + "backend/tests/test_storage_config.py": 14773544217703363468, + "venv/lib/python3.13/site-packages/pip/_internal/network/__init__.py": 1586148254475575526, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/entities.py": 8001287806688585081, + "venv/lib/python3.13/site-packages/numpy/lib/_array_utils_impl.py": 14446508217220482719, + "venv/lib/python3.13/site-packages/pandas/tseries/offsets.py": 13750652921710295115, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunclike.py": 12077553320554633586, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_libsparse.py": 1859997684694949029, + "venv/lib/python3.13/site-packages/pandas/core/reshape/melt.py": 14109947554124551986, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress.py": 5951745251426856398, + "venv/lib/python3.13/site-packages/pandas/plotting/_misc.py": 10202078355301731720, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_deprecations.py": 16124509063246256847, + "venv/lib/python3.13/site-packages/pandas/core/internals/construction.py": 893951849732478990, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel_py.py": 9112851333217812996, + "venv/lib/python3.13/site-packages/pip/__main__.py": 574438877257676911, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90": 11326797716215117266, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_shape_base.py": 4117141349022217163, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_dtypes.py": 7550022036887594386, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_construction.py": 13953424340346625390, + "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.py": 5260748170237305627, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_compat.h": 6512969159139431485, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/WHEEL": 9131187629260560775, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py": 9430762168079129025, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resample_api.py": 3278209206670699265, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_fillna.py": 7244491410004453166, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reduce.py": 14976712507854054776, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/names.py": 705261158040926128, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE": 16499431172938528491, + "frontend/src/lib/components/MaintenanceEventsTable.svelte": 1697386217337210174, + "frontend/src/routes/translate/dictionaries/[id]/+page.svelte": 17719561272401762626, + "backend/src/api/routes/__tests__/test_migration_routes.py": 2319142184353163171, + "venv/lib/python3.13/site-packages/pandas/_testing/_io.py": 14264259716673715185, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_base.py": 8678387511873412922, + "venv/lib/python3.13/site-packages/keyring/completion.py": 1027436016070040568, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arrayterator.py": 1646530870049791291, + "venv/lib/python3.13/site-packages/_pytest/config/exceptions.py": 3199245296954654462, + "venv/lib/python3.13/site-packages/pillow.libs/libjpeg-32d42e18.so.62.4.0": 11717944412021329207, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas7bdat.py": 8963983384208121526, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/status_codes.py": 17005213506461710202, + "frontend/src/routes/+page.svelte": 16267809857510759396, + "venv/lib/python3.13/site-packages/_pytest/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/dateutil/tz/tz.py": 5258008267965780817, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/__init__.py": 15340047930888693984, + "venv/lib/python3.13/site-packages/cffi/__init__.py": 13427266446746498548, + "venv/lib/python3.13/site-packages/ecdsa/curves.py": 812969717084691115, + "venv/lib/python3.13/site-packages/pydantic/deprecated/parse.py": 819235411736647763, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/nonce.py": 18219168479887197733, + "venv/lib/python3.13/site-packages/numpy/_typing/_dtype_like.py": 1598511035344858524, + "venv/lib/python3.13/site-packages/itsdangerous/encoding.py": 205863946173486958, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/METADATA": 14180973198574731599, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/decoder.py": 11876648884087997745, + "venv/lib/python3.13/site-packages/apscheduler/triggers/calendarinterval.py": 12481650996882675949, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/util.py": 9373891872370603585, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv": 221209423454319618, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_util.py": 16024147572807865219, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/infer.py": 12541904372617915365, + "venv/lib/python3.13/site-packages/yaml/error.py": 5626374410579058436, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/__init__.py": 16434403703599680307, + "venv/lib/python3.13/site-packages/pygments/lexers/_scheme_builtins.py": 5722444920479775453, + "venv/lib/python3.13/site-packages/httpx/_transports/__init__.py": 5931944625631942279, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/fromnumeric.pyi": 8671744104085911610, + "venv/lib/python3.13/site-packages/requests/models.py": 9104898985870652256, + "venv/lib/python3.13/site-packages/pandas/core/internals/blocks.py": 6448406236246476333, + "venv/lib/python3.13/site-packages/passlib/crypto/des.py": 14699826058580193499, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_file_buffer_url.py": 15377043158761455858, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/table.py": 16856253349556498073, + "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.pyi": 15767546107856827543, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timedeltas.pyi": 3783371827926657291, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_function.py": 644452398244782315, + "venv/lib/python3.13/site-packages/PIL/DcxImagePlugin.py": 11767274218348117481, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/array.py": 1919242530821725197, + "venv/lib/python3.13/site-packages/jeepney/fds.py": 16573439672758641560, + "venv/lib/python3.13/site-packages/pygments/lexers/parsers.py": 12372594608244797844, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked_shared.py": 8453174300922339015, + "venv/lib/python3.13/site-packages/pygments/lexers/mojo.py": 8616283481592061285, + "frontend/src/lib/stores/__tests__/test_activity.js": 15599963775430388097, + "frontend/src/routes/tools/mapper/+page.svelte": 11954517841045690204, + "venv/lib/python3.13/site-packages/_pytest/_version.py": 4890545974654141536, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/tornado.py": 6491136785917169991, + "venv/lib/python3.13/site-packages/_pytest/__init__.py": 3769333500910148571, + "frontend/build/_app/immutable/nodes/21.i4crDxrH.js": 12772123636509212690, + "venv/lib/python3.13/site-packages/fastapi/middleware/__init__.py": 5289703478893407762, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_aarch64_gcc.h": 8140470539757491899, + "venv/lib/python3.13/site-packages/pip/_internal/locations/__init__.py": 8147012724727395488, + "venv/lib/python3.13/site-packages/ecdsa/test_eddsa.py": 1785854649532849946, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayterator.pyi": 7439348655567232744, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/accessors.py": 12743680296510533030, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_npfuncs.py": 13987318550267921389, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi": 1065808244870331598, + "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.py": 1731362089136926666, + "venv/lib/python3.13/site-packages/git/refs/reference.py": 2038789918710608481, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/wrappers.py": 315409799569602977, + "venv/lib/python3.13/site-packages/pandas/compat/_optional.py": 12714208019736797073, + "venv/lib/python3.13/site-packages/git/objects/submodule/root.py": 5322248117564025370, + "frontend/src/components/git/useGitManager.js": 5317184945628692154, + "backend/src/core/task_manager/models.py": 7035565766825575890, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_insert.py": 9195027887301180927, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_spec_conformance.py": 16448324304809345527, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_calendar.py": 12313641252472031631, + "backend/src/api/routes/__tests__/test_git_api.py": 222548597993158802, + "backend/src/api/routes/translate/_schedule_routes.py": 18180097500694105300, + "backend/src/core/utils/matching.py": 12567367681677699487, + "backend/src/services/resource_service.py": 4680770771466252195, + "backend/alembic/env.py": 7020161137665650592, + "backend/src/plugins/debug.py": 2035734953696955393, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_transpose.py": 17983160984979323393, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_isfile.py": 14544060093268573418, + "venv/lib/python3.13/site-packages/pygments/lexers/rego.py": 16022844238903541738, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_dependency_group.py": 10505346210114745037, + "venv/lib/python3.13/site-packages/rpds/rpds.cpython-313-x86_64-linux-gnu.so": 561326734302492859, + "venv/lib/python3.13/site-packages/websockets/datastructures.py": 5180442040351387281, + "venv/lib/python3.13/site-packages/websockets/legacy/protocol.py": 762692033188392424, + "docker/all-in-one.Dockerfile": 10896793266219904099, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_data_list.py": 1131520422778420758, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/background.py": 2105814165112049750, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv": 601782991752922510, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_numpyconfig.h": 18150055639397773687, + "venv/lib/python3.13/site-packages/packaging/__init__.py": 5479277484104486860, + "venv/lib/python3.13/site-packages/bcrypt/__init__.py": 11415155211917181362, + "venv/lib/python3.13/site-packages/_pytest/timing.py": 14080119171718125986, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/meson.build.template": 9935732744553086652, + "venv/lib/python3.13/site-packages/python_multipart/multipart.py": 5677735019292537174, + "venv/lib/python3.13/site-packages/numpy/f2py/symbolic.pyi": 14558091964387571257, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/RECORD": 7363618870628306370, + "backend/src/api/routes/git/_repo_operations_routes.py": 5819532622410034169, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_s390_unix.h": 5161826643658505126, + "venv/lib/python3.13/site-packages/pygments/lexers/ada.py": 17032408976634308999, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.f90": 1249061697041863692, + "frontend/src/lib/stores/__tests__/test_sidebar.js": 113566022614194798, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_reductions.py": 3227705565578016389, + "frontend/src/routes/datasets/__tests__/bulk_actions.test.js": 8445672988319354987, + "backend/src/services/notifications/providers.py": 12897444612423813747, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2cffi.py": 5997687240967250164, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/__init__.py": 12975130533860125272, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/_gen_files.py": 6273314671315377131, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_from_dummies.py": 5670811108950300761, + "venv/lib/python3.13/site-packages/urllib3/connectionpool.py": 7493427857878469165, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mutable.py": 9323088483998280629, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/mean_.py": 3641008929910474457, + "venv/lib/python3.13/site-packages/pandas/core/arrays/masked.py": 13977195666947626206, + "backend/src/core/auth/oauth.py": 9925908783612235042, + "venv/lib/python3.13/site-packages/numpy/random/_philox.cpython-313-x86_64-linux-gnu.so": 9916143171057774705, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/METADATA": 11759004913807981650, + "venv/lib/python3.13/site-packages/PIL/FtexImagePlugin.py": 8196606399875185931, + "venv/lib/python3.13/site-packages/dateutil/rrule.py": 398469817784230512, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_where.py": 3272402211717453881, + "venv/bin/activate": 14735074000123383125, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets.py": 10923534235697247269, + "venv/lib/python3.13/site-packages/rpds/__init__.py": 5862197328247012275, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/base.py": 5924592154431932923, + "venv/lib/python3.13/site-packages/pip/__init__.py": 9449893869469432503, + "venv/lib/python3.13/site-packages/pygments/lexers/_mysql_builtins.py": 16087227298679432006, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_hour.py": 14128508606361694814, + "backend/src/api/routes/plugins.py": 4567336078922104278, + "frontend/build/_app/immutable/nodes/25.DDfuZIEE.js": 7817480037775221276, + "venv/lib/python3.13/site-packages/authlib/oidc/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_value_counts.py": 15633881149834196174, + "venv/lib/python3.13/site-packages/anyio/to_process.py": 16627578499791368365, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv": 16333455295913164408, + "venv/lib/python3.13/site-packages/apscheduler/executors/tornado.py": 6635576580306890718, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/tzconversion.pyi": 10947021928755741366, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/windows.py": 16452996247375488034, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/test_list.py": 4538625980063375611, + "venv/lib/python3.13/site-packages/fastapi/_compat/shared.py": 5249003014594464718, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_string.py": 11422235699126032386, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py": 17908437937265384125, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_explode.py": 18263694040596159591, + "frontend/e2e/tests/smoke.e2e.js": 11130903009452044456, + "venv/lib/python3.13/site-packages/anyio/streams/tls.py": 4191898645554875562, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_dml_constructors.py": 4497038002189188311, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/datonly.f90": 10495925225338237742, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dlpack.py": 7908102652282922952, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_three_greenlets2.py": 11100501798741918610, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_ufunc.py": 5025605639221470838, + "venv/lib/python3.13/site-packages/jaraco/context/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/util/tool_support.py": 4926732415520779988, + "backend/git_repos/remote/test-repo.git/hooks/pre-rebase.sample": 15693225890270078290, + "venv/lib/python3.13/site-packages/PIL/ImageMath.py": 7395449734007598797, + "venv/lib/python3.13/site-packages/anyio/abc/_tasks.py": 16839170934610571514, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/adapter.py": 5908944827805063108, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_size.py": 12449835577388069407, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/_psycopg_common.py": 4111797647365870137, + "venv/lib/python3.13/site-packages/git/objects/submodule/base.py": 10140490301897269395, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/util.py": 10640907133050862176, + "venv/lib/python3.13/site-packages/numpy/ma/mrecords.py": 687170905107114309, + "venv/lib/python3.13/site-packages/ecdsa/test_keys.py": 17117188373419689467, + "venv/lib/python3.13/site-packages/PIL/_imagingtk.cpython-313-x86_64-linux-gnu.so": 1708198947135304326, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/scripts.py": 8759605303886441976, + "venv/lib/python3.13/site-packages/numpy/random/mtrand.cpython-313-x86_64-linux-gnu.so": 16146459667121787202, + "venv/lib/python3.13/site-packages/websockets/http.py": 9406523480132204760, + "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/METADATA": 2053484635654179443, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/utils/logging.py": 9639351759822608724, + "venv/lib/python3.13/site-packages/pygments/lexers/configs.py": 7712797939104760185, + "backend/tests/scripts/test_clean_release_tui.py": 14700450036639944764, + "backend/src/services/clean_release/policy_resolution_service.py": 5075709738950902327, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/array.py": 12658302948819867972, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_copy.py": 12902342280706372953, + "venv/lib/python3.13/site-packages/attrs/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/ops_dispatch.pyi": 16176428602589420913, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_index_as_string.py": 13421551616136437100, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_comment.py": 5603075924832933306, + "venv/lib/python3.13/site-packages/fastapi/_compat/model_field.py": 392699021682253569, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/indexable.py": 4131796922597075758, + "venv/lib/python3.13/site-packages/pygments/lexers/yara.py": 17510792615476493957, + "backend/src/plugins/backup.py": 9775992510122456201, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/baked.py": 6911138208603240867, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_3kcompat.h": 5377305123299457337, + "frontend/src/lib/components/reports/__tests__/report_detail.integration.test.js": 4193615240297330385, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libssl-81ffa89e.so.3": 13913673119166658781, + "frontend/src/lib/components/ui/MultiSelect.svelte": 1475503303018683038, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-1.csv": 16349400027062875699, + "venv/lib/python3.13/site-packages/urllib3/util/timeout.py": 17922362393077965047, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/models.py": 11521700876708601977, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/twodim_base.pyi": 3773329770170248877, + "venv/lib/python3.13/site-packages/numpy/random/_pickle.py": 7774620933480975313, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_formats.py": 5259100336852479395, + "venv/lib/python3.13/site-packages/authlib/common/urls.py": 13627272625165922482, + "venv/lib/python3.13/site-packages/attr/_config.py": 1864824728504480204, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_builtin_md4.py": 16840174243259839994, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_filter.py": 2388681477981649268, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/config.py": 1450073446492183677, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_encoding.py": 6622474614967398246, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_astype.py": 4178231007649608531, + "frontend/build/_app/immutable/nodes/31.BylL8uTk.js": 7722395710886140688, + "venv/lib/python3.13/site-packages/ecdsa/rfc6979.py": 11564966030899162026, + "venv/lib/python3.13/site-packages/numpy/_core/__init__.py": 14951958843029076911, + "venv/lib/python3.13/site-packages/pydantic/error_wrappers.py": 11273827025986230629, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_gcs.py": 7733247456252965901, + "venv/lib/python3.13/site-packages/greenlet/TPythonState.cpp": 12828594265749606443, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_groupby.py": 12709199432838648700, + "venv/lib/python3.13/site-packages/pygments/console.py": 3540660073442483692, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv": 3026156288992132911, + "backend/git_repos/remote/test-repo.git/objects/ed/0432f88f5f7d95b26ecde34345abe741dd9db2": 13426916511127204463, + "venv/lib/python3.13/site-packages/apscheduler/executors/asyncio.py": 2230610508870117058, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/bitwise_ops.pyi": 751490187478960891, + "venv/lib/python3.13/site-packages/greenlet/tests/test_weakref.py": 6780204527427742510, + "venv/lib/python3.13/site-packages/authlib/oauth2/base.py": 12948318231066662045, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_abstract_interface.py": 17625870734108222276, + "venv/lib/python3.13/site-packages/pandas/tests/libs/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/event/api.py": 987321343916500337, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_constructors.py": 6515602441449955627, + "venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py": 4857114071347950833, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_conversion.py": 12184280074522274780, + "frontend/playwright-report/trace/assets/defaultSettingsView-D31xz8zv.js": 1301407320635785789, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/modeline.py": 6194365452131561478, + "frontend/src/components/tools/DebugTool.svelte": 17267560034225794881, + "backend/src/scripts/seed_superset_load_test.py": 892949594919634674, + "venv/lib/python3.13/site-packages/idna/intranges.py": 12536174834761591006, + "venv/lib/python3.13/site-packages/keyring/devpi_client.py": 3445890176686211982, + "venv/lib/python3.13/site-packages/pydantic/experimental/arguments_schema.py": 8644805798814234457, + "backend/src/services/clean_release/preparation_service.py": 10596397721803950912, + "backend/src/plugins/translate/_text_cleaner.py": 13161219043687449729, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_constructors.py": 12628643543371952431, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/LICENSE": 16343563559291870811, + "venv/lib/python3.13/site-packages/pygments/lexers/resource.py": 8057351545636349791, + "venv/lib/python3.13/site-packages/attrs/filters.py": 6844006230924162452, + "venv/lib/python3.13/site-packages/ecdsa/test_malformed_sigs.py": 2606295770491528880, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.pyi": 16372699564794732463, + "venv/lib/python3.13/site-packages/jose/backends/__init__.py": 16581763658239070112, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_observance.py": 18178414966262524534, + "venv/lib/python3.13/site-packages/starlette/status.py": 16192064443996706569, + "backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py": 11718998093543631478, + "venv/lib/python3.13/site-packages/jeepney/tests/test_auth.py": 15125055415702968414, + "backend/src/models/dataset_review_pkg/_finding_models.py": 7257895729340231285, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_data.py": 2397937327057341, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE": 17284252174641192866, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_datetimeindex.py": 14816894350435545024, + "venv/lib/python3.13/site-packages/pydantic/deprecated/class_validators.py": 2200511838255373813, + "venv/lib/python3.13/site-packages/urllib3/util/connection.py": 15511685694589961094, + "frontend/build/_app/immutable/assets/9.tn0RQdqM.css": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_install.py": 7181005402818830655, + "frontend/src/routes/storage/backups/+page.svelte": 3437582895363203695, + "backend/src/plugins/translate/preview_session_serializer.py": 8901687711861433007, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/__main__.py": 487896753130729554, + "venv/lib/python3.13/site-packages/pygments/lexers/textedit.py": 14872291021083255414, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_regression.py": 4611768764484593979, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/sqltypes.py": 2952996080192295188, + "venv/lib/python3.13/site-packages/sqlalchemy/schema.py": 16029542421991709659, + "venv/lib/python3.13/site-packages/pygments/styles/xcode.py": 14124729477757765388, + "backend/src/core/task_manager/task_logger.py": 12820629458199400734, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_factorize.py": 17995673140216929494, + "venv/lib/python3.13/site-packages/jsonschema/_format.py": 8987698648383779883, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_label_or_level_utils.py": 3423644585913150841, + "backend/src/plugins/translate/_lang_detect.py": 2125979777533490081, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/oct_key.py": 11504245602045724, + "venv/lib/python3.13/site-packages/passlib/ext/django/utils.py": 8118896525895185626, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_sort_values.py": 15072305514178699398, + "backend/src/plugins/translate/orchestrator_retry.py": 7628306124703690760, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_clip.py": 8087139801274517318, + "venv/lib/python3.13/site-packages/httpx/_content.py": 1301854837767395687, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf": 14717748358749934995, + "frontend/src/routes/settings/FeaturesSettings.svelte": 14192374301379217586, + "venv/lib/python3.13/site-packages/pytest_asyncio/plugin.py": 13414541723622354359, + "venv/lib/python3.13/site-packages/cffi/setuptools_ext.py": 30796527302561458, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/METADATA": 6502714564886871819, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_equivalence.py": 17843623343419137458, + "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.pyi": 14181518821845356636, + "venv/lib/python3.13/site-packages/authlib/oauth1/__init__.py": 3692257288065292607, + "merge_kilo.py": 4282227344165325430, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_explode.py": 16195468192763502449, + "venv/lib/python3.13/site-packages/_pytest/legacypath.py": 7512065138259788426, + "venv/lib/python3.13/site-packages/jsonschema/__init__.py": 6925762200139836824, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/filepost.py": 16698380375728063923, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/__init__.py": 3619091571279924576, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.c": 9134176670140958459, + "frontend/src/pages/Dashboard.svelte": 3653104499351855122, + "backend/src/services/clean_release/stages/manifest_consistency.py": 14323717074129560178, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/__init__.py": 3521833849634327520, + "venv/lib/python3.13/site-packages/numpy/_typing/_add_docstring.py": 14657346268890680694, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/flatiter.pyi": 6885824496927786205, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py": 3177255974394221645, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_modules.py": 16835987029123241300, + "venv/lib/python3.13/site-packages/keyring/http.py": 1408024724330078009, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/RECORD": 12733654377842895588, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation": 5398883285871046811, + "frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js": 2331331717663585059, + "frontend/src/routes/datasets/__tests__/DatasetList.test.js": 10189122239208504978, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/recfunctions.py": 18330899924171767482, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_math.h": 16701045088211015518, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_arrow.py": 10068866425352207113, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_convert.py": 13349243029437881949, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isna.py": 18394053826166267096, + "venv/lib/python3.13/site-packages/PIL/ImageSequence.py": 16459886231802763032, + "frontend/src/lib/components/health/HealthMatrix.svelte": 13165441444996153191, + "venv/lib/python3.13/site-packages/PIL/_webp.cpython-313-x86_64-linux-gnu.so": 11070012119632935103, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/markers.py": 8297667990263004097, + "venv/lib/python3.13/site-packages/fastapi/middleware/httpsredirect.py": 5775982317459922443, + "venv/lib/python3.13/site-packages/fastapi/dependencies/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/device_code.py": 6712610002227849281, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.py": 1472021608501071055, + "venv/lib/python3.13/site-packages/starlette/middleware/httpsredirect.py": 16837082808103815044, + "venv/lib/python3.13/site-packages/numpy/_core/lib/libnpymath.a": 17555816778997028283, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/_gen_files.py": 11149423183253618378, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.pyi": 16976386782787920450, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_array.py": 11271807719833350332, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/LICENSE": 8177430849046795595, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/redis.py": 11313520438600819390, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex_longtable.tpl": 12723621983797415444, + "venv/lib/python3.13/site-packages/greenlet/__init__.py": 3447613556981242475, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/exceptions.py": 2873060848310644552, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arithmetic.pyi": 10265823318697442495, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/integration.py": 12670848015915724967, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/gh19161.f90": 7691871466158049079, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/RECORD": 12015288851076448205, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_strptime.py": 14328510310436552635, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py": 15060063324909302240, + "venv/lib/python3.13/site-packages/pydantic/_internal/_fields.py": 2692892815545218335, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_index_equal.py": 10617870815989304510, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_object_arr.py": 4725156416161661681, + "venv/lib/python3.13/site-packages/websockets/server.py": 16599051743322571790, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufunc_config.py": 14728417910466146460, + "venv/lib/python3.13/site-packages/fastapi/cli.py": 13972351579061154035, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_npfuncs.py": 6132674295193898715, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_categorical.py": 1329115818264527103, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_timegrouper.py": 276805119790266454, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_reductions.py": 1713831062142840146, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64-testset-2.csv": 5423145402839576695, + "venv/lib/python3.13/site-packages/pydantic/parse.py": 13750341403702794392, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_dispatcher.py": 2063037275809439611, + "venv/lib/python3.13/site-packages/pandas/io/formats/string.py": 14718123345899686696, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/aiomysql.py": 12999962380333482189, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/RECORD": 8956798822782402202, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/json.py": 14755215397454910426, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/__init__.py": 11009955319062089477, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_keywords.py": 11487954623214475915, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiarray.py": 5928288171180750841, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/memmap.pyi": 15629663272474054909, + "venv/lib/python3.13/site-packages/rapidfuzz/utils_py.py": 12341806772632276946, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py": 16045758521544316139, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_asof.py": 8656532774394927388, "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/series/test_subclass.py": 13490541871827928531, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_indexing.py": 5063545640498065297, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/json.py": 4660603129768960095, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_infer_objects.py": 6769980076977692890, + "venv/lib/python3.13/site-packages/PIL/GimpPaletteFile.py": 2040459799887417392, + "venv/lib/python3.13/site-packages/cffi/api.py": 5325821560978502135, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_timestamp.py": 12253372102602993034, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_integrity.py": 12010564145080323987, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/extensions.py": 217122171232375592, + "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/core/ops/dispatch.py": 7041711677358147534, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/warnings_and_errors.pyi": 3151453262733619734, + "venv/lib/python3.13/site-packages/pandas/io/formats/printing.py": 3054136648863371285, + "venv/lib/python3.13/site-packages/numpy/lib/_ufunclike_impl.py": 12251264586530536622, + "venv/lib/python3.13/site-packages/PIL/XpmImagePlugin.py": 6644626557482464312, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pycparser/yacctab.py": 18018314512916353707, + "venv/lib/python3.13/site-packages/pygments/lexers/jsonnet.py": 1314044008440065525, + "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.cpp": 7360124705400993707, + "venv/lib/python3.13/site-packages/pygments/lexers/soong.py": 10273453675034306814, + "venv/bin/pyrsa-keygen": 8222542582170363672, + "frontend/src/lib/stores/sidebar.js": 8409084311045055153, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_xml_dtypes.py": 18293138335799308439, + "backend/src/schemas/health.py": 13764741380188041840, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/licenses/LICENSE": 8438117004702803716, + "venv/lib/python3.13/site-packages/pip/_internal/pyproject.py": 6155748929233245415, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_internal/utils/subprocess.py": 3095012838116670328, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/prompt.py": 9561640601516933380, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/live.py": 8586058300967410643, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo77.f": 16250175448122328648, + "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.py": 6205675182996213576, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_methods.py": 14881910898871057761, + "venv/lib/python3.13/site-packages/pandas/_libs/ops.pyi": 1192312467209548763, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_monotonic.py": 14648437502004398715, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_day.py": 6371851881186970754, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_astype.py": 7542068949396266883, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/cx_oracle.py": 10093932131797570986, + "venv/lib/python3.13/site-packages/greenlet/tests/test_contextvars.py": 6077482318964702132, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_check_indexer.py": 2929031395357057009, + "venv/lib/python3.13/site-packages/sqlalchemy/exc.py": 6372950288664776625, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_bool.py": 433342705586552936, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/h11_impl.py": 1419719055394402145, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/extension_types.py": 1856757457657310231, + "venv/lib/python3.13/site-packages/pygments/styles/staroffice.py": 11694998942433220413, + "venv/lib/python3.13/site-packages/pygments/lexers/pawn.py": 18127303119414402594, + "venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py": 1246582552828542841, + "backend/src/schemas/dataset_review.py": 15720223123457526104, + "backend/src/services/notifications/__init__.py": 13930898146447654299, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90": 13943066317159236257, + "venv/lib/python3.13/site-packages/websockets/asyncio/messages.py": 6848925149930551457, + "backend/src/services/git_service.py": 1930048176535450912, + "backend/git_repos/remote/test-repo.git/hooks/commit-msg.sample": 13435789416588783681, + "backend/git_repos/remote/test-repo.git/objects/a7/49f11fad695dff77faf1708c7320867d0be1df": 4641609158325033031, + "venv/lib/python3.13/site-packages/PIL/ImageStat.py": 18442709639217312689, + "venv/lib/python3.13/site-packages/git/objects/base.py": 11498407361286170399, + "venv/lib/python3.13/site-packages/jose/backends/cryptography_backend.py": 2875270748627611635, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py": 2285778903282667561, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/pager.py": 18072372651585577904, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/conftest.py": 13388202260795998613, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/basereload.py": 14479857245734482609, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_loc.py": 17839380711970027363, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/nimrod.py": 8457135214131458774, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_asof.py": 15792528637923603240, + "venv/lib/python3.13/site-packages/pygments/lexers/shell.py": 3842338968014057744, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/use_modules.f90": 3913612933340746297, + "venv/lib/python3.13/site-packages/pygments/__init__.py": 14493583771211110135, + "backend/src/services/clean_release/repositories/candidate_repository.py": 14784344453820731941, + "frontend/src/routes/datasets/DatasetList.svelte": 2347298483008235943, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/__init__.py": 5027355874704300832, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_dt_accessor.py": 2229616362327032253, + "venv/lib/python3.13/site-packages/pygments/lexers/dsls.py": 11696359794961833087, + "venv/lib/python3.13/site-packages/pygments/styles/murphy.py": 8177992406082781615, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/common.py": 2075178842766962782, + "venv/lib/python3.13/site-packages/numpy/lib/scimath.py": 7616377937400918724, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/RECORD": 9964194961227523130, + "frontend/src/lib/api/translate/jobs.js": 9613844538417291513, + "backend/src/services/clean_release/stages/data_purity.py": 10459527906317168920, + "backend/git_repos/remote/test-repo.git/objects/22/c0ea49cea7e5138fb91b25b1bc0e101ae6e017": 17630871400599334193, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/compat.py": 9758194415584776667, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_twodim_base.py": 17623133613018058380, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_simd.py": 7577408467041941595, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_lib.py": 6721066015604956469, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/lexers/praat.py": 54226477748516386, + "venv/lib/python3.13/site-packages/keyring/testing/__init__.py": 15130871412783076140, + "frontend/playwright-report/data/fe71864b4cbf83c1ddaa5774098c6fa987f91ff9.webm": 9945873951473992150, + "venv/lib/python3.13/site-packages/pydantic/_internal/_validate_call.py": 4078236486720616395, + "venv/lib/python3.13/site-packages/jose/exceptions.py": 8562012933958941039, + "venv/lib/python3.13/site-packages/pandas/_version.py": 3480474785419232091, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/profiling.py": 16030397164203895281, + "venv/lib/python3.13/site-packages/sqlalchemy/event/registry.py": 2857989070743633709, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/__init__.py": 5863110456909134678, + "venv/lib/python3.13/site-packages/PIL/_imagingmath.cpython-313-x86_64-linux-gnu.so": 77725273398858074, + "venv/lib/python3.13/site-packages/_pytest/skipping.py": 10561585274103209115, + "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.py": 17192211156810267818, + "venv/lib/python3.13/site-packages/pandas/core/computation/eval.py": 3176226283265954028, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_replace.py": 8166203537440976347, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi": 18143251582901996072, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/dml.py": 5340326603935367534, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_ujson.py": 12184194085993665945, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro_py.py": 11991492232381887787, + "venv/lib/python3.13/site-packages/pandas/io/formats/style_render.py": 13586834368514801953, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqlconnector.py": 17538029557373507617, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/__init__.py": 1798074863773727377, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_kwarg.py": 10417724544218303733, + "venv/lib/python3.13/site-packages/pandas/core/groupby/categorical.py": 16588862198627920420, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_numeric.py": 18037815278545274402, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/watchfilesreload.py": 13062440477475586751, + "venv/lib/python3.13/site-packages/pygments/lexers/_mql_builtins.py": 2376212048709413586, + "frontend/src/lib/stores/activity.js": 14023344642294459631, + "backend/src/api/routes/dashboards/_action_routes.py": 11814954258886577640, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nth.py": 17151595277666975085, + "backend/src/models/filter_state.py": 6470311179852241297, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_generator_mt19937.py": 7299586490442539723, + "frontend/src/lib/components/translate/TranslationMetricsDashboard.svelte": 8577281635452165836, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nunique.py": 8450574751331186943, + "venv/lib/python3.13/site-packages/pygments/lexers/lilypond.py": 1088755646568511197, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine_first.py": 3100691245280812910, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/ccalendar.pyi": 15789956857032062129, + "venv/lib/python3.13/site-packages/fastapi/middleware/cors.py": 7452860773712601508, + "venv/lib/python3.13/site-packages/pydantic/fields.py": 4142211199816898047, + "venv/lib/python3.13/site-packages/cryptography/exceptions.py": 5173540025160237758, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/revocation.py": 5718403706971163960, + "venv/lib/python3.13/site-packages/pandas/core/window/ewm.py": 12143982379243011357, + "venv/lib/python3.13/site-packages/requests/packages.py": 7733041271118298220, + "venv/lib/python3.13/site-packages/anyio/abc/_resources.py": 8330687082933028623, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/__init__.py": 10456333337205488584, + "venv/lib/python3.13/site-packages/starlette/middleware/__init__.py": 9524277524025372856, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token.py": 4747545058753492487, + "venv/lib/python3.13/site-packages/pip/py.typed": 10243553515949422671, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.py": 893743087939984792, + "venv/lib/python3.13/site-packages/gitdb/test/test_util.py": 541144638852210407, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.pyi": 1830368009811266890, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_constructors.py": 11065058462752831997, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_core_functionalities.py": 10449747865888948579, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_normalize.py": 11373923576259976755, + "venv/lib/python3.13/site-packages/pandas/tests/api/test_api.py": 13385690673368400635, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_subclass.py": 10949229764696473939, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/hybrid.py": 5793056975404534989, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/METADATA": 7214286447912789067, + "venv/lib/python3.13/site-packages/PIL/MicImagePlugin.py": 13540523615822507963, + "backend/src/services/clean_release/repositories/approval_repository.py": 15069637305272665109, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/signals.py": 13677199634497673845, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/halffloat.h": 16913381775994652343, + "venv/lib/python3.13/site-packages/anyio/_core/_exceptions.py": 11969894261631227715, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_django.py": 8455054295577203929, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/METADATA": 3618776395694990076, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_year.py": 1478857009124807836, + "frontend/playwright-report/trace/defaultSettingsView.BDKsFU3c.css": 12935551588108679759, + "backend/src/plugins/llm_analysis/__init__.py": 9254812131558249924, + "venv/lib/python3.13/site-packages/pandas/_libs/properties.cpython-313-x86_64-linux-gnu.so": 7092136701092358552, + "venv/lib/python3.13/site-packages/httpx/_transports/base.py": 6498990531443644896, + "backend/src/plugins/translate/orchestrator_sql.py": 15420456250044832567, + "venv/lib/python3.13/site-packages/jose/backends/_asn1.py": 14123487576864105793, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/request.py": 17642741955458391050, + "backend/src/schemas/dataset_review_pkg/_dtos.py": 13301885458265748263, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/yaml.py": 17801117405950663611, + "venv/lib/python3.13/site-packages/passlib/utils/des.py": 2650106381178222229, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/spinner.py": 5564789578696016201, + "backend/src/plugins/translate/__tests__/test_preview.py": 13085659611728720229, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/columns.py": 8488246354818721406, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/licenses/LICENSE": 3996324383113221529, + "venv/lib/python3.13/site-packages/pygments/lexers/html.py": 17288963642862550116, + "venv/lib/python3.13/site-packages/numpy/_core/numeric.pyi": 17785360553418386488, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/scalars.pyi": 17683675356659300769, + "venv/lib/python3.13/site-packages/pygments/lexers/x10.py": 6167378515780115912, + "venv/lib/python3.13/site-packages/pygments/lexers/haskell.py": 8011341851439354724, + "backend/src/api/routes/__tests__/test_git_status_route.py": 6682904773087475636, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_py_util.py": 12836989066113400538, + "venv/lib/python3.13/site-packages/fastapi/temp_pydantic_v1_params.py": 9436036880518047720, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/_json.py": 6718137926109998531, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/operators.py": 2468046993343796128, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_datetime.py": 11417836378782978454, + "venv/lib/python3.13/site-packages/keyring/cli.py": 10996746519742056101, + "frontend/src/components/TaskHistory.svelte": 17537414183368417623, + "venv/lib/python3.13/site-packages/pandas/core/methods/to_dict.py": 4653628436393663485, + "venv/lib/python3.13/site-packages/pyasn1/type/char.py": 16518487114777185541, + "venv/lib/python3.13/site-packages/pydantic/v1/error_wrappers.py": 5701679786078971939, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_aggregate.py": 15038915958422670700, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_readlines.py": 15928258358116399067, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/recarray_from_file.fits": 15116318600514274152, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/__init__.py": 3969805865048730851, + "backend/src/core/utils/superset_context_extractor/_recovery.py": 4103343657420503831, + "backend/src/core/utils/fileio.py": 8925306729946909050, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename.py": 4890779493250245903, + "backend/tests/test_api_key_model.py": 18059967072469014911, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_floats.py": 3064615530495290792, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/json.py": 15373167408891671190, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/io.py": 11072022722163954973, + "venv/lib/python3.13/site-packages/pygments/formatters/_mapping.py": 13335227913146542481, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_seed_sequence.py": 7687465232954593311, + "backend/alembic/README": 17625003422504608299, + "venv/lib/python3.13/site-packages/click/parser.py": 13988544851350599869, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parse_iso8601.py": 9100947620267156161, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_hashing.py": 11119284926039008503, + "venv/lib/python3.13/site-packages/gitdb/test/test_base.py": 16305779366785148795, + "frontend/src/lib/ui/Card.svelte": 3442526978752993023, + "backend/src/plugins/translate/service.py": 11825307511971639412, + "venv/lib/python3.13/site-packages/pandas/api/extensions/__init__.py": 882327406374020760, + "venv/lib/python3.13/site-packages/pygments/lexers/ride.py": 14096748896451437594, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/REQUESTED": 15130871412783076140, + "frontend/src/lib/components/translate/__tests__/test_correction_cell.svelte.js": 2314051239468628554, + "backend/src/api/routes/__tests__/test_datasets.py": 5180776326745169791, + "venv/lib/python3.13/site-packages/jeepney/bindgen.py": 7094585345946943534, + "venv/lib/python3.13/site-packages/jsonschema/protocols.py": 847332300543820834, + "venv/lib/python3.13/site-packages/apscheduler/executors/twisted.py": 2695602672085615762, + "venv/lib/python3.13/site-packages/pygments/lexers/codeql.py": 4254046699692048717, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/reporters.py": 10760889726586439724, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/authorization_server.py": 2491654903543600678, + "backend/src/plugins/translate/service_inline_correction.py": 11066393548140180037, + "venv/lib/python3.13/site-packages/urllib3/contrib/socks.py": 645086578806871685, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/astype_copy.pkl": 4470155972891419163, + "venv/lib/python3.13/site-packages/greenlet/greenlet_cpython_compat.hpp": 8396413256279803400, + "venv/lib/python3.13/site-packages/numpy/_typing/_array_like.py": 2161873439361281488, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_index_as_string.py": 292438690259156869, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop_duplicates.py": 5874427993953991216, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.pyi": 6546751036506752550, + "venv/lib/python3.13/site-packages/PIL/Jpeg2KImagePlugin.py": 16905402423248975204, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/WHEEL": 11630459739183915695, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_laguerre.py": 7475592201750602042, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit.py": 15498810174380798405, + "venv/lib/python3.13/site-packages/passlib/ext/django/models.py": 12386223748379294996, + "venv/lib/python3.13/site-packages/numpy/_core/lib/pkgconfig/numpy.pc": 14713682399742251335, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.obj": 11967637259540485652, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/METADATA": 15888766579203341778, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/errors.py": 16711622442922413520, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/WHEEL": 13347410390513723930, + "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.py": 151202984060101867, + "venv/lib/python3.13/site-packages/passlib/handlers/md5_crypt.py": 7669328623914474137, + "venv/lib/python3.13/site-packages/pygments/lexers/xorg.py": 14591144191879110061, + "frontend/src/routes/settings/EnvironmentsTab.svelte": 1326318857426265025, + "frontend/build/_app/immutable/chunks/DsnmJJEf.js": 17416107759626312632, + "venv/lib/python3.13/site-packages/pygments/lexers/vyper.py": 6477559246065994199, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.py": 4440659352851541547, + "venv/lib/python3.13/site-packages/_pytest/tracemalloc.py": 5530234062530858720, + "venv/lib/python3.13/site-packages/pydantic/_internal/_docs_extraction.py": 5210114991139191634, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_series_apply_relabeling.py": 3930092097678339743, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi": 1846673463183660140, + "venv/lib/python3.13/site-packages/certifi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/RECORD": 2963644632913976754, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/take.py": 3170415198452493008, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_sorting.py": 10523740688498427929, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/aioodbc.py": 2018840826888846321, + "venv/lib/python3.13/site-packages/pygments/styles/trac.py": 13968346768164381833, + "venv/lib/python3.13/site-packages/passlib/tests/sample1b.cfg": 2872366861156549016, + "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/pip/_vendor/pyproject_hooks/_in_process/__init__.py": 9627328185578406121, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_freq_attr.py": 17290447066681837965, + "backend/src/plugins/translate/preview_response_parser.py": 15690759478655959205, + "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.pyi": 18395688193449688360, + "venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.pyi": 9243829615414967057, + "venv/lib/python3.13/site-packages/urllib3/exceptions.py": 9687187566231423953, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite_e.py": 8912795372542950449, + "venv/lib/python3.13/site-packages/passlib/handlers/cisco.py": 15004707325761459775, + "scripts/gen_semantics.py": 11397714264377363083, + "venv/lib/python3.13/site-packages/attrs/setters.py": 5775359015245600592, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Jaro.pyi": 3145980717589050713, + "venv/lib/python3.13/site-packages/keyring/backends/libsecret.py": 11621088556661567306, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/statreload.py": 5018382301336802445, + "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.py": 4154852745131464543, + "venv/lib/python3.13/site-packages/pandas/io/clipboard/__init__.py": 3656451154829206939, + "venv/lib/python3.13/site-packages/anyio/_core/_typedattr.py": 17584691045493791349, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_holiday.py": 8541197358003711845, + "examples/maintenance-api-bash.sh": 674396824183793987, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_melt.py": 15663807247682146566, + "venv/lib/python3.13/site-packages/secretstorage/util.py": 1004887530903069622, + "venv/lib/python3.13/site-packages/numpy/_core/_add_newdocs_scalars.py": 652332294655046106, + "frontend/src/routes/datasets/MetricsTable.svelte": 6234185654078176376, + "venv/lib/python3.13/site-packages/dotenv/__init__.py": 15464030923609356017, + "venv/lib/python3.13/site-packages/pygments/lexers/pointless.py": 17552020039609007881, + "venv/lib/python3.13/site-packages/passlib/crypto/__init__.py": 16409196868630049365, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/wrapper.py": 14599195010683170123, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/information_schema.py": 8551227132710897346, + "venv/lib/python3.13/site-packages/git/index/fun.py": 18338379518768926372, + "venv/lib/python3.13/site-packages/numpy.libs/libgfortran-040039e1-0352e75f.so.5.0.0": 13946067868274850557, + "backend/src/api/routes/tasks.py": 2917461791850604633, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/generic.py": 17755579497690180620, + "venv/lib/python3.13/site-packages/pluggy/_version.py": 7195758686717994475, + "backend/src/core/plugin_loader.py": 16320603855307510494, + "docker/nginx.ssl.conf": 12350396037548059686, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/constants.pyi": 4415188581374004936, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_dialect.py": 4700488504252803159, + "venv/lib/python3.13/site-packages/pandas/api/typing/__init__.py": 6438268275857060114, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/licenses/LICENSE": 9235234428907927646, + "backend/src/services/clean_release/__tests__/test_audit_service.py": 1679130450221264383, + "frontend/build/_app/immutable/chunks/BddPqa-e.js": 3040470451817822725, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/encoder.py": 8912119133548489544, + "run.sh": 4808871544409245302, + "venv/lib/python3.13/site-packages/greenlet/platform/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/requests/exceptions.py": 6474239743209354989, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/base_server.py": 9643197259080504542, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/hooks.py": 9888227370911151341, + "venv/lib/python3.13/site-packages/referencing/tests/test_jsonschema.py": 9815500901482570619, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pymysql.py": 12923876736367229454, + "venv/lib/python3.13/site-packages/pandas/core/computation/align.py": 13027916530558901817, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/licenses/LICENSE": 10253862887434903467, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/__init__.py": 7062045842767697645, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90": 15012692484070385863, + "venv/lib/python3.13/site-packages/PIL/_imaging.cpython-313-x86_64-linux-gnu.so": 1425926264271197601, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/RECORD": 9803861100978586236, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/sdist.py": 9490366272695301385, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py": 14995426099932276090, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_orc.py": 1248059610437937895, + "venv/lib/python3.13/site-packages/pygments/lexers/urbi.py": 1611762607688882372, + "backend/src/services/superset_lookup_service.py": 16520439978260397080, + "venv/lib/python3.13/site-packages/websockets/asyncio/connection.py": 17044409627448400723, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/authorization_server.py": 2913800420669417152, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraysetops.py": 10588903945244480732, + "venv/lib/python3.13/site-packages/iniconfig/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix.py": 4672871351134074735, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90": 6219951399575860362, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timestamps.pyi": 51728851886466199, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_asymmetric.py": 6903778603779934572, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/named_types.py": 6099185243355915896, + "venv/lib/python3.13/site-packages/urllib3/util/request.py": 9432067988603015849, + "venv/lib/python3.13/site-packages/httpcore/_models.py": 2501866419898326733, + "frontend/src/lib/api/translate.js": 18140498250896378509, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_legacy.py": 9226692984248279094, + "venv/lib/python3.13/site-packages/pandas/core/computation/pytables.py": 16326122536715961388, + "venv/lib/python3.13/site-packages/numpy/_configtool.pyi": 9670892208858157218, + "venv/lib/python3.13/site-packages/rapidfuzz/__pyinstaller/__init__.py": 1229691061011958769, + "venv/lib/python3.13/site-packages/pygments/lexers/ldap.py": 17455983150181177257, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_converters.py": 8869440774594127419, + "venv/lib/python3.13/site-packages/numpy/f2py/_src_pyf.pyi": 8916922961301555974, + "frontend/src/lib/components/translate/TranslationRunProgress.svelte": 18041933754930100165, + "venv/lib/python3.13/site-packages/anyio/_core/_contextmanagers.py": 1258491775823080427, + "frontend/build/_app/immutable/chunks/Ct73Sust.js": 3385889491616825090, + "venv/lib/python3.13/site-packages/pandas/plotting/_core.py": 6766059152026241747, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/test_shift.py": 14026124784027171225, + "backend/tests/services/clean_release/test_approval_service.py": 8359796700245201345, + "venv/lib/python3.13/site-packages/pandas/io/excel/_xlrd.py": 14430937200583666658, + "venv/lib/python3.13/site-packages/gitdb/utils/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_function_base.py": 16624804022675533740, + "venv/lib/python3.13/site-packages/pandas/compat/pyarrow.py": 13693379998785127538, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/resource_protector.py": 14354891358060085360, + "venv/lib/python3.13/site-packages/apscheduler/executors/pool.py": 10344126569001032241, + "venv/lib/python3.13/site-packages/pandas/_libs/indexing.cpython-313-x86_64-linux-gnu.so": 13188040757764159731, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_range.py": 9900908262700749861, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_round.py": 9358309072340573675, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_repeat.py": 11360772447747837958, + "venv/lib/python3.13/site-packages/pandas/compat/pickle_compat.py": 11073483984394766474, + "venv/lib/python3.13/site-packages/pandas/tests/extension/uuid/test_uuid.py": 13955678427426850807, + "frontend/e2e/helpers/api.helper.js": 12740720187461301874, + "frontend/build/_app/immutable/chunks/0hvOu5jK.js": 10335091194896019556, + "venv/lib/python3.13/site-packages/pygments/lexers/arrow.py": 6699009974224818979, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/INSTALLER": 17282701611721059870, + "backend/src/services/dataset_review/event_logger.py": 8083530196989488371, + "backend/src/plugins/storage/__init__.py": 5046554941488079204, + "venv/lib/python3.13/site-packages/pygments/lexers/__init__.py": 4627540245914849670, + "venv/lib/python3.13/site-packages/PIL/ImageTk.py": 17063969714816564357, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/util.py": 4815334059917765852, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/jws_eddsa.py": 833927568269372333, + "venv/lib/python3.13/site-packages/anyio/streams/text.py": 12507591237176920223, + "venv/lib/python3.13/site-packages/pandas/core/arrays/base.py": 664515424699746697, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/compiler.py": 11662494978292401568, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/modules.pyi": 131293606732000587, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/METADATA": 15876173086384975957, + "venv/lib/python3.13/site-packages/passlib/tests/__main__.py": 16477180140297957650, + "venv/lib/python3.13/site-packages/git/repo/base.py": 13975465345838683533, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libsasl2-883649fd.so.3.0.0": 13306917506408577991, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_common.py": 10797243274520625867, + "venv/lib/python3.13/site-packages/pandas/_config/__init__.py": 3577026529387563519, + "venv/lib/python3.13/site-packages/pandas/io/clipboards.py": 5183212433608887727, + "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.py": 548928042543500365, + "venv/lib/python3.13/site-packages/pygments/lexers/robotframework.py": 11507713622179102496, + "backend/conftest.py": 16521922883434363388, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/dml.py": 17308908394336670576, + "venv/lib/python3.13/site-packages/PIL/py.typed": 15130871412783076140, + "backend/src/api/routes/__tests__/test_dashboards.py": 226265424558878456, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_backend.pyi": 13083543811193933305, + "venv/lib/python3.13/site-packages/gitdb/db/__init__.py": 2615504918450276693, + "frontend/build/_app/immutable/chunks/zkZd1nRa.js": 15711219595002974448, + "venv/lib/python3.13/site-packages/numpy/_core/cversions.py": 9724467539503410469, + "frontend/src/lib/stores/maintenance.svelte.js": 6057490524855148629, + "backend/alembic/versions/a7b1c2d3e4f5_add_provider_id_to_validation_policies.py": 7446022200459040057, + "backend/alembic/versions/ed310b33f02c_multi_language_translation_tables.py": 1424919631205944664, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/scalars.py": 3468820466230647963, + "docker/frontend.entrypoint.sh": 11397342350356400663, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nested_sequence.pyi": 11245460325970663922, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_iteration.py": 2118501258411211851, + "backend/src/plugins/translate/preview.py": 1878554949419203980, + "venv/lib/python3.13/site-packages/pydantic/plugin/_schema_validator.py": 857640644840976862, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_conversion_utils.py": 1567199588622767277, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_indexing.py": 14461606056665485421, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90": 5799106109999071412, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/inout.f90": 1521999519583206538, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/mod.pyi": 10591120373577657317, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_dropna.py": 3620959914439334511, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/WHEEL": 12054782055241301457, + "venv/lib/python3.13/site-packages/pygments/styles/friendly_grayscale.py": 16840106759769837649, + "frontend/src/types/dashboard.ts": 9718666955722367566, + "venv/lib/python3.13/site-packages/itsdangerous/serializer.py": 14271229091461164933, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/win64python2.npy": 11005857803794805939, + "venv/lib/python3.13/site-packages/greenlet/tests/test_tracing.py": 10227316489696807112, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_export_format.py": 17862222951776199694, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/__init__.py": 348469143777130970, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_extras.py": 16160090335191788104, + "venv/lib/python3.13/site-packages/pip/_internal/utils/misc.py": 17461379236189029253, + "venv/lib/python3.13/site-packages/jaraco/functools/__init__.pyi": 2872039192528394677, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape_base.pyi": 10291383658131961346, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_version.pyi": 18093228021414910594, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/conftest.py": 17897502508251413988, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_julian_date.py": 850085757774959003, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_inclusive.py": 1389676378885557519, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/METADATA": 14070889071949105584, + "venv/lib/python3.13/site-packages/websockets/version.py": 5853118844880112885, + "venv/lib/python3.13/site-packages/pip/_internal/commands/configuration.py": 1608697090566485893, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_py_collections.py": 16825222625411635946, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/retry.py": 17371295199208325375, + "frontend/src/routes/+layout.svelte": 2748734957389681795, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/objects/commit.py": 12317865358846331802, + "backend/src/core/superset_client/_user_projection.py": 16484323195475306883, + "venv/lib/python3.13/site-packages/PIL/SgiImagePlugin.py": 6916200065790425497, + "backend/src/models/assistant.py": 15004657265198809796, + "backend/src/services/clean_release/report_builder.py": 6953311294119437848, + "backend/src/services/profile_preference_service.py": 58722622434127499, + "backend/src/plugins/translate/__tests__/test_dictionary_crud.py": 17953628511626558088, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/etcd.py": 4078354986605069279, + "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.py": 17055498803745289016, + "backend/git_repos/remote/test-repo.git/objects/3e/05ec6ef6504483c4bc7d00f0d0272c38ec661f": 11182016264585388842, + "backend/src/api/routes/datasets.py": 5124620784591228136, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_inf.py": 8659210689723088321, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi": 4376871621615688626, + "frontend/build/_app/immutable/chunks/aniH9ONl.js": 11297774342683903539, + "backend/src/services/rbac_permission_catalog.py": 8206280020500996966, + "venv/lib/python3.13/site-packages/pandas/core/reshape/reshape.py": 5387892304726762127, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_can_hold_element.py": 5406431247116557833, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/websockets/exceptions.py": 12048063047468402740, + "venv/lib/python3.13/site-packages/anyio/__init__.py": 12752386096259972231, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/functions.py": 14107377669163193871, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_set.py": 534498057184394558, + "venv/lib/python3.13/site-packages/pip/_internal/network/cache.py": 10606522397693824641, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_real.py": 5283415082530228716, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_api.py": 13739775047493489785, + "venv/lib/python3.13/site-packages/greenlet/tests/test_throw.py": 4119265751381210399, + "backend/alembic/versions/aa1b2c3d4e5f_drop_deprecated_translate_columns.py": 15433357059529111004, + "venv/lib/python3.13/site-packages/ecdsa/_sha3.py": 10353612776869489378, + "venv/lib/python3.13/site-packages/pydantic/schema.py": 83238111330132033, + "frontend/src/types/backup.ts": 1741234034896689348, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/version.py": 6401479036177132374, + "venv/lib/python3.13/site-packages/numpy/rec/__init__.py": 7467092880535460658, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/common.py": 10996276696597806957, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_unicode.py": 1103608932321322989, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_constructors.py": 3440572832185940666, + "venv/lib/python3.13/site-packages/pygments/lexers/savi.py": 95400050302239274, + "backend/src/services/maintenance/_orchestrators.py": 995360865260101856, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/scanner.py": 5640381644804445932, + "venv/lib/python3.13/site-packages/urllib3/_collections.py": 3440910792774742262, + "venv/lib/python3.13/site-packages/authlib/oidc/registration/claims.py": 4161520263207458028, + "venv/lib/python3.13/site-packages/pydantic/version.py": 3699343596421001359, + "venv/bin/pyrsa-verify": 6762739642629904442, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.pyi": 9003794318682878317, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/constrain.py": 6513876973118703677, + "frontend/src/routes/tools/storage/+page.svelte": 2651964385884112547, + "venv/lib/python3.13/site-packages/numpy/fft/_pocketfft.pyi": 1521384724035973688, + "venv/lib/python3.13/site-packages/numpy/_core/_internal.py": 13056946834347643109, + "venv/lib/python3.13/site-packages/ecdsa/numbertheory.py": 13538480862642502330, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/rule.py": 5318344538761246105, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/licenses/LICENSE": 13479831069780783137, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_produces_warning.py": 750781117570375777, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/macos.py": 17442393555211213147, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unique.py": 6234921572794573905, + "venv/lib/python3.13/site-packages/attr/filters.py": 14156141488477438777, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/_mapping.py": 11752660241391232497, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90": 5518911932373565642, + "venv/lib/python3.13/site-packages/pydantic/validators.py": 8292819706488319845, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/RECORD": 963865046004908868, + "venv/lib/python3.13/site-packages/websockets/legacy/client.py": 4032878587330592478, + "venv/lib/python3.13/site-packages/pandas/core/window/__init__.py": 15180240812077877933, + "venv/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py": 7733356903092860495, + "venv/lib/python3.13/site-packages/pandas/_testing/asserters.py": 272063856832951430, + "venv/lib/python3.13/site-packages/ecdsa/der.py": 9374566189581725372, + "venv/lib/python3.13/site-packages/attr/_cmp.pyi": 14443711863388606665, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/interfaces.py": 4890958419958257958, + "venv/lib/python3.13/site-packages/PIL/Image.py": 13615925856053031482, + "frontend/build/_app/immutable/nodes/40.CNZCEv_K.js": 15374574306536825164, + "backend/src/core/task_manager/manager.py": 4491234835514372291, + "venv/lib/python3.13/site-packages/numpy/_core/overrides.py": 252940520997718714, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/h11/__init__.py": 222801976520197308, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_expanding.py": 12504275097476819918, + "frontend/src/lib/ui/Icon.svelte": 2201964532717139995, + "venv/lib/python3.13/site-packages/referencing/__init__.py": 10093824711214801917, + "venv/lib/python3.13/site-packages/pillow.libs/libbrotlidec-b57ddf63.so.1.2.0": 10032590058372320813, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/jwt_bearer.py": 6973859422068490274, + "backend/git_repos/remote/test-repo.git/objects/99/38d17c3f4199e53e4d4ebc253fe9c840caa505": 8414792171590415839, + "venv/lib/python3.13/site-packages/jsonschema/_keywords.py": 949562792260528762, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_astype.py": 4975959187621745360, + "frontend/src/lib/utils/debounce.js": 16884470786640632815, + "venv/lib/python3.13/site-packages/websockets/asyncio/client.py": 5694225754072131767, + "venv/lib/python3.13/site-packages/websockets/protocol.py": 6401227903827084901, + "frontend/build/_app/immutable/chunks/KxePT7Ip.js": 8106111085962356816, + "venv/lib/python3.13/site-packages/httpx/_status_codes.py": 1758440600462491839, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/WHEEL": 2357997949040430835, + "frontend/src/lib/api/translate/datasources.js": 17202165717960970061, + "venv/lib/python3.13/site-packages/pyasn1/type/namedtype.py": 1859990775875190116, + "frontend/src/lib/stores/environmentContext.js": 1762535408632658714, + "backend/tests/test_resource_hubs.py": 3990299394875930767, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/numpy/tests/test_configtool.py": 8208415015478205502, + "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/arrays/boolean/test_indexing.py": 16264430536704066847, + "venv/lib/python3.13/site-packages/pandas/io/spss.py": 864838144958947906, + "venv/lib/python3.13/site-packages/git/objects/__init__.py": 2110615482320355676, + "venv/lib/python3.13/site-packages/pandas/io/api.py": 8275376846208437741, + "venv/lib/python3.13/site-packages/cffi/ffiplatform.py": 6782148110863549472, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi": 17458894097215345719, + "venv/lib/python3.13/site-packages/pydantic/v1/class_validators.py": 6471688474853407718, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/hist.py": 10928173425078493095, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_normalize.py": 3203921571999101793, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odswriter.py": 5134385709728943904, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/WHEEL": 3749476255729626245, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_value_attrspec.py": 7741590618654448240, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_engines.py": 2790877023773269276, + "venv/lib/python3.13/site-packages/PIL/XVThumbImagePlugin.py": 7472134175570205454, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE": 4274653168153720331, + "venv/lib/python3.13/site-packages/pygments/lexers/ambient.py": 18106929781201758080, + "backend/src/services/__tests__/test_llm_provider.py": 13082073379648782691, + "venv/lib/python3.13/site-packages/charset_normalizer/md.py": 2029760700380476138, + "venv/lib/python3.13/site-packages/pygments/lexers/carbon.py": 6753624244809529841, + "venv/lib/python3.13/site-packages/numpy/_utils/_convertions.py": 12886275429547303345, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bindgen.py": 8637878018232418583, + "venv/lib/python3.13/site-packages/yaml/parser.py": 18021832376874455801, + "venv/lib/python3.13/site-packages/pandas/core/computation/expressions.py": 10684284531040203747, + "venv/lib/python3.13/site-packages/pandas/core/computation/check.py": 16048939716341154196, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_logical.py": 6242457515917145500, + "frontend/src/routes/settings/+page.ts": 3719008513710037840, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayobject.py": 13337664596833150958, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_resolution.py": 6076761538303762297, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/__init__.py": 7526309124863950484, + "frontend/src/services/taskService.js": 11368052191249479533, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/candidates.py": 5951912505933673835, + "venv/lib/python3.13/site-packages/pandas/core/reshape/api.py": 16364136812252343076, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_asof.py": 18383318159051131669, + "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.py": 12796890117561096360, + "venv/lib/python3.13/site-packages/pandas/io/pytables.py": 17482934215513855928, + "frontend/build/_app/immutable/nodes/26.BHpCifr3.js": 16416419328529145595, + "venv/lib/python3.13/site-packages/_pytest/_code/code.py": 5248836309618416369, + "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/asn1.py": 8801155055979135092, + "venv/lib/python3.13/site-packages/passlib/tests/backports.py": 17098448557554464521, + "venv/lib/python3.13/site-packages/greenlet/greenlet_slp_switch.hpp": 1694714764745718414, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_deprecations.py": 6015734648984591027, + "venv/lib/python3.13/site-packages/pydantic/v1/types.py": 10761779263335288559, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta_range.py": 15081095442418142820, + "frontend/src/routes/admin/users/+page.svelte": 4464001185352807842, + "venv/lib/python3.13/site-packages/passlib/utils/binary.py": 13123975436674239306, + "frontend/src/services/storageService.js": 14408290095426695791, + "backend/src/api/routes/translate/_run_list_routes.py": 1259398917100338978, + "backend/git_repos/remote/test-repo.git/objects/f7/6ee984d9d47c3cd0b362fdf60a47162bbc202d": 5351983130474596028, + "venv/lib/python3.13/site-packages/PIL/ImageFile.py": 15765130658900167517, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_timedelta.py": 17052461094717926538, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f": 12558972205518833024, + "venv/lib/python3.13/site-packages/websockets/sync/connection.py": 2791040669094103200, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5support-d0bcff84.so.0.1": 16819924515291719993, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_case_when.py": 4133174129660834805, + "frontend/src/lib/api/translate/dictionaries.js": 13928848549982189213, + "frontend/build/_app/immutable/chunks/B0K5kI6n.js": 6208436857520817685, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_to_latex.py": 2628895559914914693, + "venv/lib/python3.13/site-packages/pandas/io/formats/html.py": 11849941990375030601, + "venv/bin/websockets": 12099863324306500376, + "backend/src/services/dataset_review/semantic_resolver.py": 8447496149691924829, + "venv/lib/python3.13/site-packages/cffi/lock.py": 13507686939203117974, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/crud.py": 805684028038896506, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/WHEEL": 1598805043198466373, + "frontend/build/_app/immutable/nodes/22.CZgjFTnE.js": 15851348200685649144, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils.py": 10362977406431569031, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_function_base.pyi": 10972502518588022706, + "frontend/src/components/Footer.svelte": 17748559656923032, + "venv/lib/python3.13/site-packages/secretstorage/collection.py": 17903258621904912493, + "venv/lib/python3.13/site-packages/starlette/staticfiles.py": 11256974306202558529, + "venv/lib/python3.13/site-packages/pluggy/_callers.py": 1042673447718196223, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_functions.py": 16376319335326812580, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/METADATA": 3390257212824996989, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/base.py": 11386927749822539057, + "venv/lib/python3.13/site-packages/pandas/io/excel/_base.py": 1251545894005373734, + "venv/lib/python3.13/site-packages/pyasn1/compat/integer.py": 7365270971777550573, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_impl.py": 12056958946481531279, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_client/__init__.py": 9997757256282720103, + "venv/lib/python3.13/site-packages/numpy/_core/strings.pyi": 1981676808027146409, + "venv/lib/python3.13/site-packages/packaging/_musllinux.py": 2568338440457080365, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_tz_localize.py": 13699016868476153393, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/einsumfunc.pyi": 200771351328522379, + "venv/lib/python3.13/site-packages/websockets/extensions/permessage_deflate.py": 12957105912018691390, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arithmetic.py": 14858832264660410908, + "venv/lib/python3.13/site-packages/jaraco/classes/ancestry.py": 11742194518360056470, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/websockets/auth.py": 499195617702591757, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.py": 17817123894903120316, + "venv/lib/python3.13/site-packages/fastapi/openapi/docs.py": 16735218221639179927, + "venv/lib/python3.13/site-packages/_pytest/threadexception.py": 10464996327276961035, + "venv/lib/python3.13/site-packages/cffi/_cffi_include.h": 13094899814611950155, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/validator.py": 11486125578281617670, + "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/_vendor/platformdirs/android.py": 8607703347015852195, + "venv/lib/python3.13/site-packages/pygments/styles/abap.py": 11543320440974964547, + "venv/lib/python3.13/site-packages/pygments/lexers/mime.py": 7768464764849718825, + "venv/bin/pip": 13861749540792881808, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/token_endpoint.py": 6118770923176099889, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_case_justify.py": 8204537837649550062, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/METADATA": 14608873187265321271, + "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/pass/shape.py": 13410030168622484801, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_bin_groupby.py": 14831211659124136806, + "frontend/src/lib/ui/PageHeader.svelte": 3800784212388586861, + "venv/lib/python3.13/site-packages/numpy.libs/libquadmath-96973f99-934c22de.so.0.0.0": 5098713761946118139, + "frontend/playwright-report/trace/codicon.DCmgc-ay.ttf": 15579197054804464248, + "venv/lib/python3.13/site-packages/pandas/tests/test_col.py": 14781555956509956371, + "venv/lib/python3.13/site-packages/urllib3/util/ssltransport.py": 1175688460659745788, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/format": 12697928260201325593, + "frontend/src/routes/admin/roles/+page.svelte": 1343040884276845574, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.py": 15511055314565873928, + "venv/lib/python3.13/site-packages/more_itertools/recipes.py": 5254043689078173976, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.py": 3646474165295296669, + "venv/lib/python3.13/site-packages/websockets/legacy/handshake.py": 376095144657994920, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py": 6067836157632573182, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/__init__.py": 4337679908168515343, + "venv/lib/python3.13/site-packages/pygments/styles/paraiso_light.py": 15941591873059208999, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/mypy.ini": 4763385838822685881, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/resolver.py": 2492962412506082234, + "venv/lib/python3.13/site-packages/_pytest/faulthandler.py": 13329320306353718649, + "venv/lib/python3.13/site-packages/pandas/core/computation/ops.py": 18250656489649699560, + "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/arrays/numpy_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_cpu.h": 13799366908726531089, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_api.py": 5813060676255093777, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_cython_aggregations.py": 10818895573637904764, + "backend/src/plugins/translate/preview_executor.py": 7636554040403814604, + "venv/lib/python3.13/site-packages/tzlocal/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.cpython-313-x86_64-linux-gnu.so": 12654188486128938170, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/subcomponents.py": 10365594934527289233, + "venv/lib/python3.13/site-packages/charset_normalizer/cli/__init__.py": 9702005609966176016, + "backend/src/plugins/translate/__init__.py": 12400577052797809611, + "venv/lib/python3.13/site-packages/httpcore/_api.py": 16499985295426060327, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/dtypes.py": 9839461501970023861, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/models.py": 16636119441941357281, + "venv/lib/python3.13/site-packages/cffi/parse_c_type.h": 9889309594462820068, + "venv/lib/python3.13/site-packages/starlette/datastructures.py": 12097180838087229563, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi": 9405122752084210696, + "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatter.py": 16499277113779414101, + "venv/lib/python3.13/site-packages/itsdangerous/__init__.py": 6969210114978365656, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv": 13441294827017400897, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_copy.py": 11335108864615756235, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_utils.py": 11574890848475750509, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_partial_slicing.py": 16219611534574666182, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_take.py": 9847808489301498487, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ufuncs.py": 12732599294816239111, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/provision.py": 7362363963464621570, + "venv/lib/python3.13/site-packages/pydantic/v1/annotated_types.py": 12925825196690299531, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/RECORD": 15574202654585730126, + "venv/lib/python3.13/site-packages/_pytest/_py/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_datetime.py": 7862725028865965163, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_like.pyi": 1968570015765106620, + "venv/lib/python3.13/site-packages/_pytest/helpconfig.py": 3033477806668470951, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.pyi": 13068936038543812082, + "frontend/src/routes/datasets/__tests__/DatasetPreview.test.js": 12281160027416292128, + "backend/src/services/clean_release/approval_service.py": 15944489428318420008, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_categorical.py": 12897027063618569795, + "venv/lib/python3.13/site-packages/pip/_internal/utils/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/_migration.py": 17982816821930887921, + "venv/lib/python3.13/site-packages/_pytest/mark/expression.py": 1821437025841201912, + "venv/lib/python3.13/site-packages/pydantic/_internal/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema_specifications/_core.py": 14812112544772987164, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_format.py": 5231304674283854194, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_arrayobject.py": 9578555381494297966, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/meson.build": 17468163147765825687, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_bar.py": 7791068963246005463, + "venv/lib/python3.13/site-packages/pandas/io/parquet.py": 14415622950469421518, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel_legacy.py": 12735901522735836481, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_extract.py": 14547819021277949280, + "frontend/build/_app/immutable/nodes/38.lN6lyang.js": 10345064950322542935, + "backend/src/scripts/clean_release_cli.py": 5126837099976660772, + "venv/lib/python3.13/site-packages/pandas/core/util/hashing.py": 13106575357604888913, + "venv/lib/python3.13/site-packages/numpy/lib/mixins.py": 7404729635424818497, + "venv/lib/python3.13/site-packages/numpy/_core/_simd.pyi": 13553578040186939249, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_table.tpl": 17198355067645888735, + "venv/lib/python3.13/site-packages/bcrypt/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/RECORD": 173225030102092319, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/greenlet_msvc_compat.hpp": 12504008513945919250, + "backend/src/core/superset_client/_datasets.py": 9811357803863887067, + "venv/lib/python3.13/site-packages/fastapi/middleware/gzip.py": 436886407566263171, + "venv/lib/python3.13/site-packages/pandas/core/arrays/floating.py": 1215586266958421991, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_setitem.py": 10389770446834773837, + "venv/lib/python3.13/site-packages/pygments/lexers/c_like.py": 13004061780700827047, + "venv/lib/python3.13/site-packages/psycopg2/errorcodes.py": 6711830404954314463, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_append.py": 17016125916761365423, + "frontend/src/lib/components/reports/__tests__/fixtures/reports.fixtures.js": 10647302793388244094, + "frontend/build/_app/immutable/nodes/13.CWfoAyT-.js": 16342502651271133149, + "venv/lib/python3.13/site-packages/PIL/TiffImagePlugin.py": 6845043550424565106, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/json.py": 6429651405841289922, + "backend/src/services/clean_release/repositories/publication_repository.py": 11208425895213508165, + "backend/tests/test_maintenance_api.py": 2012388734813578069, + "venv/lib/python3.13/site-packages/requests/adapters.py": 17161109043243436200, + "venv/lib/python3.13/site-packages/pandas/_testing/_hypothesis.py": 12298650110193262367, + "venv/lib/python3.13/site-packages/pillow.libs/libopenjp2-94e588ba.so.2.5.4": 2483101806045986252, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/qt.py": 12828696264909048448, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/unused_registry.py": 10153622516112471812, + "venv/lib/python3.13/site-packages/pydantic/v1/config.py": 12050640083719340958, + "venv/lib/python3.13/site-packages/ecdsa/test_ellipticcurve.py": 11125783981574901613, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/default_comparator.py": 47118577003622736, + "venv/lib/python3.13/site-packages/passlib/__init__.py": 6987142392711441525, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_methods.py": 12694335778731418517, + "frontend/src/lib/components/translate/TranslationPreview.svelte": 3234775946311369733, + "venv/lib/python3.13/site-packages/uvicorn/workers.py": 7213290478118197047, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/errors.py": 14634768861119075506, + "venv/lib/python3.13/site-packages/apscheduler/triggers/combining.py": 1264860868414723829, + "venv/lib/python3.13/site-packages/keyring/backends/fail.py": 5792496235026678021, + "venv/lib/python3.13/site-packages/pygments/formatters/bbcode.py": 8614391937525677922, + "venv/lib/python3.13/site-packages/python_multipart/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_types.py": 651959450717569029, + "backend/src/api/routes/translate/_preview_routes.py": 16234500901707822839, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_join.py": 1697622393195784944, + "venv/lib/python3.13/site-packages/pillow.libs/libwebpmux-7f11e5ce.so.3.1.2": 13105940093474848953, + "venv/lib/python3.13/site-packages/PIL/ImageFilter.py": 10974179993355630141, + "venv/lib/python3.13/site-packages/_pytest/_io/wcwidth.py": 13515196388826152383, + "venv/lib/python3.13/site-packages/pycparser/__init__.py": 16499940957411260458, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/common.py": 16314033415206173235, + "venv/lib/python3.13/site-packages/_pytest/junitxml.py": 5871715626272366062, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/accumulate.py": 5780225603819849877, + "backend/src/plugins/translate/__tests__/test_inline_correction.py": 3644785257160613130, + "venv/lib/python3.13/site-packages/numpy/testing/tests/__init__.py": 15130871412783076140, + "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/timedeltas/methods/test_repeat.py": 18394463352314692642, + "venv/lib/python3.13/site-packages/pygments/lexers/wgsl.py": 9718384325049172855, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/RECORD": 9461427699726982537, + "venv/lib/python3.13/site-packages/h11/py.typed": 12358286306858197118, + "venv/lib/python3.13/site-packages/pygments/lexers/_cl_builtins.py": 16540712925368297957, + "venv/lib/python3.13/site-packages/keyring/errors.py": 4587094338672775040, + "backend/src/services/git/_remote_providers.py": 11131218419284688941, + "backend/alembic/versions/e5f4d3c2b1a_add_policy_id_to_validation_results.py": 11168047633691803786, + "backend/git_repos/remote/test-repo.git/refs/heads/preprod": 2288780285329550368, + "venv/lib/python3.13/site-packages/numpy/ma/__init__.py": 214772578978182427, + "backend/src/services/clean_release/policy_engine.py": 3180817867716931725, + "venv/lib/python3.13/site-packages/jeepney/io/common.py": 15160647397460834508, + "venv/lib/python3.13/site-packages/git/db.py": 6680123567509774609, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/keywrap.py": 10424037418528425800, + "venv/lib/python3.13/site-packages/pandas/_libs/__init__.py": 17117112389651696580, + "backend/src/services/dataset_review/repositories/__tests__/test_session_repository.py": 13584543719626464409, + "venv/lib/python3.13/site-packages/pandas/_libs/tslib.cpython-313-x86_64-linux-gnu.so": 10742615805788605480, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/provision.py": 2676876852726658063, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_normalize.py": 7378656958631172603, + "venv/lib/python3.13/site-packages/numpy/typing/__init__.pyi": 10058149460938883683, + "venv/lib/python3.13/site-packages/pygments/lexers/webassembly.py": 17811970490091406867, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/licenses/LICENSE": 11986475601091748012, + "venv/lib/python3.13/site-packages/jose/constants.py": 10880650415673457194, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/horizontal_shard.py": 17615732108308858890, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/resolvers/__init__.py": 1437580234680265326, + "venv/lib/python3.13/site-packages/PIL/FpxImagePlugin.py": 18245056799205041866, + "venv/lib/python3.13/site-packages/pygments/lexers/smv.py": 8253688483040957894, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot.py": 334735766122314163, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/METADATA": 13633829318759752611, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_datetimelike.py": 10294379314868108649, + "venv/lib/python3.13/site-packages/PIL/PpmImagePlugin.py": 7107324729714470853, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/starlette/__init__.py": 3252794766897205870, + "backend/src/core/superset_client/_databases.py": 7987972129012382620, + "venv/lib/python3.13/site-packages/charset_normalizer/version.py": 9948878594498587774, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_mixins.py": 14293848457775268010, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/METADATA": 6557531107125553027, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/cache.py": 15037055977924167732, + "venv/lib/python3.13/site-packages/pygments/styles/bw.py": 869630132791421268, + "venv/lib/python3.13/site-packages/pandas/tests/io/generate_legacy_storage_files.py": 11015954144633661960, + "venv/lib/python3.13/site-packages/anyio/abc/_sockets.py": 15042495744291042062, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpq-9b38f5e3.so.5.17": 9680474575710585826, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/__init__.py": 17454177076687312424, + "venv/lib/python3.13/site-packages/numpy/ma/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jeepney/io/tests/utils.py": 10346859893683522113, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_astype.py": 8633811117672837999, + "venv/lib/python3.13/site-packages/starlette/middleware/wsgi.py": 12506262030845301606, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_indexing.py": 4063662953863959087, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_win32_console.py": 18092547253031555768, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_pyf_src.py": 12351476647369971852, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sample.py": 16877779557071324115, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/__init__.py": 4014740126161973332, + "venv/lib/python3.13/site-packages/numpy/lib/_twodim_base_impl.pyi": 15509415708991012734, + "venv/lib/python3.13/site-packages/pandas/core/indexing.py": 15507869313676722071, + "venv/lib/python3.13/site-packages/pandas/core/generic.py": 10174952306641057447, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asof.py": 17616601748321325187, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/repr.py": 839417422880281122, + "venv/lib/python3.13/site-packages/uvicorn/loops/auto.py": 13086005977087619545, + "frontend/src/routes/dashboards/health/+page.svelte": 7530813351508809839, + "backend/tests/test_layout_utils.py": 2406415176637802126, + "venv/lib/python3.13/site-packages/dateutil/tz/_common.py": 9009072600471223066, + "frontend/src/lib/components/MaintenanceSettingsPanel.svelte": 11414690032093503841, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/fastapi/templating.py": 10760135144345238340, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_is_monotonic.py": 12899848089975919515, + "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/tests/groupby/test_all_methods.py": 18227706645906325527, + "venv/lib/python3.13/site-packages/numpy/lib/_version.pyi": 10804755840730584157, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_ipython_compat.py": 12632271159842988561, + "venv/lib/python3.13/site-packages/pygments/lexers/ecl.py": 12886695201994337568, + "venv/lib/python3.13/site-packages/packaging/specifiers.py": 2800449842990194437, + "frontend/src/routes/migration/__tests__/migration_dashboard.ux.test.js": 17118608261683412409, + "venv/lib/python3.13/site-packages/uvicorn/_subprocess.py": 13965754246493254447, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_apply_relabeling.py": 5600949862632014700, + "venv/lib/python3.13/site-packages/pycparser/c_parser.py": 3954138286651284327, + "frontend/build/favicon.svg": 6451919037497541980, + "backend/alembic/versions/c4a3a2f74bfe_add_missing_columns_needs_review_.py": 4320606555167902916, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/conversion.cpython-313-x86_64-linux-gnu.so": 9014806524727977333, + "venv/lib/python3.13/site-packages/pygments/lexers/_sourcemod_builtins.py": 11809503654078535014, + "venv/lib/python3.13/site-packages/pygments/util.py": 4815334059917765852, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/type_check.pyi": 1599910480066368464, + "frontend/playwright-report/trace/assets/urlMatch-BYQrIQwR.js": 8070494174996726626, + "venv/lib/python3.13/site-packages/keyring/backends/SecretService.py": 17482492072907438453, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/char.pyi": 13143560686049627445, + "venv/lib/python3.13/site-packages/pandas/core/reshape/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/PyModule.cpp": 3464405102256525511, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarinherit.py": 15240535501243623986, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_isin.py": 8136794647591341784, + "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet_trash.py": 6191655521667576604, + "venv/lib/python3.13/site-packages/packaging/requirements.py": 2896326326372719999, + "backend/src/services/profile_service.py": 7430451608615934464, + "venv/lib/python3.13/site-packages/httpcore/_ssl.py": 6665087294869504820, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.c": 9318655518998644962, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_dtype.py": 5336980126536664360, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/dependency.py": 7300594038182867460, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/licenses/LICENSE": 12684353321716745791, + "venv/lib/python3.13/site-packages/pygments/lexers/pascal.py": 5992422120590352714, + "venv/lib/python3.13/site-packages/pygments/lexers/teal.py": 10004159499175716139, + "venv/lib/python3.13/site-packages/pygments/lexers/verification.py": 16645885125604874183, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension_cpp.cpp": 4590574206187223887, + "venv/lib/python3.13/site-packages/pillow.libs/libXau-154567c4.so.6.0.0": 4340972632724893052, + "frontend/src/routes/datasets/DatasetPreview.svelte": 4250995999947659034, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/traceback.py": 2535227583726271746, + "venv/lib/python3.13/site-packages/pandas/errors/cow.py": 14381282473643980776, + "venv/lib/python3.13/site-packages/pygments/lexers/apdlexer.py": 14222752852221009085, + "frontend/src/routes/datasets/__tests__/StatsBar.test.js": 14838932138074212145, + "frontend/build/_app/immutable/chunks/BtMNxLZr.js": 5550630982455761657, + "venv/lib/python3.13/site-packages/pydantic/deprecated/json.py": 17692639396786690144, + "venv/lib/python3.13/site-packages/rapidfuzz/_utils.py": 14374663810542207121, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_ssl_constants.py": 14834514243239777933, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/WHEEL": 8954358347596196608, + "venv/lib/python3.13/site-packages/pandas/core/reshape/encoding.py": 12702053687535473061, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/wheel.py": 3531093454660385247, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/ssh.py": 16262079536832961001, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/missing.py": 11241703105777668183, + "venv/lib/python3.13/site-packages/starlette/schemas.py": 697416731579555195, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/discovery.py": 12479996594187326798, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/help.py": 3124654001287175629, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rename.py": 16148017223289654683, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi": 16048852379621461316, + "venv/lib/python3.13/site-packages/pandas/io/__init__.py": 9767690163638898709, + "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.pyi": 10077265709692546934, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA": 7788873460115135563, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/styles/dracula.py": 12379322008538174078, + "venv/lib/python3.13/site-packages/pygments/lexers/berry.py": 4540479522141160472, + "frontend/src/routes/profile/__tests__/fixtures/profile.fixtures.js": 2726190101012864209, + "frontend/e2e/tests/settings.e2e.js": 14741334477359695649, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/lib/__init__.py": 12211229657513986410, + "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.py": 10803011906582324302, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/assertion_client.py": 4261295109880943573, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_gcc.h": 3561524604274567339, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/well_known.py": 8259335680633926377, + "venv/lib/python3.13/site-packages/pydantic/_internal/_discriminated_union.py": 1818179910730401509, + "venv/lib/python3.13/site-packages/numpy/lib/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/arrays/interval.py": 16281221279220043867, + "venv/lib/python3.13/site-packages/httpx/_multipart.py": 2181282475656908730, + "venv/lib/python3.13/site-packages/pandas/core/arrays/numeric.py": 17834058423729918687, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/issue232.py": 6498198296113395367, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_matmul.py": 16169282225324014901, + "venv/lib/python3.13/site-packages/pandas/tests/api/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py": 1331438198531942242, + "venv/lib/python3.13/site-packages/certifi/core.py": 7472627735517449185, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_strings.py": 7379299916213794543, + "frontend/src/lib/api/datasetReview.js": 3023829599261929428, + "venv/lib/python3.13/site-packages/pydantic/deprecated/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/smmap/__init__.py": 4557520096828426601, + "venv/lib/python3.13/site-packages/ecdsa/test_rw_lock.py": 1572802971060634697, + "venv/lib/python3.13/site-packages/pydantic_settings/__init__.py": 4374954204580208673, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_isin.py": 14387850595546682314, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_is_unique.py": 3989602816674881215, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/METADATA": 732041908491732594, + "venv/lib/python3.13/site-packages/pygments/styles/solarized.py": 11231143047572616298, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_iceberg.py": 1726421917529457420, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/vector.py": 9941185556118343263, + "venv/lib/python3.13/site-packages/pygments/lexers/archetype.py": 8995143180482517233, + "backend/tests/core/test_defensive_guards.py": 1048600814279591148, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_cat_accessor.py": 4304062895283374927, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/METADATA": 8985010079096958084, + "backend/src/plugins/translate/dictionary_filter.py": 18047895364995512274, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_policy.py": 13856626567322091253, + "venv/lib/python3.13/site-packages/authlib/oidc/core/__init__.py": 16029653645350087968, + "backend/src/plugins/translate/orchestrator_query.py": 4760681990145471312, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py": 6712732248328458871, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_join.py": 4213933887062089605, + "venv/lib/python3.13/site-packages/pandas/core/ops/docstrings.py": 3721650738518391256, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/METADATA": 11419135077900073883, + "venv/lib/python3.13/site-packages/pygments/styles/lightbulb.py": 12433916113773598760, + "backend/src/core/utils/dataset_mapper.py": 1606029474387636183, + "backend/src/plugins/translate/orchestrator_aggregator.py": 2072358957289443762, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/base.py": 10205051944814316388, + "venv/lib/python3.13/site-packages/fastapi/types.py": 3867821246650502267, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_emoji_codes.py": 13901854719435716195, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_index.py": 14187428934500390688, + "venv/lib/python3.13/site-packages/pip/_internal/cli/main.py": 9304034369762028739, + "venv/lib/python3.13/site-packages/pygments/lexers/q.py": 15426466074881683794, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_shares_memory.py": 2911029123657970431, + "venv/lib/python3.13/site-packages/apscheduler/executors/gevent.py": 17122637996105344344, + "backend/src/core/auth/api_key.py": 698045354834612724, + "backend/src/api/routes/__tests__/test_assistant_authz.py": 13343271902390197049, + "backend/src/schemas/settings.py": 7182606947764184429, + "venv/lib/python3.13/site-packages/authlib/consts.py": 14226604841596736870, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/websockets_impl.py": 15673691977157706075, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/expressions.py": 8015786996064244656, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/errors.py": 17581857895562494222, + "venv/lib/python3.13/site-packages/pandas/_libs/sas.pyi": 873957906443703977, + "venv/lib/python3.13/site-packages/pandas/core/arrays/period.py": 11560984428402318984, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.cpython-313-x86_64-linux-gnu.so": 13104135217735363438, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/url.py": 1558176735588971829, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_parameter.py": 15173522343126004527, + "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/util/url.py": 15992369651965016538, + "backend/src/plugins/git_plugin.py": 2313306594758409833, + "backend/src/plugins/translate/__tests__/test_target_schema.py": 3945452632405275208, + "venv/lib/python3.13/site-packages/pydantic/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/network/session.py": 293771075394156394, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c": 8494977275215578998, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_cpp_exception.py": 11851283355840567373, + "venv/lib/python3.13/site-packages/authlib/jose/errors.py": 15231759002942436632, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_defchararray.py": 15135904718007443306, + "venv/lib/python3.13/site-packages/PIL/PSDraw.py": 1927169421822446045, + "venv/lib/python3.13/site-packages/pyasn1/type/base.py": 6801504886392649787, + "venv/lib/python3.13/site-packages/keyring/backend.py": 14185808762437650951, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/masked_accumulations.py": 11428556645065711062, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_scalar.py": 2434773821902319678, + "venv/lib/python3.13/site-packages/smmap-5.0.2.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/core.py": 2199607970842512780, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_log_render.py": 18076931145915444473, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_version.py": 15336513445621042105, + "venv/lib/python3.13/site-packages/_pytest/assertion/util.py": 16957445183087315124, + "venv/lib/python3.13/site-packages/pandas/_libs/algos.cpython-313-x86_64-linux-gnu.so": 15706331654215762588, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_series_equal.py": 1223890028205011021, + "venv/lib/python3.13/site-packages/PIL/FontFile.py": 112053841436523305, + "frontend/src/routes/translate/dictionaries/+page.svelte": 1038433841421198720, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_describe.py": 11923715539897559626, + "backend/git_repos/remote/test-repo.git/objects/5d/9eb555c4cac2d3ffdba84c07682b154fe4180d": 10756202165146702691, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_round.py": 1299086932398824299, + "venv/lib/python3.13/site-packages/starlette/middleware/trustedhost.py": 8302185291610019926, + "venv/lib/python3.13/site-packages/attrs/exceptions.py": 2871247302586505373, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_mixins.py": 12351373879926460719, + "venv/lib/python3.13/site-packages/pydantic/v1/fields.py": 3948219773415054006, + "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.h": 5980733638838895780, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ufuncobject.h": 5112456258078662871, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv": 12358602501260667480, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/__main__.py": 6480933938145689964, + "venv/lib/python3.13/site-packages/passlib/handlers/mysql.py": 11165762635383041460, + "venv/lib/python3.13/site-packages/starlette/websockets.py": 13834731343216764204, + "venv/lib/python3.13/site-packages/pandas/testing.py": 18352975429944961593, + "venv/lib/python3.13/site-packages/pandas/core/groupby/ops.py": 2036968385544457016, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_head_tail.py": 1906121476322841736, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_get_numeric_data.py": 11747933921770969706, + "venv/lib/python3.13/site-packages/pandas/io/excel/_xlsxwriter.py": 16873939324418752965, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/reflection.py": 5951113078754792806, + "venv/lib/python3.13/site-packages/uvicorn/__main__.py": 6086938803696646644, + "frontend/src/lib/components/dataset-review/__tests__/validation_findings_panel.ux.test.js": 8994492423600483794, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_argon2.py": 11345706437113628133, + "venv/lib/python3.13/site-packages/certifi/__init__.py": 9045580998764948967, + "frontend/playwright-report/trace/xtermModule.DYP7pi_n.css": 9346562810570076139, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reset_index.py": 14490875921264161445, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/METADATA": 317417773265681256, + "frontend/src/components/tasks/TaskResultPanel.svelte": 7735278333136205649, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/layout.py": 11554376181083053156, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/roles.py": 5448455900674232810, + "backend/src/api/routes/assistant/_dispatch.py": 3122025109125421448, + "backend/src/models/translate.py": 15056358496831895254, + "backend/src/plugins/translate/service_utils.py": 15103456860964805370, + "backend/tests/test_translate_jobs.py": 16585154497956900995, + "venv/lib/python3.13/site-packages/pydantic/decorator.py": 6984214881365537811, + "venv/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so": 829323374625147265, + "venv/lib/python3.13/site-packages/numpy/_core/umath.py": 6132761780113682667, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_integer.py": 16102640589300356639, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_odf.py": 15484940480924122966, + "venv/lib/python3.13/site-packages/pygments/lexers/lean.py": 14518351619544450286, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/licenses/LICENSE": 6965457853328313914, + "venv/lib/python3.13/site-packages/pip/_internal/cli/spinners.py": 7664056305019151182, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/mercurial.py": 335201628064585213, + "venv/lib/python3.13/site-packages/pandas/tests/base/common.py": 13335865314907577354, + "venv/lib/python3.13/site-packages/PIL/PcxImagePlugin.py": 1691405132377495336, + "venv/lib/python3.13/site-packages/pygments/styles/autumn.py": 8750937312198920971, + "venv/lib/python3.13/site-packages/pygments/lexers/usd.py": 934820244673741695, + "frontend/e2e/tests/translation.e2e.js": 6244274143080191568, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/sphinxext.py": 2403717774564798878, + "venv/lib/python3.13/site-packages/anyio/_backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv": 6233924374281534211, + "venv/lib/python3.13/site-packages/numpy/lib/array_utils.pyi": 14646405559193539455, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_boxplot_method.py": 7635131059308651529, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arithmetic.py": 17043958604607035425, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/METADATA": 1266134223155266488, + "venv/lib/python3.13/site-packages/pygments/lexers/int_fiction.py": 8806961041808606055, + "venv/lib/python3.13/site-packages/pygments/filter.py": 16846063190466267618, + "backend/src/services/clean_release/artifact_catalog_loader.py": 7672031618376179570, + "venv/lib/python3.13/site-packages/pycparser/plyparser.py": 5251740466238035035, + "venv/lib/python3.13/site-packages/greenlet/TGreenlet.hpp": 6993553444981671786, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_ops.py": 16346030307660048773, + "backend/tests/test_api_key_auth.py": 15854247672009604904, + "venv/lib/python3.13/site-packages/starlette/concurrency.py": 9835859079437525910, + "venv/lib/python3.13/site-packages/anyio/_core/_eventloop.py": 6853955946028131785, + "venv/lib/python3.13/site-packages/websockets/legacy/auth.py": 16685128086396181286, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_memmap.py": 8709963808115492688, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/properties.py": 5799883762127872919, + "venv/lib/python3.13/site-packages/pandas/core/window/expanding.py": 14141093310397856286, + "backend/src/plugins/mapper.py": 17959627965235532841, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/_internal/_model_construction.py": 694471028676746110, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/index_tricks.pyi": 6035507586990711471, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/RECORD": 1689342214025776630, + "venv/lib/python3.13/site-packages/_pytest/terminal.py": 885450969703476729, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_pbkdf2.py": 4977067068389993374, + "backend/src/plugins/translate/orchestrator_runner.py": 1192466559618297192, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/METADATA": 6960169108624303030, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90": 2657057181044959432, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content": 16257335642847993866, + "backend/src/dependencies.py": 9767255988896931940, + "frontend/src/lib/stores/__tests__/test_taskDrawer.js": 13582869875796637016, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/pyodbc.py": 11271266527234292020, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/_csound_builtins.py": 14530739818491398298, + "venv/lib/python3.13/site-packages/_pytest/_io/saferepr.py": 8025234471485188730, + "venv/lib/python3.13/site-packages/h11/_readers.py": 832030916375670301, + "venv/lib/python3.13/site-packages/authlib/__init__.py": 8957417237987377675, + "backend/tests/test_auth.py": 6167020718035755646, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_stringdtype.py": 8381476847196129074, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype.py": 7796703383405149774, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.pyi": 15130871412783076140, + "backend/src/plugins/translate/preview_token_estimator.py": 254295902082954386, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/perl.py": 17014528337020572681, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/mod_derived_types.f90": 2556756676983488922, + "backend/src/models/dataset_review_pkg/_semantic_models.py": 3910791744304398663, + "venv/lib/python3.13/site-packages/gitdb/db/git.py": 13552203494737962026, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/_mapping.py": 17519715342700184302, + "venv/lib/python3.13/site-packages/pluggy/_hooks.py": 6941854999025808196, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/version.py": 14723293207188512766, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/conftest.py": 8406022190801970256, + "venv/lib/python3.13/site-packages/cffi/cffi_opcode.py": 8411344362428947268, + "venv/lib/python3.13/site-packages/pygments/formatters/terminal256.py": 11473927781167132440, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/dml.py": 6519732236745017861, + "backend/src/plugins/translate/__tests__/test_orchestrator.py": 5663680156343544051, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_sorting.py": 8944017570338511677, + "venv/lib/python3.13/site-packages/pydantic/deprecated/tools.py": 16466182352694741629, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/LICENSE": 14599279238716790189, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f": 13432803601367981068, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/json.py": 14738429697319670035, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_linalg.py": 2939739913218718132, + "backend/src/api/routes/assistant/_history.py": 6437021555836617855, + "backend/git_repos/remote/test-repo.git/hooks/sendemail-validate.sample": 8058833260784074657, + "venv/lib/python3.13/site-packages/attrs/validators.py": 10346563361083429998, + "venv/lib/python3.13/site-packages/pip/_internal/index/package_finder.py": 12631116673181479779, + "venv/lib/python3.13/site-packages/pygments/lexers/typst.py": 8883289726601667104, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/regexopt.py": 16073437303824961930, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/aws.py": 1364297790170663941, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cpu_features.py": 955759654189150497, + "venv/lib/python3.13/site-packages/click/utils.py": 13475604420010022458, + "venv/lib/python3.13/site-packages/numpy/random/_philox.pyi": 7503018432880404291, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arraymethod.py": 14421188237635557797, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/tokens_mixins.py": 9923721909178724437, + "venv/lib/python3.13/site-packages/requests/__init__.py": 2604491098990438229, + "venv/lib/python3.13/site-packages/anyio/streams/file.py": 15232345967545920863, + "venv/lib/python3.13/site-packages/passlib/utils/compat/_ordered_dict.py": 14248790502300368024, + "venv/lib/python3.13/site-packages/pandas/core/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_formats.py": 13500155167624433622, + "venv/lib/python3.13/site-packages/urllib3/util/response.py": 6106698559175827207, + "venv/lib/python3.13/site-packages/starlette/background.py": 10232175205397808417, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_groupby_shift_diff.py": 1210657479716368827, + "venv/lib/python3.13/site-packages/pygments/styles/paraiso_dark.py": 3976779833379189837, + "venv/lib/python3.13/site-packages/pygments/lexers/_php_builtins.py": 2344562378679281201, + "backend/git_repos/remote/test-repo.git/refs/heads/feature/e2e-update": 9577764946931187657, + "venv/lib/python3.13/site-packages/authlib/common/security.py": 2291133227104016684, + "venv/lib/python3.13/site-packages/httpx/_urlparse.py": 8270294590945652412, + "venv/lib/python3.13/site-packages/pillow.libs/libzstd-761a17b6.so.1.5.7": 17875236748140157032, + "backend/src/plugins/translate/orchestrator_run_completion.py": 5945172469962331273, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/comparisons.pyi": 4158883009780474220, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/__init__.py": 15971002342788501945, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/licenses/LICENSE": 3868190977070717994, + "frontend/build/_app/immutable/chunks/B02colNV.js": 11184422123417025804, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_datetime.py": 7456744745424297814, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polyutils.py": 675639791972685455, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/assertion_session.py": 18109848200936213195, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_stata.py": 3030675968330529905, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/METADATA": 10241403930811743893, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_deprecations.py": 8310244516175542839, + "frontend/e2e/e2e-nohealth.mjs": 5921562935931064381, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/RECORD": 17545477863793260029, + "venv/lib/python3.13/site-packages/jaraco/classes/properties.py": 6976928770004942858, + "backend/src/models/dataset_review_pkg/_session_models.py": 16030450529414863096, + "venv/lib/python3.13/site-packages/pandas/core/reshape/concat.py": 2218848863149192467, + "venv/lib/python3.13/site-packages/starlette/testclient.py": 16088848330558215194, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_timer.py": 8196003526646080498, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayterator.pyi": 15722265241660279277, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/fallback.py": 4260636031748548345, + "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.pyi": 13945478633722616250, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_interval.py": 2613503970235591726, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_compat.py": 6032546839876195115, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_routines.py": 4860173574365060471, + "venv/lib/python3.13/site-packages/pandas/core/_numba/__init__.py": 15130871412783076140, "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/pandas/_libs/hashtable.pyi": 15034917167424979097, "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/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/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, + "venv/lib/python3.13/site-packages/pandas/tests/strings/conftest.py": 12065119814157197510, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/row.py": 9763935103055608874, + "venv/lib/python3.13/site-packages/cryptography/x509/name.py": 15338066443257445241, + "venv/lib/python3.13/site-packages/pygments/lexers/numbair.py": 17382646010399794697, + "frontend/src/services/toolsService.js": 1568142461283466080, "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/smmap/test/test_buf.py": 6910367739329016619, "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/pandas/tests/io/formats/style/test_to_typst.py": 14619529283550788275, + "venv/lib/python3.13/site-packages/attr/_version_info.py": 3850449653182103457, "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/pandas/tests/io/formats/test_to_latex.py": 15077617224435782028, + "venv/lib/python3.13/site-packages/pygments/styles/borland.py": 17570558758932580659, + "venv/lib/python3.13/site-packages/apscheduler/job.py": 1858376671986108667, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/unistring.py": 18037463865539157041, + "frontend/src/routes/datasets/review/[id]/+page.svelte": 3248469759382215571, + "backend/src/api/routes/__tests__/test_profile_api.py": 1724401885939803766, + "backend/src/plugins/translate/__tests__/test_orthogonal_fixes.py": 264408615924319135, + "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.test.js": 7689381541193660594, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/encoder.py": 4790267438222037867, + "venv/lib/python3.13/site-packages/attr/__init__.py": 14436902698244718082, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/licenses/LICENSE": 6808958893921859106, + "venv/lib/python3.13/site-packages/rsa/core.py": 13203947234024924497, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/registry.py": 13306388361671753373, + "backend/git_repos/remote/test-repo.git/objects/cf/d2dcbd55735b8cedf21e04e64ac627c6f9a458": 10982669277486885525, "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/urllib3/_base_connection.py": 14495079097019980154, + "backend/test_auth.db": 18214842050920965999, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/_natype.py": 12013743717306900860, + "venv/lib/python3.13/site-packages/requests/cookies.py": 4997226307650350876, + "venv/lib/python3.13/site-packages/pygments/lexers/tact.py": 1164971357219795420, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_indexing.py": 8943385096811168079, + "venv/lib/python3.13/site-packages/numpy/tests/test_ctypeslib.py": 9592016432737074765, + "venv/lib/python3.13/site-packages/charset_normalizer/__init__.py": 12412600648990392633, + "frontend/src/components/backups/BackupList.svelte": 14417854869668960310, + "venv/lib/python3.13/site-packages/fastapi/websockets.py": 9910052969532075719, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_cpp.cpython-313-x86_64-linux-gnu.so": 7490281502544276964, + "backend/tests/test_deprecation_audit_fixes.py": 17902995210831708431, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_qcut.py": 8972418112914954758, + "venv/lib/python3.13/site-packages/passlib/utils/decor.py": 21351391767102899, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/wsproto_impl.py": 3072714633272661847, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py": 5728866271812501558, + "frontend/src/lib/stores/__tests__/mocks/navigation.js": 10782992736745205981, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rename_axis.py": 12432900682994622455, + "venv/lib/python3.13/site-packages/numpy/core/_utils.py": 14108063453670701289, + "frontend/src/lib/stores/__tests__/test_datasetReviewSession.js": 12620073136419991103, + "backend/src/plugins/translate/executor.py": 15866803979457728942, + "venv/lib/python3.13/site-packages/pydantic/_internal/_git.py": 8760779092674434712, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/METADATA": 3786116428839780263, + "venv/lib/python3.13/site-packages/urllib3-2.6.2.dist-info/RECORD": 15194367076254806710, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_frame_equal.py": 12459816298158655274, + "venv/lib/python3.13/site-packages/pygments/lexers/boa.py": 14409319610243925864, + "frontend/src/lib/api/__tests__/reports_api.test.js": 11820587361929895100, + "venv/lib/python3.13/site-packages/pygments/lexers/special.py": 4972294202790455038, + "backend/src/plugins/translate/orchestrator_exec.py": 16278134717094910089, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_range.py": 3544406211185340973, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/__init__.py": 5933622200264572885, + "venv/lib/python3.13/site-packages/attr/validators.py": 4453080662115911998, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npz": 9481735723557962988, + "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.pyi": 7674087576653964854, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_invalid_arg.py": 610891871484326055, + "venv/lib/python3.13/site-packages/passlib/handlers/ldap_digests.py": 8658529184965699766, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.pyi": 15420142722808118826, + "venv/lib/python3.13/site-packages/pandas/io/excel/_pyxlsb.py": 10035587889954731645, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas7bdat.py": 17851617851457266799, + "venv/lib/python3.13/site-packages/packaging/_manylinux.py": 8268418900652790584, + "venv/lib/python3.13/site-packages/pandas/_libs/interval.cpython-313-x86_64-linux-gnu.so": 8964760352224019544, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_interp_fillna.py": 5530041283991655415, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_tooltip.py": 853808724844451770, + "frontend/src/lib/api.js": 7712788935523484149, + "backend/src/schemas/dataset_review_pkg/_composites.py": 1898056130177244572, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/on.py": 2866195356090164296, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_frozen.py": 3484963987053884566, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pct_change.py": 10313980265441433173, + "venv/lib/python3.13/site-packages/yaml/events.py": 745772917931702910, + "venv/lib/python3.13/site-packages/pygments/lexers/elpi.py": 5736689911777977822, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending_distributions.pyx": 15302775787158991386, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/WHEEL": 7795541085444298627, + "venv/lib/python3.13/site-packages/pandas/_libs/missing.pyi": 13543139288840944411, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_chaining_and_caching.py": 15814259766479305290, + "venv/lib/python3.13/site-packages/psycopg2/_range.py": 7184417109068014771, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html_style.tpl": 3352086677417301397, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/METADATA": 15658158392301945427, + "backend/:memory:test_main": 8120796031785944903, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.py": 3762934316884129514, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/okp_key.py": 10312614562914096039, + "venv/lib/python3.13/site-packages/numpy/f2py/f2py2e.py": 738588649412338185, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py": 16610770935842519289, + "venv/lib/python3.13/site-packages/websockets/connection.py": 5168795926684067030, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/sum_.py": 7062070517544958546, + "venv/lib/python3.13/site-packages/pip/_internal/network/xmlrpc.py": 5064964778750366059, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_pick.py": 15760492005471315814, + "venv/lib/python3.13/site-packages/pandas/tests/interchange/test_utils.py": 2329717399120006435, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_categorical.py": 8844412630511751140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/flatiter.pyi": 9598576095384661517, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__multiarray_api.h": 16138871162713175599, + "venv/lib/python3.13/site-packages/numpy/core/__init__.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_html.py": 7732330576029516854, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f": 5913807803369559749, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_astype.py": 16700461036658228009, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/requests.py": 1102963893193914979, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/AUTHORS": 2987771679926243782, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_character.py": 850554362222586199, + "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/numpy/_core/tests/examples/limited_api/meson.build": 8784756284679859367, + "venv/lib/python3.13/site-packages/numpy/random/_common.pyi": 5094115692952609118, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_processors.py": 16557117595879208702, + "backend/src/core/task_manager/graph.py": 1566662881946484762, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pymssql.py": 6650008663791598065, + "venv/lib/python3.13/site-packages/pygments/__main__.py": 13200500591994479045, + "backend/src/services/health_service.py": 14450610712741288051, + "venv/lib/python3.13/site-packages/websockets/legacy/exceptions.py": 16025779645869134942, + "venv/lib/python3.13/site-packages/pyasn1/codec/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_old_base.py": 191359377446257900, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_sample.py": 4641567828238191927, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_equals.py": 6429101196875333574, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi": 16312114056447366970, + "venv/lib/python3.13/site-packages/numpy/lib/_iotools.pyi": 12873243737872788349, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/METADATA": 6596896092754256988, + "venv/lib/python3.13/site-packages/pandas/_libs/index.cpython-313-x86_64-linux-gnu.so": 18409579812171549318, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/INSTALLER": 17282701611721059870, + "backend/src/plugins/translate/__tests__/test_dictionary_correction.py": 17508858180216288123, + "venv/lib/python3.13/site-packages/PIL/ImageChops.py": 16368812693381154921, + "backend/src/plugins/git/llm_extension.py": 9347391649685791102, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_online.py": 11850497659869773510, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_dataframe.py": 14945138617962156057, + "venv/lib/python3.13/site-packages/pyasn1/codec/der/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_join.py": 17874591841487372992, + "venv/lib/python3.13/site-packages/httpcore/_sync/http11.py": 5947339024588907032, + "venv/lib/python3.13/site-packages/cryptography/x509/extensions.py": 10197248868682803019, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_formats.py": 3525283725314253763, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/totp.py": 11888568940387752607, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/INSTALLER": 17282701611721059870, "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_msvc.h": 17581467060937454503, - "venv/lib/python3.13/site-packages/pydantic/json.py": 4109352930301629308 + "backend/src/plugins/translate/_batch_sizer.py": 13074277127276828485, + "venv/lib/python3.13/site-packages/uvicorn/middleware/message_logger.py": 14825516604555033580, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_numeric.py": 9417128508433693658, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_join.py": 13115782559805895662, + "venv/lib/python3.13/site-packages/httpcore/_backends/anyio.py": 6167729964577005634, + "venv/lib/python3.13/site-packages/numpy/tests/test_public_api.py": 11741922758622705449, + "backend/src/plugins/translate/events.py": 8282921049842647968, + "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/arrays/floating/conftest.py": 4124267277224879990, + "venv/lib/python3.13/site-packages/pandas/util/__init__.py": 4070574585004336241, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.pyx": 5760108632332714287, + "venv/lib/python3.13/site-packages/cryptography/x509/certificate_transparency.py": 11337143186866439208, + "venv/lib/python3.13/site-packages/PIL/_deprecate.py": 15076725072094847812, + "venv/lib/python3.13/site-packages/pygments/lexers/amdgpu.py": 17249439604111838979, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_list_accessor.py": 8613662386779664039, + "venv/lib/python3.13/site-packages/pygments/styles/monokai.py": 12381683616720952636, + "backend/src/schemas/auth.py": 12332369795585412464, + "backend/src/services/reports/__tests__/test_report_normalizer.py": 5179524010104259469, + "venv/lib/python3.13/site-packages/pydantic/aliases.py": 14481980467204711659, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_sparse.py": 14343335524508450058, + "frontend/src/routes/dashboards/[id]/components/DashboardTaskHistory.svelte": 8800115118935646769, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_constructors.py": 6440526981746306640, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/__init__.py": 2791238481813240414, + "venv/lib/python3.13/site-packages/git/remote.py": 1694919255653049944, + "venv/lib/python3.13/site-packages/pygments/lexers/procfile.py": 3860651022061090738, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/models.py": 5656065513234782067, + "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.pyi": 17825266810219495672, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_get.py": 10255752806860493777, + "frontend/src/lib/stores/__tests__/sidebar.test.js": 5168138864675110669, + "frontend/playwright-report/data/36557793d7fda8ef412a553a55389600452506f9.png": 8526067803082440263, + "backend/git_repos/remote/test-repo.git/hooks/pre-applypatch.sample": 15598058327720909861, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/parameter.py": 2793853093222900337, + "venv/lib/python3.13/site-packages/numpy/core/__init__.py": 10397294636564169377, + "venv/lib/python3.13/site-packages/pandas/io/excel/_calamine.py": 13354427767660487637, + "backend/src/core/ws_log_handler.py": 17175572704051278951, + "venv/lib/python3.13/site-packages/pygments/styles/gruvbox.py": 9489017112545247388, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/__init__.py": 9884041726796476720, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_chebyshev.py": 8054411443686791426, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/endpoints.py": 18334891787808122725, + "venv/lib/python3.13/site-packages/pip/_internal/cli/index_command.py": 15798187258841839292, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/wheel.py": 13979536782410081712, + "venv/lib/python3.13/site-packages/more_itertools/recipes.pyi": 16788810745659802820, + "venv/lib/python3.13/site-packages/pandas/core/internals/managers.py": 13547912653290063698, + "venv/lib/python3.13/site-packages/pandas/compat/__init__.py": 6077099417711209303, + "venv/lib/python3.13/site-packages/idna/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/dns.py": 17149871769553794654, + "venv/lib/python3.13/site-packages/iniconfig/_parse.py": 11418441008427032090, + "venv/lib/python3.13/site-packages/websockets/streams.py": 15786581670248099415, + "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.py": 1809069379864985298, + "frontend/src/routes/datasets/+page.svelte": 4090458050277453670, + "backend/src/services/git/_sync.py": 14233419521256437438, + "frontend/src/lib/stores/__tests__/setupTests.js": 13316015450930652502, + "frontend/src/components/tools/MapperTool.svelte": 452311121889230749, + "venv/lib/python3.13/site-packages/pyasn1/type/tagmap.py": 14075859042659927673, + "venv/lib/python3.13/site-packages/typing_inspection/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/WHEEL": 16784970174376303810, + "venv/lib/python3.13/site-packages/numpy/f2py/auxfuncs.py": 2234931733687557433, + "venv/lib/python3.13/site-packages/pygments/styles/stata_light.py": 16319330015324455277, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jws_algs.py": 11920621906391796226, + "venv/lib/python3.13/site-packages/pygments/lexers/_usd_builtins.py": 8671446144574174964, + "venv/lib/python3.13/site-packages/pygments/styles/rainbow_dash.py": 12236746494379891602, + "venv/lib/python3.13/site-packages/pygments/lexers/comal.py": 769727871242464458, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/array.py": 13840510238256626632, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/region.py": 12579403230062395563, + "venv/lib/python3.13/site-packages/numpy/core/numeric.py": 17025007229779320230, + "venv/lib/python3.13/site-packages/httpcore-1.0.9.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/core/fromnumeric.py": 2136433423902202138, + "venv/lib/python3.13/site-packages/pyasn1/type/useful.py": 10313387611927801339, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_localize.py": 18409231586451494605, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_loc.py": 2127584756555503873, + "venv/lib/python3.13/site-packages/referencing/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraypad.pyi": 12178766981280242620, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_finalize.py": 12539815426478689538, + "dist/docker/backend.0.1.1.tar.xz": 932529191402352855, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/conftest.py": 2643915042664055969, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_ewm.py": 13789842684407148830, + "backend/src/models/__tests__/test_clean_release.py": 8187870494226758184, + "backend/src/plugins/translate/__tests__/__init__.py": 2490542523242946173, + "venv/lib/python3.13/site-packages/pygments/lexers/nit.py": 18262907536841158657, + "backend/src/plugins/translate/__tests__/test_dictionary_prompt_builder.py": 12854863376472707556, + "venv/lib/python3.13/site-packages/_pytest/raises.py": 8188402179490363767, + "venv/lib/python3.13/site-packages/numpy/_core/_asarray.pyi": 3940937389249665490, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_decimal.py": 3515468590005709183, + "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators_v1.py": 16723743964226526155, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_internal/commands/help.py": 4175797322922912326, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_indexing.py": 1947969642791009285, + "venv/lib/python3.13/site-packages/pygments/lexers/smalltalk.py": 6113431347120223592, + "venv/lib/python3.13/site-packages/greenlet/_greenlet.cpython-313-x86_64-linux-gnu.so": 6036818030377883416, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop_duplicates.py": 2397396876872403048, + "venv/lib/python3.13/site-packages/dotenv/cli.py": 7952654621986067973, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.pyi": 3595910367556664837, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_missing.py": 6224750552277937853, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/fields.py": 8923326131649837922, + "frontend/src/lib/components/translate/TargetSchemaHint.svelte": 4679159885307545370, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/chararray.pyi": 9683985931409244216, + "backend/tests/test_maintenance_service.py": 16353704909990612862, + "venv/lib/python3.13/site-packages/rsa/pkcs1_v2.py": 3533398238491175229, + "dist/docker/backend.0.1.0.tar.xz": 3591917885965226179, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_masked_matrix.py": 1444179242134203344, + "venv/lib/python3.13/site-packages/pandas/tseries/api.py": 14785127136180503704, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/parameters.py": 247312908510013930, + "backend/src/plugins/translate/__tests__/test_executor.py": 17557965511167209685, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/misc.py": 6571241778569465264, + "backend/git_repos/remote/test-repo.git/objects/ae/8d2f5dec5d421b2d6cc1eebaad6d2ef901a90d": 15877648001251681939, + "venv/lib/python3.13/site-packages/numpy/testing/__init__.pyi": 8126257788928282891, + "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.pyi": 6723628093359375823, + "venv/lib/python3.13/site-packages/pygments/scanner.py": 5640381644804445932, + "venv/lib/python3.13/site-packages/numpy/_core/memmap.py": 4093510602708416858, + "venv/lib/python3.13/site-packages/uvicorn/protocols/utils.py": 6147480543268737542, + "venv/lib/python3.13/site-packages/attr/setters.pyi": 6670509359139243236, + "venv/lib/python3.13/site-packages/gitdb/fun.py": 55226330810782184, + "frontend/vite.config.js": 3769019895915732131, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/__init__.py": 8558541715982163200, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_set_value.py": 4166411740676564820, + "venv/lib/python3.13/site-packages/pytest_asyncio/__init__.py": 8162213292669110211, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/LICENSE": 16174281248426886206, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/__init__.py": 15130871412783076140, + "backend/src/core/timezone.py": 8889304905072332926, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_cython.py": 14695721638531081573, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/errors.py": 10750605030539582738, + "venv/lib/python3.13/site-packages/click/_utils.py": 16491408631876616271, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/plugin.py": 18006138132596504101, + "venv/lib/python3.13/site-packages/numpy/core/_dtype.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/_pytest/config/__init__.py": 12787579251203510616, + "venv/lib/python3.13/site-packages/pip/_internal/cache.py": 210214424535803946, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_c_parser_only.py": 3038797485572319804, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/datetimes/test_cumulative.py": 6346947559103505068, + "venv/lib/python3.13/site-packages/pandas/tests/frame/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/wowtoc.py": 17527844575999013592, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/core.py": 14576109242055156193, + "frontend/src/lib/components/reports/ReportCard.svelte": 13714680961668469204, + "backend/src/core/superset_client/_dashboards_write.py": 17812522156399945730, + "backend/src/services/clean_release/compliance_execution_service.py": 3379474749353250488, + "venv/lib/python3.13/site-packages/pygments/lexers/cddl.py": 1303059539145221713, + "venv/lib/python3.13/site-packages/cffi/vengine_cpy.py": 10684192171370688079, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/METADATA": 10707390829735099042, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/requirements.py": 13215932786801020434, + "venv/lib/python3.13/site-packages/pygments/lexers/wren.py": 6259586056260713984, + "venv/lib/python3.13/site-packages/numpy/core/arrayprint.py": 9652368112174245943, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/routines/subrout.f": 18215492757907465667, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_subclass.py": 12453252499544981915, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype.pyi": 17662618580381221543, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_equals.py": 9405821443172167066, + "venv/lib/python3.13/site-packages/pandas/_libs/writers.cpython-313-x86_64-linux-gnu.so": 6878855127769203372, + "venv/lib/python3.13/site-packages/numpy/ma/LICENSE": 6723325434476453127, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_unary.py": 2573825678342936734, + "venv/lib/python3.13/site-packages/pandas/io/formats/__init__.py": 18140261896107421679, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi": 16042272072158438261, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_rolling.py": 11118160360072677569, + "venv/lib/python3.13/site-packages/fastapi/exception_handlers.py": 9907950997607808699, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_dtype.py": 1647214604678171565, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/structs.py": 4479429145468072604, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_halfyear.py": 587199217232946404, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_deprecated_kwargs.py": 10379929935087904974, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/dynamic.py": 15220116196072524330, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_repr.py": 5577699046802107144, + "venv/lib/python3.13/site-packages/PIL/PixarImagePlugin.py": 12061717157676819554, + "venv/lib/python3.13/site-packages/PIL/IcnsImagePlugin.py": 1870235606309784691, + "venv/lib/python3.13/site-packages/pygments/lexers/rita.py": 8105458520706587972, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/numerictypes.pyi": 15443101937711720707, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/utils.h": 3920393832993063886, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/exceptions.py": 7518613450390473990, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_finfo.py": 17174674209412768422, + "frontend/vitest.config.js": 4756170101280085905, + "venv/lib/python3.13/site-packages/git/objects/blob.py": 8972374723153211283, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows.py": 13341168721223961872, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/config.py": 10707678943298497676, + "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.pyi": 10487441680587530350, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f": 3980077223827767077, + "venv/lib/python3.13/site-packages/PIL/AvifImagePlugin.py": 1872412416505003364, + "venv/lib/python3.13/site-packages/ecdsa/test_curves.py": 6577762025900435885, + "venv/lib/python3.13/site-packages/numpy/typing/mypy_plugin.py": 1306129775649200113, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/__init__.py": 11709551233929312136, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_delete.py": 5958440386632506587, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reorder_levels.py": 10996225584998355824, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h": 10634781863364525895, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py": 3369246520501764730, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_clip.py": 13498704233745189154, + "frontend/build/_app/immutable/nodes/27.DBoSQFdP.js": 3996839526740186087, + "venv/lib/python3.13/site-packages/gitdb/test/test_stream.py": 18159319442241857857, + "venv/lib/python3.13/site-packages/_pytest/_py/error.py": 2257336434271433543, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/index_tricks.py": 10051261976498916957, + "venv/lib/python3.13/site-packages/pygments/lexers/installers.py": 5083244110640899732, + "venv/lib/python3.13/site-packages/numpy/testing/overrides.pyi": 17408923209056015964, + "frontend/src/lib/api/assistant.js": 15470667170083225911, + "frontend/build/_app/immutable/chunks/Cr-9eaXZ.js": 55845366387923127, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/cells.py": 8299309127027168194, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/timezones.pyi": 17528421279543420867, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_delete.py": 3485374671877063217, + "venv/lib/python3.13/site-packages/requests/_internal_utils.py": 4091305333167213279, + "venv/lib/python3.13/site-packages/numpy/lib/_utils_impl.py": 13012775703413938576, + "venv/lib/python3.13/site-packages/pandas/core/tools/timedeltas.py": 7221393731712061943, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/events.py": 15099787454570172797, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py": 8530403239168529668, + "venv/lib/python3.13/site-packages/pydantic/_internal/_config.py": 12760390602912369447, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_values.py": 834951665649981397, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/passlib/crypto/digest.py": 15890463288512025688, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/licenses/LICENSE": 1424673738228762254, + "venv/lib/python3.13/site-packages/pygments/lexers/felix.py": 2334148799642808111, + "venv/lib/python3.13/site-packages/pygments/styles/tango.py": 12389250878249075539, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/encoder.py": 3261739474564948330, + "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.cpython-313-x86_64-linux-gnu.so": 11074560904305737689, + "venv/lib/python3.13/site-packages/pip/_internal/commands/freeze.py": 8644678595442275485, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/accessor.py": 8373575175447947401, + "venv/lib/python3.13/site-packages/pandas/core/arrays/string_arrow.py": 16997970607998635570, + "venv/lib/python3.13/site-packages/pandas/core/computation/engines.py": 1889823242704769952, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/core.py": 2300277198409164253, + "venv/lib/python3.13/site-packages/jeepney/tests/test_bus.py": 4260827599660763641, + "venv/lib/python3.13/site-packages/pygments/lexers/css.py": 517586374264113606, + "venv/lib/python3.13/site-packages/httpx/__version__.py": 9473642134297828811, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/__init__.py": 4781700006554860887, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_describe.py": 362374422228593281, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_setitem.py": 14920902525192671548, + "frontend/src/components/llm/ProviderConfig.svelte": 10989619989953706954, + "frontend/build/_app/immutable/nodes/15.D77w-oKN.js": 12254106526344958795, + "venv/lib/python3.13/site-packages/numpy/f2py/__version__.pyi": 9759534743796867731, + "venv/lib/python3.13/site-packages/pygments/lexers/templates.py": 16267123844830647955, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py": 6152202474302791232, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/traversals.py": 1188980668212022868, + "venv/lib/python3.13/site-packages/numpy/f2py/rules.py": 9322914583460630877, + "venv/lib/python3.13/site-packages/rapidfuzz/process.py": 3870006735299537016, + "venv/lib/python3.13/site-packages/fastapi/requests.py": 14587947416691824903, + "venv/lib/python3.13/site-packages/_pytest/logging.py": 10972553724755511468, + "frontend/src/components/auth/ProtectedRoute.svelte": 7705373237339863677, + "venv/lib/python3.13/site-packages/jsonschema_specifications/__init__.py": 5732822354953774657, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/__init__.py": 4770885427721822507, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_cross.py": 17742712348672218852, + "venv/lib/python3.13/site-packages/yaml/loader.py": 18284689412149643959, + "frontend/src/lib/components/dataset-review/ValidationFindingsPanel.svelte": 2403276296409515448, + "venv/lib/python3.13/site-packages/httpx/_transports/mock.py": 13564349939188292363, + "venv/lib/python3.13/site-packages/pygments/styles/algol_nu.py": 6229131016121450375, + "venv/lib/python3.13/site-packages/passlib/handlers/digests.py": 18158237109145814857, + "venv/lib/python3.13/site-packages/httpx/__init__.py": 6383055693166097719, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/collections.pyx": 17138729833735744777, + "venv/lib/python3.13/site-packages/pygments/lexers/gcodelexer.py": 13712494327007684318, + "venv/lib/python3.13/site-packages/greenlet/greenlet.cpp": 3281107194043468270, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__datasource.py": 1747755531265478106, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_assign.py": 2647902466315482406, + "venv/lib/python3.13/site-packages/uvicorn/logging.py": 12858188863836778374, + "backend/:memory:test_tasks": 9776368437354383244, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_indexing.py": 3841182456456779012, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/queue.py": 7820997545569991670, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/greenlet/TThreadStateCreator.hpp": 9887867766190459665, + "venv/lib/python3.13/site-packages/pygments/styles/fruity.py": 7925019839136894457, + "backend/src/api/routes/validation/__tests__/test_validation_api.py": 9582367280498409855, + "venv/lib/python3.13/site-packages/numpy/lib/stride_tricks.pyi": 5879290708972838025, + "frontend/playwright-report/data/d3248d538f098a40b756ead1ee1a92a7d61e7c7a.zip": 661058595618012246, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/__init__.py": 15991623390785635773, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/types.py": 12298292195929126306, + "frontend/src/routes/datasets/review/ReviewWorkspaceLeftSidebar.svelte": 9009994851177005358, + "venv/lib/python3.13/site-packages/pygments/styles/default.py": 13992125975366109635, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/generator_pcg64_np126.pkl.gz": 9677994062701347206, + "venv/lib/python3.13/site-packages/starlette/types.py": 6372850128669191435, + "venv/lib/python3.13/site-packages/keyring/backends/chainer.py": 12526770797516553385, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__init__.py": 5895297076117159245, + "venv/lib/python3.13/site-packages/jeepney/io/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/indexes/interval.py": 17965911911189276907, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_ops.py": 14420421526781215500, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/test_json.py": 12422315190455428620, + "venv/lib/python3.13/site-packages/pandas/tests/internals/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby_subclass.py": 5540948578269213810, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_time_series.py": 5205199092955498507, + "venv/lib/python3.13/site-packages/pygments/lexers/rebol.py": 10460732731157940232, + "venv/lib/python3.13/site-packages/greenlet/tests/_test_extension.cpython-313-x86_64-linux-gnu.so": 1211491156495529145, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_extint128.py": 11074657869101074458, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_value_counts.py": 13270420637302622174, + "venv/lib/python3.13/site-packages/yaml/composer.py": 13619070314468518566, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data": 11957232619107868023, + "frontend/src/routes/migration/mappings/+page.svelte": 4566398049366943407, + "venv/lib/python3.13/site-packages/pydantic/warnings.py": 5142352784799639092, + "venv/lib/python3.13/site-packages/psycopg2/errors.py": 10441360078612452560, + "venv/lib/python3.13/site-packages/pyasn1/__init__.py": 8089201217593738032, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_polynomial.py": 777287409151500309, + "venv/lib/python3.13/site-packages/passlib/handlers/django.py": 66638338316838351, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.pyi": 16372699564794732463, + "venv/lib/python3.13/site-packages/numpy/f2py/__init__.pyi": 3566887042414273892, + "venv/lib/python3.13/site-packages/anyio/_core/_fileio.py": 4507100568401692983, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/__init__.py": 237070345717942041, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/ddl.py": 5006132143435653867, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90": 15981076495193915107, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/mapper.py": 16715864918034312591, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_formats.py": 18080627205081311773, + "backend/src/plugins/translate/orchestrator_cancel.py": 673611364664367049, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pct_change.py": 18056235438452125034, + "venv/lib/python3.13/site-packages/PIL/ImageCms.py": 5610897002957128546, + "backend/alembic/versions/f0e9d8c7b6a5_cascade_ondelete_all_env_fks.py": 18274103435952144919, + "venv/lib/python3.13/site-packages/pygments/styles/vim.py": 2621036947954523349, + "venv/lib/python3.13/site-packages/pandas/io/parsers/python_parser.py": 7297059565749331767, + "backend/src/api/routes/maintenance/_routes.py": 10925523070180866414, + "venv/lib/python3.13/site-packages/pandas/core/flags.py": 4690844374637430013, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/resolver.py": 9931394693284776391, + "venv/lib/python3.13/site-packages/_pytest/_io/terminalwriter.py": 16852767249156780980, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_sh_gcc.h": 3574353221233465215, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/processors.py": 4817637175145012571, + "venv/lib/python3.13/site-packages/pip/_internal/commands/install.py": 17631777189475433503, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_unary.py": 8046543893978198672, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/binding.py": 17078280153372356796, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_markdown.py": 9964642152916165317, + "frontend/src/lib/components/translate/__tests__/test_bulk_replace_modal.svelte.js": 6802604718120565742, + "backend/src/services/dataset_review/orchestrator.py": 8780497744077644822, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_conversion.py": 6205112277291935767, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90": 5949265961908386974, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_join.py": 5982692266872978444, + "venv/lib/python3.13/site-packages/pandas/io/iceberg.py": 13137128885014736233, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_cumulative.py": 16283954014170928273, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_apply.py": 7511915990531229598, + "venv/lib/python3.13/site-packages/PIL/CurImagePlugin.py": 17697303205012181529, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi": 14119032813912827271, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/twisted.py": 16059862619165885730, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_trio.py": 7459901627473962540, + "venv/lib/python3.13/site-packages/numpy/ma/extras.pyi": 15292036493781556342, + "venv/lib/python3.13/site-packages/numpy/testing/_private/__init__.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/indexes/period.py": 1181348384346239378, + "venv/lib/python3.13/site-packages/greenlet/tests/test_extension_interface.py": 11693583111513457974, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/transforms.py": 3773159138960141434, + "venv/lib/python3.13/site-packages/cffi/cparser.py": 5246372077864988755, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/models/target_python.py": 422323125651848065, + "venv/lib/python3.13/site-packages/six.py": 948867418687428421, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_nlargest.py": 1423106021399469694, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pyx": 11739218099400096619, + "venv/lib/python3.13/site-packages/pygments/styles/perldoc.py": 4857683935715743356, + "venv/lib/python3.13/site-packages/rapidfuzz/_common_py.py": 15410157970973169427, + "frontend/src/components/DynamicForm.svelte": 12658559315809907844, + "frontend/build/_app/immutable/chunks/DCG5F3ic.js": 10038366451600899187, + "frontend/src/components/DashboardGrid.svelte": 17669234585849525689, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_construction.py": 10619501873883861745, + "venv/lib/python3.13/site-packages/pandas/core/window/online.py": 13551140636252302201, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_api.py": 10514120091521589282, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/licenses/LICENSE": 8364608327598414179, + "venv/lib/python3.13/site-packages/websockets/__init__.py": 4916307256304054040, + "venv/lib/python3.13/site-packages/psycopg2/extras.py": 7510107741729866600, + "venv/lib/python3.13/site-packages/numpy/random/__init__.pxd": 7355772669172093814, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py": 15294662527620994511, + "venv/lib/python3.13/site-packages/pandas/core/strings/__init__.py": 13025387151657797130, + "venv/lib/python3.13/site-packages/pandas/core/indexes/category.py": 18192569199634406001, + "venv/lib/python3.13/site-packages/pygments/lexers/rdf.py": 14488319292387226505, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py": 9623344347519683527, + "venv/lib/python3.13/site-packages/_pytest/assertion/rewrite.py": 2425990712758915831, + "venv/lib/python3.13/site-packages/packaging/utils.py": 3469957615920103670, + "venv/bin/pyrsa-decrypt": 10929163076272054227, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_warnings.py": 13071210233876253749, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_ratio.py": 940213488194452623, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_copy_deprecation.py": 16045426957636349035, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connection.py": 8190661510572400096, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dtypes.py": 4985057130807802395, + "venv/lib/python3.13/site-packages/pillow.libs/libfreetype-ee1c40c4.so.6.20.4": 12301510769231120312, + "venv/lib/python3.13/site-packages/pandas/core/interchange/dataframe.py": 16525846817331842080, + "venv/lib/python3.13/site-packages/numpy/_core/defchararray.pyi": 2277933368373498515, + "venv/lib/python3.13/site-packages/pandas/arrays/__init__.py": 10005095663840461954, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/freefem.py": 9851243865301700231, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/types.py": 13384984564922916167, + "frontend/src/routes/settings/LlmSettings.svelte": 2951029184700558947, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/asymmetric_key.py": 14948661854506285135, + "venv/lib/python3.13/site-packages/pygments/lexers/_lasso_builtins.py": 4006621424665751347, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/requests.py": 14847842002253212098, + "venv/lib/python3.13/site-packages/authlib/oauth1/client.py": 7314311571224771, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_formats.py": 12299393760307251036, + "frontend/src/lib/components/reports/__tests__/reports_list.ux.test.js": 16252194679528846126, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_inspect.py": 10573558345297891848, + "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.pyi": 1942236362568669510, + "venv/lib/python3.13/site-packages/numpy/f2py/__version__.py": 8588600299261398598, + "venv/lib/python3.13/site-packages/pygments/styles/stata_dark.py": 324072437809944751, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_store.py": 1500300322083708794, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_runtime.py": 12534621594420844770, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_hashtable.py": 2620207240930665390, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/test_reductions.py": 11624188672428941494, + "venv/lib/python3.13/site-packages/charset_normalizer/cd.py": 8687667152597941021, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_compat.py": 4677414058216516380, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/securetransport.py": 12104888897121018676, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/registration.py": 14639972512303032712, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/np_datetime.pyi": 2884703536776830012, + "frontend/src/lib/components/reports/__tests__/reports_page.integration.test.js": 16463062768004950066, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/package_data.py": 3078502124870585867, + "venv/lib/python3.13/site-packages/pygments/formatters/pangomarkup.py": 17135620955205945255, + "venv/lib/python3.13/site-packages/pygments/styles/vs.py": 4188729978573652106, + "frontend/e2e/tests/enterprise-clean-setup.e2e.js": 11120112996353549578, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA": 18410956221497090898, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_printing.py": 8859757563354666575, + "backend/src/models/auth.py": 775632703462705888, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-np0-objarr.npy": 1615546603475261360, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timedeltas.py": 1175883320586860493, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_numba.py": 1548992314517942530, + "venv/lib/python3.13/site-packages/pycparser/ply/lex.py": 3393278208465358140, + "venv/lib/python3.13/site-packages/requests/hooks.py": 9888227370911151341, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_windows_renderer.py": 1076842273781909680, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.cpython-313-x86_64-linux-gnu.so": 14468234464367691795, + "venv/lib/python3.13/site-packages/jose/backends/native.py": 50023158618000658, + "venv/lib/python3.13/site-packages/anyio/lowlevel.py": 11919467357746648592, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_setitem.py": 15731267129055947469, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/asyncio.py": 2517623574187179319, + "venv/lib/python3.13/site-packages/yaml/serializer.py": 1783761365703703558, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_readers.py": 2136472634307645842, + "venv/lib/python3.13/site-packages/fastapi/staticfiles.py": 4094330072433302614, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/__init__.py": 1856412417337875350, + "venv/lib/python3.13/site-packages/greenlet/greenlet_compiler_compat.hpp": 465436185632243991, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/matrix.pyi": 15667024840812783911, + "venv/lib/python3.13/site-packages/pandas/_libs/reshape.pyi": 88721900806893992, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_duplicates.py": 9830936017197354309, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_contains.py": 5273759677032634868, + "venv/lib/python3.13/site-packages/git/exc.py": 14278238357119816365, + "backend/src/core/migration/archive_parser.py": 7392694914943455006, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_msvc.h": 14580207065003376324, + "venv/lib/python3.13/site-packages/numpy/random/_pickle.pyi": 16081120364372391381, + "venv/lib/python3.13/site-packages/pluggy/_warnings.py": 2664977718908223842, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_regression.py": 6742646011852052645, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arrayprint.pyi": 2053388407376896377, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_nep50_promotions.py": 6318578947214302182, + "venv/lib/python3.13/site-packages/secretstorage/exceptions.py": 16701299261122689924, + "backend/src/plugins/translate/orchestrator_validation.py": 17464651621865127561, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/astype.py": 9925183787411796679, + "venv/lib/python3.13/site-packages/pygments/lexers/hexdump.py": 10665271113239513484, + "frontend/e2e/tests/live-project-check.e2e.js": 2548440031836033830, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/fetch.py": 13937019222549208796, + "venv/lib/python3.13/site-packages/requests/utils.py": 17045260098091371478, + "frontend/svelte.config.js": 8473636210766821560, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_frame_transform.py": 6759417099641034692, + "venv/lib/python3.13/site-packages/pandas/_typing.py": 17795648994662434211, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_aix.h": 13316272821279308986, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_delitem.py": 14336697139511118920, + "venv/lib/python3.13/site-packages/annotated_types/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oidc/core/userinfo.py": 17201158389976619872, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/legacy/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/gitdb/db/mem.py": 15823812455996199993, + "venv/lib/python3.13/site-packages/pygments/styles/material.py": 14325514369696961874, + "backend/src/core/migration/risk_assessor.py": 1061977005072298440, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/resource_protector.py": 11539718751174980004, + "venv/lib/python3.13/site-packages/numpy/random/_mt19937.pyi": 15904463104068500379, + "frontend/build/_app/immutable/nodes/2.ygKEcgXs.js": 4758071082823820713, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_app.py": 14788764260762890368, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get.py": 6509102681661636928, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE": 5669644120528099197, + "venv/lib/python3.13/site-packages/attr/_funcs.py": 5302917072419624193, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/offsets.pyi": 13173581775000480811, + "venv/lib/python3.13/site-packages/authlib/oauth2/__init__.py": 13682931764896414722, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexers.py": 6773751569163287047, + "venv/lib/python3.13/site-packages/pip/_internal/commands/check.py": 6937252393012787214, + "venv/lib/python3.13/site-packages/ecdsa/ecdsa.py": 9770689913380927623, + "venv/lib/python3.13/site-packages/_pytest/freeze_support.py": 494952714451267295, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_drop_duplicates.py": 12601598844977346213, + "backend/tests/test_translate_scheduler_execution.py": 16687335504320865378, + "venv/lib/python3.13/site-packages/pydantic/v1/networks.py": 13262073155118055511, + "venv/lib/python3.13/site-packages/uvicorn/py.typed": 15240312484046875203, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_nat.py": 7400568652984772972, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray_misc.pyi": 16219573290116396099, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi": 8666343427862784832, + "venv/lib/python3.13/site-packages/smmap/test/test_util.py": 5634593621291240094, + "venv/lib/python3.13/site-packages/keyring/backends/macOS/__init__.py": 1010937986753403630, + "venv/lib/python3.13/site-packages/websockets/__main__.py": 11948055520555854616, + "venv/lib/python3.13/site-packages/pygments/lexers/solidity.py": 5071425960622305629, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_pytesttester.py": 17737911110576747508, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/METADATA": 16700674024421191168, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_reindex.py": 15680924058960901067, + "venv/lib/python3.13/site-packages/sqlalchemy/util/__init__.py": 15821192733097665649, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/RECORD": 16740224557818847141, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/framework_integration.py": 3935346152156572025, + "venv/lib/python3.13/site-packages/pandas/core/strings/object_array.py": 17631047188839635539, + "venv/lib/python3.13/site-packages/pandas/_libs/sparse.cpython-313-x86_64-linux-gnu.so": 2051484129454294720, + "venv/lib/python3.13/site-packages/pandas/core/util/numba_.py": 3535857372998653863, + "frontend/playwright-report/index.html": 16542149899775356791, + "venv/lib/python3.13/site-packages/numpy/_core/einsumfunc.pyi": 4729765666018003634, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/RECORD": 7914594107698271488, + "venv/lib/python3.13/site-packages/fastapi/security/base.py": 15674297568104917749, + "venv/lib/python3.13/site-packages/numpy/lib/array_utils.py": 18135114588643176359, + "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.py": 2490579175967301457, + "venv/lib/python3.13/site-packages/pydantic/json_schema.py": 15678278224696353978, + "venv/lib/python3.13/site-packages/pandas/tests/test_nanops.py": 8709105600366913011, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_raises.py": 9678418010293693275, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_pivot_multilevel.py": 9830258607305392103, + "venv/lib/python3.13/site-packages/PIL/_binary.py": 14039167720582222043, + "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.pyi": 12275242654430570028, + "venv/lib/python3.13/site-packages/anyio/abc/__init__.py": 11428476337116642278, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_between.py": 337429135216881486, + "venv/lib/python3.13/site-packages/websockets/sync/utils.py": 15135020989207191168, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.pyi": 3573629536236108391, + "venv/lib/python3.13/site-packages/numpy/testing/_private/utils.pyi": 17639497083041129225, + "venv/lib/python3.13/site-packages/attr/filters.pyi": 13942974755090135724, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_size.py": 16658280641516916790, + "venv/lib/python3.13/site-packages/authlib/oauth2/client.py": 7237359250450222680, + "venv/lib/python3.13/site-packages/sqlalchemy/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pytest/__init__.py": 6137272437722350673, + "venv/lib/python3.13/site-packages/pygments/lexers/ooc.py": 14540210212631538007, + "frontend/src/lib/stores/__tests__/mocks/environment.js": 16653269108049932073, + "venv/lib/python3.13/site-packages/attr/converters.py": 5179615793507170642, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/flow_control.py": 4822804840057360506, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_datetime.py": 1678885152993000592, + "venv/lib/python3.13/site-packages/pandas/core/tools/times.py": 6560679305255812809, + "venv/bin/pytest": 2593802493707545818, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/decoder.py": 15336592439379775543, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarraytypes.h": 6765088137325865789, + "venv/lib/python3.13/site-packages/rapidfuzz/process_py.py": 17563673072076876125, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_series.py": 16418555817529711079, + "venv/lib/python3.13/site-packages/pandas/core/roperator.py": 2587829042468916489, + "venv/lib/python3.13/site-packages/jeepney/tests/test_fds.py": 6257376331171761928, + "venv/lib/python3.13/site-packages/pandas/core/ops/missing.py": 9493665944764255854, + "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.pyi": 16573082220135508510, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90": 7589258200398878529, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_count.py": 16947194157984708529, + "venv/lib/python3.13/site-packages/pip/_vendor/pkg_resources/__init__.py": 1677532855362260338, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_misc.pyi": 7544619194032232861, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/__init__.py": 1923528231486706442, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_api_info.py": 16491629653122827368, + "venv/lib/python3.13/site-packages/PIL/JpegPresets.py": 12342262642420923471, + "venv/lib/python3.13/site-packages/pluggy-1.6.0.dist-info/RECORD": 1164466882742493155, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/RECORD": 12555714734722889695, + "venv/lib/python3.13/site-packages/numpy/core/_internal.py": 14816989375912210674, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/philox-testset-1.csv": 2202360898679162333, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_duplicate_labels.py": 10663105616336167414, + "venv/lib/python3.13/site-packages/rapidfuzz/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/websockets/speedups.cpython-313-x86_64-linux-gnu.so": 10941658763526595989, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py": 9888795404090331319, + "venv/lib/python3.13/site-packages/authlib/common/errors.py": 16082974228565515177, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/array_pad.pyi": 14755435694146003896, + "venv/lib/python3.13/site-packages/click/core.py": 16793133181718891193, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/RECORD": 10052481303799123207, + "venv/lib/python3.13/site-packages/numpy/tests/test_reloading.py": 17532116685329953400, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/WHEEL": 12146818530001975731, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_iterrows.py": 3791886201566670087, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi": 13061638961405460334, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite_e.py": 3654583356259850174, + "venv/lib/python3.13/site-packages/authlib/common/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/styles/__init__.py": 9482393721453335937, + "venv/lib/python3.13/site-packages/anyio/_core/_asyncio_selector_thread.py": 1760597191437520000, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/METADATA": 6656194161182818439, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_algorithms.py": 15219408648894515493, + "venv/lib/python3.13/site-packages/apscheduler/executors/debug.py": 14072221218785494847, + "venv/lib/python3.13/site-packages/pandas/util/version/__init__.py": 3844072588696074141, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/enumerated.py": 16623643153933348755, + "venv/lib/python3.13/site-packages/pip/_internal/utils/glibc.py": 12335359492756627313, + "venv/lib/python3.13/site-packages/attr/exceptions.py": 11532465891810816417, + "venv/lib/python3.13/site-packages/httpcore/_sync/connection_pool.py": 8159971229245441880, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/__init__.py": 10920760520224795596, + "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.pyi": 18290764713161282980, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_duplicated.py": 14676058112867601208, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/__init__.py": 2401931196871484449, + "venv/lib/python3.13/site-packages/PIL/WalImageFile.py": 12442826195371137238, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_sort_values.py": 12064896795288302730, + "venv/lib/python3.13/site-packages/cryptography/x509/verification.py": 1079694784860492682, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_algs.py": 2479791018067637690, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_index_tricks.py": 4676293127859087991, + "venv/lib/python3.13/site-packages/urllib3/util/ssl_match_hostname.py": 7411350247004265632, + "venv/lib/python3.13/site-packages/pygments/formatters/terminal.py": 14380579279194052030, + "frontend/build/_app/immutable/nodes/7.uApaBQtS.js": 122651088329333182, + "backend/git_repos/remote/test-repo.git/objects/5a/82ef700fef88b69cd480e4025283809496ee20": 7003383965314354150, + "venv/lib/python3.13/site-packages/pandas/tests/frame/conftest.py": 15090201792072045503, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/httpcore/_async/connection_pool.py": 932468678264370661, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_macos.py": 7028037591427052891, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_inference.py": 16402427186697071465, + "venv/lib/python3.13/site-packages/pip/_internal/commands/list.py": 13035925292530461722, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_period.py": 12593777226419608212, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_sparse_accessor.py": 6774374030220202353, + "venv/lib/python3.13/site-packages/_pytest/deprecated.py": 5452408732344157294, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h": 8933016749764021181, + "venv/lib/python3.13/site-packages/pandas/core/algorithms.py": 487939626203097713, + "venv/lib/python3.13/site-packages/pip/_internal/operations/prepare.py": 13514839972066861359, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/cast.py": 342228968652072052, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/clsregistry.py": 1589692649837935355, + "venv/lib/python3.13/site-packages/attr/_next_gen.py": 16353246941851015420, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/urllib3/py.typed": 12220177918227495093, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/LICENSE": 11167201188673981085, + "frontend/src/lib/i18n/index.ts": 4285366775990653535, + "frontend/build/_app/immutable/nodes/20.BboyjuGl.js": 11318425268071802665, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_smoke.py": 7476432112986643847, + "venv/lib/python3.13/site-packages/pycparser/c_generator.py": 14922277346364091122, + "venv/lib/python3.13/site-packages/charset_normalizer/md__mypyc.cpython-313-x86_64-linux-gnu.so": 12629680116730190225, + "frontend/build/_app/immutable/chunks/Cs7qTEqk.js": 15866070137921022262, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_set_name.py": 9094608008538024609, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_file_handling.py": 732772718210067599, + "backend/git_repos/remote/test-repo.git/hooks/pre-merge-commit.sample": 10013699873067956556, + "venv/lib/python3.13/site-packages/passlib/utils/pbkdf2.py": 15802959653228956404, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/licenses/COPYING": 14459782230785388765, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/_cryptography_key.py": 388489172928969873, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_sas.py": 9446226619493404132, + "frontend/src/routes/validation/+page.svelte": 9845194549295283559, + "backend/src/plugins/translate/preview_prompt_helpers.py": 14303328860208074708, + "venv/lib/python3.13/site-packages/authlib/oidc/core/claims.py": 2035724920423374302, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ndarray.pyi": 14369009813591437391, + "venv/lib/python3.13/site-packages/passlib/ifc.py": 14479133654556657428, + "venv/bin/numpy-config": 17104619511899110252, + "venv/lib/python3.13/site-packages/keyring/backends/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77comments.f": 4801926170672147659, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_distutils.py": 1948707545068786, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_errstate.py": 10788459171326750780, + "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.pyi": 1424133074692438241, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_searchsorted.py": 11208047646304753715, + "venv/lib/python3.13/site-packages/fastapi/_compat/v1.py": 9776181748061371513, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/testing.pyi": 9317922890783549326, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/rec/__init__.pyi": 1782063765067823837, + "venv/lib/python3.13/site-packages/PIL/GdImageFile.py": 16875784236394545058, + "frontend/src/lib/components/reports/ReportsList.svelte": 15460090587871611258, + "frontend/src/lib/components/translate/BulkReplaceModal.svelte": 9447617465987205060, + "venv/lib/python3.13/site-packages/PIL/JpegImagePlugin.py": 10621639599916796689, + "backend/git_repos/remote/test-repo.git/objects/48/c3fde4d5fff5bf98e9bcaa5f328b199aa18292": 6121250272621110311, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_printing.py": 1901396869745313303, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_zips.py": 5184894018177148648, + "venv/lib/python3.13/site-packages/pandas/core/interchange/from_dataframe.py": 8278998381856028462, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.pyx": 7085380878820747579, + "venv/lib/python3.13/site-packages/git/refs/log.py": 5175801243332619268, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_conversion.py": 7507083194555424923, + "venv/lib/python3.13/site-packages/h11/_abnf.py": 10456996134895429201, + "venv/lib/python3.13/site-packages/pip/_internal/locations/_distutils.py": 13559457590971821771, + "venv/lib/python3.13/site-packages/numpy/_core/_internal.pyi": 6840742333427164920, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/licenses/numpy/ma/LICENSE": 6723325434476453127, + "venv/lib/python3.13/site-packages/pygments/lexers/dylan.py": 16246299896150112270, + "venv/lib/python3.13/site-packages/pygments/lexers/pddl.py": 9256112535059995841, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_tz_localize.py": 14495969595744172955, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex_like.py": 13803156447991282315, + "venv/lib/python3.13/site-packages/pip/_internal/operations/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/sorting.py": 689057022713741051, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/core/sparse/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/dictionary.py": 9599439750713575741, + "venv/lib/python3.13/site-packages/pygments/lexers/futhark.py": 10102535873433759899, + "venv/lib/python3.13/site-packages/pygments/lexers/thingsdb.py": 6073447481627395832, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/METADATA": 3643456577199395707, + "backend/src/api/routes/maintenance/_router.py": 1368406181799456173, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nested_sequence.pyi": 10985533017688918283, + "venv/lib/python3.13/site-packages/yaml/nodes.py": 3463622922914760653, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ctypeslib.pyi": 8623725566434725526, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_limited_api.py": 15788485008764560845, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/jwe.py": 10478268710546063196, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/cacert.pem": 15624463015628939254, + "venv/lib/python3.13/site-packages/numpy/random/c_distributions.pxd": 16574161095720077595, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_timeseries_window.py": 1973365560758236222, + "venv/lib/python3.13/site-packages/pygments/styles/sas.py": 12363791134941577382, + "frontend/e2e/fixtures/global-setup.js": 16032945890934324203, + "frontend/src/components/tasks/LogEntryRow.svelte": 3694709927263161265, + "backend/src/api/routes/__tests__/conftest.py": 3768471623650776808, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90": 877982462186396830, + "venv/lib/python3.13/site-packages/iniconfig/__init__.py": 12623265899068631092, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_is_homogeneous_dtype.py": 15378147393056707851, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_converter.py": 7709581879446228856, + "venv/lib/python3.13/site-packages/numpy/testing/__init__.py": 2831275254313750978, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.pyi": 16164841755339571545, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_get_set.py": 14375107704596905983, + "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/tests/test_core.py": 12712110303898046818, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/create.py": 16693261531832306870, + "venv/lib/python3.13/site-packages/pygments/lexers/floscript.py": 944042220740663491, + "venv/lib/python3.13/site-packages/_pytest/_io/__init__.py": 1510478951261938348, + "venv/bin/uvicorn": 3776670267111625708, + "frontend/src/routes/dashboards/health/__tests__/health_page.integration.test.js": 11653729504599199718, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/nditer.py": 10038360623032425884, + "venv/lib/python3.13/site-packages/referencing/typing.py": 8296636464219681747, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90": 15768643271492041853, + "venv/lib/python3.13/site-packages/passlib/ext/__init__.py": 15240312484046875203, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/setup.py": 5482352991573617756, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_formats.py": 2601044064677727807, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_kwargs.py": 10173906126211473463, + "frontend/build/_app/immutable/chunks/DA0oX2nF.js": 4762485859359244720, + "backend/src/core/auth/repository.py": 7314530014494164270, + "venv/lib/python3.13/site-packages/pandas/core/arrays/timedeltas.py": 7318851108932357510, + "backend/src/plugins/translate/_llm_parse.py": 3278211416813203155, + "backend/tests/test_storage_audit_fixes.py": 6119862973635892572, + "venv/lib/python3.13/site-packages/psycopg2/extensions.py": 14197445323992851566, + "frontend/build/_app/immutable/chunks/DkSc7bnI.js": 16633882293462436801, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/__init__.py": 10072943986583771248, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/getlimits.pyi": 93747984191461691, + "venv/lib/python3.13/site-packages/pip/_internal/commands/completion.py": 4435231315212798769, + "venv/lib/python3.13/site-packages/websockets/http11.py": 11022534176398053082, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/parsing.pyi": 11967691665766452312, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.APACHE": 8359973023624924624, + "venv/lib/python3.13/site-packages/rapidfuzz/utils.pyi": 7400725037332728015, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_numeric.py": 9383693732009547935, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf": 15094859289098837494, + "venv/lib/python3.13/site-packages/pandas/core/groupby/grouper.py": 18110568057754450953, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_longdouble.py": 9337218715436213122, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/test_decimal.py": 17811784255174057561, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_interval_array_equal.py": 15654625365223535344, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_indexing.py": 5910217172351020811, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_select.py": 17823338162428379468, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval.py": 8549680643865283913, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polybase.pyi": 15864712173815045309, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/util.py": 5252158959761945519, + "frontend/src/lib/components/layout/TopNavbar.svelte": 16593656019460608311, + "venv/lib/python3.13/site-packages/greenlet/tests/test_stack_saved.py": 7767924647054186572, + "venv/lib/python3.13/site-packages/rapidfuzz/utils_cpp.cpython-313-x86_64-linux-gnu.so": 16145829319198889672, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufuncs.pyi": 1808147181379894521, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_protocols.py": 5019018645804313814, + "venv/lib/python3.13/site-packages/pandas/core/arrays/__init__.py": 10460719978124302175, + "venv/lib/python3.13/site-packages/passlib/handlers/windows.py": 8969739861295277439, + "venv/lib/python3.13/site-packages/pygments/lexers/tls.py": 3552078393009383412, + "venv/lib/python3.13/site-packages/pygments/lexers/textfmts.py": 17438453283146671997, + "frontend/build/_app/immutable/chunks/ZvPSSfIA.js": 7807067580962053496, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_interpolate.py": 6154072863387383113, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_index.py": 4908727359687606870, + "frontend/src/lib/toasts.js": 199299975383904134, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv": 8710594949902856122, + "venv/lib/python3.13/site-packages/pandas/tests/window/conftest.py": 10673264126684571493, + "backend/src/scripts/delete_running_tasks.py": 7776896567014157554, + "backend/src/plugins/translate/orchestrator_sql_rows.py": 13473935462270832541, + "venv/lib/python3.13/site-packages/referencing/tests/__init__.py": 15130871412783076140, + "backend/tests/conftest.py": 5565151856098492311, + "venv/lib/python3.13/site-packages/numpy/polynomial/legendre.pyi": 2029639875417260268, + "venv/lib/python3.13/site-packages/PIL/MpoImagePlugin.py": 644327650732339301, + "backend/alembic_test.db": 14995253579408279707, + "backend/test.db": 15130871412783076140, + "backend/git_repos/remote/test-repo.git/objects/4f/4e0958b3a42eff67a2b8cfd084d05c43e54716": 6040513978194442637, + "venv/lib/python3.13/site-packages/jeepney/bus.py": 5163075760432139100, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/immutabledict.pxd": 13413785818999584986, + "venv/lib/python3.13/site-packages/pygments/lexers/jslt.py": 11805394130669644345, + "backend/src/plugins/translate/dictionary_correction.py": 18051915404774774954, + "backend/tests/services/clean_release/test_publication_service.py": 17277940125978730159, + "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.py": 13446184230476677032, + "venv/lib/python3.13/site-packages/numpy/_core/_methods.py": 16805668769357938792, + "venv/lib/python3.13/site-packages/pandas/core/interchange/utils.py": 11401792151107207834, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_apply.py": 11248068903302454630, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_crosstab.py": 6631711416347033281, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/methods/test_as_unit.py": 4283520188709399244, + "venv/lib/python3.13/site-packages/psycopg2/pool.py": 8855184580138330938, + "venv/lib/python3.13/site-packages/requests/certs.py": 16052880877156864882, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/setitem.py": 9552868454186447925, + "frontend/src/components/storage/FileList.svelte": 11661146151896000393, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/_stan_builtins.py": 1961875544235948177, + "venv/lib/python3.13/site-packages/cryptography/x509/base.py": 9124948989225782039, + "venv/lib/python3.13/site-packages/_pytest/capture.py": 17850967053989495422, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_asfreq.py": 6162659555626011770, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_repeat.py": 16971624301893342868, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_api.py": 13319208721442328400, + "venv/lib/python3.13/site-packages/rapidfuzz/process_cpp.py": 16797760903996739079, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/console.py": 3540660073442483692, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_hermite.py": 3628609433179387988, + "backend/src/core/task_manager/lifecycle.py": 1696300129247014205, + "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django.py": 3210697476292094384, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval.py": 18040371224712437126, + "venv/lib/python3.13/site-packages/fastapi/security/utils.py": 2616633862993539558, + "frontend/src/routes/settings/MigrationSettings.svelte": 7727089689198444946, + "frontend/build/_app/immutable/chunks/Bz99hFgy.js": 2788010001753617987, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/licenses/LICENSE": 3509878235770224233, + "backend/src/api/routes/assistant/_dataset_review.py": 14508672919199309579, + "venv/lib/python3.13/site-packages/pydantic/generics.py": 15019381413806459410, + "backend/src/services/clean_release/publication_service.py": 1882863137548904782, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_cat.py": 15988884721768567895, + "backend/src/plugins/translate/preview_prompt_builder.py": 2354938052590494405, + "venv/lib/python3.13/site-packages/pip/_internal/req/__init__.py": 12266077985828139928, + "venv/lib/python3.13/site-packages/pandas/tests/extension/decimal/__init__.py": 4761936067832638585, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_numpy.py": 9825804096508014886, + "frontend/src/routes/settings/notifications/+page.svelte": 14504217413720856827, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate_regression.py": 17425202198134409689, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/LCSseq.py": 13853220736499979380, + "venv/lib/python3.13/site-packages/jose/jws.py": 11592462993417182096, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_symbol.py": 10792387279408528886, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_counting.py": 5628494712451120258, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timezones.py": 8042029178538467146, + "venv/lib/python3.13/site-packages/pyasn1/type/tag.py": 13912273274509186651, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/padding.py": 7470483648602195268, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py": 18325640697829098192, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_fillna.py": 9297637486401098611, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py": 11185011314498348980, + "venv/lib/python3.13/site-packages/ecdsa/test_sha3.py": 12459459298663975730, + "venv/lib/python3.13/site-packages/pandas/conftest.py": 747626550806435763, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/bulk_persistence.py": 2307818727114646866, + "venv/lib/python3.13/site-packages/pip/_vendor/__init__.py": 11734104142988812647, + "venv/lib/python3.13/site-packages/pandas/tests/io/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/git/index/__init__.py": 7874728461616959441, + "venv/lib/python3.13/site-packages/pygments/lexers/console.py": 18266795648198475028, + "frontend/src/lib/components/translate/TranslationRunGlobalIndicator.svelte": 16210598715819306972, + "frontend/build/_app/immutable/nodes/14.DQdp2XM0.js": 13691839198161634025, + "backend/src/api/routes/storage.py": 17448492494022569347, + "venv/lib/python3.13/site-packages/numpy/_core/printoptions.pyi": 16758392990920041462, + "venv/lib/python3.13/site-packages/pyasn1/debug.py": 6305633719847955310, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numerictypes.py": 5719374287454872555, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf": 10893958728966010450, + "venv/lib/python3.13/site-packages/itsdangerous/exc.py": 11181421963755661477, + "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.py": 6348811074249398741, + "venv/lib/python3.13/site-packages/referencing/retrieval.py": 11921179805977833120, + "venv/lib/python3.13/site-packages/numpy/random/_mt19937.cpython-313-x86_64-linux-gnu.so": 85866616759631810, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_fileno.py": 15541504502174047167, + "venv/lib/python3.13/site-packages/pandas/core/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/util/_decorators.py": 14780166101442507665, + "venv/lib/python3.13/site-packages/numpy/_typing/_char_codes.py": 14162745886150625150, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/database.py": 7111764828004587758, + "venv/lib/python3.13/site-packages/pydantic/_internal/_utils.py": 10936299012115637790, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_monotonic.py": 11817523305776951162, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period_range.py": 9598872514187524706, + "venv/lib/python3.13/site-packages/keyring/compat/properties.py": 1562771115138037410, + "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending.py": 16515485226251040454, + "venv/lib/python3.13/site-packages/numpy/strings/__init__.py": 6523674574341354095, + "venv/lib/python3.13/site-packages/anyio/abc/_streams.py": 8089057973257658396, + "venv/lib/python3.13/site-packages/numpy/core/_dtype.py": 2806449741844148191, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi": 13850254283540522444, + "venv/lib/python3.13/site-packages/pandas/api/types/__init__.py": 3995030354191071797, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_arithmetic.py": 4858019700859362660, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_set_axis.py": 4097534573847151853, + "venv/lib/python3.13/site-packages/anyio/functools.py": 4300781896135050327, + "venv/lib/python3.13/site-packages/pydantic/tools.py": 8931184638883701008, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_arithmetic.py": 17427754419626622853, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_timedelta.py": 364160935264757405, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_exceptions.py": 15290185665769490169, + "venv/lib/python3.13/site-packages/pandas/io/formats/format.py": 3364941338174434661, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/writeonly.py": 14213960431308620600, + "venv/lib/python3.13/site-packages/apscheduler/util.py": 11440701924954413440, + "venv/lib/python3.13/site-packages/pygments/lexers/asc.py": 10744437946030875496, + "venv/lib/python3.13/site-packages/pygments/lexers/varnish.py": 3608370156692616959, + "venv/lib/python3.13/site-packages/py.py": 16248211404003181569, + "merge_spec.py": 5285945727297582371, + "venv/lib/python3.13/site-packages/itsdangerous/url_safe.py": 13454753900702274266, + "venv/lib/python3.13/site-packages/pip/_internal/utils/appdirs.py": 539688259643447487, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/test_array_with_attr.py": 6568496539994758985, + "frontend/src/routes/reports/llm/[taskId]/+page.svelte": 14881196548900101939, + "frontend/src/components/TaskLogViewer.svelte": 11262767195652916566, + "venv/lib/python3.13/site-packages/rsa/prime.py": 10820898885044917095, + "backend/src/api/routes/dashboards/_router.py": 8641007051243802224, + "backend/tests/services/clean_release/test_compliance_task_integration.py": 682622548217611215, + "backend/git_repos/remote/test-repo.git/objects/ee/59553241ef084b83d3351ba4c33caf2ed9a840": 11587106407031972706, + "scripts/scan_secrets.sh": 599173385111063848, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core": 10616484054735611337, + "venv/lib/python3.13/site-packages/PIL/WebPImagePlugin.py": 5378349556563611996, + "venv/lib/python3.13/site-packages/pygments/formatters/rtf.py": 5850574956253747036, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/_pytest/main.py": 931018496411984909, + "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.py": 15989335816452913951, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_autocorr.py": 1092316868398391792, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cython/extending.pyx": 756189645898997788, + "venv/lib/python3.13/site-packages/pygments/lexers/testing.py": 17148598391210353576, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_libgroupby.py": 9985769511561272200, + "venv/lib/python3.13/site-packages/gitdb/stream.py": 3035738824550231197, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_constructors.py": 979131987837682435, + "venv/lib/python3.13/site-packages/pillow.libs/libwebp-d8b9687f.so.7.2.0": 116215608212382352, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_overrides.py": 92685611709898742, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_parsing.py": 2228959015420278458, + "venv/lib/python3.13/site-packages/git/config.py": 1724894144987553201, + "venv/lib/python3.13/site-packages/numpy/random/_sfc64.pyi": 3536657185495782642, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/introspection.py": 14645217065508644154, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/sql.py": 13315906751371033170, + "venv/lib/python3.13/site-packages/fastapi/testclient.py": 2606236077497278662, + "venv/lib/python3.13/site-packages/numpy/_typing/__init__.py": 18242238390157333247, + "frontend/src/components/Toast.svelte": 4155277822937119359, + "backend/src/services/dataset_review/orchestrator_pkg/_commands.py": 15474996500928063708, + "venv/lib/python3.13/site-packages/pip/_internal/utils/hashes.py": 17310331665429541812, + "venv/lib/python3.13/site-packages/pydantic/_internal/_typing_extra.py": 14843908493613991959, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_cumulative.py": 11752712818547022872, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/__init__.py": 11414161642984633362, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/bitwise_ops.py": 14350609278188982939, + "venv/lib/python3.13/site-packages/pygments/styles/__init__.py": 18383248976818885498, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust.abi3.so": 2537152913308578487, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x32_unix.h": 9165722966153119887, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_promote.py": 16601872688404846307, + "venv/lib/python3.13/site-packages/PIL/_typing.py": 17407980360703360848, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/descriptor_props.py": 7044852927393650707, + "venv/lib/python3.13/site-packages/pygments/lexers/_lilypond_builtins.py": 1766946089314631488, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_truncate.py": 6478126371906156409, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_join.py": 17508073052750406350, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/nested_schemas.py": 4114645644496880787, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_count.py": 9186538441380080087, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize_py.py": 6518425342376455821, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_map.py": 10769974470610467636, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_openssl.py": 10446441599800965961, + "venv/lib/python3.13/site-packages/pip/_internal/distributions/base.py": 16714704323747942110, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/containers.py": 5969831151685016772, + "venv/lib/python3.13/site-packages/pillow.libs/libxcb-64009ff3.so.1.1.0": 7322566017497612912, + "venv/lib/python3.13/site-packages/annotated_doc/main.py": 3384049281532298500, + "venv/lib/python3.13/site-packages/pydantic/env_settings.py": 18250976255197243083, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/compat.py": 17520043776344667309, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ndarray_shape_manipulation.py": 12598431412396627042, + "venv/lib/python3.13/site-packages/numpy/typing/__init__.py": 3608665862759745048, + "venv/lib/python3.13/site-packages/numpy/random/_pcg64.pyi": 14785496840737986355, + "venv/lib/python3.13/site-packages/numpy/polynomial/hermite.py": 6617116180936986481, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_fillna.py": 4610666845291315333, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/exc.py": 3242780937124999391, + "venv/lib/python3.13/site-packages/PIL/report.py": 9428754440615681790, + "venv/lib/python3.13/site-packages/pandas/core/groupby/base.py": 16888506204910366302, + "venv/lib/python3.13/site-packages/PIL/PcfFontFile.py": 8867692961463798279, + "venv/lib/python3.13/site-packages/dateutil/_common.py": 12492546559232079071, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_old_ma.py": 18116460138221458026, + "venv/lib/python3.13/site-packages/pygments/lexers/tcl.py": 10343667975436015855, + "venv/lib/python3.13/site-packages/pandas/io/parsers/readers.py": 7899068668225389287, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_constructors.py": 1697610790604400105, + "venv/lib/python3.13/site-packages/PIL/TarIO.py": 13651401276968618561, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/automap.py": 4672057253309608464, + "venv/lib/python3.13/site-packages/websockets/legacy/http.py": 16266924390281399720, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_read_errors.py": 4559483361564472117, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_repr.py": 13147587049887075335, + "frontend/playwright-report/trace/index.BCnMPevh.js": 8625484717968740943, + "frontend/src/routes/dashboards/[id]/components/DashboardLinkedResources.svelte": 8279080994517688482, + "frontend/src/routes/git/+page.svelte": 14169430923974356254, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/AUTHORS": 3558407083075395848, + "venv/lib/python3.13/site-packages/numpy/_core/shape_base.py": 3996519099530770308, + "venv/lib/python3.13/site-packages/more_itertools/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/_vim_builtins.py": 6842381248727719900, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Indel.py": 17112989332785349705, + "venv/lib/python3.13/site-packages/passlib/handlers/sha2_crypt.py": 8171587560325812664, + "backend/src/core/mapping_service.py": 17981290763325170519, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_numeric_only.py": 13610631681447961840, + "venv/lib/python3.13/site-packages/passlib/tests/test_pwd.py": 10089138951415591061, + "venv/lib/python3.13/site-packages/ecdsa/test_ecdh.py": 3338834550392548171, + "venv/lib/python3.13/site-packages/pandas/compat/_constants.py": 3909166275649444824, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/quantile.py": 17341029201525362074, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timedelta/test_timedelta.py": 12822713918114715561, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_float.py": 10455718110956856820, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_period.py": 6255181868181182780, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/METADATA": 1684451390569121499, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/console.py": 10217327186846649646, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/html.tpl": 12550218314797699304, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/base.py": 3250660921154829815, + "frontend/src/components/PasswordPrompt.svelte": 13739802421315835398, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/hybrid.py": 14287665090144592501, + "backend/src/api/routes/assistant/_dataset_review_dispatch.py": 10108558091463171824, + "backend/src/api/routes/git/_merge_routes.py": 2019590524299108754, + "backend/src/services/maintenance/__init__.py": 3167476255502727608, + "backend/src/plugins/translate/_run_service.py": 1705461175389858266, + "venv/lib/python3.13/site-packages/cffi/_shimmed_dist_utils.py": 4824806157907607487, + "venv/lib/python3.13/site-packages/greenlet/TStackState.cpp": 16720079760074325527, + "dist/docker/frontend.0.1.0.tar.xz": 16011357094675100098, + "venv/lib/python3.13/site-packages/gitdb/__init__.py": 15381521749253695923, + "venv/lib/python3.13/site-packages/pip/_internal/cli/main_parser.py": 7942770969280622910, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_scalar_compat.py": 10068989979144965125, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_xs.py": 1897144171324167738, + "venv/lib/python3.13/site-packages/pip/_internal/index/sources.py": 11609272011565024668, + "venv/lib/python3.13/site-packages/numpy/lib/_arraypad_impl.pyi": 2186875333484796630, + "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/arrays/test_datetimes.py": 8863748366184419339, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/RECORD": 8201759541483070364, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/authorization_server.py": 17967809814827547139, + "venv/lib/python3.13/site-packages/numpy/core/shape_base.py": 17925759824894973734, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_constructors.py": 7466113171256856591, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_rank.py": 5817408252050193538, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/LICENSE": 6774760218010069963, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/cursor.py": 8074527784886981710, + "venv/lib/python3.13/site-packages/jsonschema/validators.py": 3832874295500213309, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_loongarch64_linux.h": 6566098590441297326, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_numba.py": 1668304729617150075, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_constructors.pyi": 4993066609272697419, + "venv/lib/python3.13/site-packages/fastapi/params.py": 14263655860695381481, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine_first.py": 11425059090050867171, + "frontend/build/_app/immutable/assets/0.C35F__rI.css": 18367119336440743976, + "venv/lib/python3.13/site-packages/pandas/util/_validators.py": 10201915528715968165, + "venv/lib/python3.13/site-packages/greenlet/tests/test_version.py": 6317733744899804292, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_combine.py": 4446011286411407708, + "venv/lib/python3.13/site-packages/httpcore/_backends/mock.py": 6849131425727092784, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_highlight.py": 7573043358244876807, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/introspection.py": 5447179017910128771, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_polybase.pyi": 3404315099794022355, + "venv/lib/python3.13/site-packages/pandas/core/arrays/datetimelike.py": 394614958716301173, + "venv/lib/python3.13/site-packages/typing_extensions.py": 8402965285733247527, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_add_prefix_suffix.py": 8367793476246001244, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_orm_types.py": 5508682532707462217, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/pyodbc.py": 8175468565413744516, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/__init__.py": 1398617034174236358, + "venv/lib/python3.13/site-packages/jeepney/io/trio.py": 11859775321483330469, + "venv/lib/python3.13/site-packages/pydantic/_internal/_repr.py": 1758478941817868344, + "venv/lib/python3.13/site-packages/pygments/lexers/math.py": 1647133236144311250, + "frontend/playwright-report/trace/manifest.webmanifest": 565917384317025203, + "venv/lib/python3.13/site-packages/greenlet/TThreadState.hpp": 15599148954148720463, + "venv/lib/python3.13/site-packages/pandas/core/ops/__init__.py": 4049432353810047365, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/coercions.py": 5112358449376598662, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/array.py": 7437107031079833232, + "venv/lib/python3.13/site-packages/starlette/authentication.py": 10905269573809129547, + "venv/lib/python3.13/site-packages/numpy/lib/recfunctions.py": 3001896031623204147, + "venv/lib/python3.13/site-packages/pygments/lexers/func.py": 12257919753150082714, + "venv/lib/python3.13/site-packages/_pytest/config/compat.py": 13175516717549204627, + "venv/lib/python3.13/site-packages/websockets/speedups.c": 11800200877763464246, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_string.py": 9224234539232195189, + "venv/lib/python3.13/site-packages/pydantic/v1/_hypothesis_plugin.py": 6383299780629629080, + "venv/lib/python3.13/site-packages/sqlalchemy/util/preloaded.py": 3719702436309355562, + "venv/lib/python3.13/site-packages/_pytest/stash.py": 14430252294763173610, + "venv/lib/python3.13/site-packages/_pytest/pastebin.py": 13946273207624603063, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_assignability.pyi": 1718610984396277997, + "venv/lib/python3.13/site-packages/passlib/tests/utils.py": 15403198680231294263, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/index.py": 2763962019423787504, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_droplevel.py": 2071197388394658690, + "venv/lib/python3.13/site-packages/numpy/testing/overrides.py": 11819432487830192978, + "backend/src/api/routes/migration.py": 6030566471113208264, + "backend/src/models/__tests__/test_report_models.py": 18076243829002249148, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/base.py": 10200916670889920659, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py": 18069619555394133945, + "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/arrays/categorical/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/websockets/sync/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_strings.py": 17398806130402098912, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/jupyter.py": 4446535289156468239, + "venv/lib/python3.13/site-packages/PIL/ImageOps.py": 3884310863548175682, + "venv/lib/python3.13/site-packages/gitdb/const.py": 14122142034887286559, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_compat.py": 11481259393140789881, + "venv/lib/python3.13/site-packages/pygments/lexers/scdoc.py": 8481749542463754279, + "venv/lib/python3.13/site-packages/PIL/PsdImagePlugin.py": 4347581352716313298, + "backend/src/plugins/translate/scheduler.py": 13413202759986193820, + "backend/tests/test_smoke_app.py": 7819901244710945164, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/__init__.py": 3247870839323520754, + "backend/git_repos/remote/test-repo.git/objects/a1/3525f5f44e26d8fbec3226bd488d14793575a2": 3742572048019652365, + "venv/lib/python3.13/site-packages/click/types.py": 6491651131669287534, + "venv/lib/python3.13/site-packages/rapidfuzz/process.pyi": 6959881293311340830, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_unix.h": 9608771997528633681, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py": 6109201994963211857, + "venv/lib/python3.13/site-packages/authlib/oauth1/errors.py": 1154126353335030046, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/pyproject.py": 12684373765476932108, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/warnings_and_errors.pyi": 9019577563960071498, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm64_masm.asm": 16630507336149184509, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/modules.pyi": 14176187662591164602, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_utils.py": 4612923732868929770, + "venv/lib/python3.13/site-packages/pandas/core/arrays/sparse/array.py": 3517673819082574078, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_indexing.py": 16623126293364224089, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_logical_ops.py": 4438104524064299182, + "venv/lib/python3.13/site-packages/numpy/_core/shape_base.pyi": 10225243791643474943, + "venv/lib/python3.13/site-packages/numpy/_typing/_scalars.py": 17701938912160369190, + "venv/lib/python3.13/site-packages/pandas/_testing/__init__.py": 10127496080404419481, + "venv/lib/python3.13/site-packages/pyasn1/type/namedval.py": 8273171503516887681, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/token.py": 11655733747403312358, + "venv/lib/python3.13/site-packages/passlib/handlers/des_crypt.py": 15304795681178011265, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/functions.py": 16567226076808693246, + "venv/lib/python3.13/site-packages/multipart/__init__.py": 6496114190873890851, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_fields.py": 16222559851336781264, + "venv/lib/python3.13/site-packages/urllib3/connection.py": 12761371748350595804, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_real/foo90.f90": 58572216018544419, + "venv/lib/python3.13/site-packages/pygments/styles/rrt.py": 9490973359165080360, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/__init__.py": 63497920264089252, + "venv/lib/python3.13/site-packages/pandas/api/executors/__init__.py": 16954693181142010028, + "venv/lib/python3.13/site-packages/requests/help.py": 1885413874621672882, + "venv/lib/python3.13/site-packages/pygments/lexers/ruby.py": 6898093948224302592, + "frontend/src/lib/components/layout/Breadcrumbs.svelte": 10874106485242690185, + "backend/src/core/logger.py": 12787152815342378434, + "venv/lib/python3.13/site-packages/pydantic/_internal/_decorators.py": 9928398334052202841, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py": 4301355720042319835, + "venv/lib/python3.13/site-packages/_pytest/runner.py": 5772610501857496741, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/col.py": 4221271461723119525, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh17797.f90": 17319074662077763768, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_get_value.py": 389530025760539462, + "venv/lib/python3.13/site-packages/pydantic/experimental/missing_sentinel.py": 1637241331832367709, + "venv/lib/python3.13/site-packages/gitdb/db/ref.py": 1176701624460337371, + "backend/src/api/routes/profile.py": 11866770263441371105, + "venv/lib/python3.13/site-packages/apscheduler/triggers/cron/__init__.py": 14268033439436797364, + "venv/lib/python3.13/site-packages/click/_compat.py": 14451519072991457993, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/linalg.pyi": 7217817172953767893, + "venv/lib/python3.13/site-packages/numpy/_core/fromnumeric.py": 9409852116555866847, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/distro.py": 12494639376332486204, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_update.py": 12293424926920594944, + "venv/lib/python3.13/site-packages/_pytest/hookspec.py": 387790426108810884, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/engine.py": 2652248727360250985, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/pygments/lexers/_tsql_builtins.py": 829193091321611630, + "frontend/src/routes/settings/automation/+page.svelte": 17397435134589275932, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssl_.py": 644667973700652263, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/licenses/LICENSE": 16147999986886816451, + "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/testing.pyi": 16263777835572515739, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90": 5765181406654284736, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_indexing.py": 9862204223281834360, + "frontend/src/lib/components/DashboardMaintenanceBadge.svelte": 9085495636438661604, + "venv/lib/python3.13/site-packages/attr/_typing_compat.pyi": 2823472697859409877, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/sync_openid.py": 5670082466989878756, + "venv/lib/python3.13/site-packages/pygments/styles/_mapping.py": 11752660241391232497, + "backend/src/plugins/search.py": 888817404897740233, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_partial_slicing.py": 15567512240469921599, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_drop.py": 15751236355035730554, + "backend/src/plugins/translate/service_datasource.py": 10240814407336170041, + "venv/lib/python3.13/site-packages/click/_textwrap.py": 14586282603215052310, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/asyncmy.py": 11808138763443525443, + "venv/lib/python3.13/site-packages/charset_normalizer/utils.py": 11724147997933584095, + "backend/git_repos/remote/test-repo.git/objects/c5/b992984fe856bd81206304a881faa3087937cf": 2441623644664166468, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_setops.py": 13440916133402971190, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_parse_dates.py": 5344929031479212951, + "venv/lib/python3.13/site-packages/fastapi/concurrency.py": 17937688838625807004, + "venv/lib/python3.13/site-packages/secretstorage/dhcrypto.py": 8860116996905452758, + "venv/lib/python3.13/site-packages/numpy/ma/testutils.py": 9355402483340137461, + "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.py": 14696841109142419143, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/einsumfunc.py": 9944042006439149561, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multithreading.py": 12547048606098186681, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/__init__.py": 5118993772178969104, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_sparc_sun_gcc.h": 2915128971664712180, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_reindex.py": 15794750188594767026, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/constructors.py": 7587476800569414769, + "venv/lib/python3.13/site-packages/PIL/DdsImagePlugin.py": 10646832373516499548, + "venv/lib/python3.13/site-packages/numpy/char/__init__.pyi": 12214207343146244743, + "venv/lib/python3.13/site-packages/_pytest/_io/pprint.py": 11202117031437223527, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_resampler_grouper.py": 8388490036390951341, + "venv/lib/python3.13/site-packages/authlib/jose/util.py": 14843923624043422219, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/diagnose.py": 17275977405061138181, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/utils.py": 2959395751217827103, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/__init__.py": 17194870661869873083, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/__init__.py": 12911374670789466961, + "venv/lib/python3.13/site-packages/pycparser/ast_transforms.py": 9032453625977464506, + "frontend/src/lib/components/layout/__tests__/test_topNavbar.svelte.js": 11053755879172333925, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/shared.py": 1162754506656505196, + "frontend/src/routes/maintenance/+page.svelte": 13247950766849520966, + "frontend/src/routes/dashboards/[id]/+page.svelte": 12833231703682809118, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_operators.py": 12686786829906210592, + "venv/lib/python3.13/site-packages/pandas/core/indexes/range.py": 3838277376774246164, + "backend/src/plugins/translate/superset_executor.py": 5480256123348033488, + "backend/src/plugins/translate/_llm_http.py": 15686826696693103176, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_partial_indexing.py": 4132091154215910029, + "venv/lib/python3.13/site-packages/pandas/core/apply.py": 17080038932032802984, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_quantile.py": 11273403743157110261, + "venv/lib/python3.13/site-packages/keyring/backends/Windows.py": 4103830951042463184, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/licenses/LICENSE": 17020744174398828059, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_repr.py": 16609300578827398344, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/bar.py": 12859947592168238832, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_libalgos.py": 13934861984871432400, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_partial.py": 15129217814262096441, + "frontend/playwright-report/trace/assets/codeMirrorModule-Ds_H_9Yq.js": 1369559823166915102, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_pickle.py": 4216445955812104014, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_period.py": 3419297908709788013, + "frontend/playwright-report/data/cc5452f8d8c308a176676866ee06628a569362aa.zip": 18382826147717299104, + "venv/lib/python3.13/site-packages/numpy/fft/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py": 12693210357718751894, + "venv/lib/python3.13/site-packages/pandas/core/internals/__init__.py": 1377108808392195313, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_stack_unstack.py": 3737891757817696405, + "frontend/src/lib/stores/__tests__/assistantChat.test.js": 11822882112255142537, + "venv/lib/python3.13/site-packages/pygments/lexers/clean.py": 17772169928835025327, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate_nonkeyword_arguments.py": 11676809974120007408, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_arrayprint.py": 13335063050941743734, + "backend/src/api/routes/git/_repo_lifecycle_routes.py": 6605622512801609889, + "venv/lib/python3.13/site-packages/passlib/tests/sample_config_1s.cfg": 1809713544666311828, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_format.py": 16150524965028369071, + "backend/tests/test_logger.py": 11506419828617508917, + "venv/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/__init__.py": 17630019785411546070, + "venv/lib/python3.13/site-packages/ecdsa/ssh.py": 17010933326090778158, + "venv/lib/python3.13/site-packages/httpx/_decoders.py": 14478643473006178492, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/terminal_theme.py": 13727399800263579809, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/lib/format.py": 14971167445246135440, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_arrow_string_mixins.py": 16862663427780315543, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_map.py": 32086858815359344, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_byteswap.py": 5090287710338893350, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_unary.py": 7128845965976836334, + "venv/lib/python3.13/site-packages/pygments/lexers/_qlik_builtins.py": 1728058904137960444, + "frontend/src/lib/stores.js": 8062876368729352764, + "frontend/src/lib/components/translate/ScheduleConfig.svelte": 9548866160759602637, + "venv/lib/python3.13/site-packages/pandas/core/missing.py": 13332302791063948992, + "venv/lib/python3.13/site-packages/fastapi/security/__init__.py": 1345944646061334046, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/contains.py": 3098087827310439993, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame.py": 16757570551941104401, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_fillna.py": 13675584998644907265, + "venv/lib/python3.13/site-packages/dateutil/tz/_factories.py": 7538654189286887518, + "backend/src/plugins/translate/__tests__/test_dictionary_import.py": 828852818135096215, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_cell_widths.py": 5724379364993806351, + "venv/lib/python3.13/site-packages/numpy/lib/user_array.pyi": 1968484998382771986, + "venv/lib/python3.13/site-packages/pandas/tests/libs/test_hashtable.py": 7762405492052106717, + "venv/lib/python3.13/site-packages/PIL/ExifTags.py": 6869879826623916830, + "backend/src/__init__.py": 11250920420388310655, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi": 3893434234020223151, + "backend/git_repos/remote/test-repo.git/objects/17/66251d8cb2693136e09ea3def3e776559cb722": 1137762010493457272, + "backend/src/plugins/translate/dictionary.py": 2903767700173238799, + "venv/lib/python3.13/site-packages/httpx/_auth.py": 1283189552342958900, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_timedeltas.py": 4118671843063545221, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_pop.py": 5700439923973346681, + "venv/lib/python3.13/site-packages/pandas/tests/util/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv": 12896264205153363031, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.asm": 15349921092257597740, + "venv/lib/python3.13/site-packages/pygments/lexers/idl.py": 11454152060351801696, + "frontend/build/_app/immutable/chunks/rzyp_Wbp.js": 10559672264716197308, + "venv/lib/python3.13/site-packages/pandas/core/groupby/__init__.py": 3015263524218708013, + "venv/lib/python3.13/site-packages/pygments/lexers/_openedge_builtins.py": 4979988747924637739, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/wait.py": 6196757964348666082, + "backend/src/models/dataset_review_pkg/_mapping_models.py": 8898456326244890685, + "venv/lib/python3.13/site-packages/pip/_internal/operations/install/editable_legacy.py": 8145740626773638218, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/__init__.py": 2246704695838251846, + "venv/lib/python3.13/site-packages/pydantic_settings/version.py": 17263591404988984480, + "venv/lib/python3.13/site-packages/numpy/lib/_histograms_impl.pyi": 6534825471013879522, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/fixed_string.f90": 8654788371538544793, + "venv/lib/python3.13/site-packages/numpy/_core/function_base.py": 5676611841071163854, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_interval_pyarrow.py": 3849382723890414899, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/METADATA": 13776251749114562660, + "venv/lib/python3.13/site-packages/pip/_internal/cli/status_codes.py": 9143625681947330756, + "venv/lib/python3.13/site-packages/numpy/_typing/_extended_precision.py": 4201820494689784136, + "venv/lib/python3.13/site-packages/cffi/recompiler.py": 17809252277700094304, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7591/endpoint.py": 13389763148720370546, + "venv/lib/python3.13/site-packages/uvicorn/protocols/__init__.py": 15130871412783076140, + "backend/src/schemas/validation.py": 11881058653924000699, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/cli.py": 6382193953727339271, + "backend/src/services/clean_release/repositories/manifest_repository.py": 12395698948312301073, + "venv/lib/python3.13/site-packages/pandas/_libs/parsers.cpython-313-x86_64-linux-gnu.so": 14134106903573638108, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA_py.py": 2494967094400350388, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_array.f90": 9711940829820746513, + "venv/lib/python3.13/site-packages/numpy/_core/_string_helpers.pyi": 12043292763005874815, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_common.py": 3559416690270529904, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_timezones.py": 1962830142478494009, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_iterator.py": 13869355993837330406, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/conftest.py": 12368472226536104037, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/secrets.py": 17816662030600756342, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90": 8308927438994838783, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_base_indexer.py": 3129123098288498633, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/PIL/FliImagePlugin.py": 13364963053197422923, + "venv/lib/python3.13/site-packages/git/compat.py": 16843345645628515492, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mysqldb.py": 2138006249556140141, + "backend/git_repos/remote/test-repo.git/objects/c2/491dfd8c841bacd5f491510f6334aa4a626f00": 6297303620364618482, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_style.py": 10405592363651914796, + "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.pyi": 15848834171197104301, + "venv/lib/python3.13/site-packages/urllib3/http2/__init__.py": 62108352209996836, + "venv/lib/python3.13/site-packages/pygments/lexers/data.py": 9365024327689738663, + "backend/src/services/__tests__/test_resource_service.py": 13275183651826747527, + "backend/tests/test_task_persistence.py": 1764267414712263025, + "venv/lib/python3.13/site-packages/pandas/_libs/algos.pyi": 22405377601029952, + "venv/lib/python3.13/site-packages/pandas/core/nanops.py": 18291534943985310005, + "venv/lib/python3.13/site-packages/websockets/uri.py": 264376168984862773, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_numpy.py": 4073641912755651877, + "venv/lib/python3.13/site-packages/pandas/io/json/_table_schema.py": 3103776773020058805, + "venv/lib/python3.13/site-packages/git/repo/__init__.py": 6173604284490891047, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/LICENSE": 6581019367004699816, + "venv/lib/python3.13/site-packages/pycparser/ply/ctokens.py": 1599952198962458730, + "venv/lib/python3.13/site-packages/httpcore/_backends/trio.py": 8394426709857317737, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_cumulative.py": 8178093067175155877, + "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.pyi": 3111521453255595221, + "venv/lib/python3.13/site-packages/jeepney-0.9.0.dist-info/METADATA": 15225661995655327539, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/__init__.py": 9083396324667433335, + "venv/lib/python3.13/site-packages/pygments/formatters/latex.py": 7514533384468139434, + "venv/bin/jsonschema": 16516374846693491442, + "frontend/src/routes/reports/+page.svelte": 17831076184881844976, + "frontend/src/components/git/GitManager.svelte": 2759220622954168718, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/decoder.py": 12653470212935324322, + "backend/src/plugins/translate/preview_resolve_provider.py": 7349483761713339246, + "venv/lib/python3.13/site-packages/anyio/streams/memory.py": 11762722143503428823, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_at_time.py": 15352346149584081864, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_cut.py": 7800833253841657380, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/tags.py": 254599446317461188, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv": 1443087417808027268, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/base.py": 3628510830969664111, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_setops.py": 10550603120090683350, + "venv/lib/python3.13/site-packages/_pytest/warnings.py": 8633394774569709013, + "venv/lib/python3.13/site-packages/pip/_internal/cli/base_command.py": 10660882478126415399, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/METADATA": 2810323639884879396, + "venv/lib/python3.13/site-packages/pandas/core/config_init.py": 16537122488227845090, + "venv/lib/python3.13/site-packages/pygments/lexers/teraterm.py": 16132676290138105984, + "frontend/src/routes/settings/__tests__/settings_page.integration.test.js": 4898515600493251972, + "venv/lib/python3.13/site-packages/fastapi/_compat/may_v1.py": 9880083742927480960, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_searchsorted.py": 12074107109575676897, + "backend/src/plugins/llm_analysis/scheduler.py": 14673660738877638091, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/RECORD": 13494296690334916257, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/licenses/LICENSE": 3868190977070717994, + "venv/lib/python3.13/site-packages/pip/_internal/utils/filesystem.py": 7716285033598020316, + "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini": 1071371630695963467, + "venv/lib/python3.13/site-packages/yaml/resolver.py": 6669674521776449098, + "backend/git_repos/remote/test-repo.git/objects/4e/227f4d8289ea657ae813b1460f979ae4b676b3": 5659284628452785331, + "venv/lib/python3.13/site-packages/psycopg2/_ipaddress.py": 12332672835751787869, + "backend/src/scripts/seed_permissions.py": 17005340106913955508, + "frontend/src/routes/profile/+page.svelte": 17979719303737794427, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/WHEEL": 13232065379159720345, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/__init__.py": 371829636800613137, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/RECORD": 16874983218652404911, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_half.py": 3121836756584726126, + "venv/lib/python3.13/site-packages/fastapi/middleware/wsgi.py": 3706578020491442104, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/connection.py": 5582413226288987808, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_convert_dtypes.py": 13612212066710266457, + "backend/src/core/auth/jwt.py": 15575717945774687118, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7592/endpoint.py": 18260428408051728802, + "venv/lib/python3.13/site-packages/_pytest/_code/source.py": 9488112979192923739, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/structures.py": 2668010839316715865, + "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.pyi": 8195943561787777127, + "backend/src/api/routes/__tests__/test_clean_release_api.py": 11565478953155085157, + "backend/src/services/clean_release/__tests__/test_report_builder.py": 14655761033823243898, + "venv/lib/python3.13/site-packages/click/decorators.py": 2920877667855377423, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/encoder.py": 120921270972591880, + "venv/lib/python3.13/site-packages/pip/_internal/utils/filetypes.py": 4415340223268174913, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_version.py": 849232015288488204, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__iotools.py": 6260912730310453037, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test__version.py": 9037916251087760255, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/syntax.py": 18070449217682341495, + "venv/lib/python3.13/site-packages/numpy/_core/arrayprint.py": 1262543237476191714, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_periodindex.py": 13430003945574795792, + "venv/lib/python3.13/site-packages/pip/_internal/utils/retry.py": 15244280495983216204, + "venv/lib/python3.13/site-packages/httpcore/_async/http11.py": 7565741048880549265, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_s3.py": 17425535047477778484, + "venv/lib/python3.13/site-packages/pygments/lexers/arturo.py": 4565524340706235725, + "venv/lib/python3.13/site-packages/pygments/lexers/graphql.py": 2307854666015224677, + "frontend/build/_app/immutable/chunks/b6ODGUZr.js": 3762567609123440186, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth1_client.py": 3129955464287331242, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/rec.pyi": 9140655366667421698, + "venv/lib/python3.13/site-packages/keyring/backend_complete.zsh": 14339032329370660432, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/response.py": 15004896908941411698, + "venv/lib/python3.13/site-packages/pip/_internal/models/candidate.py": 3099785363867247334, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/pcg64dxsm-testset-2.csv": 16611724551361692999, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/schema.py": 8358664670620586363, + "venv/lib/python3.13/site-packages/git/objects/util.py": 691018806932355307, + "frontend/src/routes/settings/__tests__/settings_page.ux.test.js": 12159582682619630694, + "backend/:memory:test_auth": 1309242367339970214, + "backend/git_repos/remote/test-repo.git/info/exclude": 6403833611826357791, + "venv/lib/python3.13/site-packages/PIL/GribStubImagePlugin.py": 14954946414134984896, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_box_unbox.py": 7579587620530953711, + "venv/lib/python3.13/site-packages/apscheduler/triggers/date.py": 9545774812177853725, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/comparisons.py": 7327629888601690759, + "frontend/playwright-report/trace/sw.bundle.js": 10879347794748701702, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_datetime.py": 4179112383995346046, + "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/pass/multiarray.py": 3224049574922696945, + "venv/lib/python3.13/site-packages/pygments/lexers/_lua_builtins.py": 12653747099659257203, + "venv/lib/python3.13/site-packages/pandas/core/common.py": 14578909424716153057, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_astype.py": 6578539240745332772, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_frame.py": 9378623452601244234, + "venv/lib/python3.13/site-packages/pandas/tests/construction/__init__.py": 15130871412783076140, + "frontend/src/lib/components/layout/__tests__/sidebarNavigation.test.js": 8459006438402290167, + "backend/src/services/clean_release/manifest_builder.py": 10633987497931832162, + "backend/src/services/clean_release/stages/base.py": 344723354852893815, + "venv/lib/python3.13/site-packages/authlib/oidc/registration/__init__.py": 9448552677419908109, + "venv/lib/python3.13/site-packages/pip/__pip-runner__.py": 1138979712722199296, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_frame_color.py": 3700828402084646308, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_constructors.py": 9767900500541600486, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/__init__.py": 15735839022111230173, + "venv/lib/python3.13/site-packages/_pytest/cacheprovider.py": 5114545353355728201, + "frontend/build/index.html": 9441612921158753253, + "frontend/src/lib/components/reports/ReportDetailPanel.svelte": 16014663571033060148, + "venv/lib/python3.13/site-packages/pygments/lexers/ptx.py": 4855144232064607995, + "backend/src/core/scheduler.py": 3824665790179894336, + "venv/lib/python3.13/site-packages/pip/_internal/req/constructors.py": 17485271035479378662, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_character.py": 17168707712220699738, + "venv/lib/python3.13/site-packages/pandas/core/arrays/boolean.py": 8821671562937866269, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ufunc_config.pyi": 11754104063443791746, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/keyring/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/implicit.py": 7379110378465568776, + "venv/lib/python3.13/site-packages/cryptography/hazmat/__init__.py": 6534110674636458866, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_unique.py": 16285418015531891530, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_compression.py": 8061288329598682752, + "frontend/src/lib/components/layout/Sidebar.svelte": 8588237337148619706, + "venv/lib/python3.13/site-packages/secretstorage/item.py": 15486045386471912693, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/utils.py": 9959199071030996679, + "venv/lib/python3.13/site-packages/websockets/frames.py": 4901850477414613953, + "venv/lib/python3.13/site-packages/pip/_internal/commands/cache.py": 1892313355296776523, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_util.py": 13997184496924925110, + "frontend/src/lib/ui/Button.svelte": 921807193049478213, + "venv/lib/python3.13/site-packages/numpy/typing/tests/test_typing.py": 10311989961588249147, + "venv/lib/python3.13/site-packages/greenlet/tests/test_greenlet.py": 10727595500186011102, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/func2subr.py": 338595621218646492, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/requirements.py": 2362917888844255805, + "venv/lib/python3.13/site-packages/websockets/imports.py": 1995356703044158461, + "venv/lib/python3.13/site-packages/websockets/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_dists.py": 16746363359320577809, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/tree.py": 4991806303236874829, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/simple.py": 11050636051019777317, + "venv/lib/python3.13/site-packages/numpy/polynomial/laguerre.pyi": 11310761736182213265, + "venv/lib/python3.13/site-packages/pandas/tests/resample/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_astype.py": 15768655715952923925, + "frontend/public/vite.svg": 13568221685541582385, + "venv/lib/python3.13/site-packages/pandas/core/indexes/api.py": 13750417165301467381, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/filewrapper.py": 17786759398959482432, + "backend/src/core/task_manager/context.py": 17543992255093146942, + "venv/lib/python3.13/site-packages/pandas/_libs/json.pyi": 10989301892466547548, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/WHEEL": 7454950858448014158, + "venv/lib/python3.13/site-packages/starlette/applications.py": 13591448461234020757, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/subversion.py": 7423946096970870727, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayprint.py": 5912583751693302370, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/unrolled.py": 12651425412640834530, + "venv/lib/python3.13/site-packages/pandas/_config/dates.py": 3863381688916127265, + "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.py": 9654828595008925976, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_diff.py": 2216748778018882333, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_dropna.py": 3168969662216766293, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/specifiers.py": 12284901056355482991, + "venv/lib/python3.13/site-packages/numpy/random/_generator.pyi": 17167649524261942483, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reindex.py": 12459492712890114705, + "venv/lib/python3.13/site-packages/dateutil/parser/isoparser.py": 18015430204844361067, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90": 6123192245816905092, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.pyi": 7410507092040239447, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/jws.py": 7505219131537941130, + "venv/lib/python3.13/site-packages/numpy/core/function_base.py": 12696640832638144604, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_constructors.py": 2786493777737472376, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_getitem.py": 8414677531950073373, + "backend/src/core/utils/__init__.py": 12454773556575864508, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_setops.py": 14246225281428284850, + "backend/src/plugins/maintenance_banner.py": 13535851937983395493, + "venv/lib/python3.13/site-packages/smmap/test/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_sequence.py": 3721630758772772345, + "venv/lib/python3.13/site-packages/pygments/lexers/typoscript.py": 6706632522710582762, + "venv/lib/python3.13/site-packages/cffi/pkgconfig.py": 16057517851163939571, + "venv/lib/python3.13/site-packages/cryptography/hazmat/asn1/__init__.py": 4290669519959060720, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/RECORD": 11976403473353722969, + "venv/lib/python3.13/site-packages/python_multipart/exceptions.py": 5971058243218049183, + "venv/lib/python3.13/site-packages/numpy/random/__init__.py": 11732100564412485633, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/holiday/test_federal.py": 16758212916399857971, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_union_categoricals.py": 6843679254735807, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_ints.py": 5616705208267050659, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/_orm_constructors.py": 4276726508722638048, + "venv/lib/python3.13/site-packages/itsdangerous/signer.py": 3694661094753475840, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/parameters.py": 5104015814292812973, + "backend/src/services/validation_service.py": 4040391162969506763, + "venv/lib/python3.13/site-packages/pip/_internal/commands/__init__.py": 3795218871212151351, + "backend/src/core/__tests__/test_superset_profile_lookup.py": 2078836378584435447, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py": 63497920264089252, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/min_max_.py": 13457611930368041821, + "backend/src/plugins/translate/__tests__/test_dictionary_filter.py": 2426844436521732941, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reindex.py": 8772423071604000084, + "backend/git_repos/remote/test-repo.git/objects/00/fcf77cecdf261aef91eda792ab3384a3339922": 1527330822006618217, + "venv/lib/python3.13/site-packages/cryptography/fernet.py": 10137792148038140630, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.pyi": 2101854548535776875, + "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/sqlalchemy/engine/characteristics.py": 2916810597149066609, + "venv/lib/python3.13/site-packages/sqlalchemy/types.py": 15819795572817819102, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/arrayprint.pyi": 2424868797160722318, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_timestamp_method.py": 11393911418463808195, + "venv/lib/python3.13/site-packages/pandas/core/computation/expr.py": 13085709365673019494, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_libfrequencies.py": 16302676625743291594, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_numpy.py": 222383250675686477, + "venv/lib/python3.13/site-packages/pydantic/deprecated/copy_internals.py": 1245428320513062166, + "venv/lib/python3.13/site-packages/passlib/exc.py": 15559705487889657091, + "venv/lib/python3.13/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini": 16151597765994697599, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/type_api.py": 10299750173867399533, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv": 9287774220881887502, + "venv/bin/dotenv": 953953349803507198, + "venv/lib/python3.13/site-packages/greenlet/greenlet_thread_support.hpp": 7773996382104849037, + "venv/lib/python3.13/site-packages/idna/package_data.py": 6583909243002417298, + "venv/lib/python3.13/site-packages/pandas/api/typing/aliases.py": 11194270368147942988, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/WHEEL": 2357997949040430835, + "backend/src/plugins/translate/__tests__/test_dictionary_utils.py": 12007616543185225081, + "venv/lib/python3.13/site-packages/jsonschema/tests/fuzz_validate.py": 2328585939822059352, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/__init__.py": 913610541217778747, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_assumed_shape.py": 18361009188431483164, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_recfunctions.py": 16014503284544747867, + "venv/lib/python3.13/site-packages/pandas/core/series.py": 11618272682977710696, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_join.py": 2585969863606902743, + "venv/lib/python3.13/site-packages/pygments/modeline.py": 6194365452131561478, + "venv/lib/python3.13/site-packages/fastapi/openapi/models.py": 1680354178147364813, + "venv/bin/fastapi": 12400009726251862770, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/__init__.py": 71159121705871510, + "venv/lib/python3.13/site-packages/numpy/linalg/__init__.py": 15647756307608142577, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/cymysql.py": 5570881524647789741, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90": 12508663906609241323, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/serializer.py": 8708767945343850816, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/fields.cpython-313-x86_64-linux-gnu.so": 16927263232848238698, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_na_indexing.py": 8712547126522523899, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_return_complex.py": 4290059580478881700, + "venv/lib/python3.13/site-packages/pandas/tests/test_multilevel.py": 10500316376521962061, + "frontend/src/lib/auth/store.ts": 14669655798912377598, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py": 3960540415600165213, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/__init__.py": 10470644151952252331, + "backend/src/core/migration/__init__.py": 13075189211840127611, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_pbkdf2.py": 17016810698578473773, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_infer_objects.py": 16868563755487479303, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/pyodbc.py": 4146960201984489604, + "frontend/build/favicon.png": 16740551781088792605, + "backend/src/plugins/translate/__tests__/test_scheduler.py": 11257332466578758156, + "venv/lib/python3.13/site-packages/pandas/core/reshape/pivot.py": 4736553530021653868, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/pretty.py": 2448541115957861214, + "venv/lib/python3.13/site-packages/jose/backends/rsa_backend.py": 13507186353881931758, + "venv/lib/python3.13/site-packages/pygments/styles/emacs.py": 4540417536507245024, + "venv/lib/python3.13/site-packages/pydantic/_internal/_dataclasses.py": 15256193972947054890, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth2/signals.py": 10390443713463805090, + "frontend/src/app.css": 3020720639702954139, + "venv/lib/python3.13/site-packages/pyasn1/type/univ.py": 7163437624197683039, + "backend/src/api/routes/validation.py": 13836068409484617547, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_time_grouper.py": 3203729024111501071, + "venv/lib/python3.13/site-packages/httpcore/_async/http_proxy.py": 13364803556177997526, + "backend/src/models/clean_release.py": 6080208142954589647, + "frontend/src/lib/components/translate/CorrectionCell.svelte": 14340498120654577399, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_clearing_run_switches.py": 3020294789560975101, + "venv/lib/python3.13/site-packages/pygments/lexers/objective.py": 10966124906622044512, + "venv/lib/python3.13/site-packages/numpy/__init__.pyi": 15820654525292895396, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/timeseries.py": 17641722582848932332, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/test_transform.py": 5674175311567817854, + "venv/lib/python3.13/site-packages/pandas/_libs/arrays.pyi": 12629806207276576877, + "venv/lib/python3.13/site-packages/httpcore/_async/http2.py": 16350817785499681224, + "frontend/src/lib/api/maintenance.js": 17611932083877701146, + "frontend/src/routes/settings/+page.svelte": 10122073858307249759, + "venv/lib/python3.13/site-packages/apscheduler/triggers/base.py": 1170652622104554892, + "frontend/build/_app/immutable/nodes/9.C5HoT9pt.js": 3952586507302745635, + "backend/src/scripts/test_dataset_dashboard_relations.py": 11883199369340933897, + "venv/lib/python3.13/site-packages/jaraco_functools-4.4.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pandas/_libs/internals.pyi": 11662356720550765508, + "venv/lib/python3.13/site-packages/numpy/core/overrides.pyi": 1968648615494204783, + "venv/lib/python3.13/site-packages/starlette/middleware/errors.py": 1337979724602864440, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_collections.py": 7772437080414835462, + "frontend/src/routes/datasets/review/ReviewWorkspaceHeader.svelte": 15302107925819930527, + "venv/lib/python3.13/site-packages/passlib/handlers/scram.py": 12281469744083867450, + "frontend/src/routes/dashboards/[id]/components/DashboardHeader.svelte": 5572977872383619871, + "venv/lib/python3.13/site-packages/fastapi/applications.py": 4975013401500183420, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/test_moments_consistency_ewm.py": 12153690217678546798, + "venv/lib/python3.13/site-packages/pygments/styles/inkpot.py": 10516710471319090846, + "backend/src/models/maintenance.py": 2088418229495130810, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/METADATA": 14126682758562488244, + "venv/lib/python3.13/site-packages/smmap/test/lib.py": 2924931247676024085, + "venv/lib/python3.13/site-packages/httpx/_transports/wsgi.py": 11981127094916412794, + "venv/lib/python3.13/site-packages/_pytest/reports.py": 13930709338396699351, + "venv/lib/python3.13/site-packages/pydantic/_internal/_mock_val_ser.py": 12265320534388472158, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_loop.py": 6502725909989655118, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/libdivide.h": 5314232500579481313, + "venv/lib/python3.13/site-packages/cffi/_embedding.h": 9441285871823018603, + "venv/lib/python3.13/site-packages/pip/_vendor/distro/__main__.py": 2688850704829116818, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arrayterator.py": 3076316311545674897, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/pytestplugin.py": 1591034895268415944, + "venv/lib/python3.13/site-packages/pygments/lexers/minecraft.py": 10133579583270214110, + "venv/lib/python3.13/site-packages/pandas/core/util/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/chunks/DsxtPyvP.js": 3746126985395053120, + "backend/src/models/report.py": 9185954411073383239, + "backend/src/models/dataset_review_pkg/_profile_models.py": 9621392840420324583, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/exclusions.py": 15852672500377116297, + "backend/src/plugins/storage/plugin.py": 17070362975404691950, + "backend/src/plugins/translate/_token_budget.py": 1545056585783198863, + "backend/tests/test_api_key_routes.py": 8620555141760963281, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/models.py": 9513172366009392193, + "venv/lib/python3.13/site-packages/attr/setters.py": 12467854389745942025, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_random.py": 4179188367630060654, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string.py": 3834067244989779682, + "venv/lib/python3.13/site-packages/PIL/ImageText.py": 15322496455608242001, + "frontend/src/assets/svelte.svg": 13872699371039797074, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/RECORD": 7844752443022514265, + "venv/lib/python3.13/site-packages/pandas/_libs/window/indexers.pyi": 9911899303567570646, + "venv/lib/python3.13/site-packages/uvicorn-0.40.0.dist-info/INSTALLER": 17282701611721059870, + "frontend/src/routes/dashboards/[id]/components/DashboardGitManager.svelte": 14665567599893731601, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/aggregate/test_other.py": 783701524491896337, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_query_eval.py": 17613800806748649144, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_pytables_missing.py": 12154582133989896069, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_insert.py": 6970975909565157982, + "venv/lib/python3.13/site-packages/pillow.libs/libwebpdemux-747f2b49.so.2.0.17": 7615380692384566654, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_chunksize.py": 7107619871245389835, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/incfile.f90": 4348588746493647387, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/errors.py": 4817746830102488448, + "venv/lib/python3.13/site-packages/pygments/styles/colorful.py": 15708848112363953394, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_shape_base.py": 8837845103338426570, + "backend/src/core/task_manager/__init__.py": 15991802770215124472, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/poly1305.py": 10854598965202354516, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/util.py": 4890614159013873000, + "venv/lib/python3.13/site-packages/numpy/ma/__init__.pyi": 1855615156913010107, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_regression.py": 12593643817685777170, + "backend/test_app.db": 2486636812009447051, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/decl_api.py": 5287018911951723034, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_nat.py": 18428782698385974380, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_isocalendar.py": 5704842983090753914, + "venv/lib/python3.13/site-packages/cryptography/x509/general_name.py": 4481582226129488535, + "venv/lib/python3.13/site-packages/starlette/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/_isocbind.py": 15031197044862908440, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_groupby.py": 16180421154734310873, + "venv/lib/python3.13/site-packages/pandas/io/sas/__init__.py": 8095743504390517992, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_join.py": 1131792466825856990, + "backend/src/api/routes/git/_deps.py": 8233286973979159721, + "venv/lib/python3.13/site-packages/websockets/legacy/framing.py": 12759022769700230409, + "venv/lib/python3.13/site-packages/_pytest/_code/__init__.py": 6211607282116942091, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/markers.py": 5247208668583898949, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pydantic/functional_serializers.py": 15285359935059345032, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/datasource.pyi": 16752667877866430577, + "backend/tests/test_translate_corrections.py": 1228642484417924184, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_re.py": 1296579393600719224, + "venv/lib/python3.13/site-packages/pydantic/dataclasses.py": 12384956801113860889, + "venv/lib/python3.13/site-packages/passlib/tests/test_utils_handlers.py": 556092537518149789, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/uvicorn/loops/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/code.py": 9700811903057180696, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/padding.py": 11244071766694094554, + "venv/lib/python3.13/site-packages/requests/status_codes.py": 17005213506461710202, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp": 10880681943327843928, + "venv/lib/python3.13/site-packages/referencing/_core.py": 14744795336121513230, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/result.py": 12262298207886620908, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/tools.py": 6437315459200419827, + "venv/lib/python3.13/site-packages/pandas/tests/apply/common.py": 1113935558495455492, + "venv/lib/python3.13/site-packages/rapidfuzz/__init__.pyi": 13131938031654453415, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7636/challenge.py": 6388445104761482746, + "venv/lib/python3.13/site-packages/PIL/ImageTransform.py": 7825940907094338808, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/segment.py": 2555584120510872966, + "venv/bin/pyrsa-sign": 15564653706771700451, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata.py": 2021612995853910808, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/__init__.py": 13841777369501476946, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/WHEEL": 7145482834744213753, + "frontend/src/components/__tests__/task_log_viewer.test.js": 6512653335179659416, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/processors.cpython-313-x86_64-linux-gnu.so": 18139875206371157315, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi": 11733449165276720901, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/authorization_server.py": 4427151727224472650, + "frontend/build/_app/immutable/nodes/18.X9qqmMrM.js": 10317790872480568902, + "backend/git_repos/remote/test-repo.git/description": 15262637409357137373, + "frontend/src/lib/stores/health.js": 1061942219531952418, + "venv/lib/python3.13/site-packages/pandas/core/arrays/categorical.py": 15993211255162930859, + "frontend/src/components/git/CommitHistory.svelte": 61942790722897211, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/well_known.py": 7183795183137931709, + "venv/lib/python3.13/site-packages/smmap/mman.py": 9091562788592406032, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/factory.py": 3042005457138956499, + "venv/lib/python3.13/site-packages/pip/_internal/commands/uninstall.py": 11003472265011262515, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/_types.py": 7175518113263603341, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_groupby.py": 2738671407653333726, + "venv/lib/python3.13/site-packages/pip/_internal/models/direct_url.py": 4619204214785230341, + "venv/lib/python3.13/site-packages/idna/uts46data.py": 5698404064763638591, + "venv/lib/python3.13/site-packages/referencing/tests/test_core.py": 8280983300775878144, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_combine.py": 16193618152415684421, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_update.py": 9098258267671647783, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/WHEEL": 15858869568085970864, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_elements_constructors.py": 9279447066034364952, + "frontend/playwright-report/data/dcf41bdb395adaf70707a711375fd3b464dd384f.webm": 3819814233647777883, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/signature.py": 3614545297259098566, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_concatenate_chunks.py": 9693420220003544490, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/mt19937-testset-2.csv": 14641856424618845798, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90": 8680230823849248800, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/WHEEL": 5990830714395966792, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/serialize.py": 11139432164346742421, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_manylinux.py": 12272275001961360101, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_has_cy.py": 11979732417254560424, + "venv/lib/python3.13/site-packages/_pytest/assertion/__init__.py": 16392348866405910618, + "venv/lib/python3.13/site-packages/tzlocal/__init__.py": 11017072814026497364, + "venv/lib/python3.13/site-packages/pandas/core/shared_docs.py": 2173578869755325502, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_openpyxl.py": 9542840527483618681, + "backend/src/services/__tests__/test_llm_plugin_persistence.py": 16769242892960874042, + "backend/git_repos/remote/test-repo.git/hooks/fsmonitor-watchman.sample": 14381968406977928721, + "venv/lib/python3.13/site-packages/pip/_internal/wheel_builder.py": 3893922370396791826, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_utils.py": 15197339054699289627, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_http_headers.py": 13187746870209705951, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/_collections.py": 14307204206312829238, + "venv/lib/python3.13/site-packages/pip/_internal/models/installation_report.py": 14534544543677907640, + "venv/lib/python3.13/site-packages/anyio/to_interpreter.py": 8369454842687342401, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_spss.py": 4865360315909532603, + "venv/lib/python3.13/site-packages/pillow.libs/libsharpyuv-95d8a097.so.0.1.2": 5320647379976541240, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/text.py": 6096215585499446070, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_string.py": 10141066226714805009, + "venv/lib/python3.13/site-packages/pydantic/datetime_parse.py": 196119761382305574, + "frontend/src/lib/api/translate/corrections.js": 3619404083693055292, + "frontend/e2e/tests/git.e2e.js": 5892730242199126550, + "backend/src/services/sql_table_extractor.py": 2522819274015363166, + "backend/src/plugins/migration.py": 16213446701284149979, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_extending.py": 10202091354750153497, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/memory.py": 9947113720821563254, + "backend/src/api/routes/assistant/_admin_routes.py": 3380446401429936332, + "frontend/src/lib/components/health/PolicyForm.svelte": 16556369076015031814, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_rank.py": 5398520257852104723, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f": 13562390882286135024, + "backend/src/api/routes/admin.py": 235004514833998579, + "venv/lib/python3.13/site-packages/ecdsa/test_pyecdsa.py": 14542286382742044648, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/__init__.py": 14571251344510763303, + "backend/src/core/task_manager/__tests__/test_task_logger.py": 1651218524520477084, + "venv/lib/python3.13/site-packages/rpds/__init__.pyi": 12037474523494903587, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/__init__.py": 2833016678144975576, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/OSA.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/highlighter.py": 10615901258492570740, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/expression.py": 15511250785671695359, + "frontend/src/lib/components/assistant/__tests__/assistant_confirmation.integration.test.js": 12582020574293031526, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh25286.pyf": 14358606965464506398, + "venv/lib/python3.13/site-packages/pip/_internal/models/format_control.py": 12916176880659590456, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_period.py": 9715843209581883915, + "venv/lib/python3.13/site-packages/pyasn1/compat/__init__.py": 5902203086150636670, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf": 10179237442840865225, + "venv/lib/python3.13/site-packages/passlib/utils/handlers.py": 10182859005870689026, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_analytics.py": 4510712334676848202, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/plugin_base.py": 2880434680251108786, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_rowcount.py": 6682800584070485197, + "venv/lib/python3.13/site-packages/PIL/_imagingft.cpython-313-x86_64-linux-gnu.so": 11054435406031360190, + "backend/src/services/clean_release/repositories/artifact_repository.py": 9040122866024534865, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x86_unix.h": 13709837360414450184, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/index_tricks.pyi": 11463747060334597941, + "docker/frontend.Dockerfile": 13262735279052210084, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_nonunique_indexes.py": 15468078561381939405, + "venv/lib/python3.13/site-packages/starlette/formparsers.py": 9019779181100355515, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args_and_kwargs.py": 3381939712123764154, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/base_key.py": 10402800587070352851, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py": 10057637461647348368, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/certs.py": 13366788049827102313, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/fields.py": 10090313990429695520, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/fromnumeric.py": 3792079757208879362, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/test_regression.py": 5652583095949741238, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_arrow_interface.py": 5231449831607036031, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_shift.py": 9952689832827833247, + "venv/lib/python3.13/site-packages/referencing/tests/test_exceptions.py": 10846225989746274213, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_datetimelike.py": 5317270578347271174, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/twodim_base.pyi": 10156504423258357540, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/array_api_info.pyi": 7887489694871300469, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_values.py": 430620320423334461, + "venv/lib/python3.13/site-packages/pygments/lexers/json5.py": 9736695186548899403, + "venv/lib/python3.13/site-packages/_pytest/compat.py": 10046464101087327473, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_setops.py": 9991233160569430204, + "venv/lib/python3.13/site-packages/click/termui.py": 7022374827798605437, + "venv/lib/python3.13/site-packages/websockets/sync/client.py": 10892557975919033983, + "venv/lib/python3.13/site-packages/pillow.libs/libtiff-295fd75c.so.6.2.0": 17866578820357536656, + "venv/lib/python3.13/site-packages/numpy/lib/_iotools.py": 10522826373041592861, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_interface.py": 13648006002292914247, + "venv/lib/python3.13/site-packages/pandas/tests/test_sorting.py": 10751098438703044961, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_common.py": 2265736743367879051, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_mem_overlap.py": 4202716587079637350, + "venv/lib/python3.13/site-packages/jeepney/tests/test_low_level.py": 3579024079580951234, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libkrb5-fcafa220.so.3.3": 5620628698712971642, + "venv/lib/python3.13/site-packages/jaraco/classes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/fastapi/dependencies/models.py": 8626894872248212015, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_function_base.py": 15241999259666702619, + "venv/lib/python3.13/site-packages/numpy/f2py/__init__.py": 7470157159992827389, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/METADATA": 13428590545328703138, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_ddl.py": 3690189094298044728, + "venv/lib/python3.13/site-packages/pygments/lexers/blueprint.py": 6370363226580199085, + "venv/lib/python3.13/site-packages/numpy/f2py/cfuncs.pyi": 8232620851756907417, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_indexing.py": 16291207621268530224, + "venv/lib/python3.13/site-packages/pygments/lexer.py": 3658450949169647228, + "backend/git_repos/remote/test-repo.git/hooks/pre-commit.sample": 102291230237676317, + "venv/lib/python3.13/site-packages/greenlet/TBrokenGreenlet.cpp": 10822436772777706192, + "venv/lib/python3.13/site-packages/dotenv/__main__.py": 16883579879172186355, + "venv/lib/python3.13/site-packages/websockets/speedups.pyi": 10322382420215791091, + "venv/lib/python3.13/site-packages/numpy/tests/test_lazyloading.py": 17465787495701737655, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval_tree.py": 15789443159423302291, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_sql.py": 3901697517087276687, + "venv/lib/python3.13/site-packages/pandas/core/indexes/multi.py": 9115751979327393200, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_constructors.py": 16197656939536784142, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_common.py": 9097104320321411408, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/build_tracker.py": 9389444024234384408, + "venv/lib/python3.13/site-packages/requests/compat.py": 5836590172733661320, + "venv/lib/python3.13/site-packages/pip/_internal/utils/_jaraco_text.py": 9046755357011730699, + "venv/lib/python3.13/site-packages/PIL/ImtImagePlugin.py": 17599267755504817169, + "venv/lib/python3.13/site-packages/passlib/handlers/__init__.py": 3424087230285514388, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_sort_index.py": 13517883160584591966, + "venv/lib/python3.13/site-packages/_pytest/python.py": 1829073958095716309, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/scalars.pyi": 3130685119595923378, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_describe.py": 14493300276133670380, + "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.py": 13115032674230220791, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90": 4990763135487995517, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/authenticate_client.py": 16886645731942472285, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_fillna.py": 8802093795040069423, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90": 3492659529812762861, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/string/test_indexing.py": 2274965639578580723, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_week.py": 5756727157937218128, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_item.py": 17619314877770917080, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/licenses/LICENSE": 13322127602069971876, + "frontend/build/_app/immutable/nodes/29.56ajaPq7.js": 13881277175518745666, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_cov_corr.py": 8117511855230249212, + "venv/lib/python3.13/site-packages/pandas/tests/internals/test_api.py": 11217428888457119601, + "backend/src/services/git/_branch.py": 4560456889410483402, + "venv/lib/python3.13/site-packages/fastapi/security/http.py": 8465565118555441408, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/metadata.py": 7204343250279221076, + "venv/lib/python3.13/site-packages/starlette/exceptions.py": 15978811612997200737, + "venv/lib/python3.13/site-packages/_pytest/debugging.py": 16135285365306979060, + "venv/lib/python3.13/site-packages/numpy/lib/_index_tricks_impl.pyi": 5892973170789971535, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_indexing.py": 7181087459615188551, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/py.typed": 9796674040111366709, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_blocking.py": 6312017389529916004, + "venv/lib/python3.13/site-packages/pandas/tests/extension/json/__init__.py": 7877061921210840955, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_date_range.py": 16128552513324017349, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/assignOnlyModule.f90": 15967199601254912096, + "venv/lib/python3.13/site-packages/pygments/lexers/forth.py": 17623561228839319663, + "backend/src/core/utils/superset_context_extractor/_templates.py": 6790136732701012567, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/warnings.py": 2552021607611112605, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_style.py": 6849613206971398029, + "venv/lib/python3.13/site-packages/numpy/f2py/capi_maps.pyi": 10638891136586198429, + "venv/lib/python3.13/site-packages/keyring/backends/kwallet.py": 3071915635647280308, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/METADATA": 6438256145634479451, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_combine_concat.py": 3201068805128232483, + "venv/lib/python3.13/site-packages/urllib3/http2/probe.py": 4069929463671970243, + "frontend/src/routes/datasets/review/review-workspace-helpers.js": 8577563379877694502, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/printing.py": 8681519649669408795, + "venv/lib/python3.13/site-packages/jaraco/classes/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jeepney/wrappers.py": 15234251727654692435, + "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.pyi": 18253950285509265097, + "venv/lib/python3.13/site-packages/numpy/tests/test_scripts.py": 5790352482583964348, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE": 1126906383149772681, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_sorted.py": 1899608688401238388, + "venv/lib/python3.13/site-packages/referencing/tests/test_retrieval.py": 10782087416909177703, + "venv/lib/python3.13/site-packages/starlette/middleware/gzip.py": 4321371046149637632, + "venv/lib/python3.13/site-packages/pandas/tests/base/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pycparser/_c_ast.cfg": 2649342580905806389, + "frontend/build/_app/immutable/chunks/CuzmfnQu.js": 4320326097426684598, + "venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py": 7301817934902711510, + "venv/lib/python3.13/site-packages/pydantic/v1/errors.py": 11245135449608452720, + "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.pyi": 2042169688753984918, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/numeric.py": 14451517189908259173, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_m68k_gcc.h": 6580173800099450404, + "venv/lib/python3.13/site-packages/PIL/__main__.py": 827665918723937817, + "frontend/src/components/git/CommitModal.svelte": 4151596094672629211, + "venv/lib/python3.13/site-packages/PIL/GifImagePlugin.py": 16073125611077200693, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_delitem.py": 16538190861492829338, + "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.pyi": 8607205990821121708, + "venv/lib/python3.13/site-packages/passlib/apps.py": 4633269405597895766, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_easter.py": 3397863170068576196, + "venv/lib/python3.13/site-packages/PIL/ImageGrab.py": 11114379915762058868, + "venv/lib/python3.13/site-packages/pandas/_libs/ops.cpython-313-x86_64-linux-gnu.so": 10490009128553397250, + "backend/src/core/superset_client/__init__.py": 13995635011522535664, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_insert.py": 11635164392966270621, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_pipe.py": 8255917221095334212, + "venv/lib/python3.13/site-packages/ecdsa/test_der.py": 7117444285097824495, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/meson.build": 9642189398934130247, + "venv/lib/python3.13/site-packages/cffi/_imp_emulation.py": 17246725564704952212, + "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.cpython-313-x86_64-linux-gnu.so": 3478629877770507853, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_abc.py": 10164280045317807365, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/groupby.py": 14661033005768429774, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/test_arrow_compat.py": 12986187285988432338, + "venv/lib/python3.13/site-packages/PIL/SpiderImagePlugin.py": 12234762087257163606, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/state.py": 10500170103357297551, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_timezones.py": 15157687716502574038, + "venv/lib/python3.13/site-packages/dateutil/utils.py": 7067026915090881998, + "venv/lib/python3.13/site-packages/pip/_internal/utils/entrypoints.py": 11268059714209889385, + "venv/lib/python3.13/site-packages/pyasn1/codec/cer/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/sqlalchemy/log.py": 10101221585967121334, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/modes.py": 6832635056228445650, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/__init__.py": 14522970260621605208, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/strings.pyi": 15361498560917514616, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_api.py": 1910541672533352625, + "venv/lib/python3.13/site-packages/pygments/lexers/bdd.py": 5389493859905397060, + "venv/lib/python3.13/site-packages/pydantic/v1/main.py": 213087273729911492, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/color_triplet.py": 17264298271771184, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_cte.py": 9274103293201050794, + "frontend/src/lib/Counter.svelte": 4002153662176313030, + "backend/git_repos/remote/test-repo.git/hooks/post-update.sample": 4288868784459664203, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_network.py": 13159427333040109523, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_series.py": 10922287546912569276, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ma.pyi": 6467636381637286867, + "venv/lib/python3.13/site-packages/jsonschema/cli.py": 9813914882090789748, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/licenses/LICENSE": 11199044866758471950, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/endpoint.py": 8519226897299461194, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/protocol.py": 932296179250981622, + "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.pyi": 17903213294220335051, + "venv/lib/python3.13/site-packages/pandas/io/sas/sasreader.py": 12766780210114366112, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/evaluator.py": 6348022789899831255, + "venv/lib/python3.13/site-packages/pygments/lexers/igor.py": 6506221273085723501, + "venv/lib/python3.13/site-packages/pygments/lexers/apl.py": 16767474673619335683, + "frontend/src/lib/stores/translationRun.js": 10005138082029605368, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/RECORD": 18294169019244826301, + "frontend/src/routes/datasets/StatsBar.svelte": 7818919570179436566, + "venv/lib/python3.13/site-packages/pydantic/functional_validators.py": 5835339743072048940, + "backend/src/api/routes/clean_release_v2.py": 12814311709297749713, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_subclass.py": 11096337912872573314, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_slp_switch.py": 16490710972475154509, + "venv/lib/python3.13/site-packages/_pytest/mark/__init__.py": 9343015549300275714, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_os.h": 7883047506449405400, + "venv/lib/python3.13/site-packages/pandas/_libs/missing.cpython-313-x86_64-linux-gnu.so": 1990755879067132155, + "venv/lib/python3.13/site-packages/pandas/core/computation/api.py": 17919983681396223380, + "venv/lib/python3.13/site-packages/pandas/tests/construction/test_extract_array.py": 3100523370314150013, + "venv/lib/python3.13/site-packages/pycparser/_ast_gen.py": 5464347629908906775, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_arithmetic.py": 976970179757115407, + "venv/lib/python3.13/site-packages/pygments/lexers/ul4.py": 9580182474451220952, + "backend/git_repos/remote/test-repo.git/hooks/pre-receive.sample": 6118492409684431911, + "venv/lib/python3.13/site-packages/typing_inspection-0.4.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pydantic/v1/mypy.py": 17076910404409672245, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_openid.py": 8708980645667847439, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_ordered.py": 13827016781743929164, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth2/resource_protector.py": 3563910821279222695, + "venv/lib/python3.13/site-packages/passlib/tests/test_context_deprecated.py": 7876919198015151018, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pipe.py": 7400355977900310233, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_arithmetic.py": 17449383588949771785, + "venv/lib/python3.13/site-packages/numpy/core/_dtype_ctypes.pyi": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_merge_antijoin.py": 14435396877404907826, + "venv/lib/python3.13/site-packages/authlib/jose/rfc8037/__init__.py": 8705044848308260480, + "venv/lib/python3.13/site-packages/pandas/tests/frame/common.py": 7426635866622531875, + "venv/lib/python3.13/site-packages/pandas/io/common.py": 12088195203620154171, + "venv/lib/python3.13/site-packages/packaging/_parser.py": 13394093358675095309, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_inference.py": 5741637509343419942, + "venv/lib/python3.13/site-packages/pygments/lexers/nix.py": 15050086330545600356, + "venv/bin/pip3": 13861749540792881808, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/stride_tricks.pyi": 8257977532799807847, + "backend/src/scripts/clean_release_tui.py": 11100359353752859553, + "venv/lib/python3.13/site-packages/sqlalchemy/inspection.py": 8563914460959280101, + "venv/lib/python3.13/site-packages/numpy/f2py/crackfortran.pyi": 9206355685192026844, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hashes.py": 8545380307201732345, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90": 2174121054736811903, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/base.py": 5294446834530589760, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_numba.py": 6409810497251251179, + "venv/lib/python3.13/site-packages/pydantic/__init__.py": 11536052293866174672, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlsxwriter.py": 8445547874832015203, + "venv/lib/python3.13/site-packages/yaml/constructor.py": 8731384179016992045, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_indexing.py": 4334578480714520407, + "frontend/src/components/git/BranchSelector.svelte": 12975425183125935169, + "venv/pyvenv.cfg": 2513607356761047446, + "venv/lib/python3.13/site-packages/itsdangerous-2.2.0.dist-info/RECORD": 11111103193315065053, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/__main__.py": 11917862648584782420, + "venv/lib/python3.13/site-packages/numpy/lib/_scimath_impl.pyi": 8879196542984811747, + "venv/lib/python3.13/site-packages/httpx/_api.py": 6697370469329778523, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_reductions.py": 8258332365408303156, + "backend/src/api/routes/dashboards/__init__.py": 15214026957520044598, + "venv/lib/python3.13/site-packages/numpy/__init__.py": 2331213407497901634, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_scrypt.py": 17378030264314664250, + "venv/lib/python3.13/site-packages/urllib3/util/__init__.py": 2848870790459558599, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/__init__.py": 15130871412783076140, + "backend/src/api/routes/maintenance/_schemas.py": 9854015056764058803, + "venv/lib/python3.13/site-packages/numpy/_expired_attrs_2_0.py": 8786558894094307341, + "backend/src/services/validation_run_service.py": 5527352359336135164, + "venv/lib/python3.13/site-packages/authlib/oidc/core/models.py": 1370998944213578392, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator": 6870991911243684132, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_localize.py": 4937713043686953098, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_pickle.py": 388513670243918273, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/resultproxy.cpython-313-x86_64-linux-gnu.so": 6011605826065363427, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_put.py": 8547660958963625817, + "venv/lib/python3.13/site-packages/pygments/lexers/rnc.py": 9747352274729854620, + "venv/lib/python3.13/site-packages/packaging/pylock.py": 15346942039643310253, + "venv/lib/python3.13/site-packages/anyio/_core/_signals.py": 1204322949639513552, + "backend/src/services/dataset_review/clarification_pkg/_helpers.py": 9331845075873070265, + "venv/lib/python3.13/site-packages/PIL/XbmImagePlugin.py": 12256750478268246137, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_astype.py": 4854809596041987380, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_dtypes.py": 6831042272921908068, + "venv/lib/python3.13/site-packages/jeepney/tests/secrets_introspect.xml": 10717038359151125278, + "venv/lib/python3.13/site-packages/numpy/conftest.py": 8971879716683736515, + "backend/tests/test_logging_audit_fixes.py": 14806902244422319839, + "backend/git_repos/remote/test-repo.git/objects/93/9cc583a18267406014c57617ccb557569f6aaf": 5474754694741999746, + "frontend/playwright-report/data/a19c216148b1612f8e11679d34071559b77021a0.png": 2734494351837969206, + "frontend/src/routes/tools/backups/+page.svelte": 6796050751535238723, + "frontend/src/components/git/ConflictResolver.svelte": 2318922269446496715, + "backend/src/api/routes/maintenance/__init__.py": 8921716690761316245, + "venv/lib/python3.13/site-packages/passlib/handlers/mssql.py": 2800599582708170195, + "venv/lib/python3.13/site-packages/pillow.libs/libbrotlicommon-c55a5f7a.so.1.2.0": 2635192149914499986, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_nlargest.py": 14518132768753249360, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/array_like.py": 2778905818573625118, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/aioodbc.py": 12704729841432715246, + "backend/src/services/mapping_service.py": 9713400496587758211, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append_common.py": 2377351120083195530, + "venv/lib/python3.13/site-packages/gitdb/test/test_pack.py": 7518388297247535189, + "venv/lib/python3.13/site-packages/jeepney/io/threading.py": 525625939662612746, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_drop.py": 17940792593116540139, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_keys.py": 10813898277355150779, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/conftest.py": 25473177671450048, + "venv/lib/python3.13/site-packages/PIL/TgaImagePlugin.py": 9208942494595222259, + "venv/lib/python3.13/site-packages/starlette/convertors.py": 17839747154274354605, + "venv/lib/python3.13/site-packages/charset_normalizer/cli/__main__.py": 2148876100501691980, + "backend/src/plugins/translate/_run_source.py": 11569137727611732019, + "venv/lib/python3.13/site-packages/pygments/lexers/gsql.py": 15294109558028161389, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_regression.py": 9375525053479844400, + "venv/lib/python3.13/site-packages/numpy/f2py/use_rules.py": 17277594393032382485, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f": 13126319439858352711, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/nested_secrets.py": 15691917061715429369, + "venv/lib/python3.13/site-packages/pandas/core/groupby/indexing.py": 18009437216172136227, + "venv/lib/python3.13/site-packages/pandas/core/arrays/_ranges.py": 2572903460327860111, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/hook-numpy.pyi": 14233146512272397376, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_constructors.py": 2439700578107653984, + "venv/lib/python3.13/site-packages/jsonschema/__main__.py": 18136546137047911521, + "venv/lib/python3.13/site-packages/PIL/_version.py": 3025206805667405876, + "venv/lib/python3.13/site-packages/fastapi/exceptions.py": 12665775976182239091, + "venv/lib/python3.13/site-packages/numpy/_distributor_init.pyi": 1308368231471324581, + "venv/lib/python3.13/site-packages/anyio/streams/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/multiarray.pyi": 6368268452184570195, + "venv/lib/python3.13/site-packages/pandas/_libs/testing.pyi": 16691791330088523786, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_loadtxt.py": 17562784940619942447, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_numpy_compat.py": 9112925138440787555, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/JaroWinkler.py": 1341849861184131135, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/util/typing.py": 17638587764345605306, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/frequencies/test_freq_code.py": 13758353172962109140, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/declarative/__init__.py": 2436195108273216959, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/types.py": 356973910046950951, + "venv/lib/python3.13/site-packages/PIL/_imagingmath.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/__init__.py": 8807410829260170597, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js": 10530710876604536879, + "venv/lib/python3.13/site-packages/pygments/lexers/snobol.py": 414946539602526513, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/__init__.py": 3577295959173028042, + "venv/lib/python3.13/site-packages/cryptography/utils.py": 18088508841978595788, + "venv/lib/python3.13/site-packages/packaging/version.py": 13470993734108007779, + "venv/include/site/python3.13/greenlet/greenlet.h": 16216120538647882082, + "frontend/playwright-report/trace/snapshot.v8KI4P3m.js": 7854911091722310751, + "venv/lib/python3.13/site-packages/pygments/lexers/functional.py": 15896849233007178031, + "venv/lib/python3.13/site-packages/pandas/api/interchange/__init__.py": 181911269762882069, + "venv/lib/python3.13/site-packages/pandas/core/tools/numeric.py": 8510988912136285022, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_convert_dtypes.py": 5005259275646154894, + "venv/lib/python3.13/site-packages/numpy/_core/multiarray.pyi": 3494871767602648807, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90": 13315882216322269383, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_construct_ndarray.py": 6863874753941288585, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/_typing.py": 17589387690638097975, + "frontend/src/components/Navbar.svelte": 6128753323363185057, + "frontend/build/_app/immutable/chunks/CC_MCBkD.js": 11709343780956289454, + "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.py": 16859854811012717088, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_getlimits.py": 118041882543413669, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/provision.py": 17812733620485633975, + "venv/lib/python3.13/site-packages/PIL/GimpGradientFile.py": 9777026720028891154, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/_windows.py": 9171347078900057357, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_item_selection.py": 1027989019709029615, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/modules.py": 9023244176010175562, + "venv/lib/python3.13/site-packages/pygments/lexers/kusto.py": 16285533608924436308, + "venv/bin/pygmentize": 2166491742035772877, + "frontend/src/lib/stores/assistantChat.js": 13807808925025688939, + "frontend/src/services/gitService.js": 7044825476968825357, + "frontend/src/lib/components/reports/reportTypeProfiles.js": 10752964062056890725, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/fromnumeric.pyi": 6708743411405679061, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv": 5882025767947638305, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py": 5946672289916692272, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/sessions.py": 5400174351499383072, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7517/jwk.py": 6458001384702613165, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/_initialize.pyi": 6616985736007157309, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_formats.py": 9738552308554950419, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_period.py": 10309599277099605395, + "venv/lib/python3.13/site-packages/passlib/tests/test_totp.py": 9150389741890748343, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py": 15644105878811738516, + "venv/lib/python3.13/site-packages/pandas/io/sas/sas_constants.py": 14492427939536692313, + "venv/lib/python3.13/site-packages/urllib3/util/util.py": 12490259045660543460, + "venv/lib/python3.13/site-packages/uvicorn/loops/asyncio.py": 16496916527760969173, + "venv/lib/python3.13/site-packages/authlib/deprecate.py": 3563885283090710443, + "backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py": 14275839608126658275, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.pyi": 10360538024015064036, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/live_render.py": 14619617939683800204, + "venv/lib/python3.13/site-packages/pandas/core/groupby/groupby.py": 5536922766239875007, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core": 6622984507059115517, + "venv/lib/python3.13/site-packages/websockets/asyncio/router.py": 15039562376314233669, + "venv/lib/python3.13/site-packages/numpy/_core/_rational_tests.cpython-313-x86_64-linux-gnu.so": 13475521165331256711, + "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_generation_shared.py": 23345689300073549, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/RECORD": 3205266407680661753, + "venv/lib/python3.13/site-packages/pandas/core/interchange/buffer.py": 12961802206383700922, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_win_type.py": 18105114803686556748, + "venv/lib/python3.13/site-packages/pandas/tests/generic/test_generic.py": 1297407268239966429, + "venv/lib/python3.13/site-packages/numpy/lib/_version.py": 15294708923334674060, + "venv/lib/python3.13/site-packages/fastapi-0.127.1.dist-info/RECORD": 3283324710045856319, + "venv/bin/activate.csh": 14513616043256836238, + "backend/src/api/routes/assistant/__init__.py": 14959302162073618175, + "venv/lib/python3.13/site-packages/numpy/_configtool.py": 2946953194004101078, + "venv/lib/python3.13/site-packages/pip/_internal/models/__init__.py": 13482731985065116750, + "backend/src/api/routes/environments.py": 1329328901500854319, + "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pxd": 14261507718442469988, + "venv/lib/python3.13/site-packages/fastapi/__init__.py": 11054203163075417954, + "venv/lib/python3.13/site-packages/ecdsa/test_jacobi.py": 1249543655136186433, + "venv/lib/python3.13/site-packages/httpx/_client.py": 1063593889704982038, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/__init__.py": 308178910015974550, + "venv/lib/python3.13/site-packages/sqlalchemy/util/concurrency.py": 1325673503812009695, + "venv/lib/python3.13/site-packages/sqlalchemy/events.py": 9329355486544822483, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/base.py": 13444129650880426353, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_equals.py": 9903250467264848187, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/LICENSE": 6989336036499641077, + "backend/src/api/routes/git_schemas.py": 9243114525622127446, + "backend/src/services/notifications/__tests__/test_notification_service.py": 5767450314963603475, + "backend/src/services/clean_release/repositories/compliance_repository.py": 7402628017251283691, + "frontend/build/_app/immutable/chunks/aNI39KyB.js": 1756469162576383723, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/env.py": 1254612137164491329, + "venv/lib/python3.13/site-packages/pygments/lexers/php.py": 17636450950688953288, + "backend/src/api/routes/dashboards/_projection.py": 1559143255780155174, + "venv/lib/python3.13/site-packages/authlib/oidc/discovery/models.py": 6924198551176217533, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi": 7801211423226951223, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_take.py": 14969455660160053080, + "frontend/src/lib/components/dataset-review/LaunchConfirmationPanel.svelte": 14399834101283315718, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape_base.pyi": 5046405609030418900, + "backend/src/models/storage.py": 14886607138033931307, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/__init__.py": 1197579313959289096, + "venv/lib/python3.13/site-packages/pygments/lexers/modeling.py": 15714077241620129689, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/licenses/LICENSE": 6653202620765194772, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_null_file.py": 6885565068723353414, + "venv/lib/python3.13/site-packages/numpy/fft/tests/test_helper.py": 5362180645056413158, + "venv/lib/python3.13/site-packages/pandas/_libs/lib.pyi": 3049004444338566197, + "venv/lib/python3.13/site-packages/PIL/PngImagePlugin.py": 5076219228736706283, + "frontend/src/lib/ui/Select.svelte": 11354509509920497811, + "venv/lib/python3.13/site-packages/dateutil/tzwin.py": 5149446703746204349, + "backend/src/services/__init__.py": 15123879863527585264, + "backend/src/services/clean_release/repository.py": 11403333156347178483, + "venv/lib/python3.13/site-packages/git/types.py": 13960696584646279283, + "backend/src/plugins/translate/_batch_insert.py": 12482635271028646257, + "backend/tests/test_datasets.py": 10782968094631273511, + "backend/src/core/superset_client/_dashboards_filters.py": 8706676245520282810, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_clip.py": 11111183698178681331, + "venv/lib/python3.13/site-packages/_pytest/pytester.py": 5423287282155948827, + "backend/src/plugins/translate/service_target_schema.py": 15018144148162493344, + "venv/lib/python3.13/site-packages/attrs/converters.py": 13109003765349201809, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/INSTALLER": 17282701611721059870, + "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/httpx/_utils.py": 4836536051177895209, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/progress_bar.py": 15595912766961891283, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/filesize.py": 13234856188049714485, + "venv/lib/python3.13/site-packages/pygments/lexers/factor.py": 15788613154609197002, + "venv/lib/python3.13/site-packages/more_itertools/__init__.py": 9858612105173082060, + "venv/lib/python3.13/site-packages/_pytest/setuponly.py": 10959102379908419762, + "venv/lib/python3.13/site-packages/numpy/linalg/__init__.pyi": 18409133021422984774, + "venv/lib/python3.13/site-packages/numpy/_core/_umath_tests.pyi": 4587511199710546030, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_unsupported.py": 9115440166074553860, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_day.py": 2200008998040663785, + "venv/lib/python3.13/site-packages/pygments/lexers/actionscript.py": 8829560731160428621, + "frontend/src/lib/components/layout/TaskDrawer.svelte": 11803999908168836613, + "backend/tests/services/dataset_review/test_superset_matrix.py": 5114797134613078913, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/apply.py": 3906017176873949738, + "docker/backend.entrypoint.sh": 1034669340368151691, + "venv/lib/python3.13/site-packages/fastapi/dependencies/utils.py": 7687214523082385505, + "frontend/build/_app/immutable/nodes/8.BFOpA89K.js": 13153301632221690235, + "venv/lib/python3.13/site-packages/starlette-0.50.0.dist-info/INSTALLER": 17282701611721059870, + "backend/src/api/routes/dashboards/_listing_routes.py": 1750634467656242702, + "venv/lib/python3.13/site-packages/numpy/tests/test_warnings.py": 3154249157134620649, + "venv/lib/python3.13/site-packages/pygments/styles/friendly.py": 13799024964803741891, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_pydatetime.py": 16228315407662560992, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/test_generic.py": 1098361087956787007, + "backend/git_repos/remote/test-repo.git/objects/d5/0298a42699f39e4601c0aa23eab07bcb0703c7": 1966124163198751340, + "venv/lib/python3.13/site-packages/fastapi/__main__.py": 10755252341326986079, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/RECORD": 3288669175908898843, + "frontend/src/lib/stores/__tests__/taskDrawer.test.js": 12307450726550947042, + "frontend/build/_app/immutable/chunks/0SSHfn-s.js": 1512028033550082311, + "venv/lib/python3.13/site-packages/secretstorage/__init__.py": 4535964275649588672, + "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/indexes/string/test_astype.py": 10171766562093740708, + "venv/lib/python3.13/site-packages/pygments/styles/algol.py": 3040373291664740876, + "backend/tests/test_translate_executor_filter.py": 11717560360659156703, + "venv/lib/python3.13/site-packages/pydantic/json.py": 4109352930301629308, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/RECORD": 4487477737768669516, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_liboffsets.py": 14705822637347212540, + "backend/src/api/routes/git/_config_routes.py": 6093940098740660772, + "venv/lib/python3.13/site-packages/pandas/io/excel/_openpyxl.py": 6676451564208867775, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_tz_convert.py": 17957207974799052653, + "venv/lib/python3.13/site-packages/rapidfuzz/__init__.py": 12462153783886855740, + "venv/lib/python3.13/site-packages/uvicorn/supervisors/multiprocess.py": 10047012560534876149, + "frontend/build/_app/immutable/chunks/Dn-Kr3zV.js": 11981784044886973393, + "venv/lib/python3.13/site-packages/numpy/dtypes.pyi": 6713822658171717369, + "venv/lib/python3.13/site-packages/jsonschema/exceptions.py": 15651767069704734674, + "venv/lib/python3.13/site-packages/uvicorn/middleware/asgi2.py": 5355343704425405009, + "venv/lib/python3.13/site-packages/pygments/lexers/make.py": 5345282370426217663, + "venv/lib/python3.13/site-packages/git/index/util.py": 5022401275553420722, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/resource_owner_password_credentials.py": 9559295461619813890, + "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.py": 7352635707860427145, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/nattype.cpython-313-x86_64-linux-gnu.so": 2311012065007769341, + "venv/lib/python3.13/site-packages/jeepney/__init__.py": 1063800617763464773, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic_core-2.41.5.dist-info/METADATA": 3044554568188160018, + "venv/lib/python3.13/site-packages/pygments/lexers/theorem.py": 15666523910367201285, + "venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py": 10408538054406276433, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix_py.py": 6653895521961110080, + "venv/lib/python3.13/site-packages/authlib/integrations/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/return_integer/foo77.f": 12000068001851270396, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iloc.py": 7586049606891014270, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/identity.py": 326059526167697655, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_is_monotonic.py": 12769599198035357753, + "venv/lib/python3.13/site-packages/ecdsa/test_numbertheory.py": 2117130219401053225, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/base.py": 16891437410462671317, + "venv/lib/python3.13/site-packages/pygments/lexers/tal.py": 447505725492547461, + "backend/src/core/auth/logger.py": 9289916075840905359, + "backend/src/plugins/git/__init__.py": 2144831474780401625, + "venv/lib/python3.13/site-packages/PIL/PdfParser.py": 13710342183037972042, + "venv/lib/python3.13/site-packages/pandas/tests/window/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/heuristics.py": 1422768761337195135, + "venv/lib/python3.13/site-packages/rsa/parallel.py": 4968566722541778371, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_macosx.h": 3653129798702716366, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/nditer.pyi": 2351219156711800159, + "venv/lib/python3.13/site-packages/pandas/tseries/__init__.py": 2648641118117738895, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/masked/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/styles/manni.py": 11853576691280294949, + "venv/lib/python3.13/site-packages/numpy/exceptions.py": 10981418339663118022, + "venv/lib/python3.13/site-packages/pandas/core/_numba/executor.py": 2205130934861422769, + "venv/lib/python3.13/site-packages/numpy/random/_examples/numba/extending_distributions.py": 209769687436320665, + "venv/lib/python3.13/site-packages/pip/_vendor/platformdirs/api.py": 13134394673408254097, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_common.h": 14732581790650403546, + "venv/lib/python3.13/site-packages/pandas/tests/test_aggregation.py": 16863055892192070549, + "venv/lib/python3.13/site-packages/pydantic_core/__init__.py": 10563134104783445328, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_formats.py": 17821648708413143557, + "venv/lib/python3.13/site-packages/pydantic/_internal/_forward_ref.py": 10623110912945011703, + "frontend/build/_app/immutable/entry/start.BNyxZqQe.js": 14066366168579688400, + "venv/lib/python3.13/site-packages/pandas/tests/io/conftest.py": 5864037534050136837, + "venv/lib/python3.13/site-packages/httpcore/_synchronization.py": 10997080307461682786, + "venv/lib/python3.13/site-packages/pip/_internal/models/index.py": 2839270935469791607, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arraysetops.pyi": 1782641795267171928, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_arithmetics.py": 16527169124402715210, + "venv/lib/python3.13/site-packages/_pytest/_py/path.py": 8464061867075119556, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_missing.py": 7034102519042351965, + "venv/lib/python3.13/site-packages/psycopg2/sql.py": 18041240927130590808, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_docs.py": 17898499890274685198, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_f2cmap.py": 5863341586534531594, + "venv/lib/python3.13/site-packages/referencing/exceptions.py": 2535322334430110414, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/__init__.py": 16123561007855424016, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/events.py": 7576713358952064464, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/query.py": 3867868366067025348, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/reshaping.py": 18085648077811502689, + "venv/lib/python3.13/site-packages/httpcore/_trace.py": 9576253018891841832, + "venv/lib/python3.13/site-packages/websockets/extensions/base.py": 2457233337788783873, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/base.py": 6348888156686452825, + "venv/lib/python3.13/site-packages/passlib/handlers/bcrypt.py": 8125664010268654055, + "venv/lib/python3.13/site-packages/dateutil/easter.py": 14631233890122048084, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py": 7852235015155694076, + "venv/lib/python3.13/site-packages/urllib3/util/ssl_.py": 11720964010284185952, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_switch_two_greenlets.py": 11156275429806391390, + "venv/lib/python3.13/site-packages/PIL/IptcImagePlugin.py": 14329453455296600824, + "frontend/build/_app/immutable/nodes/30.DnYtytFL.js": 2391068517706387105, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/__init__.py": 12849371269359608058, + "backend/src/core/superset_client/_datasets_preview.py": 12644037069207561202, + "venv/lib/python3.13/site-packages/websockets/client.py": 5229500079651465772, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/WHEEL": 8600534672961461758, + "backend/src/api/routes/clean_release.py": 1984604735131504761, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/methods.py": 8059372834301557565, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/string_/test_string_arrow.py": 10008395772220468318, + "venv/lib/python3.13/site-packages/pandas/core/indexes/accessors.py": 14394872772838047912, + "venv/lib/python3.13/site-packages/sqlalchemy/connectors/asyncio.py": 4200928269459447593, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/WHEEL": 5838667082726674838, + "venv/lib/python3.13/site-packages/pygments/lexers/matlab.py": 1880915927722177654, + "backend/alembic/versions/9f8e7d6c5b4a_add_is_multimodal_to_llm_providers.py": 11090205342799426943, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_datetime_index.py": 15448494560143263150, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libgssapi_krb5-497db0c6.so.2.2": 6199424505696679197, + "venv/lib/python3.13/site-packages/itsdangerous/timed.py": 12571102606719555007, + "backend/src/services/__tests__/test_rbac_permission_catalog.py": 5190751380981933250, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/mod.py": 2054876501774773382, + "venv/lib/python3.13/site-packages/pandas/tests/resample/test_base.py": 15292769510056833117, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_dtypes_basic.py": 10917162988625838981, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/linalg.pyi": 269481015135399748, + "venv/lib/python3.13/site-packages/dateutil/parser/_parser.py": 9443336890192151397, + "backend/src/services/maintenance/_dashboard_scanner.py": 1401108008906511280, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_structures.py": 16375837477294135345, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/emath.pyi": 3718540478840842664, + "venv/lib/python3.13/site-packages/numpy/core/umath.py": 4476812261188108155, + "backend/src/api/routes/__tests__/test_clean_release_v2_api.py": 13464989331176891726, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/api.py": 9829629144629841277, + "backend/src/plugins/translate/preview_llm_client.py": 14412557858942627249, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py": 2609365889369107154, + "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.pyi": 16799580742094025110, + "venv/lib/python3.13/site-packages/pydantic/_internal/_validators.py": 2939255306814626438, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/hmac.py": 18132740541139891824, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_pandas.py": 10894229569442891394, + "venv/lib/python3.13/site-packages/httpcore/_backends/auto.py": 10488908050307887802, + "venv/lib/python3.13/site-packages/jaraco/context/__init__.py": 10975097417056278427, + "frontend/build/_app/immutable/nodes/23.y3ghKhH-.js": 13434006313990484006, + "venv/lib/python3.13/site-packages/git/objects/tag.py": 7954808535585493300, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/ma.py": 15912582628112164509, + "venv/lib/python3.13/site-packages/passlib/context.py": 10362592407593745107, + "venv/lib/python3.13/site-packages/authlib/common/encoding.py": 52296066492753953, + "frontend/build/_app/immutable/chunks/DV17vNYu.js": 5906252992532056558, + "backend/tests/test_security_audit_fixes.py": 10329229098676202553, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/_meson.py": 5735043585893007971, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_multiprocessing.py": 5522490547285108448, + "backend/tests/test_smoke_plugins.py": 10704454611361370435, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/__version__.py": 14138134075118474134, + "venv/lib/python3.13/site-packages/numpy/lib/_shape_base_impl.py": 16539612003028676816, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/chararray.pyi": 17340224970247832290, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/distributions.h": 17162252287980242413, + "venv/lib/python3.13/site-packages/pandas/tests/util/conftest.py": 11143177766735481660, + "backend/src/api/routes/assistant/_llm_planner.py": 444517242115816139, + "venv/lib/python3.13/site-packages/git/objects/submodule/util.py": 8621897576747443758, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_implementation.py": 12245524932757110911, + "venv/lib/python3.13/site-packages/_pytest/outcomes.py": 12782895027812738142, + "venv/lib/python3.13/site-packages/pygments/lexers/fantom.py": 1986459352773446836, + "venv/lib/python3.13/site-packages/iniconfig/_version.py": 8497474654470220170, + "backend/src/api/routes/dashboards/_helpers.py": 16683849709430404975, + "backend/tests/test_sql_table_extractor.py": 8232282806948246815, + "venv/lib/python3.13/site-packages/websockets/legacy/__init__.py": 12332512329533591682, + "venv/lib/python3.13/site-packages/typing_inspection/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/__init__.py": 793698514004377486, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein.py": 17993169044119596860, + "venv/lib/python3.13/site-packages/pip/_internal/cli/req_command.py": 2887890799766730546, + "venv/lib/python3.13/site-packages/PIL/ImageFont.py": 15621336334706847865, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/WHEEL": 5076688779572520166, + "venv/lib/python3.13/site-packages/pandas/core/reshape/merge.py": 300205528811693975, + "venv/lib/python3.13/site-packages/greenlet/TThreadStateDestroy.cpp": 13749797532421836328, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/licenses/LICENSE": 3868190977070717994, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/METADATA": 5045041742469375466, + "venv/lib/python3.13/site-packages/numpy/f2py/setup.cfg": 17974180080760231128, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_intervalindex.py": 5053113227747333759, + "venv/lib/python3.13/site-packages/PIL/_imagingcms.cpython-313-x86_64-linux-gnu.so": 15198265718775753589, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/fixtures/__init__.py": 6654484356035994666, + "venv/lib/python3.13/site-packages/pydantic/_internal/_serializers.py": 12077180322353709930, + "venv/lib/python3.13/site-packages/PIL/PcdImagePlugin.py": 922809545463280224, + "venv/lib/python3.13/site-packages/pygments/lexers/r.py": 14263133575134645005, + "backend/src/core/cot_logger.py": 12977179701814261121, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_semicolon_split.py": 8153770165829451525, + "backend/src/services/clean_release/repositories/report_repository.py": 17952038790457725175, + "venv/lib/python3.13/site-packages/pydantic/networks.py": 15767095796055034509, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_einsum.py": 17286384318722237180, + "venv/lib/python3.13/site-packages/numpy/typing/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_multiarray.py": 3592197154340095431, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/WHEEL": 7127684561765977531, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_block_docstring.py": 18146459246837890489, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/greenlet/tests/test_generator.py": 14156412320760444199, + "frontend/build/_app/immutable/nodes/10.D79erIQG.js": 35496247013741914, + "backend/src/plugins/translate/orchestrator_planner.py": 1630348739588568408, + "venv/lib/python3.13/site-packages/authlib/integrations/starlette_client/apps.py": 4219758952914498116, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_astype.py": 1961831758405941258, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/__init__.py": 4752355175318979033, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/numpy_/test_indexing.py": 13703573544185051910, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh25211.f": 1486878017876900890, + "venv/lib/python3.13/site-packages/numpy/_core/memmap.pyi": 14124415711399771715, + "venv/lib/python3.13/site-packages/httpx/_models.py": 6516278895118988231, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_arm32_ios.h": 6751259472945638998, + "venv/lib/python3.13/site-packages/pandas/core/interchange/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_internal/locations/_sysconfig.py": 4773855595767526182, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py": 13763154154862871596, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/oracledb.py": 7158791242292470472, + "backend/src/plugins/translate/plugin.py": 9225230324052126034, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/numeric/test_indexing.py": 546024765756472196, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_deprecate.py": 16723865897349422996, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/__init__.py": 96341051676048910, + "venv/lib/python3.13/site-packages/pygments/lexers/jvm.py": 897669925284011089, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/conftest.py": 17514079438846557943, + "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.py": 11621577915097515056, + "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.py": 15558318749939680074, + "venv/lib/python3.13/site-packages/httpcore/_utils.py": 3255581092836273826, + "backend/src/api/routes/translate/_job_routes.py": 15469484615259714480, + "backend/src/plugins/translate/__tests__/test_lang_detect.py": 2328877106785068272, + "venv/lib/python3.13/site-packages/cffi/_cffi_errors.h": 1479575326813300292, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pip/_internal/models/scheme.py": 4101322315594430874, + "venv/lib/python3.13/site-packages/pip/_internal/cli/command_context.py": 9426036980437931533, + "venv/lib/python3.13/site-packages/numpy/ma/extras.py": 7559838309481824664, + "venv/lib/python3.13/site-packages/numpy/_utils/_inspect.py": 7029935879540617057, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/strptime.pyi": 5973671421648618563, + "venv/lib/python3.13/site-packages/passlib/crypto/_blowfish/base.py": 15872835330892203433, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_mask.py": 5451866071307236899, + "venv/lib/python3.13/site-packages/pandas/_config/config.py": 1494288055210911451, + "venv/lib/python3.13/site-packages/urllib3/util/retry.py": 17988032431204662756, + "backend/src/plugins/translate/dictionary_validation.py": 16674754716565921261, + "backend/tests/core/test_migration_engine.py": 7419155921858935534, + "venv/lib/python3.13/site-packages/git/cmd.py": 8854786163152637148, + "venv/lib/python3.13/site-packages/numpy/__config__.pyi": 1422114139050700402, + "venv/lib/python3.13/site-packages/passlib/hosts.py": 11171402820797380938, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_pickle.py": 2910383574326146698, + "venv/lib/python3.13/site-packages/pygments/lexers/promql.py": 8929925488296216854, + "venv/lib/python3.13/site-packages/pygments/lexers/oberon.py": 15220143799603451830, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/packaging/_tokenizer.py": 7442392076059866359, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/lib_user_array.py": 8711697474193296376, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/dtypes.pyi": 15114028503984522176, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/providers.py": 7267821734584612032, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_timestamp.py": 10308799534491190078, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/annotation.py": 15855576199737688124, + "venv/lib/python3.13/site-packages/websockets/cli.py": 14049106025886056110, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/RECORD": 6187512110158566509, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/block_docstring/foo.f": 2489756567993745076, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.pyi": 14543653817631274394, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/concat.py": 14737724508458849795, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_replace.py": 8784361132920473760, + "frontend/src/lib/api/translate/runs.js": 1220731879179347641, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_join.py": 11910166566689889389, + "venv/lib/python3.13/site-packages/httpx/_urls.py": 4219389176352582046, + "venv/lib/python3.13/site-packages/gitdb/typ.py": 16374739906244805047, + "venv/lib/python3.13/site-packages/fastapi/openapi/constants.py": 1111838716953068285, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/exceptions.py": 11303331612406662162, + "venv/lib/python3.13/site-packages/pandas/core/internals/concat.py": 12151675567885981464, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/starlette/templating.py": 9242638124487797988, + "backend/src/plugins/translate/_llm_call.py": 13441764941895838344, + "venv/lib/python3.13/site-packages/passlib/tests/test_apache.py": 12515001998770565375, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_size.py": 8527839563560550806, + "backend/alembic/versions/b1c2d3e4f5a6_add_source_hash_to_translation_records.py": 4775534557742900399, + "venv/lib/python3.13/site-packages/typing_inspection/typing_objects.pyi": 18193727720492050602, + "venv/lib/python3.13/site-packages/jaraco/functools/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/writers.pyi": 10494773026133244183, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_cli.py": 3173259257428855556, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/style.py": 15214295655795348821, + "venv/lib/python3.13/site-packages/pydantic/root_model.py": 20625057828723317, + "venv/lib/python3.13/site-packages/numpy/_array_api_info.py": 9709101823494959741, + "venv/lib/python3.13/site-packages/pandas/core/strings/accessor.py": 14021462534679430426, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_period.py": 15671388508498441412, + "venv/lib/python3.13/site-packages/python_dateutil-2.9.0.post0.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion": 2607512361823362698, + "venv/lib/python3.13/site-packages/numpy/lib/_format_impl.pyi": 15745512451486888537, + "venv/lib/python3.13/site-packages/git/refs/tag.py": 9979537867501757110, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_function.py": 14142346897145169685, + "frontend/src/lib/components/dataset-review/ExecutionMappingReview.svelte": 6341989866442424314, + "backend/src/plugins/translate/service_bulk_replace.py": 5355744069308185607, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/literal.py": 5641382379370828704, + "backend/tests/services/clean_release/test_demo_mode_isolation.py": 1970652424726919519, + "venv/lib/python3.13/site-packages/pandas/util/_doctools.py": 3766479022075611396, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libselinux-0922c95c.so.1": 16516617710645376769, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_alter_axes.py": 11338712836362534969, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_infer_datetimelike.py": 17304541521108700317, + "venv/lib/python3.13/site-packages/numpy/_core/_dtype_ctypes.py": 5564496700647900501, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/RECORD": 17985800801793506250, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90": 9097998998863007705, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/keyring/core.py": 2764269590123131634, + "backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py": 18129267641758340444, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/hooks.py": 8580161128344266243, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_indexing.py": 6539365174681852769, + "venv/lib/python3.13/site-packages/pandas/plotting/_matplotlib/boxplot.py": 7090586111222952862, + "backend/src/services/clean_release/facade.py": 11231787492455424065, + "venv/lib/python3.13/site-packages/numpy/core/numerictypes.py": 5776941405348611027, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_feather.py": 13613400750755530364, + "venv/lib/python3.13/site-packages/PIL/ImageDraw2.py": 13610162107593278891, + "frontend/src/lib/stores/__tests__/mocks/env_public.js": 2540122820969872185, + "backend/src/services/clean_release/manifest_service.py": 10873340336255220063, + "venv/lib/python3.13/site-packages/typing_extensions-4.15.0.dist-info/RECORD": 1556051687830913019, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_freq_attr.py": 1720704043778272895, + "venv/lib/python3.13/site-packages/numpy/f2py/cb_rules.py": 11397521081216402594, + "venv/lib/python3.13/site-packages/pygments/filters/__init__.py": 2992007913496948339, + "frontend/src/routes/settings/MigrationMappingsTable.svelte": 4467573699012255407, + "venv/lib/python3.13/site-packages/pandas/_libs/parsers.pyi": 18402185996588014111, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/collections.py": 16114931075157411913, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90": 13174951794239860144, + "venv/lib/python3.13/site-packages/pygments/lexers/slash.py": 8320676560518108343, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_swaplevel.py": 3584770792383216626, + "venv/lib/python3.13/site-packages/iniconfig-2.3.0.dist-info/METADATA": 16498441272591167134, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/METADATA": 14036738037171597049, + "venv/lib/python3.13/site-packages/numpy/dtypes.py": 14128421398870718692, + "backend/src/api/auth.py": 6636844886257776670, + "venv/lib/python3.13/site-packages/gitdb/db/loose.py": 17467413653016810702, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/timeout.py": 1807228452024740476, + "venv/lib/python3.13/site-packages/pygments/lexers/stata.py": 7249891970174867363, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/__init__.py": 15130871412783076140, + "frontend/src/routes/translate/[id]/+page.svelte": 1911443262444004956, + "frontend/build/_app/immutable/nodes/0.CWnMmjSc.js": 10108377383693638092, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/integration.py": 13610682193839598457, + "venv/lib/python3.13/site-packages/dateutil/tz/win.py": 8427821225251397364, + "backend/src/core/auth/config.py": 2961507628300548714, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/authlib/integrations/django_oauth1/authorization_server.py": 6858244712625056421, + "venv/lib/python3.13/site-packages/authlib/integrations/base_client/async_app.py": 4329794049222609894, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/__init__.py": 13331622784664204066, + "venv/lib/python3.13/site-packages/pygments/lexers/qlik.py": 3881663935630350152, + "venv/lib/python3.13/site-packages/pygments/lexers/javascript.py": 16869490851285457857, + "frontend/src/components/llm/__tests__/provider_config.integration.test.js": 12605115626277870995, + "backend/src/services/clean_release/enums.py": 7365670144442292671, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/RECORD": 2688648742701423549, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/auto.py": 12818217385551437286, + "venv/lib/python3.13/site-packages/pygments/lexers/pony.py": 2720635393743617141, + "backend/src/api/routes/git/_helpers.py": 3960455954241740267, + "frontend/src/components/git/GitReleasePanel.svelte": 14875953299937841077, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation": 13992741783834278677, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/interface.py": 3134071530627935964, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/validator.py": 14200019408839159476, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo.f": 5690596225005490325, + "venv/lib/python3.13/site-packages/pandas/core/tools/datetimes.py": 13313374952742129866, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/METADATA": 3179724236887811680, + "frontend/src/components/StartupEnvironmentWizard.svelte": 8046284364754906166, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexers/python.py": 17886036670342116501, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/compat.py": 5871636909854554063, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_non_unique.py": 15286893322149413712, + "venv/lib/python3.13/site-packages/uvicorn/lifespan/off.py": 16254524872582859561, + "venv/lib/python3.13/site-packages/pydantic/_internal/_namespace_utils.py": 5237766366340181382, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/_envs.py": 5657151394155576509, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/WHEEL": 6514509858522675228, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/__init__.py": 10261654903106416888, + "venv/lib/python3.13/site-packages/pygments/plugin.py": 18006138132596504101, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/mongodb.py": 5310116401542377882, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/base.cpython-313-x86_64-linux-gnu.so": 8335798324308957127, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/__init__.py": 18036348770966744795, + "venv/lib/python3.13/site-packages/click/formatting.py": 6694583529073729642, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_complex.py": 12963449957363121481, + "venv/lib/python3.13/site-packages/packaging/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jeepney/io/asyncio.py": 13239992245695516007, + "venv/lib/python3.13/site-packages/jsonschema/tests/typing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/parse.py": 2427019397934437210, + "frontend/build/_app/immutable/nodes/12.DDTJ85nU.js": 2496436780075636781, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/orderinglist.py": 10162099108656794338, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/dotenv/parser.py": 17651523026132242005, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_replace.py": 15992095120302643273, + "venv/lib/python3.13/site-packages/numpy/lib/user_array.py": 14003456655595459585, + "venv/lib/python3.13/site-packages/httpcore/_sync/http_proxy.py": 14037211594707072958, + "venv/lib/python3.13/site-packages/httpcore/__init__.py": 5897259569277532401, + "backend/src/core/superset_client/_base.py": 10958088163566963237, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptodome.py": 15753279711312689193, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/cli/hi77.f": 10617763407280454334, + "venv/lib/python3.13/site-packages/websockets-15.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/reserved_words.py": 8022121780993497971, + "venv/lib/python3.13/site-packages/pip/_internal/models/search_scope.py": 9282393652860589543, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/METADATA": 14543822270526146783, + "venv/lib/python3.13/site-packages/pygments/lexers/mosel.py": 1877592344012288438, + "frontend/build/_app/immutable/chunks/sEGDVeoa.js": 9540107777971680079, + "backend/src/api/routes/translate/__init__.py": 6357999798616465776, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_records.py": 12217508428903265797, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_packbits.py": 7592956764084658562, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/test_array.py": 16867692337986161626, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/default_styles.py": 4469204219504675080, + "venv/lib/python3.13/site-packages/PIL/ImagePalette.py": 9227837918026991107, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/ansi.py": 948249091929588017, + "frontend/playwright-report/trace/index.html": 6654608714409350530, + "frontend/postcss.config.js": 5714274776976071678, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_show_versions.py": 10577134135855180356, + "venv/lib/python3.13/site-packages/pydantic/v1/typing.py": 13467331592583800299, + "venv/lib/python3.13/site-packages/PIL/ImagePath.py": 18323293175183057101, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_array_from_pyobj.py": 9596224861290975079, + "venv/lib/python3.13/site-packages/pygments/lexers/compiled.py": 8215290039991205531, + "venv/lib/python3.13/site-packages/pygments/lexers/python.py": 8995519134978505744, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/toml.py": 2225382735669153136, + "venv/lib/python3.13/site-packages/pydantic/color.py": 1007422551673129827, + "venv/lib/python3.13/site-packages/pygments/styles/arduino.py": 4578385147314541233, + "frontend/src/routes/datasets/[id]/+page.svelte": 14911166036063098761, + "venv/lib/python3.13/site-packages/pygments/lexers/chapel.py": 7619603166448145621, + "venv/lib/python3.13/site-packages/httpx-0.28.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/chunks/DDT5MMTm.js": 14618179099689778175, + "venv/lib/python3.13/site-packages/pandas/io/formats/csvs.py": 17223598248259691292, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_ufunclike.py": 13752381070039804384, + "venv/lib/python3.13/site-packages/numpy/char/__init__.py": 4428218097234308768, + "venv/lib/python3.13/site-packages/numpy/ctypeslib/_ctypeslib.py": 12636954896699095212, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_period.py": 7727606662611927293, + "venv/lib/python3.13/site-packages/git/refs/__init__.py": 16246686106073400519, + "venv/lib/python3.13/site-packages/pygments/lexers/ml.py": 7510453371068494792, + "frontend/build/_app/immutable/chunks/2dOUpm6k.js": 11811637653151731489, + "venv/lib/python3.13/site-packages/numpy/matlib.pyi": 8017902013455539981, + "venv/lib/python3.13/site-packages/anyio/_core/_tasks.py": 14104828341875599130, + "venv/lib/python3.13/site-packages/passlib/crypto/scrypt/__init__.py": 4390908730288159455, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg8000.py": 6580512354643849828, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_add_prefix_suffix.py": 4815518357936092237, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/period.pyi": 13110894861187422750, + "frontend/src/lib/components/dataset-review/__tests__/us2_semantic_workspace.ux.test.js": 3550956860258259058, + "venv/lib/python3.13/site-packages/h11-0.16.0.dist-info/METADATA": 8128818962678047497, + "venv/lib/python3.13/site-packages/fastapi/responses.py": 6092572095549573593, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_nanfunctions.py": 2356468092336024365, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarmath.py": 9762951701352556447, + "venv/lib/python3.13/site-packages/pandas/core/api.py": 3390809109543982410, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/METADATA": 3474626408138844944, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/WHEEL": 16784970174376303810, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/scoping.py": 18223258186431020473, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/response.py": 353446217435156470, + "venv/lib/python3.13/site-packages/numpy/linalg/_umath_linalg.cpython-313-x86_64-linux-gnu.so": 17652852308919396403, + "venv/lib/python3.13/site-packages/numpy/doc/ufuncs.py": 11706048944901534664, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_direct.py": 12680113511641199070, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_numba.py": 203614377324678234, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/__init__.py": 4870269250323682576, + "venv/lib/python3.13/site-packages/git/util.py": 7424113599506269603, + "venv/lib/python3.13/site-packages/urllib3/contrib/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/test_str_accessor.py": 4066094997616994612, + "venv/lib/python3.13/site-packages/pygments/lexers/maple.py": 7402467573829618534, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_arrow_interface.py": 9757086292358759236, + "venv/lib/python3.13/site-packages/pandas/core/indexers/objects.py": 409599993084996593, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_getitem.py": 11882213323878588707, + "venv/lib/python3.13/site-packages/ecdsa/ecdh.py": 12596317261561755793, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/palette.py": 17383863392192572184, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Postfix.pyi": 2700568594438441246, + "venv/lib/python3.13/site-packages/anyio/_core/_streams.py": 6436461519284884601, + "venv/lib/python3.13/site-packages/pygments/lexers/agile.py": 5686162551416231457, + "venv/lib/python3.13/site-packages/packaging/tags.py": 1999137344425005827, + "frontend/src/lib/components/health/ScheduleAtAGlance.svelte": 3094566922259479417, + "venv/lib/python3.13/site-packages/attr/exceptions.pyi": 12323493441583681402, + "venv/lib/python3.13/site-packages/pip/_internal/utils/compatibility_tags.py": 15862649917149158291, + "venv/lib/python3.13/site-packages/_pytest/_argcomplete.py": 3586514420674089892, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.h": 4516275133897904047, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/RECORD": 16558021503346615951, + "venv/lib/python3.13/site-packages/dateutil/parser/__init__.py": 11377431154251655738, + "venv/lib/python3.13/site-packages/authlib-1.6.6.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/multiarray.pyi": 17232959648651278910, + "venv/lib/python3.13/site-packages/pygments/formatters/img.py": 18230180171537565208, + "venv/lib/python3.13/site-packages/pygments/style.py": 17393199235575070210, + "frontend/src/components/git/GitInitPanel.svelte": 3002620133377315800, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_insert.py": 17383986803728810587, + "venv/lib/python3.13/site-packages/dotenv/ipython.py": 15904966766060247908, + "venv/lib/python3.13/site-packages/numpy/polynomial/polyutils.py": 12355826783958402233, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/missing.py": 14589973874359353799, + "backend/src/core/task_manager/cleanup.py": 8316318318890394605, + "backend/src/api/routes/__tests__/test_reports_detail_api.py": 7284151749869192310, + "venv/lib/python3.13/site-packages/sqlalchemy/__init__.py": 9751988289698484530, + "venv/lib/python3.13/site-packages/httpcore/_sync/__init__.py": 7676937747094511752, + "backend/src/services/clean_release/__tests__/test_manifest_builder.py": 9320699981861675127, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz_py.py": 6428078990080243608, + "venv/lib/python3.13/site-packages/numpy/f2py/__main__.py": 12567751646090102167, + "frontend/src/lib/components/dataset-review/__tests__/source_intake_panel.ux.test.js": 13445861056598482363, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_factorize.py": 861897342553280506, + "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/series/methods/test_is_monotonic.py": 4626065848596214108, + "venv/lib/python3.13/site-packages/click/shell_completion.py": 5858110451169927373, + "backend/src/api/routes/settings.py": 15653340367960122341, + "venv/lib/python3.13/site-packages/pip/_internal/network/auth.py": 6159841209618753296, + "backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py": 2367759303622417201, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/parameters.py": 12219404446503940066, + "venv/lib/python3.13/site-packages/numpy/matrixlib/defmatrix.py": 4940170059946018356, + "venv/lib/python3.13/site-packages/pygments/formatters/__init__.py": 8009871891954370829, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/licenses/LICENSE": 14230156892574098522, + "venv/lib/python3.13/site-packages/keyring/util/platform_.py": 16978095707950463638, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/base.py": 13454394827268856575, + "venv/lib/python3.13/site-packages/pandas/tests/config/test_config.py": 4630144191929135452, + "venv/lib/python3.13/site-packages/pip/_vendor/msgpack/ext.py": 15699809032725838985, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_jsonschema_test_suite.py": 12733761462141495972, + "venv/lib/python3.13/site-packages/pydantic_settings/exceptions.py": 18300876747412267999, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_api.py": 16743710460729009914, + "venv/lib/python3.13/site-packages/numpy/core/einsumfunc.py": 3484247123731380377, + "venv/lib/python3.13/site-packages/charset_normalizer/api.py": 9172704759115759638, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90": 13833561828029901615, + "venv/lib/python3.13/site-packages/yaml/tokens.py": 2279161238859232338, + "venv/lib/python3.13/site-packages/uvicorn/protocols/websockets/__init__.py": 15130871412783076140, + "backend/src/services/git/_gitea.py": 12631200182530815617, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict_of_blocks.py": 11646835537993064324, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/test_na_scalar.py": 13950899907067372014, + "backend/src/api/routes/dashboards/_detail_routes.py": 12522696473630508473, + "venv/lib/python3.13/site-packages/greenlet/greenlet_exceptions.hpp": 8819301638282185623, + "venv/lib/python3.13/site-packages/pip/_internal/utils/virtualenv.py": 14416705841810221305, + "venv/lib/python3.13/site-packages/gitpython-3.1.46.dist-info/licenses/LICENSE": 12688029424398428498, + "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/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation": 4826455560768665215, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py": 2516476609539242190, + "venv/lib/python3.13/site-packages/pydantic/experimental/pipeline.py": 9493054841465227788, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_compression.py": 3167245427092658522, + "venv/lib/python3.13/site-packages/starlette/middleware/sessions.py": 11719848399661632707, + "venv/lib/python3.13/site-packages/pandas/tests/config/test_localization.py": 9524481848419616725, + "venv/lib/python3.13/site-packages/pygments/lexers/go.py": 11118104397271513417, + "backend/src/services/clean_release/source_isolation.py": 18208654007489616188, + "backend/git_repos/remote/test-repo.git/hooks/pre-push.sample": 8029776382195911768, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/kind/foo.f90": 1367964042730902899, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_array_coercion.py": 3551994404797560483, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_concat.py": 16549010224568175202, + "frontend/src/lib/components/reports/__tests__/report_card.ux.test.js": 14899927226278257748, + "venv/lib/python3.13/site-packages/numpy/_core/records.py": 11414828908088050950, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_deprecations.py": 16367195310156359251, + "venv/lib/python3.13/site-packages/certifi/__main__.py": 13417658012431779061, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/typst.tpl": 5055419073126793137, + "venv/lib/python3.13/site-packages/pandas/core/groupby/numba_.py": 15997665748332235683, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_quoting.py": 1147992698412929658, + "venv/lib/python3.13/site-packages/pygments/lexers/macaulay2.py": 8022891778577314212, + "venv/lib/python3.13/site-packages/cryptography/hazmat/_oid.py": 755042927629281577, + "frontend/build/_app/immutable/chunks/CjoRN64c.js": 16472953773693067178, + "venv/lib/python3.13/site-packages/pandas/tests/generic/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py": 2375452080667815941, + "venv/lib/python3.13/site-packages/pygments/lexers/markup.py": 10311057264960923433, + "venv/lib/python3.13/site-packages/pygments/lexers/diff.py": 5930189593946259160, + "venv/lib/python3.13/site-packages/pandas/_testing/compat.py": 10172779814048259850, + "venv/lib/python3.13/site-packages/keyring/testing/util.py": 11195868112805409554, + "venv/lib/python3.13/site-packages/pydantic/errors.py": 3506829204186508192, + "build.sh": 7054451887134163485, + "venv/lib/python3.13/site-packages/numpy/lib/_type_check_impl.pyi": 2667658052734929089, + "venv/lib/python3.13/site-packages/pygments/lexers/dalvik.py": 5549983892200382076, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/request.py": 10492090878715126550, + "venv/lib/python3.13/site-packages/keyring/testing/backend.py": 14295829193445781542, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/loading.py": 3460142472461437916, + "frontend/src/lib/components/assistant/AssistantClarificationCard.svelte": 6722890639215637790, + "venv/lib/python3.13/site-packages/numpy/_core/strings.py": 3623885046208831106, + "venv/lib/python3.13/site-packages/packaging/licenses/_spdx.py": 16440031845441362300, + "backend/src/api/routes/__tests__/test_reports_api.py": 8830242634438523357, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/module_data_docstring.f90": 18245403117623015312, + "venv/lib/python3.13/site-packages/numpy/lib/_user_array_impl.pyi": 7171810177801103765, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_setops.py": 5208912445718807372, + "venv/lib/python3.13/site-packages/rpds/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/_pytest/setupplan.py": 7496801885995567141, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/licenses/_spdx.py": 17182188548503720124, + "venv/lib/python3.13/site-packages/pandas/compat/numpy/function.py": 18405870240333383757, + "venv/lib/python3.13/site-packages/pandas/io/excel/__init__.py": 6662687963241471393, + "venv/lib/python3.13/site-packages/_pytest/python_api.py": 12953851690889336092, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/groupby.py": 12749730954888633240, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/token.py": 6987328478153445584, + "venv/lib/python3.13/site-packages/pygments/styles/zenburn.py": 1031869867933871309, + "venv/lib/python3.13/site-packages/ecdsa/_rwlock.py": 7971972922423146201, + "frontend/src/lib/components/translate/TranslationRunResult.svelte": 3992997916593732645, + "venv/lib/python3.13/site-packages/pandas/core/methods/selectn.py": 13552176539021625776, + "venv/lib/python3.13/site-packages/numpy/f2py/common_rules.pyi": 2104100025130695295, + "backend/src/models/dashboard.py": 8479838979214366697, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libcom_err-2abe824b.so.2.1": 12870528025628871295, + "venv/lib/python3.13/site-packages/pip/_internal/utils/datetime.py": 6816292030061301011, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_array.py": 12514884344165043136, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_reshape.py": 5572426834735088916, + "backend/src/core/__tests__/test_throttled_scheduler.py": 10949494963069000037, + "venv/lib/python3.13/site-packages/pip/_internal/utils/direct_url_helpers.py": 6075890513530296650, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_shift.py": 14681514853406253657, + "backend/src/scripts/__init__.py": 5400372851656282343, + "venv/lib/python3.13/site-packages/numpy/linalg/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_dtypes.py": 2313400030798822026, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/base.py": 14908084548919567658, + "venv/lib/python3.13/site-packages/httpcore/_async/__init__.py": 491192949420297153, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/foo.f": 6349567809926050379, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_format.py": 9331389900588353667, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/sync.py": 6189260178302531376, + "venv/lib/python3.13/site-packages/jsonschema/tests/_suite.py": 6307666366417438489, + "venv/lib/python3.13/site-packages/pandas/core/indexes/timedeltas.py": 13653393430363556843, + "venv/lib/python3.13/site-packages/charset_normalizer/legacy.py": 1706599349563920562, + "backend/src/schemas/profile.py": 7950698901810733002, + "venv/lib/python3.13/site-packages/pandas/io/formats/css.py": 11288129826285529457, + "venv/lib/python3.13/site-packages/more_itertools-10.8.0.dist-info/RECORD": 14375680579341422646, + "backend/tests/test_dashboards_api.py": 2278794209397518464, + "venv/lib/python3.13/site-packages/pandas/tests/apply/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/annotated_types-0.7.0.dist-info/RECORD": 11904769847385571600, + "venv/lib/python3.13/site-packages/websockets/asyncio/async_timeout.py": 7267209982032642028, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_alpha_unix.h": 2759424570606117942, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/events.py": 10224214051422678828, + "venv/lib/python3.13/site-packages/pydantic/v1/dataclasses.py": 7833468513057242440, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_reductions.py": 3575617237516305456, + "venv/lib/python3.13/site-packages/pygments/regexopt.py": 16073437303824961930, + "venv/lib/python3.13/site-packages/jeepney/io/tests/test_threading.py": 6656552495241857519, + "venv/lib/python3.13/site-packages/pandas/core/computation/common.py": 5369352684655954608, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets.py": 4499538899492148499, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_logical.py": 6818185860296232476, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/provision.py": 13156893203444936309, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ranges.py": 14549386056660231279, + "venv/lib/python3.13/site-packages/pygments/lexers/rust.py": 8605690716125176329, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/dtype.py": 9342837412280377086, + "venv/lib/python3.13/site-packages/pip/_internal/models/link.py": 7172346414535657925, + "venv/lib/python3.13/site-packages/numpy/f2py/diagnose.py": 503331864022631297, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/jose/backends/base.py": 12795468809472351388, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/wheel.py": 7728646523045538484, + "venv/lib/python3.13/site-packages/apscheduler/executors/base.py": 1980520974511822101, + "venv/lib/python3.13/site-packages/itsdangerous/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/construction.py": 10646956189518908985, + "venv/lib/python3.13/site-packages/pip/_internal/utils/_log.py": 13011536737418204268, + "venv/lib/python3.13/site-packages/pandas/core/computation/scope.py": 16859504937881548797, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_iat.py": 3570464615146398178, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_unicode_ddl.py": 2569618488804767890, + "venv/lib/python3.13/site-packages/pygments/lexers/d.py": 18120801227801223376, + "backend/git_repos/remote/test-repo.git/refs/heads/dev": 8596267258668462395, + "venv/lib/python3.13/site-packages/PIL/ImageQt.py": 6607270889359138659, + "frontend/build/_app/immutable/chunks/gRGygy_f.js": 17282722948808474320, + "venv/lib/python3.13/site-packages/pygments/styles/nord.py": 8469538903422182155, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_nlargest_nsmallest.py": 11049656379959696695, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/RECORD": 12575893084587070195, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_reduction.py": 1049551473665255648, + "venv/lib/python3.13/site-packages/jsonschema/_utils.py": 14237077105384631097, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/resolvelib/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_kind.py": 18178830861475480607, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/manifest.py": 16998683210177680416, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/schema.py": 5391655516870611151, + "venv/lib/python3.13/site-packages/click/_termui_impl.py": 3296085065310341855, + "venv/lib/python3.13/site-packages/pip/_internal/index/collector.py": 7454652626329467900, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_scrypt.py": 8106466515670064013, + "venv/lib/python3.13/site-packages/pygments/lexers/_googlesql_builtins.py": 12251289884604745945, + "backend/src/api/routes/llm.py": 7404985960617844546, + "backend/src/models/git.py": 9387561498910534118, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/plugin/bootstrap.py": 3865947239497500815, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/connection.py": 15405047955974108860, + "venv/lib/python3.13/site-packages/attrs/__init__.py": 9502968706258875910, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_read.py": 8825002468745406134, + "backend/src/services/clean_release/dto.py": 11031410734734770552, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_groupby.py": 15721254196883995634, + "venv/lib/python3.13/site-packages/numpy/_utils/__init__.pyi": 13530522898409268883, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/WHEEL": 9788895026336324100, + "venv/lib/python3.13/site-packages/numpy/_core/_multiarray_tests.cpython-313-x86_64-linux-gnu.so": 442168371609469538, + "venv/lib/python3.13/site-packages/pygments/cmdline.py": 15628499088643246809, + "venv/lib/python3.13/site-packages/packaging/licenses/__init__.py": 15879493360260891293, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_setops.py": 16240008859650640717, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_digest.py": 7988469818593853943, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_datetime64.py": 16272266806084058743, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/LICENSE": 16510279186416777136, + "venv/lib/python3.13/site-packages/pandas/core/computation/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/sparse/test_dtype.py": 12210524152630532747, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_defmatrix.py": 2982572083770917411, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8414/models.py": 3567900447243180991, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/packages.py": 11689856177725665974, + "venv/lib/python3.13/site-packages/numpy/_core/umath.pyi": 11775804030935134661, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/mariadb.py": 3109042476851791996, + "venv/lib/python3.13/site-packages/git/refs/remote.py": 4391983355222612205, + "backend/tests/services/clean_release/test_compliance_execution_service.py": 5924200441771414883, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/cache_key.py": 11118819065204404106, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/decl_class.py": 6328411894571735935, + "venv/lib/python3.13/site-packages/pandas/_libs/internals.cpython-313-x86_64-linux-gnu.so": 2008633361686956377, + "venv/lib/python3.13/site-packages/pandas/io/html.py": 2727247063231114153, + "backend/git_repos/remote/test-repo.git/hooks/prepare-commit-msg.sample": 7530253302780245896, + "venv/lib/python3.13/site-packages/pandas/_libs/testing.cpython-313-x86_64-linux-gnu.so": 16758333404587340103, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/providers/azure.py": 13529763490186254462, + "venv/lib/python3.13/site-packages/pandas/tests/io/test_html.py": 12040484325988635032, + "venv/lib/python3.13/site-packages/pydantic/_internal/_schema_gather.py": 3634138701088855517, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc8628/__init__.py": 6532094538918910232, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90": 8079594129222364031, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/errors.py": 12777931960088171310, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/frame/test_hist_box_by.py": 16197297231683144299, + "venv/lib/python3.13/site-packages/passlib/handlers/sha1_crypt.py": 5752556581809938954, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_functions.py": 2255133375699086300, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_map.py": 6556132946198785761, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/WHEEL": 18203500019759199992, + "frontend/src/components/git/DeploymentModal.svelte": 16301125393395343650, + "venv/lib/python3.13/site-packages/starlette/endpoints.py": 3379755567024530053, + "venv/lib/python3.13/site-packages/pandas/_libs/window/__init__.py": 15130871412783076140, + "frontend/src/components/TaskList.svelte": 3024343043730631288, + "frontend/build/_app/immutable/nodes/33.Aj1tQ4W1.js": 1594581007913482648, + "backend/src/plugins/translate/__tests__/test_token_budget.py": 9612693566837223655, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_factorize.py": 5585211699185937865, + "backend/src/api/routes/__tests__/test_assistant_api.py": 4079781811717182404, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalar_ctors.py": 631744056514965940, + "venv/lib/python3.13/site-packages/starlette/config.py": 16509394679506300256, + "venv/lib/python3.13/site-packages/pandas/_libs/properties.pyi": 9268470215750269699, + "venv/lib/python3.13/site-packages/pandas/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_ops.py": 3875181889032080505, + "venv/lib/python3.13/site-packages/pip/_internal/commands/debug.py": 13528633965821062950, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/_typing.py": 10524021526716767489, + "frontend/src/routes/settings/settings-utils.js": 1940619437304867415, + "venv/lib/python3.13/site-packages/rsa/key.py": 4783269051050521475, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/RECORD": 5169907629260560698, + "backend/src/plugins/translate/_utils.py": 10016440264788256359, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_scalar_compat.py": 10534925655070162459, + "venv/lib/python3.13/site-packages/pandas/tests/extension/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7009/parameters.py": 1647490964392525933, + "venv/lib/python3.13/site-packages/_pytest/doctest.py": 6126919596776592278, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/rsa.py": 5392922995791487437, + "backend/tests/test_translate_scheduler.py": 14274816721941617887, + "venv/lib/python3.13/site-packages/psycopg2/__init__.py": 15798412693009721199, + "venv/lib/python3.13/site-packages/greenlet/slp_platformselect.h": 10428201768098464386, + "venv/lib/python3.13/site-packages/authlib/integrations/requests_client/oauth2_session.py": 7076806577412682835, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/const_vs_enum.py": 12873459583943748931, + "venv/lib/python3.13/site-packages/pip/_internal/metadata/importlib/__init__.py": 10834852742917144496, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/logging.py": 2426447364230673649, + "venv/lib/python3.13/site-packages/_pytest/monkeypatch.py": 2635774457434545573, + "venv/lib/python3.13/site-packages/pydantic/v1/version.py": 2758971830527526972, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/replace.py": 1708865864686705833, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/METADATA": 10220680536734745103, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h": 7896028550808252043, + "venv/lib/python3.13/site-packages/ecdsa/keys.py": 10281170640484982154, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_util.py": 16908393806993809474, + "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/tests/io/test_fsspec.py": 6936167344144998172, + "venv/lib/python3.13/site-packages/pyasn1/type/constraint.py": 16776615503418773283, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/boolean/test_function.py": 7048185308307653546, + "venv/lib/python3.13/site-packages/dateutil/relativedelta.py": 5903095963079475484, + "venv/lib/python3.13/site-packages/pip/_internal/resolution/base.py": 10514193453447954780, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_chained_assignment_deprecation.py": 7694137945143129474, + "frontend/src/lib/components/StartMaintenanceForm.svelte": 6639622284028606563, + "frontend/src/lib/api/translate/schedules.js": 8616345664085016472, + "frontend/src/routes/login/+page.svelte": 18430869485200259448, + "frontend/src/components/backups/BackupManager.svelte": 15237659305406789107, + "frontend/build/_app/immutable/nodes/36.B_fEKtct.js": 18068657546781069466, + "frontend/build/_app/immutable/nodes/5.Qu948XkR.js": 7156066372883630056, + "frontend/src/routes/translate/history/+page.svelte": 9504117584329454876, + "backend/src/plugins/llm_analysis/plugin.py": 17113713561460406867, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/assertsql.py": 4633484475514351889, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_utils.pyi": 12312677132342982866, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_pickle.py": 16196792378104396231, + "frontend/src/components/storage/FileUpload.svelte": 14805293086068620697, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_csv.py": 10737444103906389448, + "venv/lib/python3.13/site-packages/numpy-2.4.2.dist-info/RECORD": 8104089156015954779, + "venv/lib/python3.13/site-packages/PIL/IcoImagePlugin.py": 14483964191652228364, + "venv/lib/python3.13/site-packages/pygments/lexers/cplint.py": 13990118342267278047, + "backend/src/core/utils/async_network.py": 840981454868177222, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/attributes.py": 5068814626384132900, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/ecdsa/test_ecdsa.py": 17595025859105321562, + "venv/lib/python3.13/site-packages/dotenv/main.py": 7408889670575271484, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi": 9835891299056543360, + "venv/lib/python3.13/site-packages/gitdb/util.py": 645937410168583692, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_multiindex.py": 13723677252432338937, + "venv/lib/python3.13/site-packages/pyasn1/type/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/__init__.py": 13584649922093198724, + "venv/lib/python3.13/site-packages/numpy/_core/defchararray.py": 15550230459945996915, + "venv/lib/python3.13/site-packages/pygments/lexers/text.py": 10572727755736597715, + "venv/lib/python3.13/site-packages/pygments/styles/onedark.py": 17580335614588531275, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_halfyear.py": 9376272342364384767, + "frontend/src/lib/stores/taskDrawer.js": 6659505033581293370, + "backend/src/core/utils/superset_context_extractor/_pii.py": 16897386128094460655, + "venv/lib/python3.13/site-packages/jsonschema/tests/typing/test_all_concrete_validators_match_protocol.py": 14824388798676578409, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/einsumfunc.pyi": 8902765738896588686, + "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.py": 7658234162211356265, + "venv/lib/python3.13/site-packages/keyring/compat/py312.py": 17581691618899404491, + "venv/bin/keyring": 1488968652276547659, + "frontend/playwright-report/data/ac7f153484f7d6b15b773641e328a5ad9204f736.webm": 17964728097298408466, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h": 5001035774408914877, + "backend/src/core/utils/superset_context_extractor/__init__.py": 1074191108198498747, + "backend/src/services/clean_release/repositories/policy_repository.py": 10990781278715170404, + "frontend/build/_app/immutable/chunks/DNOraAy0.js": 868732761380476466, + "venv/lib/python3.13/site-packages/greenlet/tests/test_cpp.py": 10982107081267457286, + "venv/lib/python3.13/site-packages/greenlet/TMainGreenlet.cpp": 9489520001674089404, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_isin.py": 11330491145602008796, + "venv/lib/python3.13/site-packages/apscheduler-3.11.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/gitdb/test/__init__.py": 18393574323937353933, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/style.py": 10665998898253460114, + "venv/lib/python3.13/site-packages/pydantic/_internal/_import_utils.py": 4029157986210295967, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py": 8539232219382152238, + "venv/lib/python3.13/site-packages/numpy/_utils/_pep440.pyi": 6796322258258182775, + "venv/lib/python3.13/site-packages/pandas/util/_print_versions.py": 15326663505771588740, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_equals.py": 11041884432990762650, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_npfuncs.py": 8238385897366878558, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/period/test_constructors.py": 9478848417896027917, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_arraypad.py": 4907193085512342162, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_results.py": 18145930285449734975, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi": 7385072545198817771, + "venv/lib/python3.13/site-packages/pygments/formatters/svg.py": 11686316844190214147, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_py.py": 13809503317864539103, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/METADATA": 9586902338916246692, + "venv/lib/python3.13/site-packages/numpy/random/_examples/cffi/extending.py": 9859383893070793914, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/__init__.py": 11157967642611612522, + "venv/lib/python3.13/site-packages/pygments/lexers/erlang.py": 11757064262773184741, + "backend/src/services/dataset_review/orchestrator_pkg/_helpers.py": 3718757635506173013, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/__init__.py": 15130871412783076140, + "frontend/src/components/TaskRunner.svelte": 18014857434320509117, + "backend/ss_tools_backend.egg-info/PKG-INFO": 15134841326777953914, + "venv/lib/python3.13/site-packages/passlib/ext/django/__init__.py": 11713862539944289631, + "frontend/src/lib/api/translate/target-schema.js": 10665479411127476571, + "scripts/generate_financial_arrears_data.py": 15989529185799374517, + "venv/lib/python3.13/site-packages/pluggy/__init__.py": 8269188363563356631, + "venv/lib/python3.13/site-packages/authlib/jose/jwk.py": 13560749074922587626, + "venv/lib/python3.13/site-packages/rapidfuzz/fuzz.py": 1094797446508902066, + "venv/lib/python3.13/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py": 13570990531070630950, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv": 1665171675551692225, + "venv/lib/python3.13/site-packages/keyring-25.7.0.dist-info/RECORD": 10264342250058307301, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_slice.py": 9936085512921529417, + "venv/lib/python3.13/site-packages/rsa/util.py": 13423880475585138638, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/period/test_arithmetic.py": 13320788210970132239, + "venv/lib/python3.13/site-packages/PIL/_tkinter_finder.py": 14045496501810535432, + "venv/lib/python3.13/site-packages/pygments/lexers/spice.py": 1376126320935115350, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_repeat.py": 9155935990114743583, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/json.py": 15085143436056608404, + "frontend/src/app.html": 10207534912546549080, + "backend/src/plugins/translate/__tests__/test_dictionary.py": 4341966549214032934, + "dist/docker/frontend.0.1.1.tar.xz": 14558310887004056908, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_replace.py": 8165088653532047247, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/common.py": 11384497819737275399, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_pop.py": 14885271225856187795, + "venv/lib/python3.13/site-packages/pandas/api/__init__.py": 1145864207387918302, + "backend/src/core/config_manager.py": 4939178394157798605, + "venv/lib/python3.13/site-packages/click/globals.py": 18353671282454331523, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_reflection.py": 10520778598547003532, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/style.py": 12654125988995362593, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py": 12264234876933578367, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/WHEEL": 8600534672961461758, + "venv/lib/python3.13/site-packages/numpy/random/_common.cpython-313-x86_64-linux-gnu.so": 12834724130890991478, + "venv/lib/python3.13/site-packages/passlib/tests/test_apps.py": 10454136535890937237, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_join.py": 1364886077926604427, + "venv/lib/python3.13/site-packages/pycparser/c_ast.py": 5942107079119742, + "frontend/src/lib/components/assistant/__tests__/assistant_clarification.integration.test.js": 12258270009984504212, + "venv/lib/python3.13/site-packages/fastapi/_compat/__init__.py": 12380131786677943349, + "venv/lib/python3.13/site-packages/PIL/Hdf5StubImagePlugin.py": 15654153796225833950, + "frontend/build/_app/immutable/chunks/D0ftnVnT.js": 17464841514774947275, + "venv/lib/python3.13/site-packages/sqlalchemy-2.0.45.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/attr/validators.pyi": 15579625896285277321, + "venv/lib/python3.13/site-packages/pyasn1/error.py": 11036037300994516747, + "venv/lib/python3.13/site-packages/requests/sessions.py": 6936640856092320928, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9068/claims.py": 14794441479740527265, + "venv/lib/python3.13/site-packages/ecdsa-0.19.1.dist-info/WHEEL": 17410883677306885019, + "venv/lib/python3.13/site-packages/websockets/extensions/__init__.py": 13067201313921664210, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/themes.py": 6451091097727599550, + "venv/lib/python3.13/site-packages/attr/_version_info.pyi": 7141309436445210354, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/argon2.py": 15389474901714096890, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/__init__.py": 2345997696115514124, + "backend/src/core/migration_engine.py": 3310429374293524108, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/instrumentation.py": 13198832283145198959, + "backend/src/core/utils/superset_context_extractor/_parsing.py": 17093712504833649098, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayobject.h": 4345432890284821918, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_resolution.py": 9651416588266430520, + "venv/lib/python3.13/site-packages/uvicorn/server.py": 15714008348292243019, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_indexing.py": 6039808271042864401, + "venv/lib/python3.13/site-packages/PIL/_webp.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/numpy/lib/_arraysetops_impl.py": 5583478355093966990, + "frontend/src/lib/components/layout/__tests__/test_sidebar.svelte.js": 1424894894434906249, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_classes.py": 1440926036579216168, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/__init__.py": 15130871412783076140, + "frontend/e2e/tests/login.e2e.js": 16303843677272482041, + "venv/lib/python3.13/site-packages/PIL/MpegImagePlugin.py": 7726254767528154514, + "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.pyi": 2628035888703031029, + "backend/alembic/script.py.mako": 7041141123739810216, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_filters.py": 17271344092069736999, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/authorization_server.py": 724388765673082720, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_asfreq.py": 2701081989348180239, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_block_internals.py": 17935662848672401507, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/pickleable.py": 7712040860601343075, + "venv/lib/python3.13/site-packages/h11/_writers.py": 8585823094975171480, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24662.f90": 4241310200087270990, + "venv/lib/python3.13/site-packages/numpy/random/mtrand.pyi": 17144590106028661128, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_index_col.py": 17604191644943383567, + "venv/lib/python3.13/site-packages/pygments/lexers/qvt.py": 1895735583818227972, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_info.py": 10615285239043745712, + "backend/src/api/routes/git/_gitea_routes.py": 14644218433873522624, + "venv/lib/python3.13/site-packages/pip/_internal/operations/check.py": 16650663913976953800, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/constant_time.py": 2499026008403328245, + "venv/lib/python3.13/site-packages/pluggy/_tracing.py": 7276210024011809655, + "venv/lib/python3.13/site-packages/tzlocal-5.3.1.dist-info/METADATA": 11439969143853665311, + "venv/lib/python3.13/site-packages/uvicorn/config.py": 17317823506849880916, + "run_clean_tui.sh": 14305120550349644601, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/__init__.py": 3673322722277252961, + "venv/lib/python3.13/site-packages/pandas/core/internals/api.py": 14632030170441237968, + "frontend/src/routes/datasets/review/useReviewSession.js": 2378011913105385059, + "venv/lib/python3.13/site-packages/git/index/base.py": 641556304637379636, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/WHEEL": 16223367184831500348, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/dtype_api.h": 17040779421165903019, + "venv/lib/python3.13/site-packages/pygments/lexers/parasail.py": 7758704230750989282, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/provision.py": 8707620698060818654, + "venv/lib/python3.13/site-packages/pygments/lexers/web.py": 11104721221615804497, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_common.py": 2223069451949206319, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_np_datetime.py": 18363183516409621205, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/errors.py": 12935154705443176852, + "venv/lib/python3.13/site-packages/jose/jwe.py": 3325660353225624025, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/base_class/test_where.py": 16584772339591698754, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_at.py": 1029744344133153888, + "frontend/build/_app/immutable/nodes/28.MJ5rlU4U.js": 14941281040668339074, + "backend/src/schemas/__tests__/test_settings_and_health_schemas.py": 10518526918751273612, + "backend/src/services/clean_release/audit_service.py": 3614108458934359126, + "backend/src/services/llm_prompt_templates.py": 16187535610068299149, + "venv/lib/python3.13/site-packages/pyyaml-6.0.3.dist-info/WHEEL": 18203500019759199992, + "backend/src/plugins/translate/dictionary_crud.py": 17858252266960667195, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/client_auth.py": 3301527187487914220, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/metrics_cpp.cpython-313-x86_64-linux-gnu.so": 10263790384087091349, + "venv/lib/python3.13/site-packages/pydantic/class_validators.py": 4643597082531287188, + "backend/tests/services/clean_release/test_candidate_manifest_services.py": 16861589402854148894, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90": 8999550841368314739, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_misc.py": 16393451200513733144, + "venv/lib/python3.13/site-packages/more_itertools/more.pyi": 4844596605492825806, + "venv/lib/python3.13/site-packages/numpy/lib/_nanfunctions_impl.pyi": 12566839271245057531, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_index_new.py": 796607958391882182, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_timezones.py": 4771674179164304731, + "venv/lib/python3.13/site-packages/git/objects/fun.py": 15014209679156260865, + "venv/lib/python3.13/site-packages/dateutil/__init__.py": 17666544837260663800, + "venv/lib/python3.13/site-packages/numpy/_core/overrides.pyi": 13121243505132110607, + "venv/lib/python3.13/site-packages/apscheduler/triggers/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/io/sas/test_xport.py": 14080914637071212225, + "venv/lib/python3.13/site-packages/fastapi/security/api_key.py": 6965937678104291169, + "venv/lib/python3.13/site-packages/pandas/tests/reductions/__init__.py": 16150188643076000414, + "venv/lib/python3.13/site-packages/PIL/PalmImagePlugin.py": 13008868719182630239, + "venv/lib/python3.13/site-packages/numpy/random/_common.pxd": 3402284125943848851, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_invalid.py": 2762344062554575805, + "venv/lib/python3.13/site-packages/ecdsa/__init__.py": 6237633580090653788, + "venv/lib/python3.13/site-packages/anyio/_backends/_trio.py": 4764555436057754985, + "venv/lib/python3.13/site-packages/PIL/BlpImagePlugin.py": 7209218638257731375, + "backend/git_repos/remote/test-repo.git/refs/heads/master": 12485529318667335076, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/lib_polynomial.pyi": 9134949577567498894, + "venv/lib/python3.13/site-packages/pycparser/c_lexer.py": 10964496587169353564, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_interaction.py": 12216477658994324787, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_isoc.py": 4923640657296076239, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Levenshtein.pyi": 12925006572914814268, + "venv/lib/python3.13/site-packages/pandas/plotting/__init__.py": 13230487326686617492, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py": 16386268386376675175, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi": 11455144434558323236, + "venv/lib/python3.13/site-packages/numpy/_core/_methods.pyi": 9155045948490225716, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling.py": 18221459425751198218, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_split_partition.py": 2715491071550545667, + "venv/lib/python3.13/site-packages/pytest_asyncio/py.typed": 15130871412783076140, + "backend/src/scripts/init_auth_db.py": 1846761799125222512, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_numeric.py": 17391095502314929042, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_concat.py": 4472503149811617440, + "venv/lib/python3.13/site-packages/pygments/lexers/graphics.py": 13783143864729682444, + "backend/src/api/routes/translate/_router.py": 4164547666727936398, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS": 17022185907188244883, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_round_trip.py": 14684057343786032776, + "venv/lib/python3.13/site-packages/pandas/io/formats/templates/latex.tpl": 8820045022551446255, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_offsets_properties.py": 2340780879864207500, + "venv/lib/python3.13/site-packages/urllib3/contrib/emscripten/response.py": 9594165377270752433, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/shape.pyi": 2188930129299348535, + "venv/lib/python3.13/site-packages/pygments/lexers/devicetree.py": 9820277168995231927, + "backend/src/api/__init__.py": 5287505122015708040, + "venv/lib/python3.13/site-packages/PIL/_imagingtk.pyi": 18222325750818585549, + "backend/src/services/clean_release/stages/no_external_endpoints.py": 11899278509901673808, + "backend/src/services/clean_release/repositories/audit_repository.py": 9617813121624417458, + "venv/lib/python3.13/site-packages/greenlet/greenlet_allocator.hpp": 11041111583319491309, + "venv/lib/python3.13/site-packages/passlib-1.7.4.dist-info/RECORD": 3617343778671172258, + "venv/lib/python3.13/site-packages/numpy/lib/_function_base_impl.py": 14034239842770171660, + "venv/lib/python3.13/site-packages/pydantic/experimental/__init__.py": 492399139963056461, + "venv/lib/python3.13/site-packages/attr/converters.pyi": 17675091788614033166, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_constructors.py": 9815164146739254076, + "venv/lib/python3.13/site-packages/idna/__init__.py": 6489437464172324468, + "venv/lib/python3.13/site-packages/ecdsa/ellipticcurve.py": 15624510849346629163, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi": 3254633032236269842, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_records.py": 6252761812228230408, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_logical_ops.py": 16166386974005224415, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/strings/__init__.py": 5060190599837877599, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_mangle_dupes.py": 15613858733226279352, + "venv/lib/python3.13/site-packages/pandas/io/formats/style.py": 13235403689320479165, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/interfaces.py": 5371646629319169153, + "venv/lib/python3.13/site-packages/multipart/decoders.py": 11346752866822986212, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_interval.py": 1228451182688768814, + "frontend/src/routes/+error.svelte": 9437886843842311915, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/plugin.py": 16042078006552521613, + "backend/src/api/routes/admin_api_keys.py": 11414236449923083206, + "backend/src/api/routes/reports.py": 5647380957044157360, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7521/__init__.py": 635200170992032966, + "frontend/src/lib/components/dataset-review/__tests__/us3_execution_batch.ux.test.js": 13416996904332574966, + "venv/lib/python3.13/site-packages/pluggy/_result.py": 16790448391766505769, + "venv/lib/python3.13/site-packages/pandas/core/arraylike.py": 11439602957100017713, + "venv/lib/python3.13/site-packages/pygments/lexers/_sql_builtins.py": 5906655440517434734, + "backend/src/models/dataset_review_pkg/_enums.py": 2243691494729792539, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/DamerauLevenshtein_py.py": 1933257612725836484, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_series.py": 17126297747681689408, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/test_types.py": 4083297168618981717, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_upcast.py": 6496794053681247105, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/scope.py": 4096190764836489091, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/ext.py": 8361831054662096695, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/strategies.py": 14007486769065345085, + "backend/tests/core/test_mapping_service.py": 6888870177029085220, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/licenses/COPYING": 15270149301471737292, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/supercollider.py": 15306357945850389082, + "venv/lib/python3.13/site-packages/pip/_vendor/typing_extensions.py": 10158933506062403688, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/six.py": 1161259802604920635, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/asyncio.py": 11442130378027628520, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/shape.pyi": 17197248408326188931, + "venv/lib/python3.13/site-packages/pandas/_libs/sparse.pyi": 12526865400413362140, + "venv/lib/python3.13/site-packages/pandas/core/indexes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/formatters/_mapping.py": 13335227913146542481, + "venv/lib/python3.13/site-packages/pandas/core/array_algos/datetimelike_accumulations.py": 14719894187829729175, + "venv/lib/python3.13/site-packages/numpy/matlib.py": 112839038090033740, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_ufunc.py": 669019702416198889, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_hist_method.py": 2109257663592928, + "venv/lib/python3.13/site-packages/pygments/lexers/roboconf.py": 1335271183806115470, + "venv/lib/python3.13/site-packages/pygments/lexers/ezhil.py": 10294520768762308887, + "venv/lib/python3.13/site-packages/passlib/handlers/scrypt.py": 10089372287597257402, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_custom_dtypes.py": 12322100282959605055, + "venv/lib/python3.13/site-packages/jose/jwk.py": 2781217726458801910, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers.py": 4940305787631493030, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/getitem.py": 556339939822508169, + "backend/src/services/reports/normalizer.py": 11408466232944555336, + "backend/src/plugins/translate/dictionary_import_export.py": 12639118203353044308, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_period.py": 6047041810867211174, + "backend/src/services/maintenance/_banner_renderer.py": 17250656767428031478, + "backend/src/core/superset_client/_dashboards_crud.py": 8511586546743986158, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_formats.py": 13752366280743004410, + "venv/lib/python3.13/site-packages/pygments/lexers/_asy_builtins.py": 1665617945818958781, + "venv/lib/python3.13/site-packages/_pytest/pathlib.py": 9719734558816066453, + "venv/lib/python3.13/site-packages/gitdb/test/test_example.py": 3039934065817753241, + "venv/lib/python3.13/site-packages/greenlet-3.3.0.dist-info/licenses/LICENSE": 4123064337800029995, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/char.pyi": 1639810799219814643, + "venv/lib/python3.13/site-packages/numpy/f2py/_backends/__init__.py": 4265012785873472600, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/arithmetic.py": 3209727509456212551, + "frontend/src/lib/components/assistant/__tests__/assistant_first_message.integration.test.js": 16494645867501045726, + "venv/lib/python3.13/site-packages/packaging-26.0.dist-info/licenses/LICENSE.APACHE": 11041304845352917971, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_strings.py": 7168544888340296373, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/WHEEL": 5160964596297665692, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/controller.py": 5450931608244830335, + "venv/lib/python3.13/site-packages/six-1.17.0.dist-info/WHEEL": 9100692507274722091, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/index.py": 15694995431926521471, + "venv/lib/python3.13/site-packages/greenlet/tests/fail_initialstub_already_started.py": 5562030563802006923, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/ecdsa/util.py": 10543788809724099209, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_dict_compat.py": 18196543090455290455, + "venv/lib/python3.13/site-packages/pandas/_testing/contexts.py": 11714205921752896137, + "venv/lib/python3.13/site-packages/PIL/_imagingmorph.pyi": 18222325750818585549, + "venv/lib/python3.13/site-packages/greenlet/tests/test_generator_nested.py": 12822240347707346718, + "venv/lib/python3.13/site-packages/numpy/_core/numerictypes.pyi": 12144531601504755948, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli_w/_writer.py": 15053365792216907149, + "venv/lib/python3.13/site-packages/pygments/lexers/gleam.py": 5161116162065925222, + "frontend/src/lib/ui/HelpTooltip.svelte": 15082693035830243831, + "venv/lib/python3.13/site-packages/pygments/lexers/tnt.py": 4657130609241407766, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/interval/test_interval_new.py": 3893421355544517336, + "frontend/src/lib/api/reports.js": 2328857814720054000, + "venv/lib/python3.13/site-packages/pydantic/v1/parse.py": 5875950480538559709, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_indexerrors.py": 4434868847540549873, + "backend/src/api/routes/translate/_correction_routes.py": 12437040676784563126, + "venv/lib/python3.13/site-packages/click/testing.py": 15973659312284678327, + "backend/alembic/versions/543d43d752b8_migrate_old_dictionary_entries_and_.py": 10988663686444687907, + "venv/lib/python3.13/site-packages/pandas/tests/io/excel/test_xlrd.py": 9982457234958102003, + "venv/lib/python3.13/site-packages/numpy/random/tests/test_randomstate.py": 11205714006000849926, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py": 14946223589457772924, + "venv/lib/python3.13/site-packages/certifi/cacert.pem": 14727832973577663826, + "venv/lib/python3.13/site-packages/pillow-12.1.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/testing/tests/test_utils.py": 5291132432383518704, + "venv/lib/python3.13/site-packages/cffi-2.0.0.dist-info/METADATA": 5628172948035858892, + "frontend/build/_app/immutable/chunks/C2DipQLT.js": 333538434576244034, + "venv/lib/python3.13/site-packages/pandas/tests/api/test_types.py": 8889829773923216769, + "backend/src/plugins/translate/prompt_builder.py": 9619706108488955349, + "backend/src/services/clean_release/stages/__init__.py": 11595548160903612178, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/blocking.py": 3483388533957772681, + "venv/lib/python3.13/site-packages/pydantic/main.py": 14086938579850319884, + "venv/lib/python3.13/site-packages/numpy/lib/_datasource.py": 18136853038949826147, + "venv/lib/python3.13/site-packages/pydantic/v1/decorator.py": 6124748023704700724, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_type_check.py": 3935091606923106753, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/transform/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/type_adapter.py": 10162988530225478692, + "models": 14346352665111990852, + "frontend/e2e/fixtures/auth.fixture.js": 13628564118439575126, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/nodes/39.x6Tr2rq6.js": 8373901766277015937, + "venv/lib/python3.13/site-packages/pandas/io/xml.py": 326466573926392764, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex_like.py": 1407890639206728014, + "venv/lib/python3.13/site-packages/rsa/randnum.py": 13958355153634534526, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_categorical.py": 18254320571347851153, + "venv/lib/python3.13/site-packages/pip/_internal/models/wheel.py": 10473287225032326206, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_validate.py": 12789481642730855139, + "venv/lib/python3.13/site-packages/yaml/reader.py": 9873075843010693205, + "venv/lib/python3.13/site-packages/attr/_make.py": 2348458829123990579, + "venv/lib/python3.13/site-packages/pandas/core/_numba/kernels/var_.py": 12699521091170347311, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_api.py": 14120915875574640262, + "venv/lib/python3.13/site-packages/pygments/lexers/fortran.py": 6859638690245583968, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9207/__init__.py": 8434616194114282088, + "venv/lib/python3.13/site-packages/sqlalchemy/util/deprecations.py": 7020540470348910770, + "venv/lib/python3.13/site-packages/tzlocal/utils.py": 7893867974548929154, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_subclass.py": 16342917051908786497, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/window/numba_.py": 1444123360986509769, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/scalar_string.f90": 15018631706178918578, + "venv/lib/python3.13/site-packages/numpy/fft/_helper.pyi": 9546918341939102632, + "venv/lib/python3.13/site-packages/pygments/lexers/inferno.py": 9056274496469409594, + "frontend/src/routes/dashboards/+page.svelte": 5715934441651304054, + "venv/lib/python3.13/site-packages/numpy/_core/_type_aliases.py": 1644743742545329282, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimelike_/test_indexing.py": 1926721846569184112, + "venv/lib/python3.13/site-packages/numpy/matrixlib/__init__.py": 18402126171936308228, + "venv/lib/python3.13/site-packages/pydantic_settings/sources/utils.py": 8633356372647820801, + "backend/src/api/routes/translate/_run_routes.py": 6617818713940695689, + "backend/git_repos/remote/test-repo.git/hooks/push-to-checkout.sample": 4825338927654285910, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_coercion.py": 3339075591248270762, + "frontend/src/routes/storage/+page.svelte": 5003283673039328108, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_grouping.py": 5994909693214299971, + "backend/src/models/llm.py": 9128215579699548047, + "venv/lib/python3.13/site-packages/cryptography/hazmat/backends/openssl/backend.py": 9072112660082423691, + "venv/lib/python3.13/site-packages/fastapi/security/open_id_connect_url.py": 3502444317759870079, + "venv/lib/python3.13/site-packages/rapidfuzz/_feature_detector.py": 15458248567257759500, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/test_internals.py": 10472508540875131797, + "venv/lib/python3.13/site-packages/pandas/core/reshape/tile.py": 17137524194129840833, + "venv/lib/python3.13/site-packages/pandas/tests/copy_view/index/test_timedeltaindex.py": 2359681317403710563, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/misc/extended_precision.pyi": 6541258584648209609, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunclike.pyi": 14623308681600207918, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_formats.py": 1265319125235346745, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_reductions.py": 2816859231048302619, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/dtypes/test_categorical.py": 9615571808720893016, + "venv/lib/python3.13/site-packages/certifi-2025.11.12.dist-info/WHEEL": 16097436423493754389, + "frontend/src/lib/components/dataset-review/CompiledSQLPreview.svelte": 4866254539173481462, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/filter.py": 16846063190466267618, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_function.py": 13492077564015386528, + "frontend/src/components/RepositoryDashboardGrid.svelte": 14921738329941705036, + "venv/lib/python3.13/site-packages/_pytest/warning_types.py": 10695097290648045427, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_overlaps.py": 8287716909793575347, + "backend/src/core/superset_client/_layout_utils.py": 15652481146450199710, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/histograms.pyi": 2281259341486424755, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufunc_config.pyi": 2005481648919369399, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_rolling_quantile.py": 4225791949463893856, + "venv/lib/python3.13/site-packages/numpy/core/_multiarray_umath.py": 10973016138581934035, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/object/test_astype.py": 563689238486630866, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_to_excel.py": 5467043641314706635, + "backend/src/models/task.py": 1786589344409008831, + "venv/lib/python3.13/site-packages/anyio/pytest_plugin.py": 4165280709813718099, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/__ufunc_api.c": 11535375410441493281, + "venv/lib/python3.13/site-packages/numpy/linalg/_linalg.pyi": 9629457630163613604, + "venv/lib/python3.13/site-packages/numpy/random/lib/libnpyrandom.a": 1802449692091040396, + "venv/lib/python3.13/site-packages/numpy/_typing/_ufunc.pyi": 6286629088867436848, + "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.py": 5570375156851166818, + "venv/lib/python3.13/site-packages/passlib/tests/test_crypto_des.py": 7198931807116651263, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_equals.py": 18261810467289276844, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/python3.npy": 4957143805477405905, + "venv/lib/python3.13/site-packages/sqlalchemy/util/topological.py": 11586868018611359415, + "frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js": 13047006106880121194, + "backend/tests/test_log_persistence.py": 11073909507089982937, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/control.py": 2034518223411945438, + "venv/lib/python3.13/site-packages/ecdsa/errors.py": 11755424742691057760, + "venv/lib/python3.13/site-packages/fastapi/routing.py": 466387159689567541, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/exceptions.py": 14982764273485726199, + "venv/lib/python3.13/site-packages/numpy/lib/format.pyi": 11752225430594536662, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/AB.inc": 10441778083831997423, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/util.py": 6088868370298560146, + "venv/lib/python3.13/site-packages/passlib/handlers/roundup.py": 3844280972451753019, + "venv/lib/python3.13/site-packages/ecdsa/_version.py": 17707102226558781833, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_replace.py": 4953527309376861139, + "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/dtypes/test_empty.py": 6845813091876023610, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pydantic/alias_generators.py": 5991580234179623842, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_stride_tricks.py": 1064774375151677743, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/engines.py": 10876954465293959720, + "venv/lib/python3.13/site-packages/websockets/sync/server.py": 7966978001578584901, + "venv/lib/python3.13/site-packages/rsa/py.typed": 11041940105507257053, + "venv/lib/python3.13/site-packages/pydantic/_internal/_generics.py": 16438159042939059717, + "venv/lib/python3.13/site-packages/rapidfuzz-3.14.3.dist-info/licenses/LICENSE": 5563356551734678258, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6749/grants/client_credentials.py": 256154392957334831, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7516/__init__.py": 11121941644106061453, + "venv/lib/python3.13/site-packages/urllib3/poolmanager.py": 15431313180245757657, + "venv/lib/python3.13/site-packages/jeepney/tests/test_wrappers.py": 4813328996575597980, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_indexing.py": 17106010337164216722, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_assert_numpy_array_equal.py": 2089426719574307767, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/jmespath.py": 7426464251945393925, + "venv/lib/python3.13/site-packages/websockets/legacy/server.py": 5390090919193784186, + "frontend/src/routes/admin/settings/llm/+page.svelte": 3079157958329647867, + "backend/src/services/notifications/service.py": 7032100258837946310, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/nditer.pyi": 33523064068376750, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_fiscal.py": 14652343698825214870, + "venv/lib/python3.13/site-packages/anyio/_core/__init__.py": 15130871412783076140, + "backend/src/api/routes/git/_repo_routes.py": 7367823490321383813, + "venv/lib/python3.13/site-packages/keyring/backends/macOS/api.py": 4502902558534812719, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_extension.py": 4831602527247293866, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/connectionpool.py": 10453724680327835821, + "venv/lib/python3.13/site-packages/pandas/tests/series/accessors/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/passlib/hash.py": 5238710192614935875, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_empty.py": 13006241382741353569, + "venv/lib/python3.13/site-packages/psycopg2/_json.py": 9729420372294281405, + "venv/lib/python3.13/site-packages/pytest_asyncio-1.3.0.dist-info/METADATA": 12747626683405487434, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_value_counts.py": 12340872812120847127, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_astype.py": 8505605634958454768, + "venv/lib/python3.13/site-packages/pandas/tests/computation/test_eval.py": 2921337784087808487, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_constructors.py": 12118296571694122743, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/common/test_index.py": 1551768441102117466, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/util.cpython-313-x86_64-linux-gnu.so": 12473903676666680134, + "venv/lib/python3.13/site-packages/PIL/ImageShow.py": 11437096951764124817, + "venv/lib/python3.13/site-packages/referencing-0.37.0.dist-info/licenses/COPYING": 14459782230785388765, + "frontend/build/_app/immutable/chunks/DSCvrbNj.js": 7995659532253982919, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libpcre-9513aab5.so.1.2.0": 12298861477332583668, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/auth.py": 912521029864094489, + "venv/lib/python3.13/site-packages/numpy/random/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/core/resample.py": 13814298871925341617, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/pg_catalog.py": 15726448028057859831, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mssql/base.py": 7855217087916771270, + "frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js": 6561454515118560091, + "frontend/build/_app/immutable/chunks/BAEbOLv3.js": 18043792224008034479, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_dtypes.py": 481191723198819568, + "venv/lib/python3.13/site-packages/urllib3/fields.py": 9503202008440141421, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/RECORD": 6518517239543344179, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi": 10548370574281981402, + "venv/lib/python3.13/site-packages/anyio/_core/_tempfile.py": 230288423480899091, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/jsonschema/_legacy_keywords.py": 16481666133229715822, + "venv/lib/python3.13/site-packages/annotated_doc/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/array_with_attr/array.py": 13040461386712513615, + "venv/lib/python3.13/site-packages/charset_normalizer/__main__.py": 8887772289570078278, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_x64_masm.obj": 2884737706935637437, + "backend/src/core/utils/superset_context_extractor/_base.py": 2165790563924045511, + "backend/src/api/routes/__tests__/test_tasks_logs.py": 17724385243163092479, + "venv/lib/python3.13/site-packages/idna/compat.py": 9758194415584776667, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/regression/f77fixedform.f95": 10898637805043867370, + "venv/lib/python3.13/site-packages/pyasn1-0.6.2.dist-info/zip-safe": 15240312484046875203, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_matrix_linalg.py": 2858987911347541177, + "venv/lib/python3.13/site-packages/numpy/__init__.pxd": 13527602429695748857, + "venv/lib/python3.13/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv": 10950201682596097452, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_tzconversion.py": 7205566353454584259, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_unstack.py": 11834917665446437163, + "venv/lib/python3.13/site-packages/pandas/io/pickle.py": 5418646169167774144, + "venv/lib/python3.13/site-packages/idna/idnadata.py": 200840860629525970, + "venv/lib/python3.13/site-packages/pygments/styles/lovelace.py": 15082819162722685616, + "venv/lib/python3.13/site-packages/gitdb/db/pack.py": 13460574575424209609, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_freq_attr.py": 7685756734926749093, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc6750/__init__.py": 11526998905763262175, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_timedelta.py": 7742506012012398830, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/__init__.py": 15130871412783076140, + "backend/src/api/routes/git/__init__.py": 14824479456728364642, + "venv/lib/python3.13/site-packages/numpy/lib/_polynomial_impl.py": 12771179468704314203, + "backend/src/services/profile_utils.py": 3954310438409803447, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/licenses/LICENSE": 14524289631770661180, + "backend/alembic/versions/2a7b8c9d0e1f_add_target_languages_to_translation_jobs.py": 7201017059554918882, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_quantile.py": 11966156706220948315, + "backend/src/services/reports/__tests__/test_report_service.py": 7145268223824508607, + "venv/lib/python3.13/site-packages/httpcore/_sync/connection.py": 1539337414493486168, + "venv/lib/python3.13/site-packages/fastapi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/integrations/django_client/apps.py": 14151733532064278336, + "venv/lib/python3.13/site-packages/pandas/core/window/common.py": 17956497339875932377, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_cisco.py": 1786475632318043669, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/liblber-1c9097e2.so.2.0.200": 2651879839738900594, + "backend/src/api/routes/dashboards/_schemas.py": 10686942001147126057, + "venv/lib/python3.13/site-packages/keyring/credentials.py": 14515496037842724455, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi": 16934250836612138541, + "backend/src/core/utils/superset_context_extractor/_filters.py": 281666313889333545, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_conversion.py": 9159276697339089788, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_rank.py": 14115215895836854973, + "venv/lib/python3.13/site-packages/pandas/tests/extension/base/ops.py": 13451323660386712332, + "venv/lib/python3.13/site-packages/pygments/lexers/unicon.py": 1155454077052833821, + "frontend/build/_app/immutable/nodes/1.BHRH2YId.js": 6292738163244332451, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_validators.py": 14178329676643700151, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_histograms.py": 47631283818191049, + "venv/lib/python3.13/site-packages/anyio/streams/buffered.py": 8916188172110578587, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/__init__.py": 11283047029180207588, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py": 7707707044867513457, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/test_get_dummies.py": 16112674981222844375, + "venv/lib/python3.13/site-packages/pip/_vendor/resolvelib/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/resample/conftest.py": 1643522609234951699, + "venv/lib/python3.13/site-packages/jeepney/io/tests/conftest.py": 13381752264278264218, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_elffile.py": 5728213398707817049, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_to_frame.py": 4303613319747945709, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_eng_formatting.py": 14768815444701392013, + "venv/lib/python3.13/site-packages/click/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/implicit.py": 5400555157488808948, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pxd": 9126772093305708921, + "venv/lib/python3.13/site-packages/pandas/tests/test_take.py": 17628004130770326677, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/mock.py": 14010776046610111182, + "venv/lib/python3.13/site-packages/httpcore/_sync/interfaces.py": 1532245423878428608, + "venv/lib/python3.13/site-packages/python_dotenv-1.2.1.dist-info/METADATA": 2604612822968175379, + "venv/lib/python3.13/site-packages/authlib/oidc/core/util.py": 5364455058429522633, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/auto.py": 15947958974558543657, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_timedelta64.py": 16821719402662529276, + "venv/lib/python3.13/site-packages/starlette/middleware/cors.py": 11384893784314197864, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_print.py": 598821365691498702, + "frontend/src/routes/admin/settings/+page.svelte": 15536865086528222650, + "venv/lib/python3.13/site-packages/numpy/random/__init__.pyi": 13833571330152615376, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_reshape.py": 10576230966727810832, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_npy_units.py": 8966226962799105383, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/lib_utils.pyi": 3708905060001289515, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_indexing_slow.py": 12558235638488427077, + "frontend/build/_app/immutable/chunks/BEgtrFG1.js": 8322179021947182552, + "backend/src/core/auth/__init__.py": 16435384828055133073, + "venv/lib/python3.13/site-packages/pandas/_libs/hashing.cpython-313-x86_64-linux-gnu.so": 16124435225170610034, + "docker/nginx.conf": 14595959129793115016, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py": 1359143503575245224, + "venv/lib/python3.13/site-packages/urllib3/__init__.py": 1854778274753799815, + "backend/src/services/clean_release/repositories/__init__.py": 9926779835387630811, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_scalar_compat.py": 1306236983392218709, + "backend/src/api/routes/assistant/_command_parser.py": 2745692387994130159, + "venv/lib/python3.13/site-packages/jsonschema-4.25.1.dist-info/METADATA": 4954909612926293404, + "venv/lib/python3.13/site-packages/rpds_py-0.30.0.dist-info/WHEEL": 14929202952940710322, + "venv/lib/python3.13/site-packages/httpx/_transports/default.py": 8391302827983907910, + "venv/lib/python3.13/site-packages/_pytest/assertion/truncate.py": 14000392306994773741, + "venv/lib/python3.13/site-packages/jsonschema_specifications-2025.9.1.dist-info/WHEEL": 2357997949040430835, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/wrapper.py": 4633931060151989960, + "venv/lib/python3.13/site-packages/pygments/lexers/grammar_notation.py": 9009644754106884095, + "venv/lib/python3.13/site-packages/pytest-9.0.2.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/starlette/middleware/base.py": 16850428285382256618, + "venv/lib/python3.13/site-packages/authlib/jose/drafts/_jwe_enc_cryptography.py": 4383854709657749855, + "venv/lib/python3.13/site-packages/numpy/lib/scimath.pyi": 18165025261847276375, + "venv/lib/python3.13/site-packages/bcrypt/_bcrypt.abi3.so": 8691731321358529264, + "venv/lib/python3.13/site-packages/keyring/backend_complete.bash": 16589214602970214174, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_csky_gcc.h": 12929785267195988209, + "venv/lib/python3.13/site-packages/referencing/_attrs.pyi": 10030665705880994025, + "venv/lib/python3.13/site-packages/rsa/pem.py": 3118524021576082054, + "venv/lib/python3.13/site-packages/bcrypt/__about__.py": 11196369962175692786, + "venv/lib/python3.13/site-packages/pandas/tests/test_optional_dependency.py": 7930709646653025355, + "venv/lib/python3.13/site-packages/pandas/tests/window/moments/conftest.py": 6137462119729731945, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_asfreq.py": 12721047184483392773, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/methods/test_to_frame.py": 2169381747938271444, + "venv/lib/python3.13/site-packages/pandas/tests/series/test_iteration.py": 15247340610412364508, + "venv/lib/python3.13/site-packages/pandas/util/_exceptions.py": 14426860079366867683, + "venv/lib/python3.13/site-packages/fastapi/openapi/utils.py": 9058442333718187759, + "venv/lib/python3.13/site-packages/pip/_internal/cli/__init__.py": 11914508471759255927, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/histograms.pyi": 9255620158831643201, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE": 14610443802372107702, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarrayobject.h": 7320510589635636690, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/arithmetic.pyi": 467927803068643024, + "venv/lib/python3.13/site-packages/passlib/handlers/postgres.py": 14162382430051693313, + "venv/lib/python3.13/site-packages/pydantic/v1/datetime_parse.py": 10467114625921924095, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/methods/test_as_unit.py": 8492383355919959393, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_lexsort.py": 10394832796613968484, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_truncate.py": 9623613657871046837, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_analytics.py": 8155550493311083506, + "venv/lib/python3.13/site-packages/sqlalchemy/sql/naming.py": 14503932124671438340, + "venv/lib/python3.13/site-packages/passlib/tests/sample1.cfg": 9597283806285213340, + "venv/lib/python3.13/site-packages/git/refs/symbolic.py": 14996822770181935589, + "venv/lib/python3.13/site-packages/pygments/lexers/openscad.py": 13045825115225232396, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc9101/__init__.py": 8632038387100622009, + "scripts/build_offline_docker_bundle.sh": 9577721838839060974, + "venv/lib/python3.13/site-packages/charset_normalizer-3.4.4.dist-info/METADATA": 4975169119201255384, + "frontend/playwright-report/trace/snapshot.html": 11716473056415565262, + "backend/src/core/async_superset_client.py": 5842980152216372100, + "backend/src/core/middleware/trace.py": 13093835356377196397, + "backend/src/plugins/translate/orchestrator_config.py": 1227864697811313446, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_one_public_routine.f90": 7957683453180939605, + "backend/alembic/versions/b0c1d2e3f4a5_cascade_ondelete_translate_fks.py": 1764442834210967136, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/packages/__init__.py": 15130871412783076140, + "frontend/src/routes/settings/SystemSettings.svelte": 17084926955388049976, + "venv/lib/python3.13/site-packages/pip/_internal/locations/base.py": 7966628150470073365, + "backend/git_repos/remote/test-repo.git/refs/heads/feature/test": 7714224145564125988, + "venv/lib/python3.13/site-packages/numpy/tests/test_numpy_config.py": 3636377988901907424, + "frontend/build/_app/immutable/nodes/17.Dl6K4370.js": 14461856651958270415, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/__init__.py": 16532856661318424631, + "venv/lib/python3.13/site-packages/annotated_types/__init__.py": 7367790549779882749, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_conversion.pyi": 11580106670226366710, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/instrumentation.py": 14882045449667214075, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/RECORD": 9502524172853437600, + "venv/lib/python3.13/site-packages/pip/_vendor/dependency_groups/_toml_compat.py": 10196543528439925412, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/test_callback.py": 1689177048527329209, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7515/models.py": 17356033861792227817, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_copy.py": 3114918520437707410, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_append.py": 13152738905565588661, + "venv/lib/python3.13/site-packages/pygments/lexers/meson.py": 14659991367778746658, + "backend/src/services/clean_release/__tests__/test_policy_engine.py": 15331910119765064311, + "venv/lib/python3.13/site-packages/jeepney/io/blocking.py": 4699555965372200059, + "venv/lib/python3.13/site-packages/pydantic/mypy.py": 10034028441785588819, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_comparison.py": 4611207880323503098, + "venv/lib/python3.13/site-packages/greenlet/PyGreenlet.hpp": 6366432579621298231, + "venv/lib/python3.13/site-packages/pip/_vendor/truststore/__init__.py": 1948986914452928735, + "venv/lib/python3.13/site-packages/pygments/styles/gh_dark.py": 7717523746712391809, + "venv/lib/python3.13/site-packages/pandas/tests/io/pytables/test_errors.py": 3301889847545579393, + "venv/lib/python3.13/site-packages/passlib/tests/test_win32.py": 13932956220195912963, + "frontend/src/pages/Settings.svelte": 12818597464628135154, + "venv/lib/python3.13/site-packages/pip/_internal/utils/wheel.py": 450504439085405418, + "venv/lib/python3.13/site-packages/websockets/typing.py": 13268801935274185287, + "venv/lib/python3.13/site-packages/uvicorn/middleware/wsgi.py": 9179913252056394958, + "venv/lib/python3.13/site-packages/packaging/metadata.py": 9168255069163141470, + "venv/lib/python3.13/site-packages/pandas/tests/io/xml/test_to_xml.py": 8477770807916990981, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/relationships.py": 8401569216905291119, + "venv/lib/python3.13/site-packages/PIL/BufrStubImagePlugin.py": 5520941821175895889, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/__init__.py": 16146480198665866916, + "backend/git_repos/remote/test-repo.git/hooks/update.sample": 8204581436750313444, + "venv/lib/python3.13/site-packages/cffi/backend_ctypes.py": 2042566833861899211, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas-3.0.1.dist-info/REQUESTED": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/_pytesttester.pyi": 5750506937526308405, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/models.py": 17870758731501836303, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/rsa_key.py": 7092106298733667895, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/__init__.py": 2397613800206300456, + "venv/lib/python3.13/site-packages/pandas/tseries/holiday.py": 1134358927599488799, + "venv/lib/python3.13/site-packages/numpy/_distributor_init.py": 1101690714183863290, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_to_timestamp.py": 17572983799929378095, + "venv/lib/python3.13/site-packages/cryptography/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data": 9599129816090399315, + "venv/lib/python3.13/site-packages/urllib3/_request_methods.py": 13671055114247516883, + "venv/lib/python3.13/site-packages/rsa-4.9.1.dist-info/LICENSE": 8423899413955829149, + "venv/lib/python3.13/site-packages/authlib/oidc/core/grants/util.py": 18279366777506483176, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/usecols/test_usecols_basic.py": 16382444980424010514, + "venv/lib/python3.13/site-packages/secretstorage-3.5.0.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pygments/lexers/monte.py": 15158829991357994573, + "venv/lib/python3.13/site-packages/numpy/polynomial/tests/test_legendre.py": 18266595775500927868, + "venv/lib/python3.13/site-packages/numpy/ma/mrecords.pyi": 8945514863366384484, + "venv/lib/python3.13/site-packages/click/exceptions.py": 9734955259447933725, + "venv/lib/python3.13/site-packages/numpy/tests/test__all__.py": 10689265249302359388, + "venv/lib/python3.13/site-packages/numpy/core/overrides.py": 11228841530565061867, + "venv/lib/python3.13/site-packages/pandas/tests/extension/list/array.py": 8065856342131357421, + "venv/lib/python3.13/site-packages/pydantic/v1/validators.py": 1060954771151908883, + "venv/lib/python3.13/site-packages/python_jose-3.5.0.dist-info/RECORD": 16342326945648353387, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/LICENSE": 2032205056284080825, + "venv/lib/python3.13/site-packages/pycparser/ply/__init__.py": 5040371336745852622, + "venv/lib/python3.13/site-packages/numpy/ma/tests/test_mrecords.py": 15952147778503828707, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/suite/__init__.py": 697601512486720554, + "venv/lib/python3.13/site-packages/python_multipart/decoders.py": 14252672585219598429, + "venv/lib/python3.13/site-packages/passlib/tests/test_handlers_bcrypt.py": 11146468670439284889, + "venv/lib/python3.13/site-packages/pygments/lexers/tablegen.py": 2917626373516779857, + "frontend/src/lib/stores/datasetReviewSession.js": 3915919349382526215, + "venv/lib/python3.13/site-packages/pandas/core/arrays/numpy_.py": 16641729409992576358, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_index.py": 12015738970771703312, + "frontend/src/routes/datasets/__tests__/split_view.test.js": 6143972529940917004, + "venv/lib/python3.13/site-packages/apscheduler/triggers/interval.py": 3964550092873794670, + "venv/lib/python3.13/site-packages/rsa/transform.py": 12261738253972114335, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/proxy.py": 13008557041076030198, + "venv/lib/python3.13/site-packages/pandas/tests/plotting/test_backend.py": 17793139799410518847, + "venv/lib/python3.13/site-packages/numpy/f2py/f90mod_rules.py": 2953876934840155920, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_interval.py": 14749388246573356959, + "venv/lib/python3.13/site-packages/pygments/lexers/haxe.py": 1915270891525929751, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_to_dict.py": 808180749933361743, + "venv/lib/python3.13/site-packages/numpy/linalg/lapack_lite.pyi": 14069586330277925998, + "frontend/src/services/adminService.js": 6375990585512014277, + "frontend/build/_app/immutable/chunks/DWg3slHj.js": 16432655720744147297, + "backend/src/services/clean_release/__tests__/test_source_isolation.py": 17714198919084455758, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_extension.py": 17245018204352082978, + "backend/tests/scripts/test_clean_release_tui_v2.py": 16893299982170941753, + "venv/lib/python3.13/site-packages/numpy/f2py/rules.pyi": 1342380029484127983, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_comparisons.py": 2764694394636775220, + "backend/git_repos/remote/test-repo.git/refs/heads/main": 7667767390913789840, + "venv/lib/python3.13/site-packages/keyring/util/__init__.py": 9635016046220094473, + "backend/src/core/utils/superset_compilation_adapter.py": 4974836712746468095, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_astype.py": 15275720655739710249, + "venv/lib/python3.13/site-packages/pip/_vendor/certifi/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/fastapi/_compat/main.py": 13016492818231995760, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/codec.py": 14814999235499530522, + "backend/tests/scripts/test_clean_release_cli.py": 13978106497618764226, + "backend/git_repos/remote/test-repo.git/objects/aa/ea042a37c6f7bd010d91db93951328da7f01cc": 11936716919619613939, + "venv/lib/python3.13/site-packages/sqlalchemy/pool/base.py": 16951268065271931235, + "venv/lib/python3.13/site-packages/pandas/tests/frame/test_cumulative.py": 15644124412739892167, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/version.py": 5000350193835202949, + "venv/lib/python3.13/site-packages/pip/_internal/network/utils.py": 13421242949994555055, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Prefix_py.py": 17041764258638228993, + "venv/lib/python3.13/site-packages/sqlalchemy/cyextension/__init__.py": 12290228927283601067, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/utils.py": 3710235316419562274, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/test_sort.py": 11941630642630249576, + "frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js": 3674649277514557450, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/_tokenizer.py": 7994281991455916540, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_setops.py": 15365064654930699428, + "venv/lib/python3.13/site-packages/numpy/lib/__init__.pyi": 1537495515469182226, + "venv/lib/python3.13/site-packages/numpy/f2py/src/fortranobject.c": 2519219289444051739, + "venv/lib/python3.13/site-packages/pandas/core/arrays/string_.py": 14865733321317939478, + "venv/lib/python3.13/site-packages/numpy/matrixlib/tests/test_regression.py": 16266600037241221681, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py": 18229054440703471493, + "venv/lib/python3.13/site-packages/apscheduler/jobstores/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/strings/__init__.pyi": 6213864891045042045, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/methods/test_insert.py": 15536994417338770457, + "venv/lib/python3.13/site-packages/numpy/_core/_exceptions.pyi": 3661113433078225952, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/_py_row.py": 918740441973901148, + "venv/lib/python3.13/site-packages/pygments/lexers/mips.py": 2078929831513352031, + "venv/lib/python3.13/site-packages/pygments/lexers/csound.py": 2175454840368374515, + "venv/lib/python3.13/site-packages/pip-25.1.1.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/itsdangerous/_json.py": 4872267972688724005, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/__init__.py": 6489437464172324468, + "venv/lib/python3.13/site-packages/pandas/_libs/groupby.pyi": 6154952803757623626, + "venv/lib/python3.13/site-packages/numpy/random/bit_generator.pyi": 15790738442952696034, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_setitem.py": 2059440410065814114, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/ufuncs.pyi": 14995898537484305307, + "venv/lib/python3.13/site-packages/pandas/tests/dtypes/cast/test_find_common_type.py": 9581516171321396333, + "venv/lib/python3.13/site-packages/pydantic/annotated_handlers.py": 10186120300163345360, + "venv/lib/python3.13/site-packages/pandas/core/frame.py": 2630807744775247533, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_repr.py": 11737029058271003097, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_arithmetic.py": 11620920548943067949, + "venv/lib/python3.13/site-packages/git/objects/tree.py": 10239027037919781330, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming_py.py": 16133454512601432815, + "venv/lib/python3.13/site-packages/pip/_internal/cli/autocompletion.py": 7651919329635563739, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/gh24008.f": 3872245077994936272, + "venv/lib/python3.13/site-packages/dateutil/_version.py": 8279235793001245767, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_constructors.py": 11786151805350138436, + "venv/lib/python3.13/site-packages/idna/core.py": 7725813731640753267, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_datetime.py": 13781712980921881470, + "venv/lib/python3.13/site-packages/rsa/asn1.py": 3861968161559322784, + "venv/lib/python3.13/site-packages/rapidfuzz/distance/Hamming.pyi": 4432290176776357346, + "venv/lib/python3.13/site-packages/tzlocal/win32.py": 1949985224569608978, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc_linux.h": 15772978805500070727, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_stack.py": 5316826578695144945, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c": 5472633890472031814, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7518/jwe_encs.py": 9703572751543253904, + "venv/lib/python3.13/site-packages/pandas/api/internals.py": 5188134630996087511, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py": 11425629729736599320, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/locators.py": 7638945613579396718, + "venv/lib/python3.13/site-packages/numpy/__config__.py": 15794735729525094396, + "venv/lib/python3.13/site-packages/pandas/tests/series/indexing/test_getitem.py": 18202683049446557047, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py": 7421910137064160936, + "venv/lib/python3.13/site-packages/pip/_internal/commands/lock.py": 14782882714168174465, + "venv/lib/python3.13/site-packages/uvicorn/protocols/http/httptools_impl.py": 10367325397209016951, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/dtype.pyi": 465999539608816848, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/gevent.py": 4811840397266785551, + "examples/maintenance-api-python.py": 18279360934407602079, + "frontend/static/favicon.svg": 6451919037497541980, + "frontend/playwright-report/trace/index.CzXZzn5A.css": 10367596602957476705, + "frontend/playwright-report/data/b13be72bc9111c369dd61bcb4b41565873341170.zip": 9286336518597330572, + "frontend/src/lib/api/translate/__tests__/test-target-schema.test.js": 2329724860725977662, + "frontend/src/lib/components/translate/TermCorrectionPopup.svelte": 5276611147503580165, + "frontend/src/routes/datasets/review/+page.svelte": 12909115647298935839, + "frontend/src/routes/settings/LoggingSettings.svelte": 1737218883899664063, + "frontend/tailwind.config.js": 13139381085024634801, + "venv/lib/python3.13/site-packages/pandas/tests/window/test_pairwise.py": 2673370322448160842, + "frontend/src/routes/datasets/ColumnsTable.svelte": 1880884265008014080, + "venv/lib/python3.13/site-packages/pygments/unistring.py": 18037463865539157041, + "venv/lib/python3.13/site-packages/packaging/markers.py": 11602308203217831543, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-1.csv": 5708101386018266998, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/mysql/expression.py": 1248029135284283479, + "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/foxpro.py": 14032656072384708293, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/sqlalchemy/event/legacy.py": 13465911776953636949, + "frontend/src/lib/components/assistant/AssistantChatPanel.svelte": 4130047433623185888, + "frontend/tests/maintenance-store.test.ts": 7211673236234440419, + "backend/src/core/superset_client/_charts.py": 8811593556038212857, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayscalars.h": 16142050006935459679, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_scalarprint.py": 9482100952562512933, + "backend/git_repos/remote/test-repo.git/objects/6a/f2b28e314c04fb4e03476c12d6491213591512": 4526311953587849385, + "venv/lib/python3.13/site-packages/authlib/jose/rfc7519/claims.py": 12645788445743898136, + "venv/lib/python3.13/site-packages/_pytest/mark/structures.py": 12237146603608917650, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/auth.py": 13542332344403032059, + "venv/lib/python3.13/site-packages/passlib/utils/compat/__init__.py": 17369882236606423129, + "venv/lib/python3.13/site-packages/pandas/io/formats/xml.py": 12235904458551067063, + "venv/lib/python3.13/site-packages/pandas/tests/test_downstream.py": 5635510753354256507, + "frontend/src/routes/datasets/review/__tests__/dataset_review_entry.ux.test.js": 5439236328736424365, + "frontend/src/components/git/GitMergeDialog.svelte": 17029360862035548928, + "venv/lib/python3.13/site-packages/jeepney/tests/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pandas/_libs/tslibs/vectorized.pyi": 15498895254516573071, + "backend/src/core/config_models.py": 2535711893860826646, + "backend/src/plugins/llm_analysis/service.py": 11342659046054748840, + "backend/src/plugins/translate/orchestrator.py": 2899451611486868631, + "venv/lib/python3.13/site-packages/pandas/tests/computation/test_compat.py": 11655000938111420543, + "backend/src/plugins/translate/sql_generator.py": 900251269659959067, + "venv/lib/python3.13/site-packages/httpx/_transports/asgi.py": 12335675489870745729, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/type_check.pyi": 9177256991985898824, + "venv/lib/python3.13/site-packages/idna-3.11.dist-info/RECORD": 11541505360973709787, + "venv/lib/python3.13/site-packages/pandas/_libs/byteswap.cpython-313-x86_64-linux-gnu.so": 17856848989827220388, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/util.py": 3591114320020964752, + "venv/lib/python3.13/site-packages/sqlalchemy/util/queue.py": 1289234691048379395, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/__init__.py": 13331622784664204066, + "backend/src/api/routes/__tests__/test_reports_openapi_conformance.py": 17043883737206361151, + "frontend/src/routes/datasets/review/ReviewWorkspaceRightRail.svelte": 13437011381072252917, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/emoji.py": 9166774203918731896, + "backend/git_repos/remote/test-repo.git/objects/6f/85e20ce3ef98cf07a2f102498b71b9462552c5": 3012017807908986452, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content": 12465123883296161860, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_month.py": 14597470286884431085, + "backend/src/plugins/translate/_batch_proc.py": 5830558923416766212, + "venv/lib/python3.13/site-packages/pygments/lexers/sql.py": 15566262873151658034, + "backend/alembic.ini": 8897071018956157084, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_validate_args.py": 5821040955806257450, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_custom_business_month.py": 1613806538807726074, + "venv/lib/python3.13/site-packages/greenlet/platform/switch_ppc64_linux.h": 4071314837793906998, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi": 1626154870044880426, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90": 8048650253889213460, + "venv/lib/python3.13/site-packages/psycopg2_binary-2.9.11.dist-info/licenses/LICENSE": 5757922580822401219, + "venv/lib/python3.13/site-packages/pandas/_libs/hashing.pyi": 5241441378073929968, + "venv/lib/python3.13/site-packages/PIL/ImageWin.py": 13635870584232081323, + "frontend/src/components/tasks/TaskLogPanel.svelte": 4685456099513280294, + "venv/lib/python3.13/site-packages/httpx/py.typed": 15130871412783076140, + "backend/src/services/clean_release/stages/internal_sources_only.py": 15680055221844544848, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/test_setops.py": 15196593522537569500, + "venv/lib/python3.13/site-packages/pandas/core/arrays/arrow/_arrow_utils.py": 17808805047762566525, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/url.py": 9692934100602135106, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/concat/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pygments/lexers/business.py": 10410439210806697214, + "backend/src/services/security_badge_service.py": 6269749758059921511, + "backend/src/plugins/llm_analysis/__tests__/test_client_headers.py": 5527172390260032966, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/postgresql/psycopg.py": 8023549900603235601, + "backend/git_repos/remote/test-repo.git/objects/52/ec4a78c629329b8b572ec9d5205271c111baac": 18054296544295201561, + "venv/lib/python3.13/site-packages/pygments/lexers/prql.py": 1159462562014166646, + "venv/lib/python3.13/site-packages/pip/_internal/utils/urls.py": 8698341051522816167, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/multi/test_drop.py": 11341278355685583133, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_align.py": 6050248183327934780, + "venv/lib/python3.13/site-packages/numpy/_core/printoptions.py": 3897105663572772838, + "venv/lib/python3.13/site-packages/authlib/oauth1/rfc5849/util.py": 2866856507760047219, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/integer/test_concat.py": 1351478313334379336, + "backend/src/services/dataset_review/__init__.py": 15781509495698823404, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/base.py": 17992335652981439676, + "venv/lib/python3.13/site-packages/bcrypt-4.0.1.dist-info/WHEEL": 691462085217888236, + "venv/lib/python3.13/site-packages/pip/_internal/vcs/git.py": 17060377178521307324, + "venv/lib/python3.13/site-packages/jaraco_context-6.0.2.dist-info/WHEEL": 16097436423493754389, + "venv/lib/python3.13/site-packages/pygments/lexers/prolog.py": 599539463980699865, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py": 17106903014205241774, + "venv/lib/python3.13/site-packages/pydantic/v1/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/numpy/polynomial/_polytypes.pyi": 7528777458251688517, + "venv/lib/python3.13/site-packages/cffi/verifier.py": 8473599757770867754, + "venv/lib/python3.13/site-packages/numpy/lib/tests/test_io.py": 4199750143323741326, + "venv/lib/python3.13/site-packages/pandas/io/sql.py": 12592024569011796790, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py": 5126234270435358377, + "venv/lib/python3.13/site-packages/anyio-4.12.0.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_read_fwf.py": 13684564756628524738, + "venv/lib/python3.13/site-packages/pandas/tests/series/methods/test_reset_index.py": 5946666595195952693, + "venv/lib/python3.13/site-packages/click/_winconsole.py": 8133229457213704188, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_formats.py": 2743326139283991615, + "venv/lib/python3.13/site-packages/pydantic/v1/env_settings.py": 6194387033830177219, + "venv/lib/python3.13/site-packages/passlib/tests/sample1c.cfg": 13088198405762342506, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/common.py": 9354442374897565498, + "venv/lib/python3.13/site-packages/pygments/lexers/crystal.py": 3579547906957125755, + "backend/src/plugins/translate/preview_session_ops.py": 14499196532448992687, + "venv/lib/python3.13/site-packages/pandas/tests/base/test_misc.py": 9190561773853901527, + "frontend/src/lib/stores/__tests__/mocks/state.js": 3616783395254238777, + "venv/lib/python3.13/site-packages/numpy/core/defchararray.py": 11371045148957547088, + "venv/lib/python3.13/site-packages/pip/_vendor/idna/intranges.py": 12536174834761591006, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/ciphers/aead.py": 8740476942925346444, + "backend/src/services/git/_status.py": 11400014053359523156, + "venv/lib/python3.13/site-packages/pandas/tests/apply/test_str.py": 149688376805129532, + "venv/lib/python3.13/site-packages/requests-2.32.5.dist-info/RECORD": 9678861487447993169, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90": 1409455010615482779, + "venv/lib/python3.13/site-packages/sqlalchemy/testing/util.py": 955993052529739164, + "venv/lib/python3.13/site-packages/PIL/McIdasImagePlugin.py": 14137545069906812251, + "frontend/src/lib/ui/LanguageSwitcher.svelte": 3899734183369041614, + "venv/lib/python3.13/site-packages/pygments/lexers/lisp.py": 11872331622183590758, + "venv/lib/python3.13/site-packages/pandas/core/accessor.py": 1188716996113179524, + "venv/lib/python3.13/site-packages/pycparser/lextab.py": 16045770806700381661, + "backend/src/services/dataset_review/clarification_engine.py": 13640221555439415988, + "venv/lib/python3.13/site-packages/pip/_vendor/tomli/__init__.py": 12906995259233516197, + "venv/lib/python3.13/site-packages/pandas/core/base.py": 10262717073058743378, + "backend/test_pat_api.py": 4206656943734821967, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_align.py": 10284128457194204574, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/period/test_tools.py": 13994164937603424236, + "venv/lib/python3.13/site-packages/attrs/__init__.pyi": 14353885498883901855, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_ufunc.py": 3326502989311831856, + "backend/src/services/clean_release/__tests__/test_compliance_orchestrator.py": 4990536554328205752, + "venv/lib/python3.13/site-packages/numpy/_core/getlimits.pyi": 15746478550640231553, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/__init__.py": 14571251344510763303, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/categorical/test_category.py": 3944898528119364040, + "venv/lib/python3.13/site-packages/pandas/io/formats/info.py": 215303194287834907, + "venv/lib/python3.13/site-packages/pip/_internal/operations/build/metadata_editable.py": 12494407279914732338, + "venv/lib/python3.13/site-packages/numpy/lib/_arrayterator_impl.pyi": 2744889206277418389, + "venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py": 14190849361275154667, + "venv/lib/python3.13/site-packages/requests/__version__.py": 6677532709758546816, + "venv/lib/python3.13/site-packages/greenlet/PyGreenletUnswitchable.cpp": 3160733517193315684, + "venv/lib/python3.13/site-packages/cryptography-46.0.3.dist-info/licenses/LICENSE.BSD": 3858254215169937333, + "venv/lib/python3.13/site-packages/pandas/core/window/doc.py": 4204367435727844696, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_coercion.py": 7261787308019145312, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_set_value.py": 17480833128128893268, + "venv/lib/python3.13/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated": 11193150813314469394, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/interval/test_pickle.py": 6232650893735715362, + "venv/lib/python3.13/site-packages/numpy/_core/_simd.cpython-313-x86_64-linux-gnu.so": 12609666221355091416, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/test_categorical.py": 10863578845754547294, + "frontend/src/lib/api/validation.js": 10650815174196870103, + "venv/lib/python3.13/site-packages/greenlet/CObjects.cpp": 3454797518210223926, + "venv/lib/python3.13/site-packages/passlib/utils/md4.py": 4521366665754877351, + "venv/lib/python3.13/site-packages/passlib/tests/test_registry.py": 15377817946543064293, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/interval/test_formats.py": 10263085276270778330, + "venv/lib/python3.13/site-packages/sqlalchemy/orm/util.py": 2176177435997659667, + "venv/lib/python3.13/site-packages/PIL/BmpImagePlugin.py": 16682567630621529903, + "venv/lib/python3.13/site-packages/fastapi/middleware/trustedhost.py": 4285622102799027823, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_umath.py": 13010939919217862164, + "venv/lib/python3.13/site-packages/PIL/_imagingmorph.cpython-313-x86_64-linux-gnu.so": 11171810899664471137, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_constructors.py": 5627819885594450614, + "venv/lib/python3.13/site-packages/numpy/_core/records.pyi": 14194354215405544730, + "venv/lib/python3.13/site-packages/pandas/tests/arithmetic/test_object.py": 9215781825358309147, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/methods/test_kurt.py": 2898715045429898166, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_file.py": 5180401483285462901, + "venv/lib/python3.13/site-packages/pip/_vendor/distlib/metadata.py": 1362166613223529108, + "venv/lib/python3.13/site-packages/pip/_internal/index/__init__.py": 14829074315307489628, + "venv/lib/python3.13/site-packages/jsonschema/tests/test_utils.py": 8668650648802195016, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/pass/random.py": 12722750410117529986, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/__init__.py": 15130871412783076140, + "venv/lib/python3.13/site-packages/pycparser-2.23.dist-info/INSTALLER": 17282701611721059870, + "venv/lib/python3.13/site-packages/pygments/lexers/_cocoa_builtins.py": 15468347167912293394, + "venv/lib/python3.13/site-packages/keyring/__main__.py": 14602212239605295451, + "venv/lib/python3.13/site-packages/passlib/totp.py": 14590474309565233318, + "venv/lib/python3.13/site-packages/pygments/lexers/fift.py": 7537570342576781911, + "venv/lib/python3.13/site-packages/pandas/tests/reshape/merge/test_multi.py": 4612816468258071810, + "venv/lib/python3.13/site-packages/PIL/ImageMode.py": 2361901066832921091, + "venv/lib/python3.13/site-packages/pygments/lexers/ncl.py": 14838368780033177943, + "venv/lib/python3.13/site-packages/pydantic_settings-2.13.0.dist-info/METADATA": 3448868793744358515, + "venv/lib/python3.13/site-packages/sqlalchemy/engine/util.py": 1520899420719605380, + "venv/lib/python3.13/site-packages/pygments/lexers/sieve.py": 15757825442941567629, + "backend/src/core/task_manager/__tests__/test_context.py": 4211690952139950648, + "backend/src/core/task_manager/event_bus.py": 15798578020529126889, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/floating/test_construction.py": 6564829381134214401, + "backend/src/api/routes/assistant/_resolvers.py": 6365921685100086434, + "venv/lib/python3.13/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py": 8079219938116542284, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/timedeltas/test_searchsorted.py": 11161416745923343741, + "venv/lib/python3.13/site-packages/urllib3/filepost.py": 3814725067598042920, + "venv/lib/python3.13/site-packages/pygments/lexers/graphviz.py": 15677908982985025500, + "venv/lib/python3.13/site-packages/greenlet/tests/__init__.py": 1181423074160870921, + "frontend/build/_app/immutable/chunks/DgoIDw4h.js": 10605176285482573925, + "venv/lib/python3.13/site-packages/passlib/handlers/oracle.py": 12959175637015399815, + "venv/lib/python3.13/site-packages/packaging/_structures.py": 13086687542872305890, + "frontend/build/_app/immutable/chunks/C9EOgT5J.js": 5509721048432890523, + "venv/lib/python3.13/site-packages/apscheduler/schedulers/__init__.py": 16211693040174992594, + "venv/lib/python3.13/site-packages/pandas/tests/strings/test_get_dummies.py": 14871264482622327003, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_parse_dates.py": 7597935994945336408, + "venv/lib/python3.13/site-packages/numpy/testing/_private/extbuild.py": 4984721349618127021, + "venv/lib/python3.13/site-packages/numpy/lib/_datasource.pyi": 5894423389796456573, + "venv/lib/python3.13/site-packages/pygments/lexers/hdl.py": 6772823608124143123, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/theme.py": 14225878259183479398, + "venv/lib/python3.13/site-packages/PIL/QoiImagePlugin.py": 17663704273100331654, + "venv/lib/python3.13/site-packages/charset_normalizer/constant.py": 3070316197495651997, + "venv/lib/python3.13/site-packages/pygments/lexers/_ada_builtins.py": 16331776886501464264, + "venv/lib/python3.13/site-packages/pandas/tests/groupby/test_missing.py": 2976310411820303374, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py2-objarr.npy": 9694707264403109829, + "frontend/src/routes/migration/+page.svelte": 8832866232148007450, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/util/ssltransport.py": 8148652555908329980, + "venv/lib/python3.13/site-packages/pygments/lexers/_luau_builtins.py": 13690910306072616818, + "venv/lib/python3.13/site-packages/psycopg2_binary.libs/libldap-2974a1ba.so.2.0.200": 13590569080612602445, + "venv/lib/python3.13/site-packages/gitdb/exc.py": 13975852664048821278, + "backend/src/services/__tests__/test_llm_prompt_templates.py": 17912427710321938757, + "venv/lib/python3.13/site-packages/pygments/lexers/julia.py": 13516407944275342328, + "backend/src/services/clean_release/mappers.py": 8684357784135236729, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_multi_thread.py": 5660352470978621226, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py": 16768579082462294745, + "venv/lib/python3.13/site-packages/pandas/tests/tools/test_to_datetime.py": 3499461736474530062, + "venv/lib/python3.13/site-packages/attrs-25.4.0.dist-info/METADATA": 15987199384245264478, + "venv/lib/python3.13/site-packages/numpy/_core/tests/test_records.py": 18167578114159312327, + "venv/lib/python3.13/site-packages/pandas/_libs/groupby.cpython-313-x86_64-linux-gnu.so": 14931394220112658268, + "venv/lib/python3.13/site-packages/pandas/tests/test_common.py": 8987965560487646705, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi": 3533739482029983817, + "venv/lib/python3.13/site-packages/pygments/lexers/trafficscript.py": 776604244051744646, + "venv/lib/python3.13/site-packages/cryptography/x509/oid.py": 13909847799728532602, + "venv/lib/python3.13/site-packages/websockets/sync/messages.py": 15699091325918681038, + "venv/lib/python3.13/site-packages/authlib/integrations/sqla_oauth2/client_mixin.py": 17980753662107479779, + "venv/lib/python3.13/site-packages/attr/_compat.py": 4016698632899969390, + "venv/lib/python3.13/site-packages/jeepney/bus_messages.py": 5871341372541525842, + "venv/lib/python3.13/site-packages/numpy/exceptions.pyi": 13942486291715303235, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/reveal/polynomial_series.pyi": 7112486730197067087, + "venv/lib/python3.13/site-packages/authlib/integrations/httpx_client/oauth2_client.py": 6742098857947604729, + "venv/lib/python3.13/site-packages/pip/_vendor/pygments/lexer.py": 14400766876373764268, + "venv/lib/python3.13/site-packages/pandas/core/methods/describe.py": 17006836623161521092, + "venv/lib/python3.13/site-packages/pip/_vendor/urllib3/contrib/appengine.py": 16194997685865850655, + "venv/lib/python3.13/site-packages/pydantic/typing.py": 6661252174518316760, + "venv/lib/python3.13/site-packages/numpy/random/_bounded_integers.pyi": 14150710436003340771, + "venv/lib/python3.13/site-packages/pandas/tests/extension/test_common.py": 9446944526144164255, + "venv/lib/python3.13/site-packages/sqlalchemy/ext/mypy/__init__.py": 260774374497653876, + "venv/lib/python3.13/site-packages/pyasn1/codec/native/__init__.py": 15728752901274520502, + "venv/lib/python3.13/site-packages/pandas/tests/tseries/offsets/test_business_year.py": 17441853503700184299, + "venv/lib/python3.13/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz": 17626265752554406355, + "venv/lib/python3.13/site-packages/numpy/core/records.py": 12604652690721760437, + "venv/lib/python3.13/site-packages/annotated_doc/__init__.py": 6834198874252778425, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/categorical/test_algos.py": 5356470832688354593, + "venv/lib/python3.13/site-packages/authlib/oidc/core/errors.py": 18154419146257747681, + "venv/lib/python3.13/site-packages/numpy/_core/include/numpy/random/bitgen.h": 12421210767114721499, + "venv/bin/httpx": 6651007446865716794, + "venv/lib/python3.13/site-packages/pygments/styles/pastie.py": 15784474766258831882, + "venv/lib/python3.13/site-packages/uvicorn/_compat.py": 2593000889619875759, + "frontend/build/_app/immutable/chunks/_Pf3rQig.js": 13183249556030654823, + "venv/lib/python3.13/site-packages/pandas/tseries/frequencies.py": 2262381949755250516, + "venv/lib/python3.13/site-packages/pip/_internal/req/req_uninstall.py": 3515239440812977025, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/test_contains.py": 17630310725250553247, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/WHEEL": 7314207500206292683, + "venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.cpython-313-x86_64-linux-gnu.so": 13917011878259810696, + "venv/lib/python3.13/site-packages/passlib/handlers/phpass.py": 16489430001449160264, + "venv/lib/python3.13/site-packages/sqlalchemy/dialects/oracle/base.py": 13634605726041717070, + "venv/bin/activate.fish": 5275961582873298085, + "venv/lib/python3.13/site-packages/httpcore/_backends/sync.py": 576247220834179928, + "frontend/e2e/tests/migration.e2e.js": 12564023806718668322, + "venv/lib/python3.13/site-packages/numpy/lib/tests/data/py3-objarr.npz": 12369168483236619421, + "venv/lib/python3.13/site-packages/pandas/tests/arrays/timedeltas/test_reductions.py": 14432782234851468060, + "venv/lib/python3.13/site-packages/httpx/_exceptions.py": 18399489130669465891, + "venv/lib/python3.13/site-packages/pandas/core/interchange/column.py": 9498044216416177656, + "venv/lib/python3.13/site-packages/pip/_vendor/cachecontrol/caches/__init__.py": 11808051681178127650, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/callback/gh26681.f90": 1515497186927052106, + "venv/lib/python3.13/site-packages/PIL/ImageDraw.py": 12919304671639673744, + "venv/lib/python3.13/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE": 1641332741515411734, + "venv/lib/python3.13/site-packages/gitdb-4.0.12.dist-info/AUTHORS": 10073225185964928425, + "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/lib_polynomial.pyi": 4266795948450921502, + "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/tests/indexes/datetimes/methods/test_snap.py": 4515844385819802784, + "venv/lib/python3.13/site-packages/pygments-2.19.2.dist-info/licenses/LICENSE": 4672913476475760762, + "venv/lib/python3.13/site-packages/fastapi/utils.py": 15402403831700548944, + "venv/lib/python3.13/site-packages/pandas/tests/indexing/multiindex/test_iloc.py": 16160558158155038350, + "frontend/src/lib/ui/index.ts": 6883965364006817450, + "venv/lib/python3.13/site-packages/pydantic/v1/__init__.py": 1642038155370734658, + "frontend/build/_app/immutable/chunks/CTzDW2Lk.js": 14040680713815065540, + "venv/lib/python3.13/site-packages/pip/_internal/network/download.py": 5256731341219268693, + "backend/src/api/routes/health.py": 4494840518139445701, + "venv/lib/python3.13/site-packages/pip/_internal/utils/setuptools_build.py": 13594639612360346306, + "venv/lib/python3.13/site-packages/smmap/util.py": 13276170835044840023, + "venv/lib/python3.13/site-packages/pygments/styles/coffee.py": 17584414468786822371, + "venv/lib/python3.13/site-packages/passlib/tests/test_ext_django_source.py": 15577951591316518967, + "backend/src/plugins/translate/orchestrator_lang_stats.py": 5713612003349083382, + "venv/lib/python3.13/site-packages/pyasn1/codec/ber/eoo.py": 5126566925877730303, + "venv/lib/python3.13/site-packages/numpy/_core/tests/examples/cython/setup.py": 17086801293303202021, + "venv/lib/python3.13/site-packages/charset_normalizer/py.typed": 15130871412783076140, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/markup.py": 5413800947725916538, + "venv/lib/python3.13/site-packages/websockets/headers.py": 13587146967490088657, + "venv/lib/python3.13/site-packages/pydantic/v1/utils.py": 902648247561165429, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64-testset-2.csv": 4052796393463357888, + "backend/git_repos/remote/test-repo.git/objects/8c/4ea7958b7a7e140d27e1e7d8d1f9912fdf5992": 5862166356451798197, + "venv/lib/python3.13/site-packages/click-8.3.1.dist-info/METADATA": 3188324716322823755, + "venv/lib/python3.13/site-packages/authlib/integrations/flask_oauth1/__init__.py": 13749066369790839334, + "venv/lib/python3.13/site-packages/pandas/tests/frame/indexing/test_take.py": 1216902953519121176, + "venv/lib/python3.13/site-packages/numpy/polynomial/polynomial.pyi": 9935587108964614958, + "venv/lib/python3.13/site-packages/yaml/__init__.py": 11044333164208875121, + "venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py": 13206297306768491360, + "venv/lib/python3.13/site-packages/pygments/lexers/scripting.py": 4167168074165473790, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/_internal_utils.py": 4091305333167213279, + "venv/lib/python3.13/site-packages/numpy/_typing/_nbit_base.py": 7446626038222262489, + "venv/lib/python3.13/site-packages/pandas/tests/test_flags.py": 411845322592830527, + "venv/lib/python3.13/site-packages/PIL/TiffTags.py": 8688883943071546469, + "venv/lib/python3.13/site-packages/uvicorn/_types.py": 3339389597716220585, + "frontend/build/_app/immutable/chunks/BVk3Uk_6.js": 15316567731933897520, + "venv/lib/python3.13/site-packages/python_multipart-0.0.21.dist-info/RECORD": 7266315886702289726, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/timestamp/test_constructors.py": 17392287676196409733, + "venv/lib/python3.13/site-packages/numpy/polynomial/chebyshev.pyi": 5269136485429780038, + "venv/lib/python3.13/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py": 8395157526634674143, + "venv/lib/python3.13/site-packages/httpx/_config.py": 8800538050293498928, + "venv/lib/python3.13/site-packages/pip/_vendor/requests/cookies.py": 4997226307650350876, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/file_proxy.py": 17695135735211897444, + "venv/lib/python3.13/site-packages/pydantic/_internal/_generate_schema.py": 7343380095251236503, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/ranges/test_setops.py": 17350958906336246626, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/test_css.py": 17765129030290410902, + "venv/lib/python3.13/site-packages/pandas/_libs/join.pyi": 369262334342439364, + "venv/lib/python3.13/site-packages/pandas/tests/io/json/test_json_table_schema.py": 14454690938977069049, + "venv/lib/python3.13/site-packages/pygments/lexers/graph.py": 10445044822847205061, + "venv/lib/python3.13/site-packages/psycopg2/_psycopg.cpython-313-x86_64-linux-gnu.so": 13471342289207537479, + "venv/lib/python3.13/site-packages/pygments/lexers/whiley.py": 218468511185731869, + "backend/src/models/__tests__/test_models.py": 1386812925656974657, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7662/token_validator.py": 13917237710752731397, + "venv/lib/python3.13/site-packages/numpy/core/getlimits.py": 14257687540182552408, + "venv/lib/python3.13/site-packages/pandas/tests/util/test_doc.py": 7865575374100528149, + "venv/lib/python3.13/site-packages/pandas/tests/io/parser/test_python_parser_only.py": 12231449578582108346, + "venv/lib/python3.13/site-packages/greenlet/platform/setup_switch_x64_masm.cmd": 8473866644286785815, + "venv/lib/python3.13/site-packages/numpy/random/tests/data/sfc64_np126.pkl.gz": 1630203486813146863, + "venv/lib/python3.13/site-packages/httpx/_main.py": 1812303705973265093, + "venv/lib/python3.13/site-packages/authlib/oauth2/rfc7523/client.py": 18443944554871937480, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_round.py": 8336918400205461173, + "venv/lib/python3.13/site-packages/annotated_doc-0.0.4.dist-info/METADATA": 10810011740984652381, + "venv/lib/python3.13/site-packages/jsonschema/_types.py": 9250091433305395923, + "venv/lib/python3.13/site-packages/pandas/tests/frame/constructors/test_from_dict.py": 4937173601709369119, + "venv/lib/python3.13/site-packages/pandas/core/ops/invalid.py": 10186546927135277579, + "venv/lib/python3.13/site-packages/anyio/streams/stapled.py": 9733127303038397237, + "venv/lib/python3.13/site-packages/pandas/tests/tslibs/test_resolution.py": 18198858926948468112, + "venv/lib/python3.13/site-packages/httpcore/_sync/http2.py": 11167798787131917524, + "venv/lib/python3.13/site-packages/pydantic/v1/generics.py": 1150594223414883339, + "venv/lib/python3.13/site-packages/pandas/tests/scalar/interval/__init__.py": 15130871412783076140, + "frontend/build/_app/immutable/nodes/4.euBhzXnG.js": 8827989315454731607, + "backend/git_repos/remote/test-repo.git/objects/22/91d2eb86d77accf7401f8952778809cd1aa4d4": 5120428041118096941, + "backend/src/models/dataset_review_pkg/_clarification_models.py": 13264800784251426725, + "venv/lib/python3.13/site-packages/numpy/typing/tests/data/fail/bitwise_ops.pyi": 15598239133239520456, + "venv/lib/python3.13/site-packages/pandas/tests/indexes/datetimes/test_pickle.py": 8705060420848529055, + "venv/lib/python3.13/site-packages/pandas/core/indexers/__init__.py": 1756397319068017890, + "venv/lib/python3.13/site-packages/pandas/compat/numpy/__init__.py": 1037113402100731082, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/string/string.f": 17328443345813567449, + "venv/lib/python3.13/site-packages/numpy/polynomial/__init__.pyi": 8708830448398500675, + "venv/lib/python3.13/site-packages/cryptography/__about__.py": 10471312538528457144, + "venv/bin/f2py": 11006035631504708368, + "venv/lib/python3.13/site-packages/passlib/tests/_test_bad_register.py": 5446848310854472376, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/panel.py": 17832701246248000383, + "venv/lib/python3.13/site-packages/jaraco.classes-3.4.0.dist-info/RECORD": 1051307407005554409, + "venv/lib/python3.13/site-packages/pandas/tests/frame/methods/test_reindex.py": 16348619731902304844, + "frontend/build/_app/immutable/chunks/DcMPZ_fa.js": 6501595943098370468, + "venv/lib/python3.13/site-packages/pip/_vendor/packaging/py.typed": 15130871412783076140, + "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_round.py": 14996007456708990295, + "venv/lib/python3.13/site-packages/pandas/tests/io/formats/style/test_style.py": 14810883299259169406, + "venv/lib/python3.13/site-packages/_pytest/unraisableexception.py": 4597178803320514675, + "frontend/src/components/MappingTable.svelte": 17937756426921453860, + "venv/lib/python3.13/site-packages/git/diff.py": 6691274015605451565, + "venv/lib/python3.13/site-packages/anyio/_core/_subprocesses.py": 7271614043537119143, + "venv/lib/python3.13/site-packages/pandas/core/indexes/datetimes.py": 14331984919364185787, + "venv/lib/python3.13/site-packages/numpy/f2py/tests/src/common/block.f": 10727418304254548946, + "venv/lib/python3.13/site-packages/pandas/core/dtypes/inference.py": 2786441797589123900, + "venv/lib/python3.13/site-packages/pip/_vendor/rich/_spinners.py": 15873416546130487469 } } \ No newline at end of file diff --git a/.opencode/agents/closure-gate.md b/.opencode/agents/closure-gate.md index 91b8d3ee..4d984383 100644 --- a/.opencode/agents/closure-gate.md +++ b/.opencode/agents/closure-gate.md @@ -11,6 +11,8 @@ steps: 60 color: primary --- +MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})` + You are Kilo Code, acting as the Closure Gate. #region Closure.Gate [C:3] [TYPE Agent] [SEMANTICS closure,audit,compression,summary] @@ -27,13 +29,13 @@ You are Kilo Code, acting as the Closure Gate. @DATA_CONTRACT WorkerResults -> ClosureSummary #endregion Closure.Gate -## AXIOM MCP RECOMMENDATION -При финальном аудите используй axiom tools для объективной верификации: -- **`axiom_semantic_validation audit_contracts`** — проверь, что после внедрения нет нарушенных контрактов. -- **`axiom_semantic_validation audit_belief_protocol`** — проверь, что все C5-контракты имеют @RATIONALE/@REJECTED. -- **`axiom_semantic_context workspace_health`** — сравни состояние индекса до/после (was 1286 orphans, стало?). -- **`axiom_semantic_discovery search_contracts`** — проверь, что новые контракты появились в индексе. -- **`axiom_runtime_evidence read_events`** — проверь runtime-события на наличие ошибок. +## Axiom MCP Tools +See `semantics-core` §VI for the canonical tool reference. For closure audit: +- `axiom_semantic_validation audit_contracts` — verify no broken contracts post-implementation +- `axiom_semantic_validation audit_belief_protocol` — verify C5 contracts have @RATIONALE/@REJECTED +- **`axiom_semantic_context workspace_health`** — сравни состояние индекса до/после (проверь динамику orphans и unresolved relations). +- `axiom_semantic_discovery search_contracts` — verify new contracts appear in index +- `axiom_runtime_evidence read_events` — check for runtime errors --- @@ -83,6 +85,6 @@ Surface these as unresolved: - `[NEED_CONTEXT: ...]` markers not resolved - Decision memory debt accumulated without documentation - Test gaps in C4/C5 contracts -- **ANCHOR CORRUPTION: mismatched `#region`/`#endregion` count, duplicate `#endregion`, `@C N` artifacts, `@COMPLEXITY N` instead of `[C:N]`** — these are NOT cosmetic; they destroy the semantic index. Reject worker output immediately if detected. +- **ANCHOR CORRUPTION: mismatched `#region`/`#endregion` count, duplicate `#endregion`, `@C N` artifacts, `@COMPLEXITY N` instead of `[C:N]`** — these are NOT cosmetic; they destroy the semantic index. Follow `semantics-contracts` §VIII for the full anti-corruption protocol. Reject worker output immediately if detected. #endregion Closure.Gate diff --git a/.opencode/agents/fullstack-coder.md b/.opencode/agents/fullstack-coder.md index e1af7e4f..10f91d5b 100644 --- a/.opencode/agents/fullstack-coder.md +++ b/.opencode/agents/fullstack-coder.md @@ -14,49 +14,23 @@ MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contract #region Fullstack.Coder [C:4] [TYPE Agent] [SEMANTICS implementation,fullstack,python,svelte,integration] -## CONTRACT MANDATE — WHY YOU NEED THIS, NOT JUST WHAT TO DO +## Protocol Reference +Load and follow these skills (MANDATORY): +- `skill({name="semantics-core"})` — tier definitions (§III), anchor syntax (§II), tag catalog, Axiom MCP tools (§VI) +- `skill({name="semantics-contracts"})` — anti-corruption protocol (§VIII), ADR, verifiable edit loop +- `skill({name="semantics-python"})` — Python examples (C1-C5) +- `skill({name="semantics-svelte"})` — Svelte examples (C1-C5), UX contracts +- `skill({name="molecular-cot-logging"})` — REASON/REFLECT/EXPLORE wire format -You are a long-horizon agent operating across TWO stacks (Python backend + Svelte frontend). Your FIM training never saw GRACE contracts. Without an explicit cognitive harness, your deterministic failure modes are: +## Cognitive Frame — WHY contracts prevent YOUR specific failures +You operate across TWO stacks (Python backend + Svelte frontend). Without GRACE contracts, your deterministic failure modes: +1. **CONTEXT AMNESIA** — after 20 commits across both stacks, you forget what was decided. `@RATIONALE`/`@REJECTED` are your external memory. +2. **CROSS-STACK CONTRACT DRIFT** — backend Pydantic schema changes, frontend TypeScript types don't follow. `@RELATION` edges cross the stack boundary. +3. **FUNCTION BLOAT (both stacks)** — you silently add branches until a C3 function hits C4 or a component hits 300 lines. INV_7 is a self-check. +4. **REJECTED REGRESSION** — you re-implement a broken solution from across the stack boundary. `@REJECTED` tags are active guardrails. -**1. CONTEXT AMNESIA** — after 20 commits across backend and frontend files, you forget what was decided. -→ `@RATIONALE`/`@REJECTED` in code are YOUR external memory. Read them before every edit in BOTH stacks. -*Example failure: you chose `lingua` over `pycld3` on the backend. Without `@REJECTED pycld3` in the AST, you or another agent re-proposes it next sprint.* - -**2. CROSS-STACK CONTRACT DRIFT** — backend Pydantic schema changes, frontend TypeScript types don't follow. -→ `@RELATION` edges cross the stack boundary. Write `@RELATION DEPENDS_ON` in the API route AND the consuming component. The graph traces both sides. - -**3. FUNCTION BLOAT (both stacks)** — you silently add branches until a C3 function hits C4 complexity or a component hits 300 lines. -→ INV_7 (CC ≤ 10, module < 400 lines) is a self-check. Branch 6 in a C3 function = decompose, don't patch. - -**4. REJECTED REGRESSION** — you re-implement a broken solution from across the stack boundary. -→ `@REJECTED` tags are active guardrails. Before ANY edit on either stack, read the @REJECTED on that contract. - -**CONCLUSION:** Contracts are not documentation. They are YOUR cognitive exoskeleton — the external AST memory your Transformer brain lacks. Drop the anchor on either stack, and cross-stack reasoning collapses. - -### OPERATIONAL RULES - -**CONTRACT-FIRST:** Before `def` or `