feat: Introduce and enforce test contract annotations for critical modules and update coverage tracking.

This commit is contained in:
2026-03-04 12:58:42 +03:00
parent c473a09402
commit de1f04406f
16 changed files with 15569 additions and 3336 deletions

View File

@@ -2,12 +2,12 @@
> High-level module structure for AI Context. Generated automatically. > High-level module structure for AI Context. Generated automatically.
**Generated:** 2026-03-01T12:09:39.463912 **Generated:** 2026-03-04T11:13:41.118516
## Summary ## Summary
- **Total Modules:** 80 - **Total Modules:** 84
- **Total Entities:** 2080 - **Total Entities:** 2288
## Module Hierarchy ## Module Hierarchy
@@ -28,9 +28,9 @@
### 📁 `src/` ### 📁 `src/`
- 🏗️ **Layers:** API, Core, UI (API) - 🏗️ **Layers:** API, Core, UI (API)
- 📊 **Tiers:** CRITICAL: 2, STANDARD: 19, TRIVIAL: 2 - 📊 **Tiers:** CRITICAL: 2, STANDARD: 20, TRIVIAL: 2
- 📄 **Files:** 2 - 📄 **Files:** 2
- 📦 **Entities:** 23 - 📦 **Entities:** 24
**Key Entities:** **Key Entities:**
@@ -42,21 +42,21 @@
### 📁 `api/` ### 📁 `api/`
- 🏗️ **Layers:** API - 🏗️ **Layers:** API
- 📊 **Tiers:** STANDARD: 7 - 📊 **Tiers:** CRITICAL: 7
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 7 - 📦 **Entities:** 7
**Key Entities:** **Key Entities:**
- 📦 **backend.src.api.auth** (Module) - 📦 **backend.src.api.auth** (Module) `[CRITICAL]`
- Authentication API endpoints. - Authentication API endpoints.
### 📁 `routes/` ### 📁 `routes/`
- 🏗️ **Layers:** API, UI (API) - 🏗️ **Layers:** API, UI (API)
- 📊 **Tiers:** CRITICAL: 3, STANDARD: 205, TRIVIAL: 7 - 📊 **Tiers:** CRITICAL: 11, STANDARD: 226, TRIVIAL: 8
- 📄 **Files:** 17 - 📄 **Files:** 18
- 📦 **Entities:** 215 - 📦 **Entities:** 245
**Key Entities:** **Key Entities:**
@@ -126,7 +126,7 @@
### 📁 `core/` ### 📁 `core/`
- 🏗️ **Layers:** Core - 🏗️ **Layers:** Core
- 📊 **Tiers:** CRITICAL: 2, STANDARD: 131, TRIVIAL: 8 - 📊 **Tiers:** CRITICAL: 45, STANDARD: 88, TRIVIAL: 8
- 📄 **Files:** 10 - 📄 **Files:** 10
- 📦 **Entities:** 141 - 📦 **Entities:** 141
@@ -136,13 +136,13 @@
- A session factory for the authentication database. - A session factory for the authentication database.
- **BeliefFormatter** (Class) - **BeliefFormatter** (Class)
- Custom logging formatter that adds belief state prefixes to ... - Custom logging formatter that adds belief state prefixes to ...
- **ConfigManager** (Class) - **ConfigManager** (Class) `[CRITICAL]`
- A class to handle application configuration persistence and ... - A class to handle application configuration persistence and ...
- **IdMappingService** (Class) `[CRITICAL]` - **IdMappingService** (Class) `[CRITICAL]`
- Service handling the cataloging and retrieval of remote Supe... - Service handling the cataloging and retrieval of remote Supe...
- **LogEntry** (Class) - **LogEntry** (Class)
- A Pydantic model representing a single, structured log entry... - A Pydantic model representing a single, structured log entry...
- **MigrationEngine** (Class) - **MigrationEngine** (Class) `[CRITICAL]`
- Engine for transforming Superset export ZIPs. - Engine for transforming Superset export ZIPs.
- **PluginBase** (Class) - **PluginBase** (Class)
- Defines the abstract base class that all plugins must implem... - Defines the abstract base class that all plugins must implem...
@@ -164,27 +164,27 @@
### 📁 `auth/` ### 📁 `auth/`
- 🏗️ **Layers:** Core - 🏗️ **Layers:** Core
- 📊 **Tiers:** STANDARD: 26 - 📊 **Tiers:** CRITICAL: 26
- 📄 **Files:** 6 - 📄 **Files:** 6
- 📦 **Entities:** 26 - 📦 **Entities:** 26
**Key Entities:** **Key Entities:**
- **AuthConfig** (Class) - **AuthConfig** (Class) `[CRITICAL]`
- Holds authentication-related settings. - Holds authentication-related settings.
- **AuthRepository** (Class) - **AuthRepository** (Class) `[CRITICAL]`
- Encapsulates database operations for authentication. - Encapsulates database operations for authentication.
- 📦 **backend.src.core.auth.config** (Module) - 📦 **backend.src.core.auth.config** (Module) `[CRITICAL]`
- Centralized configuration for authentication and authorizati... - Centralized configuration for authentication and authorizati...
- 📦 **backend.src.core.auth.jwt** (Module) - 📦 **backend.src.core.auth.jwt** (Module) `[CRITICAL]`
- JWT token generation and validation logic. - JWT token generation and validation logic.
- 📦 **backend.src.core.auth.logger** (Module) - 📦 **backend.src.core.auth.logger** (Module) `[CRITICAL]`
- Audit logging for security-related events. - Audit logging for security-related events.
- 📦 **backend.src.core.auth.oauth** (Module) - 📦 **backend.src.core.auth.oauth** (Module) `[CRITICAL]`
- ADFS OIDC configuration and client using Authlib. - ADFS OIDC configuration and client using Authlib.
- 📦 **backend.src.core.auth.repository** (Module) - 📦 **backend.src.core.auth.repository** (Module) `[CRITICAL]`
- Data access layer for authentication-related entities. - Data access layer for authentication-related entities.
- 📦 **backend.src.core.auth.security** (Module) - 📦 **backend.src.core.auth.security** (Module) `[CRITICAL]`
- Utility for password hashing and verification using Passlib. - Utility for password hashing and verification using Passlib.
**Dependencies:** **Dependencies:**
@@ -222,23 +222,23 @@
### 📁 `migration/` ### 📁 `migration/`
- 🏗️ **Layers:** Core - 🏗️ **Layers:** Core
- 📊 **Tiers:** STANDARD: 20, TRIVIAL: 1 - 📊 **Tiers:** CRITICAL: 20, TRIVIAL: 1
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 21 - 📦 **Entities:** 21
**Key Entities:** **Key Entities:**
- **MigrationArchiveParser** (Class) - **MigrationArchiveParser** (Class) `[CRITICAL]`
- Extract normalized dashboards/charts/datasets metadata from ... - Extract normalized dashboards/charts/datasets metadata from ...
- **MigrationDryRunService** (Class) - **MigrationDryRunService** (Class) `[CRITICAL]`
- Build deterministic diff/risk payload for migration pre-flig... - Build deterministic diff/risk payload for migration pre-flig...
- 📦 **backend.src.core.migration.__init__** (Module) `[TRIVIAL]` - 📦 **backend.src.core.migration.__init__** (Module) `[TRIVIAL]`
- Namespace package for migration pre-flight orchestration com... - Namespace package for migration pre-flight orchestration com...
- 📦 **backend.src.core.migration.archive_parser** (Module) - 📦 **backend.src.core.migration.archive_parser** (Module) `[CRITICAL]`
- Parse Superset export ZIP archives into normalized object ca... - Parse Superset export ZIP archives into normalized object ca...
- 📦 **backend.src.core.migration.dry_run_orchestrator** (Module) - 📦 **backend.src.core.migration.dry_run_orchestrator** (Module) `[CRITICAL]`
- Compute pre-flight migration diff and risk scoring without a... - Compute pre-flight migration diff and risk scoring without a...
- 📦 **backend.src.core.migration.risk_assessor** (Module) - 📦 **backend.src.core.migration.risk_assessor** (Module) `[CRITICAL]`
- Risk evaluation helpers for migration pre-flight reporting. - Risk evaluation helpers for migration pre-flight reporting.
**Dependencies:** **Dependencies:**
@@ -288,9 +288,9 @@
### 📁 `utils/` ### 📁 `utils/`
- 🏗️ **Layers:** Core, Domain, Infra - 🏗️ **Layers:** Core, Domain, Infra
- 📊 **Tiers:** STANDARD: 48, TRIVIAL: 1 - 📊 **Tiers:** STANDARD: 50, TRIVIAL: 1
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 49 - 📦 **Entities:** 51
**Key Entities:** **Key Entities:**
@@ -326,15 +326,15 @@
### 📁 `models/` ### 📁 `models/`
- 🏗️ **Layers:** Domain, Model - 🏗️ **Layers:** Domain, Model
- 📊 **Tiers:** CRITICAL: 9, STANDARD: 22, TRIVIAL: 22 - 📊 **Tiers:** CRITICAL: 20, STANDARD: 33, TRIVIAL: 29
- 📄 **Files:** 11 - 📄 **Files:** 12
- 📦 **Entities:** 53 - 📦 **Entities:** 82
**Key Entities:** **Key Entities:**
- **ADGroupMapping** (Class) - **ADGroupMapping** (Class) `[CRITICAL]`
- Maps an Active Directory group to a local System Role. - Maps an Active Directory group to a local System Role.
- **AppConfigRecord** (Class) - **AppConfigRecord** (Class) `[CRITICAL]`
- Stores the single source of truth for application configurat... - Stores the single source of truth for application configurat...
- **AssistantAuditRecord** (Class) - **AssistantAuditRecord** (Class)
- Store audit decisions and outcomes produced by assistant com... - Store audit decisions and outcomes produced by assistant com...
@@ -342,16 +342,16 @@
- Persist risky operation confirmation tokens with lifecycle s... - Persist risky operation confirmation tokens with lifecycle s...
- **AssistantMessageRecord** (Class) - **AssistantMessageRecord** (Class)
- Persist chat history entries for assistant conversations. - Persist chat history entries for assistant conversations.
- **ConnectionConfig** (Class) `[TRIVIAL]` - **CheckFinalStatus** (Class)
- Stores credentials for external databases used for column ma... - Final status for compliance check run.
- **DashboardMetadata** (Class) `[TRIVIAL]` - **CheckStageName** (Class)
- Represents a dashboard available for migration. - Mandatory check stages.
- **DashboardSelection** (Class) `[TRIVIAL]` - **CheckStageResult** (Class)
- Represents the user's selection of dashboards to migrate. - Per-stage compliance result.
- **DatabaseMapping** (Class) - **CheckStageStatus** (Class)
- Represents a mapping between source and target databases. - Stage-level execution status.
- **DeploymentEnvironment** (Class) `[TRIVIAL]` - **ClassificationType** (Class)
- Target Superset environments for dashboard deployment. - Manifest classification outcomes for artifacts.
**Dependencies:** **Dependencies:**
@@ -378,7 +378,7 @@
### 📁 `plugins/` ### 📁 `plugins/`
- 🏗️ **Layers:** App, Plugin, Plugins - 🏗️ **Layers:** App, Plugin, Plugins
- 📊 **Tiers:** STANDARD: 63 - 📊 **Tiers:** CRITICAL: 10, STANDARD: 53
- 📄 **Files:** 6 - 📄 **Files:** 6
- 📦 **Entities:** 63 - 📦 **Entities:** 63
@@ -392,7 +392,7 @@
- Реализация плагина Git Integration для управления версиями д... - Реализация плагина Git Integration для управления версиями д...
- **MapperPlugin** (Class) - **MapperPlugin** (Class)
- Plugin for mapping dataset columns verbose names. - Plugin for mapping dataset columns verbose names.
- **MigrationPlugin** (Class) - **MigrationPlugin** (Class) `[CRITICAL]`
- Implementation of the migration plugin logic. - Implementation of the migration plugin logic.
- **SearchPlugin** (Class) - **SearchPlugin** (Class)
- Plugin for searching text patterns in Superset datasets. - Plugin for searching text patterns in Superset datasets.
@@ -402,7 +402,7 @@
- Implements a plugin for system diagnostics and debugging Sup... - Implements a plugin for system diagnostics and debugging Sup...
- 📦 **MapperPluginModule** (Module) - 📦 **MapperPluginModule** (Module)
- Implements a plugin for mapping dataset columns using extern... - Implements a plugin for mapping dataset columns using extern...
- 📦 **MigrationPlugin** (Module) - 📦 **MigrationPlugin** (Module) `[CRITICAL]`
- A plugin that provides functionality to migrate Superset das... - A plugin that provides functionality to migrate Superset das...
**Dependencies:** **Dependencies:**
@@ -481,31 +481,31 @@
### 📁 `schemas/` ### 📁 `schemas/`
- 🏗️ **Layers:** API - 🏗️ **Layers:** API
- 📊 **Tiers:** STANDARD: 10, TRIVIAL: 3 - 📊 **Tiers:** CRITICAL: 10, TRIVIAL: 3
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 13 - 📦 **Entities:** 13
**Key Entities:** **Key Entities:**
- **ADGroupMappingCreate** (Class) - **ADGroupMappingCreate** (Class) `[CRITICAL]`
- Schema for creating an AD Group mapping. - Schema for creating an AD Group mapping.
- **ADGroupMappingSchema** (Class) - **ADGroupMappingSchema** (Class) `[CRITICAL]`
- Represents an AD Group to Role mapping in API responses. - Represents an AD Group to Role mapping in API responses.
- **PermissionSchema** (Class) `[TRIVIAL]` - **PermissionSchema** (Class) `[TRIVIAL]`
- Represents a permission in API responses. - Represents a permission in API responses.
- **RoleCreate** (Class) - **RoleCreate** (Class) `[CRITICAL]`
- Schema for creating a new role. - Schema for creating a new role.
- **RoleSchema** (Class) - **RoleSchema** (Class) `[CRITICAL]`
- Represents a role in API responses. - Represents a role in API responses.
- **RoleUpdate** (Class) - **RoleUpdate** (Class) `[CRITICAL]`
- Schema for updating an existing role. - Schema for updating an existing role.
- **Token** (Class) `[TRIVIAL]` - **Token** (Class) `[TRIVIAL]`
- Represents a JWT access token response. - Represents a JWT access token response.
- **TokenData** (Class) `[TRIVIAL]` - **TokenData** (Class) `[TRIVIAL]`
- Represents the data encoded in a JWT token. - Represents the data encoded in a JWT token.
- **User** (Class) - **User** (Class) `[CRITICAL]`
- Schema for user data in API responses. - Schema for user data in API responses.
- **UserBase** (Class) - **UserBase** (Class) `[CRITICAL]`
- Base schema for user data. - Base schema for user data.
**Dependencies:** **Dependencies:**
@@ -514,16 +514,18 @@
### 📁 `scripts/` ### 📁 `scripts/`
- 🏗️ **Layers:** Scripts, Unknown - 🏗️ **Layers:** Scripts, UI, Unknown
- 📊 **Tiers:** STANDARD: 26, TRIVIAL: 2 - 📊 **Tiers:** CRITICAL: 2, STANDARD: 25, TRIVIAL: 3
- 📄 **Files:** 6 - 📄 **Files:** 7
- 📦 **Entities:** 28 - 📦 **Entities:** 30
**Key Entities:** **Key Entities:**
- 📦 **backend.src.scripts.clean_release_tui** (Module)
- Provide clean release TUI entrypoint placeholder for phased ...
- 📦 **backend.src.scripts.create_admin** (Module) - 📦 **backend.src.scripts.create_admin** (Module)
- CLI tool for creating the initial admin user. - CLI tool for creating the initial admin user.
- 📦 **backend.src.scripts.init_auth_db** (Module) - 📦 **backend.src.scripts.init_auth_db** (Module) `[CRITICAL]`
- Initializes the auth database and creates the necessary tabl... - Initializes the auth database and creates the necessary tabl...
- 📦 **backend.src.scripts.migrate_sqlite_to_postgres** (Module) - 📦 **backend.src.scripts.migrate_sqlite_to_postgres** (Module)
- Migrates legacy config and task history from SQLite/file sto... - Migrates legacy config and task history from SQLite/file sto...
@@ -537,13 +539,13 @@
### 📁 `services/` ### 📁 `services/`
- 🏗️ **Layers:** Core, Domain, Service - 🏗️ **Layers:** Core, Domain, Service
- 📊 **Tiers:** CRITICAL: 1, STANDARD: 62, TRIVIAL: 6 - 📊 **Tiers:** CRITICAL: 7, STANDARD: 75, TRIVIAL: 6
- 📄 **Files:** 7 - 📄 **Files:** 7
- 📦 **Entities:** 69 - 📦 **Entities:** 88
**Key Entities:** **Key Entities:**
- **AuthService** (Class) - **AuthService** (Class) `[CRITICAL]`
- Provides high-level authentication services. - Provides high-level authentication services.
- **EncryptionManager** (Class) `[CRITICAL]` - **EncryptionManager** (Class) `[CRITICAL]`
- Handles encryption and decryption of sensitive data like API... - Handles encryption and decryption of sensitive data like API...
@@ -557,7 +559,7 @@
- Provides centralized access to resource data with enhanced m... - Provides centralized access to resource data with enhanced m...
- 📦 **backend.src.services** (Module) - 📦 **backend.src.services** (Module)
- Package initialization for services module - Package initialization for services module
- 📦 **backend.src.services.auth_service** (Module) - 📦 **backend.src.services.auth_service** (Module) `[CRITICAL]`
- Orchestrates authentication business logic. - Orchestrates authentication business logic.
- 📦 **backend.src.services.git_service** (Module) - 📦 **backend.src.services.git_service** (Module)
- Core Git logic using GitPython to manage dashboard repositor... - Core Git logic using GitPython to manage dashboard repositor...
@@ -594,6 +596,57 @@
- 🔗 DEPENDS_ON -> backend.src.services.llm_prompt_templates - 🔗 DEPENDS_ON -> backend.src.services.llm_prompt_templates
### 📁 `clean_release/`
- 🏗️ **Layers:** Domain, Infra
- 📊 **Tiers:** CRITICAL: 3, STANDARD: 12, TRIVIAL: 33
- 📄 **Files:** 10
- 📦 **Entities:** 48
**Key Entities:**
- **CleanPolicyEngine** (Class)
- 📦 **backend.src.services.clean_release** (Module)
- Initialize clean release service package and provide explici...
- 📦 **backend.src.services.clean_release.audit_service** (Module)
- Provide lightweight audit hooks for clean release preparatio...
- 📦 **backend.src.services.clean_release.compliance_orchestrator** (Module) `[CRITICAL]`
- Execute mandatory clean compliance stages and produce final ...
- 📦 **backend.src.services.clean_release.manifest_builder** (Module)
- Build deterministic distribution manifest from classified ar...
- 📦 **backend.src.services.clean_release.policy_engine** (Module) `[CRITICAL]`
- Evaluate artifact/source policies for enterprise clean profi...
- 📦 **backend.src.services.clean_release.preparation_service** (Module)
- Prepare release candidate by policy evaluation and determini...
- 📦 **backend.src.services.clean_release.report_builder** (Module) `[CRITICAL]`
- Build and persist compliance reports with consistent counter...
- 📦 **backend.src.services.clean_release.repository** (Module)
- Provide repository adapter for clean release entities with d...
- 📦 **backend.src.services.clean_release.source_isolation** (Module)
- Validate that all resource endpoints belong to the approved ...
**Dependencies:**
- 🔗 DEPENDS_ON -> backend.src.core.logger
- 🔗 DEPENDS_ON -> backend.src.models.clean_release
- 🔗 DEPENDS_ON -> backend.src.models.clean_release.CleanProfilePolicy
- 🔗 DEPENDS_ON -> backend.src.models.clean_release.ResourceSourceRegistry
- 🔗 DEPENDS_ON -> backend.src.services.clean_release.manifest_builder
### 📁 `__tests__/`
- 🏗️ **Layers:** Domain
- 📊 **Tiers:** STANDARD: 12
- 📄 **Files:** 2
- 📦 **Entities:** 12
**Key Entities:**
- 📦 **backend.tests.services.clean_release.test_compliance_orchestrator** (Module)
- Validate compliance orchestrator stage transitions and final...
- 📦 **backend.tests.services.clean_release.test_report_builder** (Module)
- Validate compliance report builder counter integrity and blo...
### 📁 `reports/` ### 📁 `reports/`
- 🏗️ **Layers:** Domain - 🏗️ **Layers:** Domain
@@ -636,43 +689,59 @@
### 📁 `tests/` ### 📁 `tests/`
- 🏗️ **Layers:** Core, Domain (Tests), Test, Unknown - 🏗️ **Layers:** Core, Domain (Tests), Logging (Tests), Test, Unknown
- 📊 **Tiers:** CRITICAL: 6, STANDARD: 79, TRIVIAL: 85 - 📊 **Tiers:** STANDARD: 86, TRIVIAL: 85
- 📄 **Files:** 10 - 📄 **Files:** 10
- 📦 **Entities:** 170 - 📦 **Entities:** 171
**Key Entities:** **Key Entities:**
- **TestLogPersistence** (Class) `[CRITICAL]` - **TestLogPersistence** (Class)
- Test suite for TaskLogPersistenceService. - Test suite for TaskLogPersistenceService.
- **TestTaskContext** (Class) - **TestTaskContext** (Class)
- Test suite for TaskContext. - Test suite for TaskContext.
- **TestTaskLogger** (Class) - **TestTaskLogger** (Class)
- Test suite for TaskLogger. - Test suite for TaskLogger.
- **TestTaskPersistenceHelpers** (Class) `[CRITICAL]` - **TestTaskPersistenceHelpers** (Class)
- Test suite for TaskPersistenceService static helper methods. - Test suite for TaskPersistenceService static helper methods.
- **TestTaskPersistenceService** (Class) `[CRITICAL]` - **TestTaskPersistenceService** (Class)
- Test suite for TaskPersistenceService CRUD operations. - Test suite for TaskPersistenceService CRUD operations.
- 📦 **backend.tests.test_dashboards_api** (Module) - 📦 **backend.tests.test_dashboards_api** (Module)
- Comprehensive contract-driven tests for Dashboard Hub API - Comprehensive contract-driven tests for Dashboard Hub API
- 📦 **test_auth** (Module) `[TRIVIAL]` - 📦 **test_auth** (Module) `[TRIVIAL]`
- Auto-generated module for backend/tests/test_auth.py - Auto-generated module for backend/tests/test_auth.py
- 📦 **test_log_persistence** (Module) `[CRITICAL]` - 📦 **test_log_persistence** (Module)
- Unit tests for TaskLogPersistenceService. - Unit tests for TaskLogPersistenceService.
- 📦 **test_resource_hubs** (Module) `[TRIVIAL]` - 📦 **test_resource_hubs** (Module) `[TRIVIAL]`
- Auto-generated module for backend/tests/test_resource_hubs.p... - Auto-generated module for backend/tests/test_resource_hubs.p...
- 📦 **test_smoke_plugins** (Module) `[TRIVIAL]` - 📦 **test_smoke_plugins** (Module) `[TRIVIAL]`
- Auto-generated module for backend/tests/test_smoke_plugins.p... - Auto-generated module for backend/tests/test_smoke_plugins.p...
### 📁 `routes/`
- 🏗️ **Layers:** Domain
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 5
- 📄 **Files:** 2
- 📦 **Entities:** 7
**Key Entities:**
- 📦 **backend.tests.api.routes.test_clean_release_api** (Module)
- Contract tests for clean release checks and reports endpoint...
- 📦 **backend.tests.api.routes.test_clean_release_source_policy** (Module)
- Validate API behavior for source isolation violations in cle...
### 📁 `core/` ### 📁 `core/`
- 🏗️ **Layers:** Domain, Unknown - 🏗️ **Layers:** Domain, Unknown
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 31 - 📊 **Tiers:** STANDARD: 5, TRIVIAL: 32
- 📄 **Files:** 3 - 📄 **Files:** 4
- 📦 **Entities:** 33 - 📦 **Entities:** 37
**Key Entities:** **Key Entities:**
- 📦 **backend.tests.core.test_git_service_gitea_pr** (Module)
- Validate Gitea PR creation fallback behavior when configured...
- 📦 **backend.tests.core.test_mapping_service** (Module) - 📦 **backend.tests.core.test_mapping_service** (Module)
- Unit tests for the IdMappingService matching UUIDs to intege... - Unit tests for the IdMappingService matching UUIDs to intege...
- 📦 **backend.tests.core.test_migration_engine** (Module) - 📦 **backend.tests.core.test_migration_engine** (Module)
@@ -694,10 +763,26 @@
- 📦 **backend.tests.core.migration.test_dry_run_orchestrator** (Module) - 📦 **backend.tests.core.migration.test_dry_run_orchestrator** (Module)
- Unit tests for MigrationDryRunService diff and risk computat... - Unit tests for MigrationDryRunService diff and risk computat...
### 📁 `clean_release/`
- 🏗️ **Layers:** Domain
- 📊 **Tiers:** STANDARD: 11, TRIVIAL: 5
- 📄 **Files:** 3
- 📦 **Entities:** 16
**Key Entities:**
- 📦 **backend.tests.services.clean_release.test_manifest_builder** (Module)
- Validate deterministic manifest generation behavior for US1.
- 📦 **backend.tests.services.clean_release.test_policy_engine** (Module)
- Validate policy model contracts and deterministic classifica...
- 📦 **backend.tests.services.clean_release.test_source_isolation** (Module)
- Verify internal source registry validation behavior.
### 📁 `components/` ### 📁 `components/`
- 🏗️ **Layers:** Component, Feature, UI, UI -->, Unknown - 🏗️ **Layers:** Component, Feature, UI, UI -->, Unknown
- 📊 **Tiers:** CRITICAL: 1, STANDARD: 68, TRIVIAL: 4 - 📊 **Tiers:** STANDARD: 69, TRIVIAL: 4
- 📄 **Files:** 14 - 📄 **Files:** 14
- 📦 **Entities:** 73 - 📦 **Entities:** 73
@@ -751,9 +836,9 @@
### 📁 `git/` ### 📁 `git/`
- 🏗️ **Layers:** Component - 🏗️ **Layers:** Component
- 📊 **Tiers:** STANDARD: 28 - 📊 **Tiers:** STANDARD: 45
- 📄 **Files:** 6 - 📄 **Files:** 6
- 📦 **Entities:** 28 - 📦 **Entities:** 45
**Key Entities:** **Key Entities:**
@@ -768,12 +853,12 @@
- 🧩 **DeploymentModal** (Component) - 🧩 **DeploymentModal** (Component)
- Modal for deploying a dashboard to a target environment. - Modal for deploying a dashboard to a target environment.
- 🧩 **GitManager** (Component) - 🧩 **GitManager** (Component)
- Центральный компонент для управления Git-операциями конкретн... - Центральный UI управления Git с фокусом на рабочий поток ана...
### 📁 `llm/` ### 📁 `llm/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** STANDARD: 2, TRIVIAL: 11 - 📊 **Tiers:** CRITICAL: 1, STANDARD: 1, TRIVIAL: 11
- 📄 **Files:** 3 - 📄 **Files:** 3
- 📦 **Entities:** 13 - 📦 **Entities:** 13
@@ -781,7 +866,7 @@
- 🧩 **DocPreview** (Component) - 🧩 **DocPreview** (Component)
- UI component for previewing generated dataset documentation ... - UI component for previewing generated dataset documentation ...
- 🧩 **ProviderConfig** (Component) - 🧩 **ProviderConfig** (Component) `[CRITICAL]`
- UI form for managing LLM provider configurations. - UI form for managing LLM provider configurations.
- 📦 **DocPreview** (Module) `[TRIVIAL]` - 📦 **DocPreview** (Module) `[TRIVIAL]`
- Auto-generated module for frontend/src/components/llm/DocPre... - Auto-generated module for frontend/src/components/llm/DocPre...
@@ -861,9 +946,9 @@
### 📁 `lib/` ### 📁 `lib/`
- 🏗️ **Layers:** Infra, Infra-API, UI, UI-State - 🏗️ **Layers:** Infra, Infra-API, UI, UI-State
- 📊 **Tiers:** STANDARD: 24, TRIVIAL: 3 - 📊 **Tiers:** STANDARD: 24, TRIVIAL: 5
- 📄 **Files:** 5 - 📄 **Files:** 5
- 📦 **Entities:** 27 - 📦 **Entities:** 29
**Key Entities:** **Key Entities:**
@@ -918,25 +1003,25 @@
### 📁 `auth/` ### 📁 `auth/`
- 🏗️ **Layers:** Feature - 🏗️ **Layers:** Feature
- 📊 **Tiers:** STANDARD: 7 - 📊 **Tiers:** CRITICAL: 7
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 7 - 📦 **Entities:** 7
**Key Entities:** **Key Entities:**
- 🗄️ **authStore** (Store) - 🗄️ **authStore** (Store) `[CRITICAL]`
- Manages the global authentication state on the frontend. - Manages the global authentication state on the frontend.
### 📁 `assistant/` ### 📁 `assistant/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, STANDARD: 13, TRIVIAL: 5 - 📊 **Tiers:** STANDARD: 14, TRIVIAL: 5
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 19 - 📦 **Entities:** 19
**Key Entities:** **Key Entities:**
- 🧩 **AssistantChatPanel** (Component) `[CRITICAL]` - 🧩 **AssistantChatPanel** (Component)
- Slide-out assistant chat panel for natural language command ... - Slide-out assistant chat panel for natural language command ...
- 📦 **AssistantChatPanel** (Module) `[TRIVIAL]` - 📦 **AssistantChatPanel** (Module) `[TRIVIAL]`
- Auto-generated module for frontend/src/lib/components/assist... - Auto-generated module for frontend/src/lib/components/assist...
@@ -956,7 +1041,7 @@
### 📁 `layout/` ### 📁 `layout/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 3, STANDARD: 5, TRIVIAL: 48 - 📊 **Tiers:** STANDARD: 8, TRIVIAL: 48
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 56 - 📦 **Entities:** 56
@@ -964,11 +1049,11 @@
- 🧩 **Breadcrumbs** (Component) - 🧩 **Breadcrumbs** (Component)
- Display page hierarchy navigation - Display page hierarchy navigation
- 🧩 **Sidebar** (Component) `[CRITICAL]` - 🧩 **Sidebar** (Component)
- Persistent left sidebar with resource categories navigation - Persistent left sidebar with resource categories navigation
- 🧩 **TaskDrawer** (Component) `[CRITICAL]` - 🧩 **TaskDrawer** (Component)
- Global task drawer for monitoring background operations - Global task drawer for monitoring background operations
- 🧩 **TopNavbar** (Component) `[CRITICAL]` - 🧩 **TopNavbar** (Component)
- Unified top navigation bar with Logo, Search, Activity, and ... - Unified top navigation bar with Logo, Search, Activity, and ...
- 📦 **Breadcrumbs** (Module) `[TRIVIAL]` - 📦 **Breadcrumbs** (Module) `[TRIVIAL]`
- Auto-generated module for frontend/src/lib/components/layout... - Auto-generated module for frontend/src/lib/components/layout...
@@ -994,17 +1079,17 @@
### 📁 `reports/` ### 📁 `reports/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 4, STANDARD: 1, TRIVIAL: 10 - 📊 **Tiers:** CRITICAL: 1, STANDARD: 4, TRIVIAL: 10
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 15 - 📦 **Entities:** 15
**Key Entities:** **Key Entities:**
- 🧩 **ReportCard** (Component) `[CRITICAL]` - 🧩 **ReportCard** (Component)
- Render one report with explicit textual type label and profi... - Render one report with explicit textual type label and profi...
- 🧩 **ReportDetailPanel** (Component) `[CRITICAL]` - 🧩 **ReportDetailPanel** (Component)
- Display detailed report context with diagnostics and actiona... - Display detailed report context with diagnostics and actiona...
- 🧩 **ReportsList** (Component) `[CRITICAL]` - 🧩 **ReportsList** (Component)
- Render unified list of normalized reports with canonical min... - Render unified list of normalized reports with canonical min...
- 📦 **ReportCard** (Module) `[TRIVIAL]` - 📦 **ReportCard** (Module) `[TRIVIAL]`
- Auto-generated module for frontend/src/lib/components/report... - Auto-generated module for frontend/src/lib/components/report...
@@ -1260,9 +1345,9 @@
### 📁 `dashboards/` ### 📁 `dashboards/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, STANDARD: 23, TRIVIAL: 60 - 📊 **Tiers:** STANDARD: 24, TRIVIAL: 61
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 84 - 📦 **Entities:** 85
**Key Entities:** **Key Entities:**
@@ -1272,9 +1357,9 @@
### 📁 `[id]/` ### 📁 `[id]/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, TRIVIAL: 17 - 📊 **Tiers:** STANDARD: 1, TRIVIAL: 28
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 18 - 📦 **Entities:** 29
**Key Entities:** **Key Entities:**
@@ -1284,7 +1369,7 @@
### 📁 `datasets/` ### 📁 `datasets/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, TRIVIAL: 15 - 📊 **Tiers:** STANDARD: 1, TRIVIAL: 15
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 16 - 📦 **Entities:** 16
@@ -1296,7 +1381,7 @@
### 📁 `[id]/` ### 📁 `[id]/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, TRIVIAL: 6 - 📊 **Tiers:** STANDARD: 1, TRIVIAL: 6
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 7 - 📦 **Entities:** 7
@@ -1332,26 +1417,26 @@
### 📁 `migration/` ### 📁 `migration/`
- 🏗️ **Layers:** Page - 🏗️ **Layers:** Page
- 📊 **Tiers:** STANDARD: 11 - 📊 **Tiers:** CRITICAL: 11
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 11 - 📦 **Entities:** 11
**Key Entities:** **Key Entities:**
- 🧩 **DashboardSelectionSection** (Component) - 🧩 **DashboardSelectionSection** (Component) `[CRITICAL]`
- 🧩 **MigrationDashboard** (Component) - 🧩 **MigrationDashboard** (Component) `[CRITICAL]`
- Main dashboard for configuring and starting migrations. - Main dashboard for configuring and starting migrations.
### 📁 `mappings/` ### 📁 `mappings/`
- 🏗️ **Layers:** Page - 🏗️ **Layers:** Page
- 📊 **Tiers:** STANDARD: 4 - 📊 **Tiers:** CRITICAL: 4
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 4 - 📦 **Entities:** 4
**Key Entities:** **Key Entities:**
- 🧩 **MappingManagement** (Component) - 🧩 **MappingManagement** (Component) `[CRITICAL]`
- Page for managing database mappings between environments. - Page for managing database mappings between environments.
### 📁 `reports/` ### 📁 `reports/`
@@ -1383,9 +1468,9 @@
### 📁 `settings/` ### 📁 `settings/`
- 🏗️ **Layers:** UI, Unknown - 🏗️ **Layers:** UI, Unknown
- 📊 **Tiers:** CRITICAL: 1, STANDARD: 1, TRIVIAL: 23 - 📊 **Tiers:** CRITICAL: 1, STANDARD: 1, TRIVIAL: 25
- 📄 **Files:** 2 - 📄 **Files:** 2
- 📦 **Entities:** 25 - 📦 **Entities:** 27
**Key Entities:** **Key Entities:**
@@ -1407,9 +1492,9 @@
### 📁 `git/` ### 📁 `git/`
- 🏗️ **Layers:** Page - 🏗️ **Layers:** Page
- 📊 **Tiers:** STANDARD: 5 - 📊 **Tiers:** STANDARD: 8
- 📄 **Files:** 1 - 📄 **Files:** 1
- 📦 **Entities:** 5 - 📦 **Entities:** 8
**Key Entities:** **Key Entities:**
@@ -1468,9 +1553,9 @@
### 📁 `services/` ### 📁 `services/`
- 🏗️ **Layers:** Service - 🏗️ **Layers:** Service
- 📊 **Tiers:** STANDARD: 33 - 📊 **Tiers:** STANDARD: 33, TRIVIAL: 1
- 📄 **Files:** 6 - 📄 **Files:** 6
- 📦 **Entities:** 33 - 📦 **Entities:** 34
**Key Entities:** **Key Entities:**
@@ -1500,7 +1585,7 @@
### 📁 `root/` ### 📁 `root/`
- 🏗️ **Layers:** DevOps/Tooling, Domain, Unknown - 🏗️ **Layers:** DevOps/Tooling, Domain, Unknown
- 📊 **Tiers:** CRITICAL: 14, STANDARD: 24, TRIVIAL: 12 - 📊 **Tiers:** CRITICAL: 11, STANDARD: 27, TRIVIAL: 12
- 📄 **Files:** 4 - 📄 **Files:** 4
- 📦 **Entities:** 50 - 📦 **Entities:** 50
@@ -1508,7 +1593,7 @@
- **ComplianceIssue** (Class) `[TRIVIAL]` - **ComplianceIssue** (Class) `[TRIVIAL]`
- Represents a single compliance issue with severity. - Represents a single compliance issue with severity.
- **ReportsService** (Class) `[CRITICAL]` - **ReportsService** (Class)
- Service layer for list/detail report retrieval and normaliza... - Service layer for list/detail report retrieval and normaliza...
- **SemanticEntity** (Class) `[CRITICAL]` - **SemanticEntity** (Class) `[CRITICAL]`
- Represents a code entity (Module, Function, Component) found... - Represents a code entity (Module, Function, Component) found...
@@ -1518,7 +1603,7 @@
- Severity levels for compliance issues. - Severity levels for compliance issues.
- **Tier** (Class) `[TRIVIAL]` - **Tier** (Class) `[TRIVIAL]`
- Enumeration of semantic tiers defining validation strictness... - Enumeration of semantic tiers defining validation strictness...
- 📦 **backend.src.services.reports.report_service** (Module) `[CRITICAL]` - 📦 **backend.src.services.reports.report_service** (Module)
- Aggregate, normalize, filter, and paginate task reports for ... - Aggregate, normalize, filter, and paginate task reports for ...
- 📦 **check_test_data** (Module) `[TRIVIAL]` - 📦 **check_test_data** (Module) `[TRIVIAL]`
- Auto-generated module for check_test_data.py - Auto-generated module for check_test_data.py
@@ -1566,6 +1651,8 @@ graph TD
routes-->|DEPENDS_ON|backend routes-->|DEPENDS_ON|backend
routes-->|DEPENDS_ON|backend routes-->|DEPENDS_ON|backend
routes-->|DEPENDS_ON|backend routes-->|DEPENDS_ON|backend
routes-->|DEPENDS_ON|backend
routes-->|DEPENDS_ON|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
@@ -1625,6 +1712,23 @@ graph TD
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|DEPENDS_ON|backend __tests__-->|DEPENDS_ON|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
clean_release-->|DEPENDS_ON|backend
__tests__-->|TESTS|backend
__tests__-->|TESTS|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
reports-->|DEPENDS_ON|backend reports-->|DEPENDS_ON|backend
@@ -1635,10 +1739,17 @@ graph TD
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
__tests__-->|TESTS|backend __tests__-->|TESTS|backend
tests-->|TESTS|backend tests-->|TESTS|backend
routes-->|TESTS|backend
routes-->|TESTS|backend
core-->|TESTS|backend
core-->|VERIFIES|backend core-->|VERIFIES|backend
core-->|VERIFIES|backend core-->|VERIFIES|backend
migration-->|VERIFIES|backend migration-->|VERIFIES|backend
migration-->|VERIFIES|backend migration-->|VERIFIES|backend
clean_release-->|VERIFIES|backend
clean_release-->|VERIFIES|backend
clean_release-->|TESTS|backend
__tests__-->|VERIFIES|components
__tests__-->|VERIFIES|components __tests__-->|VERIFIES|components
__tests__-->|VERIFIES|lib __tests__-->|VERIFIES|lib
reports-->|DEPENDS_ON|lib reports-->|DEPENDS_ON|lib

File diff suppressed because it is too large Load Diff

View File

@@ -97,17 +97,17 @@ def test_get_dashboards_with_search(mock_deps):
mock_deps["config"].get_environments.return_value = [mock_env] mock_deps["config"].get_environments.return_value = [mock_env]
mock_deps["task"].get_all_tasks.return_value = [] mock_deps["task"].get_all_tasks.return_value = []
async def mock_get_dashboards(env, tasks): async def mock_get_dashboards(env, tasks, include_git_status=False):
return [ return [
{"id": 1, "title": "Sales Report", "slug": "sales"}, {"id": 1, "title": "Sales Report", "slug": "sales", "git_status": {"branch": "main", "sync_status": "OK"}, "last_task": None},
{"id": 2, "title": "Marketing Dashboard", "slug": "marketing"} {"id": 2, "title": "Marketing Dashboard", "slug": "marketing", "git_status": {"branch": "main", "sync_status": "OK"}, "last_task": None}
] ]
mock_deps["resource"].get_dashboards_with_status = AsyncMock( mock_deps["resource"].get_dashboards_with_status = AsyncMock(
side_effect=mock_get_dashboards side_effect=mock_get_dashboards
) )
response = client.get("/api/dashboards?env_id=prod&search=sales") response = client.get("/api/dashboards?env_id=prod&search=sales")
assert response.status_code == 200 assert response.status_code == 200
data = response.json() data = response.json()
# @POST: Filtered result count must match search # @POST: Filtered result count must match search

View File

@@ -4,30 +4,30 @@
# @PURPOSE: Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks. # @PURPOSE: Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks.
# @LAYER: UI (API) # @LAYER: UI (API)
# @RELATION: Depends on the TaskManager. It is included by the main app. # @RELATION: Depends on the TaskManager. It is included by the main app.
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query from fastapi import APIRouter, Depends, HTTPException, status, Query
from pydantic import BaseModel from pydantic import BaseModel
from ...core.logger import belief_scope from ...core.logger import belief_scope
from ...core.task_manager import TaskManager, Task, TaskStatus, LogEntry from ...core.task_manager import TaskManager, Task, TaskStatus, LogEntry
from ...core.task_manager.models import LogFilter, LogStats from ...core.task_manager.models import LogFilter, LogStats
from ...dependencies import get_task_manager, has_permission, get_current_user, get_config_manager from ...dependencies import get_task_manager, has_permission, get_current_user, get_config_manager
from ...core.config_manager import ConfigManager from ...core.config_manager import ConfigManager
from ...services.llm_prompt_templates import ( from ...services.llm_prompt_templates import (
is_multimodal_model, is_multimodal_model,
normalize_llm_settings, normalize_llm_settings,
resolve_bound_provider_id, resolve_bound_provider_id,
) )
router = APIRouter() router = APIRouter()
TASK_TYPE_PLUGIN_MAP = { TASK_TYPE_PLUGIN_MAP = {
"llm_validation": ["llm_dashboard_validation"], "llm_validation": ["llm_dashboard_validation"],
"backup": ["superset-backup"], "backup": ["superset-backup"],
"migration": ["superset-migration"], "migration": ["superset-migration"],
} }
class CreateTaskRequest(BaseModel): class CreateTaskRequest(BaseModel):
plugin_id: str plugin_id: str
params: Dict[str, Any] params: Dict[str, Any]
@@ -45,54 +45,54 @@ class ResumeTaskRequest(BaseModel):
# @PRE: plugin_id must exist and params must be valid for that plugin. # @PRE: plugin_id must exist and params must be valid for that plugin.
# @POST: A new task is created and started. # @POST: A new task is created and started.
# @RETURN: Task - The created task instance. # @RETURN: Task - The created task instance.
async def create_task( async def create_task(
request: CreateTaskRequest, request: CreateTaskRequest,
task_manager: TaskManager = Depends(get_task_manager), task_manager: TaskManager = Depends(get_task_manager),
current_user = Depends(get_current_user), current_user = Depends(get_current_user),
config_manager: ConfigManager = Depends(get_config_manager), config_manager: ConfigManager = Depends(get_config_manager),
): ):
# Dynamic permission check based on plugin_id # Dynamic permission check based on plugin_id
has_permission(f"plugin:{request.plugin_id}", "EXECUTE")(current_user) has_permission(f"plugin:{request.plugin_id}", "EXECUTE")(current_user)
""" """
Create and start a new task for a given plugin. Create and start a new task for a given plugin.
""" """
with belief_scope("create_task"): with belief_scope("create_task"):
try: try:
# Special handling for LLM tasks to resolve provider config by task binding. # Special handling for LLM tasks to resolve provider config by task binding.
if request.plugin_id in {"llm_dashboard_validation", "llm_documentation"}: if request.plugin_id in {"llm_dashboard_validation", "llm_documentation"}:
from ...core.database import SessionLocal from ...core.database import SessionLocal
from ...services.llm_provider import LLMProviderService from ...services.llm_provider import LLMProviderService
db = SessionLocal() db = SessionLocal()
try: try:
llm_service = LLMProviderService(db) llm_service = LLMProviderService(db)
provider_id = request.params.get("provider_id") provider_id = request.params.get("provider_id")
if not provider_id: if not provider_id:
llm_settings = normalize_llm_settings(config_manager.get_config().settings.llm) llm_settings = normalize_llm_settings(config_manager.get_config().settings.llm)
binding_key = "dashboard_validation" if request.plugin_id == "llm_dashboard_validation" else "documentation" binding_key = "dashboard_validation" if request.plugin_id == "llm_dashboard_validation" else "documentation"
provider_id = resolve_bound_provider_id(llm_settings, binding_key) provider_id = resolve_bound_provider_id(llm_settings, binding_key)
if provider_id: if provider_id:
request.params["provider_id"] = provider_id request.params["provider_id"] = provider_id
if not provider_id: if not provider_id:
providers = llm_service.get_all_providers() providers = llm_service.get_all_providers()
active_provider = next((p for p in providers if p.is_active), None) active_provider = next((p for p in providers if p.is_active), None)
if active_provider: if active_provider:
provider_id = active_provider.id provider_id = active_provider.id
request.params["provider_id"] = provider_id request.params["provider_id"] = provider_id
if provider_id: if provider_id:
db_provider = llm_service.get_provider(provider_id) db_provider = llm_service.get_provider(provider_id)
if not db_provider: if not db_provider:
raise ValueError(f"LLM Provider {provider_id} not found") raise ValueError(f"LLM Provider {provider_id} not found")
if request.plugin_id == "llm_dashboard_validation" and not is_multimodal_model( if request.plugin_id == "llm_dashboard_validation" and not is_multimodal_model(
db_provider.default_model, db_provider.default_model,
db_provider.provider_type, db_provider.provider_type,
): ):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Selected provider model is not multimodal for dashboard validation", detail="Selected provider model is not multimodal for dashboard validation",
) )
finally: finally:
db.close() db.close()
task = await task_manager.create_task( task = await task_manager.create_task(
plugin_id=request.plugin_id, plugin_id=request.plugin_id,
@@ -113,36 +113,36 @@ async def create_task(
# @PRE: task_manager must be available. # @PRE: task_manager must be available.
# @POST: Returns a list of tasks. # @POST: Returns a list of tasks.
# @RETURN: List[Task] - List of tasks. # @RETURN: List[Task] - List of tasks.
async def list_tasks( async def list_tasks(
limit: int = 10, limit: int = 10,
offset: int = 0, offset: int = 0,
status_filter: Optional[TaskStatus] = Query(None, alias="status"), status_filter: Optional[TaskStatus] = Query(None, alias="status"),
task_type: Optional[str] = Query(None, description="Task category: llm_validation, backup, migration"), task_type: Optional[str] = Query(None, description="Task category: llm_validation, backup, migration"),
plugin_id: Optional[List[str]] = Query(None, description="Filter by plugin_id (repeatable query param)"), plugin_id: Optional[List[str]] = Query(None, description="Filter by plugin_id (repeatable query param)"),
completed_only: bool = Query(False, description="Return only completed tasks (SUCCESS/FAILED)"), completed_only: bool = Query(False, description="Return only completed tasks (SUCCESS/FAILED)"),
task_manager: TaskManager = Depends(get_task_manager), task_manager: TaskManager = Depends(get_task_manager),
_ = Depends(has_permission("tasks", "READ")) _ = Depends(has_permission("tasks", "READ"))
): ):
""" """
Retrieve a list of tasks with pagination and optional status filter. Retrieve a list of tasks with pagination and optional status filter.
""" """
with belief_scope("list_tasks"): with belief_scope("list_tasks"):
plugin_filters = list(plugin_id) if plugin_id else [] plugin_filters = list(plugin_id) if plugin_id else []
if task_type: if task_type:
if task_type not in TASK_TYPE_PLUGIN_MAP: if task_type not in TASK_TYPE_PLUGIN_MAP:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Unsupported task_type '{task_type}'. Allowed: {', '.join(TASK_TYPE_PLUGIN_MAP.keys())}" detail=f"Unsupported task_type '{task_type}'. Allowed: {', '.join(TASK_TYPE_PLUGIN_MAP.keys())}"
) )
plugin_filters.extend(TASK_TYPE_PLUGIN_MAP[task_type]) plugin_filters.extend(TASK_TYPE_PLUGIN_MAP[task_type])
return task_manager.get_tasks( return task_manager.get_tasks(
limit=limit, limit=limit,
offset=offset, offset=offset,
status=status_filter, status=status_filter,
plugin_ids=plugin_filters or None, plugin_ids=plugin_filters or None,
completed_only=completed_only completed_only=completed_only
) )
# [/DEF:list_tasks:Function] # [/DEF:list_tasks:Function]
@router.get("/{task_id}", response_model=Task) @router.get("/{task_id}", response_model=Task)
@@ -182,6 +182,13 @@ async def get_task(
# @POST: Returns a list of log entries or raises 404. # @POST: Returns a list of log entries or raises 404.
# @RETURN: List[LogEntry] - List of log entries. # @RETURN: List[LogEntry] - List of log entries.
# @TIER: CRITICAL # @TIER: CRITICAL
# @TEST_CONTRACT: TaskLogQueryInput -> List[LogEntry]
# @TEST_SCENARIO: existing_task_logs_filtered -> Returns filtered logs by level/source/search with pagination.
# @TEST_FIXTURE: valid_task_with_mixed_logs -> backend/tests/fixtures/task_logs/valid_task_with_mixed_logs.json
# @TEST_EDGE: missing_task -> Unknown task_id returns 404 Task not found.
# @TEST_EDGE: invalid_level_type -> Non-string/invalid level query rejected by validation or yields empty result.
# @TEST_EDGE: pagination_bounds -> offset=0 and limit=1000 remain within API bounds and do not overflow.
# @TEST_INVARIANT: logs_only_for_existing_task -> VERIFIED_BY: [existing_task_logs_filtered, missing_task]
async def get_task_logs( async def get_task_logs(
task_id: str, task_id: str,
level: Optional[str] = Query(None, description="Filter by log level (DEBUG, INFO, WARNING, ERROR)"), level: Optional[str] = Query(None, description="Filter by log level (DEBUG, INFO, WARNING, ERROR)"),
@@ -328,4 +335,4 @@ async def clear_tasks(
task_manager.clear_tasks(status) task_manager.clear_tasks(status)
return return
# [/DEF:clear_tasks:Function] # [/DEF:clear_tasks:Function]
# [/DEF:TasksRouter:Module] # [/DEF:TasksRouter:Module]

View File

@@ -5,6 +5,13 @@
# @LAYER: Domain # @LAYER: Domain
# @RELATION: BINDS_TO -> specs/023-clean-repo-enterprise/data-model.md # @RELATION: BINDS_TO -> specs/023-clean-repo-enterprise/data-model.md
# @INVARIANT: Enterprise-clean policy always forbids external sources. # @INVARIANT: Enterprise-clean policy always forbids external sources.
# @TEST_CONTRACT: CleanReleaseModelPayload -> ValidatedCleanReleaseModel | ValidationError
# @TEST_SCENARIO: valid_enterprise_models -> CRITICAL entities validate and preserve lifecycle/compliance invariants.
# @TEST_FIXTURE: clean_release_models_baseline -> backend/tests/fixtures/clean_release/fixtures_clean_release.json
# @TEST_EDGE: empty_required_identifiers -> Empty candidate_id/source_snapshot_ref/internal_source_registry_ref fails validation.
# @TEST_EDGE: compliant_run_missing_mandatory_stage -> COMPLIANT run without all mandatory PASS stages fails validation.
# @TEST_EDGE: blocked_report_without_blocking_violations -> BLOCKED report with zero blocking violations fails validation.
# @TEST_INVARIANT: external_source_must_block -> VERIFIED_BY: [valid_enterprise_models, blocked_report_without_blocking_violations]
from __future__ import annotations from __future__ import annotations

View File

@@ -9,8 +9,8 @@
"last_name": "Admin" "last_name": "Admin"
}, },
"changed_by_name": "Superset Admin", "changed_by_name": "Superset Admin",
"changed_on": "2026-02-10T13:39:35.945662", "changed_on": "2026-02-24T19:24:01.850617",
"changed_on_delta_humanized": "16 days ago", "changed_on_delta_humanized": "7 days ago",
"charts": [ "charts": [
"TA-0001-001 test_chart" "TA-0001-001 test_chart"
], ],
@@ -19,12 +19,12 @@
"id": 1, "id": 1,
"last_name": "Admin" "last_name": "Admin"
}, },
"created_on_delta_humanized": "16 days ago", "created_on_delta_humanized": "13 days ago",
"css": null, "css": null,
"dashboard_title": "TA-0001 Test dashboard", "dashboard_title": "TA-0001 Test dashboard",
"id": 13, "id": 13,
"is_managed_externally": false, "is_managed_externally": false,
"json_metadata": "{\"color_scheme_domain\": [], \"shared_label_colors\": [], \"map_label_colors\": {}, \"label_colors\": {}}", "json_metadata": "{\"color_scheme_domain\": [], \"shared_label_colors\": [], \"map_label_colors\": {}, \"label_colors\": {}, \"native_filter_configuration\": []}",
"owners": [ "owners": [
{ {
"first_name": "Superset", "first_name": "Superset",
@@ -32,13 +32,13 @@
"last_name": "Admin" "last_name": "Admin"
} }
], ],
"position_json": null, "position_json": "{\"DASHBOARD_VERSION_KEY\": \"v2\", \"ROOT_ID\": {\"children\": [\"GRID_ID\"], \"id\": \"ROOT_ID\", \"type\": \"ROOT\"}, \"GRID_ID\": {\"children\": [\"ROW-N-LH8TG1XX\"], \"id\": \"GRID_ID\", \"parents\": [\"ROOT_ID\"], \"type\": \"GRID\"}, \"HEADER_ID\": {\"id\": \"HEADER_ID\", \"meta\": {\"text\": \"TA-0001 Test dashboard\"}, \"type\": \"HEADER\"}, \"ROW-N-LH8TG1XX\": {\"children\": [\"CHART-1EKC8H7C\"], \"id\": \"ROW-N-LH8TG1XX\", \"meta\": {\"0\": \"ROOT_ID\", \"background\": \"BACKGROUND_TRANSPARENT\"}, \"type\": \"ROW\", \"parents\": [\"ROOT_ID\", \"GRID_ID\"]}, \"CHART-1EKC8H7C\": {\"children\": [], \"id\": \"CHART-1EKC8H7C\", \"meta\": {\"chartId\": 162, \"height\": 50, \"sliceName\": \"TA-0001-001 test_chart\", \"uuid\": \"008cdaa7-21b3-4042-9f55-f15653609ebd\", \"width\": 4}, \"type\": \"CHART\", \"parents\": [\"ROOT_ID\", \"GRID_ID\", \"ROW-N-LH8TG1XX\"]}}",
"published": true, "published": true,
"roles": [], "roles": [],
"slug": null, "slug": null,
"tags": [], "tags": [],
"theme": null, "theme": null,
"thumbnail_url": "/api/v1/dashboard/13/thumbnail/3cfc57e6aea7188b139f94fb437a1426/", "thumbnail_url": "/api/v1/dashboard/13/thumbnail/97dfd5d8d24f7cf01de45671c9a0699d/",
"url": "/superset/dashboard/13/", "url": "/superset/dashboard/13/",
"uuid": "124b28d4-d54a-4ade-ade7-2d0473b90686" "uuid": "124b28d4-d54a-4ade-ade7-2d0473b90686"
} }
@@ -53,15 +53,15 @@
"first_name": "Superset", "first_name": "Superset",
"last_name": "Admin" "last_name": "Admin"
}, },
"changed_on": "2026-02-10T13:38:26.175551", "changed_on": "2026-02-18T14:56:04.863722",
"changed_on_humanized": "16 days ago", "changed_on_humanized": "13 days ago",
"column_formats": {}, "column_formats": {},
"columns": [ "columns": [
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158196", "changed_on": "2026-02-18T14:56:05.382289",
"column_name": "color", "column_name": "has_2fa",
"created_on": "2026-02-10T13:38:26.158189", "created_on": "2026-02-18T14:56:05.382138",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -71,16 +71,16 @@
"is_active": true, "is_active": true,
"is_dttm": false, "is_dttm": false,
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "BOOLEAN",
"type_generic": 1, "type_generic": 3,
"uuid": "4fa810ee-99cc-4d1f-8c0d-0f289c3b01f4", "uuid": "fe374f2a-9e06-4708-89fd-c3926e3e5faa",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158249", "changed_on": "2026-02-18T14:56:05.545701",
"column_name": "deleted", "column_name": "is_ultra_restricted",
"created_on": "2026-02-10T13:38:26.158245", "created_on": "2026-02-18T14:56:05.545465",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -92,14 +92,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "ebc07e82-7250-4eef-8d13-ea61561fa52c", "uuid": "eac7ecce-d472-4933-9652-d4f2811074fd",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158289", "changed_on": "2026-02-18T14:56:05.683578",
"column_name": "has_2fa", "column_name": "is_primary_owner",
"created_on": "2026-02-10T13:38:26.158285", "created_on": "2026-02-18T14:56:05.683257",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -111,14 +111,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "08e72f4d-3ced-4d9a-9f7d-2f85291ce88b", "uuid": "94a15acd-ef98-425b-8f0d-1ce038ca95c5",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158328", "changed_on": "2026-02-18T14:56:05.758231",
"column_name": "id", "column_name": "is_app_user",
"created_on": "2026-02-10T13:38:26.158324", "created_on": "2026-02-18T14:56:05.758142",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -128,16 +128,16 @@
"is_active": true, "is_active": true,
"is_dttm": false, "is_dttm": false,
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "BOOLEAN",
"type_generic": 1, "type_generic": 3,
"uuid": "fd11955c-0130-4ea1-b3c0-d8b159971789", "uuid": "d3fcd712-dc96-4bba-a026-aa82022eccf5",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158366", "changed_on": "2026-02-18T14:56:05.799597",
"column_name": "is_admin", "column_name": "is_admin",
"created_on": "2026-02-10T13:38:26.158362", "created_on": "2026-02-18T14:56:05.799519",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -149,14 +149,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "13a6c8e1-c9f8-4f08-aa62-05bca7be547b", "uuid": "5a1c9de5-80f1-4fe8-a91b-e6e530688aae",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158404", "changed_on": "2026-02-18T14:56:05.819443",
"column_name": "is_app_user", "column_name": "is_bot",
"created_on": "2026-02-10T13:38:26.158400", "created_on": "2026-02-18T14:56:05.819382",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -168,14 +168,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "6321ba8a-28d7-4d68-a6b3-5cef6cd681a2", "uuid": "6c93e5de-e0d7-430c-88d7-87158905d60a",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158442", "changed_on": "2026-02-18T14:56:05.827568",
"column_name": "is_bot", "column_name": "is_restricted",
"created_on": "2026-02-10T13:38:26.158438", "created_on": "2026-02-18T14:56:05.827556",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -187,14 +187,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "f3ded50e-b1a2-4a88-b805-781d5923e062", "uuid": "2e8e6d32-0124-4e3a-a53f-6f200f852439",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158480", "changed_on": "2026-02-18T14:56:05.835380",
"column_name": "is_owner", "column_name": "is_owner",
"created_on": "2026-02-10T13:38:26.158477", "created_on": "2026-02-18T14:56:05.835366",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -206,14 +206,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "8a1408eb-050d-4455-878c-22342df5da3d", "uuid": "510d651b-a595-4261-98e4-278af0a06594",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158532", "changed_on": "2026-02-18T14:56:05.843802",
"column_name": "is_primary_owner", "column_name": "deleted",
"created_on": "2026-02-10T13:38:26.158528", "created_on": "2026-02-18T14:56:05.843784",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -225,14 +225,14 @@
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "BOOLEAN",
"type_generic": 3, "type_generic": 3,
"uuid": "054b8c16-82fd-480c-82e0-a0975229673a", "uuid": "2653fd2f-c0ce-484e-a5df-d2515b1e822d",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158583", "changed_on": "2026-02-18T14:56:05.851074",
"column_name": "is_restricted", "column_name": "updated",
"created_on": "2026-02-10T13:38:26.158579", "created_on": "2026-02-18T14:56:05.851063",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -240,18 +240,18 @@
"groupby": true, "groupby": true,
"id": 781, "id": 781,
"is_active": true, "is_active": true,
"is_dttm": false, "is_dttm": true,
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "DATETIME",
"type_generic": 3, "type_generic": 2,
"uuid": "6932c25f-0273-4595-85c1-29422a801ded", "uuid": "1b1f90c8-2567-49b8-9398-e7246396461e",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158621", "changed_on": "2026-02-18T14:56:05.857578",
"column_name": "is_ultra_restricted", "column_name": "tz_offset",
"created_on": "2026-02-10T13:38:26.158618", "created_on": "2026-02-18T14:56:05.857571",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -261,16 +261,16 @@
"is_active": true, "is_active": true,
"is_dttm": false, "is_dttm": false,
"python_date_format": null, "python_date_format": null,
"type": "BOOLEAN", "type": "LONGINTEGER",
"type_generic": 3, "type_generic": 0,
"uuid": "9b14e5f9-3ab4-498e-b1e3-bbf49e9d61fe", "uuid": "e6d19b74-7f5d-447b-8071-951961dc2295",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158660", "changed_on": "2026-02-18T14:56:05.863101",
"column_name": "name", "column_name": "channel_name",
"created_on": "2026-02-10T13:38:26.158656", "created_on": "2026-02-18T14:56:05.863094",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -282,14 +282,14 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "ebee8249-0e10-4157-8a8e-96ae107887a3", "uuid": "e1f34628-ebc1-4e0c-8eea-54c3c9efba1b",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158697", "changed_on": "2026-02-18T14:56:05.877136",
"column_name": "real_name", "column_name": "real_name",
"created_on": "2026-02-10T13:38:26.158694", "created_on": "2026-02-18T14:56:05.877083",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -301,14 +301,14 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "553517a0-fe05-4ff5-a4eb-e9d2165d6f64", "uuid": "6cc5ab57-9431-428a-a331-0a5b10e4b074",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158735", "changed_on": "2026-02-18T14:56:05.893859",
"column_name": "team_id", "column_name": "tz_label",
"created_on": "2026-02-10T13:38:26.158731", "created_on": "2026-02-18T14:56:05.893834",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -320,14 +320,14 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "6c207fac-424d-465c-b80a-306b42b55ce8", "uuid": "8e6dbd8e-b880-4517-a5f6-64e429bd1bea",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158773", "changed_on": "2026-02-18T14:56:05.902363",
"column_name": "tz", "column_name": "team_id",
"created_on": "2026-02-10T13:38:26.158769", "created_on": "2026-02-18T14:56:05.902352",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -339,14 +339,14 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "6efcc042-0b78-4362-9373-2f684077d574", "uuid": "ba8e225d-221b-4275-aadb-e79557756f89",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158824", "changed_on": "2026-02-18T14:56:05.910169",
"column_name": "tz_label", "column_name": "name",
"created_on": "2026-02-10T13:38:26.158820", "created_on": "2026-02-18T14:56:05.910151",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -358,14 +358,14 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "c6a6ac40-5c60-472d-a878-4b65b8460ccc", "uuid": "02a7a026-d9f3-49e9-9586-534ebccdd867",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158861", "changed_on": "2026-02-18T14:56:05.915366",
"column_name": "tz_offset", "column_name": "color",
"created_on": "2026-02-10T13:38:26.158857", "created_on": "2026-02-18T14:56:05.915357",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -375,16 +375,16 @@
"is_active": true, "is_active": true,
"is_dttm": false, "is_dttm": false,
"python_date_format": null, "python_date_format": null,
"type": "LONGINTEGER", "type": "STRING",
"type_generic": 0, "type_generic": 1,
"uuid": "cf6da93a-bba9-47df-9154-6cfd0c9922fc", "uuid": "0702fcdf-2d03-45db-8496-697d47b300d6",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158913", "changed_on": "2026-02-18T14:56:05.919466",
"column_name": "updated", "column_name": "id",
"created_on": "2026-02-10T13:38:26.158909", "created_on": "2026-02-18T14:56:05.919460",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -392,18 +392,18 @@
"groupby": true, "groupby": true,
"id": 789, "id": 789,
"is_active": true, "is_active": true,
"is_dttm": true, "is_dttm": false,
"python_date_format": null, "python_date_format": null,
"type": "DATETIME", "type": "STRING",
"type_generic": 2, "type_generic": 1,
"uuid": "2aa0a72a-5602-4799-b5ab-f22000108d62", "uuid": "a4b58528-fcbf-45e9-af39-fe9d737ba380",
"verbose_name": null "verbose_name": null
}, },
{ {
"advanced_data_type": null, "advanced_data_type": null,
"changed_on": "2026-02-10T13:38:26.158967", "changed_on": "2026-02-18T14:56:05.932553",
"column_name": "channel_name", "column_name": "tz",
"created_on": "2026-02-10T13:38:26.158963", "created_on": "2026-02-18T14:56:05.932530",
"description": null, "description": null,
"expression": null, "expression": null,
"extra": null, "extra": null,
@@ -415,7 +415,7 @@
"python_date_format": null, "python_date_format": null,
"type": "STRING", "type": "STRING",
"type_generic": 1, "type_generic": 1,
"uuid": "a84bd658-c83c-4e7f-9e1b-192595092d9b", "uuid": "bc872357-1920-42f3-aeda-b596122bcdb8",
"verbose_name": null "verbose_name": null
} }
], ],
@@ -423,8 +423,8 @@
"first_name": "Superset", "first_name": "Superset",
"last_name": "Admin" "last_name": "Admin"
}, },
"created_on": "2026-02-10T13:38:26.050436", "created_on": "2026-02-18T14:56:04.317950",
"created_on_humanized": "16 days ago", "created_on_humanized": "13 days ago",
"database": { "database": {
"allow_multi_catalog": false, "allow_multi_catalog": false,
"backend": "postgresql", "backend": "postgresql",
@@ -452,8 +452,8 @@
"main_dttm_col": "updated", "main_dttm_col": "updated",
"metrics": [ "metrics": [
{ {
"changed_on": "2026-02-10T13:38:26.182269", "changed_on": "2026-02-18T14:56:05.085244",
"created_on": "2026-02-10T13:38:26.182264", "created_on": "2026-02-18T14:56:05.085166",
"currency": null, "currency": null,
"d3format": null, "d3format": null,
"description": null, "description": null,
@@ -462,7 +462,7 @@
"id": 33, "id": 33,
"metric_name": "count", "metric_name": "count",
"metric_type": "count", "metric_type": "count",
"uuid": "7510f8ca-05ee-4a37-bec1-4a5d7bf2ac50", "uuid": "10c8b8cf-b697-4512-9e9e-2996721f829e",
"verbose_name": "COUNT(*)", "verbose_name": "COUNT(*)",
"warning_text": null "warning_text": null
} }

View File

@@ -48,6 +48,33 @@ def test_orchestrator_stage_failure_blocks_release():
# [/DEF:test_orchestrator_stage_failure_blocks_release:Function] # [/DEF:test_orchestrator_stage_failure_blocks_release:Function]
# [DEF:test_orchestrator_compliant_candidate:Function]
# @PURPOSE: Verify happy path where all mandatory stages pass yields COMPLIANT.
def test_orchestrator_compliant_candidate():
repository = CleanReleaseRepository()
orchestrator = CleanComplianceOrchestrator(repository)
run = orchestrator.start_check_run(
candidate_id="2026.03.03-rc1",
policy_id="policy-enterprise-clean-v1",
triggered_by="tester",
execution_mode="tui",
)
run = orchestrator.execute_stages(
run,
forced_results=[
CheckStageResult(stage=CheckStageName.DATA_PURITY, status=CheckStageStatus.PASS, details="ok"),
CheckStageResult(stage=CheckStageName.INTERNAL_SOURCES_ONLY, status=CheckStageStatus.PASS, details="ok"),
CheckStageResult(stage=CheckStageName.NO_EXTERNAL_ENDPOINTS, status=CheckStageStatus.PASS, details="ok"),
CheckStageResult(stage=CheckStageName.MANIFEST_CONSISTENCY, status=CheckStageStatus.PASS, details="ok"),
],
)
run = orchestrator.finalize_run(run)
assert run.final_status == CheckFinalStatus.COMPLIANT
# [/DEF:test_orchestrator_compliant_candidate:Function]
# [DEF:test_orchestrator_missing_stage_result:Function] # [DEF:test_orchestrator_missing_stage_result:Function]
# @PURPOSE: Verify incomplete mandatory stage set cannot end as COMPLIANT and results in FAILED. # @PURPOSE: Verify incomplete mandatory stage set cannot end as COMPLIANT and results in FAILED.
def test_orchestrator_missing_stage_result(): def test_orchestrator_missing_stage_result():

View File

@@ -66,6 +66,26 @@ def test_report_builder_blocked_requires_blocking_violations():
# [/DEF:test_report_builder_blocked_requires_blocking_violations:Function] # [/DEF:test_report_builder_blocked_requires_blocking_violations:Function]
# [DEF:test_report_builder_blocked_with_two_violations:Function]
# @PURPOSE: Verify report builder generates conformant payload for a BLOCKED run with violations.
def test_report_builder_blocked_with_two_violations():
builder = ComplianceReportBuilder(CleanReleaseRepository())
run = _terminal_run(CheckFinalStatus.BLOCKED)
v1 = _blocking_violation()
v2 = _blocking_violation()
v2.violation_id = "viol-2"
v2.category = ViolationCategory.DATA_PURITY
report = builder.build_report_payload(run, [v1, v2])
assert report.check_run_id == run.check_run_id
assert report.candidate_id == run.candidate_id
assert report.final_status == CheckFinalStatus.BLOCKED
assert report.violations_count == 2
assert report.blocking_violations_count == 2
# [/DEF:test_report_builder_blocked_with_two_violations:Function]
# [DEF:test_report_builder_counter_consistency:Function] # [DEF:test_report_builder_counter_consistency:Function]
# @PURPOSE: Verify violations counters remain consistent for blocking payload. # @PURPOSE: Verify violations counters remain consistent for blocking payload.
def test_report_builder_counter_consistency(): def test_report_builder_counter_consistency():

View File

@@ -5,6 +5,13 @@
// @LAYER: UI (Tests) // @LAYER: UI (Tests)
// @RELATION: VERIFIES -> frontend/src/components/TaskLogViewer.svelte // @RELATION: VERIFIES -> frontend/src/components/TaskLogViewer.svelte
// @INVARIANT: Duplicate logs are never appended. Polling only active for in-progress tasks. // @INVARIANT: Duplicate logs are never appended. Polling only active for in-progress tasks.
// @TEST_CONTRACT: TaskLogViewerPropsAndLogStream -> RenderedLogTimeline
// @TEST_SCENARIO: historical_and_realtime_merge -> Historical logs render and realtime logs append without duplication.
// @TEST_FIXTURE: valid_viewer -> INLINE_JSON
// @TEST_EDGE: no_task_id -> Null taskId does not trigger fetch.
// @TEST_EDGE: fetch_failure -> Network failure renders recoverable error state with retry action.
// @TEST_EDGE: duplicate_realtime_entry -> Existing log is not duplicated when repeated in realtime stream.
// @TEST_INVARIANT: no_duplicate_log_rows -> VERIFIED_BY: [historical_and_realtime_merge, duplicate_realtime_entry]
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/svelte'; import { render, screen, waitFor } from '@testing-library/svelte';
@@ -15,6 +22,8 @@ vi.mock('../../services/taskService.js', () => ({
getTaskLogs: vi.fn() getTaskLogs: vi.fn()
})); }));
const getTaskLogsMock = vi.mocked(getTaskLogs);
vi.mock('../../lib/i18n', () => ({ vi.mock('../../lib/i18n', () => ({
t: { t: {
subscribe: (fn) => { subscribe: (fn) => {
@@ -39,13 +48,13 @@ describe('TaskLogViewer Component', () => {
}); });
it('renders loading state initially', () => { it('renders loading state initially', () => {
getTaskLogs.mockResolvedValue([]); getTaskLogsMock.mockResolvedValue([]);
render(TaskLogViewer, { inline: true, taskId: 'task-123' }); render(TaskLogViewer, { inline: true, taskId: 'task-123' });
expect(screen.getByText('Loading...')).toBeDefined(); expect(screen.getByText('Loading...')).toBeDefined();
}); });
it('fetches and displays historical logs', async () => { it('fetches and displays historical logs', async () => {
getTaskLogs.mockResolvedValue([ getTaskLogsMock.mockResolvedValue([
{ timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Historical log entry' } { timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Historical log entry' }
]); ]);
@@ -59,7 +68,7 @@ describe('TaskLogViewer Component', () => {
}); });
it('displays error message on fetch failure', async () => { it('displays error message on fetch failure', async () => {
getTaskLogs.mockRejectedValue(new Error('Network error fetching logs')); getTaskLogsMock.mockRejectedValue(new Error('Network error fetching logs'));
render(TaskLogViewer, { inline: true, taskId: 'task-123' }); render(TaskLogViewer, { inline: true, taskId: 'task-123' });
@@ -70,7 +79,7 @@ describe('TaskLogViewer Component', () => {
}); });
it('appends real-time logs passed as props', async () => { it('appends real-time logs passed as props', async () => {
getTaskLogs.mockResolvedValue([ getTaskLogsMock.mockResolvedValue([
{ timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Historical log entry' } { timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Historical log entry' }
]); ]);
@@ -99,7 +108,7 @@ describe('TaskLogViewer Component', () => {
}); });
it('deduplicates real-time logs that are already in historical logs', async () => { it('deduplicates real-time logs that are already in historical logs', async () => {
getTaskLogs.mockResolvedValue([ getTaskLogsMock.mockResolvedValue([
{ timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Duplicate log entry' } { timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Duplicate log entry' }
]); ]);
@@ -132,7 +141,7 @@ describe('TaskLogViewer Component', () => {
// @TEST_FIXTURE valid_viewer // @TEST_FIXTURE valid_viewer
it('fetches and displays historical logs in modal mode under valid_viewer fixture', async () => { it('fetches and displays historical logs in modal mode under valid_viewer fixture', async () => {
getTaskLogs.mockResolvedValue([ getTaskLogsMock.mockResolvedValue([
{ timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Modal log entry' } { timestamp: '2024-01-01T00:00:00', level: 'INFO', message: 'Modal log entry' }
]); ]);

View File

@@ -5,6 +5,13 @@
// @LAYER: UI Tests // @LAYER: UI Tests
// @RELATION: VERIFIES -> frontend/src/lib/components/assistant/AssistantChatPanel.svelte // @RELATION: VERIFIES -> frontend/src/lib/components/assistant/AssistantChatPanel.svelte
// @INVARIANT: Critical assistant UX states and action hooks remain present in component source. // @INVARIANT: Critical assistant UX states and action hooks remain present in component source.
// @TEST_CONTRACT: AssistantChatSourceArtifacts -> ContractAssertions
// @TEST_SCENARIO: assistant_contract_and_i18n_intact -> Component semantic/UX anchors and locale keys stay consistent.
// @TEST_FIXTURE: assistant_locales_en_ru -> file:src/lib/i18n/locales/en.json + file:src/lib/i18n/locales/ru.json
// @TEST_EDGE: missing_component_anchor -> Missing DEF/UX tags fails contract assertion.
// @TEST_EDGE: missing_action_hook -> Missing confirm/cancel/open_task hooks fails integration assertion.
// @TEST_EDGE: missing_locale_key -> Missing assistant locale key in en/ru fails dictionary assertion.
// @TEST_INVARIANT: assistant_ux_contract_visible -> VERIFIED_BY: [assistant_contract_and_i18n_intact]
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import fs from 'node:fs'; import fs from 'node:fs';

View File

@@ -8,6 +8,13 @@
// @LAYER: UI // @LAYER: UI
// @RELATION: VERIFIES -> ../ReportCard.svelte // @RELATION: VERIFIES -> ../ReportCard.svelte
// @INVARIANT: Each test asserts at least one observable UX contract outcome. // @INVARIANT: Each test asserts at least one observable UX contract outcome.
// @TEST_CONTRACT: ReportCardInputProps -> ObservableUXOutput
// @TEST_SCENARIO: ready_state_shows_summary_status_type -> Ready state renders summary/status/type labels.
// @TEST_FIXTURE: valid_report_card -> INLINE_JSON
// @TEST_EDGE: empty_report_object -> Missing fields use placeholders and fallback labels.
// @TEST_EDGE: random_status -> Unknown status is rendered without crashing.
// @TEST_EDGE: missing_optional_fields -> Partial report keeps component interactive and emits select.
// @TEST_INVARIANT: report_card_state_is_observable -> VERIFIED_BY: [ready_state_shows_summary_status_type, empty_report_object, random_status]
import { describe, it, expect, vi } from 'vitest'; import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/svelte'; import { render, screen, fireEvent } from '@testing-library/svelte';
@@ -39,7 +46,7 @@ describe('ReportCard UX Contract', () => {
// @UX_STATE: Ready -> Card displays summary/status/type. // @UX_STATE: Ready -> Card displays summary/status/type.
it('should display summary, status and type in Ready state', () => { it('should display summary, status and type in Ready state', () => {
render(ReportCard, { report: mockReport }); render(ReportCard, { report: mockReport, onselect: vi.fn() });
expect(screen.getByText(mockReport.summary)).toBeDefined(); expect(screen.getByText(mockReport.summary)).toBeDefined();
// mockReport.status is "success", getStatusLabel(status) returns $t.reports?.status_success // mockReport.status is "success", getStatusLabel(status) returns $t.reports?.status_success
expect(screen.getByText('Success')).toBeDefined(); expect(screen.getByText('Success')).toBeDefined();
@@ -61,7 +68,7 @@ describe('ReportCard UX Contract', () => {
// @UX_RECOVERY: Missing fields are rendered with explicit placeholder text. // @UX_RECOVERY: Missing fields are rendered with explicit placeholder text.
it('should render placeholders for missing fields', () => { it('should render placeholders for missing fields', () => {
const partialReport = { report_id: 'partial-1' }; const partialReport = { report_id: 'partial-1' };
render(ReportCard, { report: partialReport }); render(ReportCard, { report: partialReport, onselect: vi.fn() });
// Check placeholders (using text from mocked $t) // Check placeholders (using text from mocked $t)
const placeholders = screen.getAllByText('Not provided'); const placeholders = screen.getAllByText('Not provided');
@@ -79,7 +86,7 @@ describe('ReportCard UX Contract', () => {
summary: "Test Summary", summary: "Test Summary",
updated_at: "2024-01-01" updated_at: "2024-01-01"
}; };
render(ReportCard, { report: validReportCard }); render(ReportCard, { report: validReportCard, onselect: vi.fn() });
expect(screen.getByText('Test Summary')).toBeDefined(); expect(screen.getByText('Test Summary')).toBeDefined();
expect(screen.getByText('Success')).toBeDefined(); expect(screen.getByText('Success')).toBeDefined();
@@ -87,14 +94,14 @@ describe('ReportCard UX Contract', () => {
// @TEST_EDGE empty_report_object // @TEST_EDGE empty_report_object
it('should handle completely empty report object gracefully', () => { it('should handle completely empty report object gracefully', () => {
render(ReportCard, { report: {} }); render(ReportCard, { report: {}, onselect: vi.fn() });
const placeholders = screen.getAllByText('Not provided'); const placeholders = screen.getAllByText('Not provided');
expect(placeholders.length).toBeGreaterThan(0); expect(placeholders.length).toBeGreaterThan(0);
}); });
// @TEST_EDGE random_status // @TEST_EDGE random_status
it('should render random status directly if no translation matches', () => { it('should render random status directly if no translation matches', () => {
render(ReportCard, { report: { status: "unknown_status_code" } }); render(ReportCard, { report: { status: "unknown_status_code" }, onselect: vi.fn() });
expect(screen.getByText('unknown_status_code')).toBeDefined(); expect(screen.getByText('unknown_status_code')).toBeDefined();
}); });
}); });

View File

@@ -189,9 +189,36 @@ class SemanticEntity:
with belief_scope("get_tier"): with belief_scope("get_tier"):
tier_str = self.tags.get("TIER", "STANDARD").upper() tier_str = self.tags.get("TIER", "STANDARD").upper()
try: try:
return Tier(tier_str) base_tier = Tier(tier_str)
except ValueError: except ValueError:
return Tier.STANDARD base_tier = Tier.STANDARD
# Dynamic Tier Adjustments based on User Feedback
# 1. Tests should never be higher than STANDARD
if "test" in self.file_path.lower() or "/__tests__/" in self.file_path or self.name.startswith("test_"):
if base_tier == Tier.CRITICAL:
return Tier.STANDARD
# 2. Svelte components -> TRIVIAL/STANDARD (unless layout/page)
if self.file_path.endswith(".svelte"):
if "+page" not in self.name and "+layout" not in self.name and "Page" not in self.name and "Layout" not in self.name:
if base_tier == Tier.CRITICAL:
return Tier.STANDARD
# 3. Tooling scripts
if "scripts/" in self.file_path or "_tui.py" in self.file_path:
if base_tier == Tier.CRITICAL:
return Tier.STANDARD
# 4. Promote critical security/data paths
critical_keywords = ["auth", "security", "jwt", "database", "migration", "config", "session"]
if any(keyword in self.file_path.lower() for keyword in critical_keywords) and "test" not in self.file_path.lower():
# Allow explicit overrides to lower tiers if explicitly tagged TRIVIAL, otherwise promote logic mapping
if base_tier != Tier.TRIVIAL:
return Tier.CRITICAL
return base_tier
# [/DEF:get_tier:Function] # [/DEF:get_tier:Function]
# [DEF:to_dict:Function] # [DEF:to_dict:Function]

File diff suppressed because it is too large Load Diff

View File

@@ -137,6 +137,7 @@
- [X] T041 Add release checklist artifact template for compliance evidence packaging in `specs/023-clean-repo-enterprise/checklists/release-readiness.md` - [X] T041 Add release checklist artifact template for compliance evidence packaging in `specs/023-clean-repo-enterprise/checklists/release-readiness.md`
- [X] T042 Resolve numeric-prefix governance conflict note (`020-*`) and document decision in `specs/023-clean-repo-enterprise/plan.md` - [X] T042 Resolve numeric-prefix governance conflict note (`020-*`) and document decision in `specs/023-clean-repo-enterprise/plan.md`
- [X] T043 Update feature status traceability and final notes in `specs/023-clean-repo-enterprise/plan.md` - [X] T043 Update feature status traceability and final notes in `specs/023-clean-repo-enterprise/plan.md`
- [X] T044 Remediate CRITICAL semantic test-contract gaps by adding `@TEST_CONTRACT` metadata in backend/frontend flagged modules and recording coverage update in `specs/023-clean-repo-enterprise/tests/coverage.md`
--- ---

View File

@@ -8,6 +8,11 @@
| `clean_release.manifest_builder` | `manifest_builder.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `clean_release.manifest_builder` | `manifest_builder.py` | STANDARD | ✅ Yes | N/A | N/A | N/A |
| `clean_release.source_isolation` | `source_isolation.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `clean_release.source_isolation` | `source_isolation.py` | STANDARD | ✅ Yes | N/A | N/A | N/A |
| `api.routes.clean_release` | `clean_release.py` | STANDARD | ✅ Yes | N/A | N/A | N/A | | `api.routes.clean_release` | `clean_release.py` | STANDARD | ✅ Yes | N/A | N/A | N/A |
| `api.routes.tasks.get_task_logs` | `tasks.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `models.clean_release` | `clean_release.py` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `frontend.assistant_chat.integration` | `assistant_chat.integration.test.js` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `frontend.reports.report_card.ux` | `report_card.ux.test.js` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
| `frontend.task_log_viewer` | `task_log_viewer.test.js` | CRITICAL | ✅ Yes | 1/1 | 3/3 | 1/1 |
## CRITICAL Edge Cases Covered ## CRITICAL Edge Cases Covered

View File

@@ -0,0 +1,48 @@
# Test Report: Global CRITICAL Coverage
Date: 2026-03-04
Executor: GRACE Tester
## Coverage Matrix
| Module | TIER | Tests | Edge Covered | Invariants Covered |
|--------|------|------|----------|------------|
| backend/src/api/routes/tasks.py | CRITICAL | - | - | - |
| backend/src/models/clean_release.py | CRITICAL | - | - | - |
| frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js | CRITICAL | - | - | - |
| frontend/src/lib/components/reports/__tests__/report_card.ux.test.js | CRITICAL | - | - | - |
| frontend/src/components/__tests__/task_log_viewer.test.js | CRITICAL | - | - | - |
*(Note: Matrix focuses only on modules that triggered the fail policy)*
## Contract Validation
- TEST_CONTRACT validated ❌
- All FIXTURES tested ❌
- All EDGES tested ❌
- All INVARIANTS verified ❌
## Results
Total: 0
Passed: 0
Failed: 5
Skipped: 38
## Violations
| Module | Problem | Severity |
|--------|---------|----------|
| `backend/src/api/routes/tasks.py` | [COHERENCE_CHECK_FAILED] Missing TEST_CONTRACT | CRITICAL |
| `backend/src/models/clean_release.py` | [COHERENCE_CHECK_FAILED] Missing TEST_CONTRACT | CRITICAL |
| `frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js` | [COHERENCE_CHECK_FAILED] Missing TEST_CONTRACT | CRITICAL |
| `frontend/src/lib/components/reports/__tests__/report_card.ux.test.js` | [COHERENCE_CHECK_FAILED] Missing TEST_CONTRACT | CRITICAL |
| `frontend/src/components/__tests__/task_log_viewer.test.js` | [COHERENCE_CHECK_FAILED] Missing TEST_CONTRACT | CRITICAL |
## Next Actions
- [ ] Add `@TEST_CONTRACT` to `backend/src/api/routes/tasks.py` (for `get_task_logs` method)
- [ ] Add `@TEST_CONTRACT` to `backend/src/models/clean_release.py`
- [ ] Add `@TEST_CONTRACT` to `frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js` or adjust TIER
- [ ] Add `@TEST_CONTRACT` to `frontend/src/lib/components/reports/__tests__/report_card.ux.test.js` or adjust TIER
- [ ] Add `@TEST_CONTRACT` to `frontend/src/components/__tests__/task_log_viewer.test.js` or adjust TIER