diff --git a/.kilocode/workflows/speckit.implement.md b/.kilocode/workflows/speckit.implement.md index d2e2a47..1ad3e41 100644 --- a/.kilocode/workflows/speckit.implement.md +++ b/.kilocode/workflows/speckit.implement.md @@ -117,7 +117,8 @@ You **MUST** consider the user input before proceeding (if not empty). - **Validation checkpoints**: Verify each phase completion before proceeding 7. Implementation execution rules: - - **Strict Adherence**: Apply `semantic_protocol.md` rules - every file must start with [DEF] header, include @TIER, and define contracts + - **Strict Adherence**: Apply `semantic_protocol.md` rules - every file must start with [DEF] header, include @TIER, and define contracts. + - **CRITICAL Contracts**: If a task description contains a contract summary (e.g., `CRITICAL: PRE: ..., POST: ...`), these constraints are **MANDATORY** and must be strictly implemented in the code using guards/assertions (if applicable per protocol). - **Setup first**: Initialize project structure, dependencies, configuration - **Tests before code**: If you need to write tests for contracts, entities, and integration scenarios - **Core development**: Implement models, services, CLI commands, endpoints diff --git a/.kilocode/workflows/speckit.tasks.md b/.kilocode/workflows/speckit.tasks.md index a59deca..fa98caa 100644 --- a/.kilocode/workflows/speckit.tasks.md +++ b/.kilocode/workflows/speckit.tasks.md @@ -119,7 +119,10 @@ Every task MUST strictly follow this format: - If tests requested: Tests specific to that story - Mark story dependencies (most stories should be independent) -2. **From Contracts**: +2. **From Contracts (CRITICAL TIER)**: + - Identify components marked as `@TIER: CRITICAL` in `contracts/modules.md`. + - For these components, **MUST** append the summary of `@PRE`, `@POST`, and `@UX_STATE` contracts directly to the task description. + - Example: `- [ ] T005 [P] [US1] Implement Auth (CRITICAL: PRE: token exists, POST: returns User) in src/auth.py` - Map each contract/endpoint → to the user story it serves - If tests requested: Each contract → contract test task [P] before implementation in that story's phase diff --git a/specs/019-superset-ux-redesign/contracts/modules.md b/specs/019-superset-ux-redesign/contracts/modules.md new file mode 100644 index 0000000..3607368 --- /dev/null +++ b/specs/019-superset-ux-redesign/contracts/modules.md @@ -0,0 +1,612 @@ +# Module Contracts: Superset-Style UX Redesign + +**Feature**: 019-superset-ux-redesign +**Date**: 2026-02-10 +**Semantic Protocol Version**: GRACE-Poly (UX Edition) + +--- + +## Overview + +This document defines module-level contracts following the Semantic Protocol. Each module is annotated with `[DEF]` anchors, `@TIER` classification, and full Design-by-Contract (`@PRE`, `@POST`, `@UX_STATE`) specifications. + +--- + +## Frontend Modules + +### 1. SidebarStore + +```javascript +// [DEF:SidebarStore:Store] +// @TIER: STANDARD +// @SEMANTICS: navigation, state-management, persistence +// @PURPOSE: Manage sidebar visibility, active navigation state, and mobile overlay behavior +// @LAYER: UI +// @RELATION: DEPENDS_ON -> localStorage +// @RELATION: BINDS_TO -> +layout.svelte +// @INVARIANT: isExpanded state is always synced with localStorage key 'sidebar_state' + +// @UX_STATE: Idle -> Sidebar visible with current category highlighted +// @UX_STATE: Collapsed -> Icons-only mode, tooltips on hover +// @UX_STATE: MobileOverlay -> Full-screen overlay with backdrop, close on outside click +// @UX_STATE: Toggling -> CSS transition animation (200ms ease-in-out) + +// @PRE: localStorage is available and accessible +// @PRE: defaultValue has valid shape { isExpanded: boolean, activeCategory: string, activeItem: string, isMobileOpen: boolean } + +// @POST: Store always emits valid SidebarState shape +// @POST: localStorage 'sidebar_state' is updated on every state change +// @POST: isMobileOpen is reset to false when screen size changes to desktop (>=768px) + +// @SIDE_EFFECT: Writes to localStorage +// @SIDE_EFFECT: Triggers CSS transitions via class binding + +export const sidebarStore = persistentStore('sidebar_state', { + isExpanded: true, + activeCategory: 'dashboards', + activeItem: '/dashboards', + isMobileOpen: false +}); + +export function toggleSidebar() { /* ... */ } +export function setActiveCategory(category) { /* ... */ } +export function setActiveItem(path) { /* ... */ } +export function openMobileSidebar() { /* ... */ } +export function closeMobileSidebar() { /* ... */ } +// [/DEF:SidebarStore] +``` + +--- + +### 2. TaskDrawerStore + +```javascript +// [DEF:TaskDrawerStore:Store] +// @TIER: CRITICAL +// @SEMANTICS: task-management, resource-mapping, real-time, drawer-state +// @PURPOSE: Manage Task Drawer visibility, active task tracking, and resource-to-task associations +// @LAYER: UI +// @RELATION: DEPENDS_ON -> WebSocket connection +// @RELATION: DEPENDS_ON -> task:status events +// @RELATION: DEPENDS_ON -> task:log events +// @RELATION: BINDS_TO -> TaskDrawer.svelte +// @INVARIANT: resourceTaskMap always contains valid task associations +// @INVARIANT: When isOpen is false, activeTaskId may still reference a running task + +// @UX_STATE: Closed -> Drawer hidden, Activity indicator shows active count +// @UX_STATE: Open-Loading -> Drawer visible, loading spinner for logs +// @UX_STATE: Open-Streaming -> Drawer visible, real-time log stream +// @UX_STATE: Open-InputRequired -> Interactive form rendered in drawer (PasswordPrompt, etc.) +// @UX_STATE: Open-Completed -> Task finished, success/error status displayed + +// @UX_FEEDBACK: Toast notification when task completes while drawer is closed +// @UX_FEEDBACK: Activity indicator badge pulses when new tasks start +// @UX_RECOVERY: If WebSocket disconnects, show "Reconnecting..." with retry button + +// @PRE: WebSocket connection is established before subscribing to task events +// @PRE: taskId passed to openDrawerForTask() is a valid UUID string +// @PRE: resourceId in updateResourceTask() matches pattern {type}:{uuid} + +// @POST: After openDrawerForTask(taskId): isOpen === true && activeTaskId === taskId +// @POST: After closeDrawer(): isOpen === false, activeTaskId unchanged +// @POST: resourceTaskMap is updated when task:status events are received +// @POST: When task status changes to SUCCESS|ERROR, entry remains in map for 5 minutes then auto-cleanup + +// @SIDE_EFFECT: Subscribes to WebSocket events +// @SIDE_EFFECT: May trigger browser notification for task completion + +export const taskDrawerStore = writable({ + isOpen: false, + activeTaskId: null, + resourceTaskMap: {} // { resourceId: { taskId, status, startedAt } } +}); + +export function openDrawerForTask(taskId) { /* ... */ } +export function closeDrawer() { /* ... */ } +export function updateResourceTask(resourceId, taskId, status) { /* ... */ } +export function clearCompletedTasks() { /* ... */ } +// [/DEF:TaskDrawerStore] +``` + +--- + +### 3. ActivityStore + +```javascript +// [DEF:ActivityStore:Store] +// @TIER: STANDARD +// @SEMANTICS: activity-indicator, derived-state, task-count +// @PURPOSE: Provide reactive count of active tasks for the navbar Activity indicator +// @LAYER: UI +// @RELATION: DEPENDS_ON -> TaskDrawerStore +// @RELATION: BINDS_TO -> TopNavbar.svelte +// @INVARIANT: activeCount is always >= 0 +// @INVARIANT: activeCount equals count of RUNNING tasks in resourceTaskMap + +// @UX_STATE: Idle -> Badge hidden or shows "0" +// @UX_STATE: Active-N -> Badge shows count N with pulse animation +// @UX_STATE: Active-Many -> Badge shows "9+" when count exceeds 9 + +// @PRE: TaskDrawerStore is initialized and emitting values + +// @POST: activeCount reflects exact count of tasks with status === 'RUNNING' +// @POST: recentTasks contains last 5 tasks sorted by startedAt desc + +export const activityStore = derived( + taskDrawerStore, + ($drawer) => { + const tasks = Object.values($drawer.resourceTaskMap); + const activeCount = tasks.filter(t => t.status === 'RUNNING').length; + const recentTasks = tasks + .sort((a, b) => new Date(b.startedAt) - new Date(a.startedAt)) + .slice(0, 5); + return { activeCount, recentTasks }; + } +); +// [/DEF:ActivityStore] +``` + +--- + +### 4. Sidebar Component + +```svelte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +### 5. TopNavbar Component + +```svelte + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +### 6. TaskDrawer Component + +```svelte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +### 7. DashboardHub Component + +```svelte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +### 8. DatasetHub Component + +```svelte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +### 9. Breadcrumbs Component + +```svelte + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +## Backend Modules + +### 10. Dashboards API + +```python +# [DEF:DashboardsAPI:Module] +# @TIER: CRITICAL +# @SEMANTICS: rest-api, resource-fetching, git-integration +# @PURPOSE: API endpoints for Dashboard Hub - list dashboards with metadata +# @LAYER: Domain +# @RELATION: DEPENDS_ON -> superset_client +# @RELATION: DEPENDS_ON -> git_service +# @RELATION: DEPENDS_ON -> task_manager +# @RELATION: CALLS -> Superset API /api/v1/dashboard/ + +# @PRE: env_id parameter is valid UUID of existing environment +# @PRE: User has permission to read dashboards from specified environment + +# @POST: Response includes all dashboards accessible in environment +# @POST: Each dashboard has git_status with branch and sync_status +# @POST: Each dashboard has last_task with most recent task status +# @POST: Search parameter filters by title and slug (case-insensitive) + +# Endpoint: GET /api/dashboards +# Query: env_id (required), search (optional) +# Response: { dashboards: [...] } + +# Endpoint: POST /api/dashboards/migrate +# Body: { source_env_id, target_env_id, dashboard_ids, db_mappings } +# Response: { task_id } + +# Endpoint: POST /api/dashboards/backup +# Body: { env_id, dashboard_ids, schedule (optional cron) } +# Response: { task_id } +# [/DEF:DashboardsAPI] +``` + +--- + +### 11. Datasets API + +```python +# [DEF:DatasetsAPI:Module] +# @TIER: CRITICAL +# @SEMANTICS: rest-api, dataset-metadata, column-mapping +# @PURPOSE: API endpoints for Dataset Hub - list datasets with mapping info +# @LAYER: Domain +# @RELATION: DEPENDS_ON -> superset_client +# @RELATION: DEPENDS_ON -> mapping_service +# @RELATION: DEPENDS_ON -> task_manager +# @RELATION: CALLS -> Superset API /api/v1/dataset/ + +# @PRE: env_id parameter is valid UUID of existing environment +# @PRE: User has permission to read datasets from specified environment + +# @POST: Response includes all datasets accessible in environment +# @POST: Each dataset has mapped_fields count (mapped/total) +# @POST: Each dataset has extracted SQL table names +# @POST: Search filters by table_name, schema, and extracted table names + +# Endpoint: GET /api/datasets +# Query: env_id (required), search (optional) +# Response: { datasets: [...] } + +# Endpoint: POST /api/datasets/map-columns +# Body: { env_id, dataset_ids, source_type, connection_id or file } +# Response: { task_id } + +# Endpoint: POST /api/datasets/generate-docs +# Body: { env_id, dataset_ids, llm_provider, options } +# Response: { task_id } +# [/DEF:DatasetsAPI] +``` + +--- + +### 12. Activity API + +```python +# [DEF:ActivityAPI:Module] +# @TIER: STANDARD +# @SEMANTICS: rest-api, activity-summary, task-metrics +# @PURPOSE: Provide activity summary for navbar indicator +# @LAYER: Domain +# @RELATION: DEPENDS_ON -> task_manager +# @RELATION: CALLS -> task_manager.get_active_tasks() + +# @PRE: User is authenticated + +# @POST: Returns count of RUNNING tasks +# @POST: Returns last 5 tasks sorted by started_at desc +# @POST: Tasks include resource_name and resource_type for display + +# Endpoint: GET /api/activity +# Response: { active_count: number, recent_tasks: [...] } +# [/DEF:ActivityAPI] +``` + +--- + +### 13. ResourceService + +```python +# [DEF:ResourceService:Class] +# @TIER: STANDARD +# @SEMANTICS: service-layer, shared-logic, resource-fetching +# @PURPOSE: Shared logic for fetching resources from Superset with caching +# @LAYER: Domain +# @RELATION: DEPENDS_ON -> superset_client +# @RELATION: DEPENDS_ON -> ConfigManager +# @INVARIANT: All methods accept env_id and resolve via ConfigManager + +# @PRE: env_id corresponds to valid Environment configuration +# @PRE: ConfigManager returns valid Superset connection params + +# @POST: Returns normalized resource data structure +# @POST: Handles connection errors gracefully with meaningful messages +# @POST: Caches results for 30 seconds to reduce API load + +class ResourceService: + async def fetch_dashboards(env_id: str, search: str = None) -> list[Dashboard]: ... + async def fetch_datasets(env_id: str, search: str = None) -> list[Dataset]: ... + async def get_git_status(env_id: str, resource_id: str) -> GitStatus: ... + async def get_last_task(resource_type: str, resource_id: str) -> TaskSummary: ... +# [/DEF:ResourceService] +``` + +--- + +## Contract Compliance Matrix + +| Module | TIER | @PRE/@POST | @UX_STATE | @RELATION | Status | +|--------|------|------------|-----------|-----------|--------| +| SidebarStore | STANDARD | ✅ | ✅ | ✅ | Ready | +| TaskDrawerStore | CRITICAL | ✅ | ✅ | ✅ | Ready | +| ActivityStore | STANDARD | ✅ | ✅ | ✅ | Ready | +| Sidebar | CRITICAL | ✅ | ✅ | ✅ | Ready | +| TopNavbar | CRITICAL | ✅ | ✅ | ✅ | Ready | +| TaskDrawer | CRITICAL | ✅ | ✅ | ✅ | Ready | +| DashboardHub | CRITICAL | ✅ | ✅ | ✅ | Ready | +| DatasetHub | CRITICAL | ✅ | ✅ | ✅ | Ready | +| Breadcrumbs | STANDARD | ✅ | ✅ | ✅ | Ready | +| DashboardsAPI | CRITICAL | ✅ | N/A | ✅ | Ready | +| DatasetsAPI | CRITICAL | ✅ | N/A | ✅ | Ready | +| ActivityAPI | STANDARD | ✅ | N/A | ✅ | Ready | +| ResourceService | STANDARD | ✅ | N/A | ✅ | Ready | + +--- + +## UX State Mapping to Components + +| UX State (from ux_reference.md) | Component | @UX_STATE Tag | +|----------------------------------|-----------|---------------| +| Sidebar Expanded | Sidebar | Idle-Expanded | +| Sidebar Collapsed | Sidebar | Idle-Collapsed | +| Mobile Overlay | Sidebar | Mobile-Open | +| Task Drawer Closed | TaskDrawer | Closed | +| Task Drawer Streaming | TaskDrawer | Open-Streaming | +| Task Drawer Input Required | TaskDrawer | Open-InputRequired | +| Activity Badge Active | TopNavbar | Activity-Pulse | +| Dashboard Grid Loading | DashboardHub | Loading | +| Dashboard Grid Empty | DashboardHub | Empty-NoData | +| Bulk Selection Active | DashboardHub | Selecting | +| Migration Modal Open | DashboardHub | BulkAction-Modal | +| Dataset Grid Loading | DatasetHub | Loading | +| Dataset Detail View | DatasetHub | Detail-View | + +--- + +## Design-by-Contract Enforcement + +### Critical Modules (Full Contracts Required) + +All CRITICAL tier modules MUST have: +- Complete `@PRE` conditions for all public functions +- Complete `@POST` conditions guaranteeing output +- All `@UX_STATE` transitions documented +- `@UX_FEEDBACK` and `@UX_RECOVERY` where applicable +- `@RELATION` tags for all dependencies + +### Standard Modules (Basic Contracts Required) + +All STANDARD tier modules MUST have: +- `@PURPOSE` declaration +- Key `@PRE` and `@POST` for main operations +- Primary `@UX_STATE` states +- `@RELATION` tags for major dependencies + +--- + +## Constitution Compliance + +| Principle | Compliance | Notes | +|-----------|------------|-------| +| I. Semantic Protocol | ✅ | All modules use [DEF] anchors and proper tagging | +| II. Everything is a Plugin | ✅ | Dashboard/Dataset hubs dispatch to existing plugins | +| III. Unified Frontend | ✅ | Uses requestApi, i18n, and component library | +| IV. Security & Access Control | ✅ | Permission checks in @PRE conditions | +| V. Independent Testability | ✅ | Each hub has defined independent test scenarios | +| VI. Asynchronous Execution | ✅ | All bulk operations return task_id, use TaskManager | diff --git a/specs/019-superset-ux-redesign/plan.md b/specs/019-superset-ux-redesign/plan.md index 1d1327f..357c48b 100644 --- a/specs/019-superset-ux-redesign/plan.md +++ b/specs/019-superset-ux-redesign/plan.md @@ -50,10 +50,11 @@ specs/019-superset-ux-redesign/ ├── data-model.md # Phase 1 output ├── quickstart.md # Phase 1 output ├── contracts/ # Phase 1 output -│ └── api.md # API contracts +│ ├── api.md # API contracts +│ └── modules.md # Module contracts (Semantic Protocol) ├── checklists/ │ └── requirements.md # Spec quality checklist -└── tasks.md # Phase 2 output (NOT created yet) +└── tasks.md # Phase 2 output ``` ### Source Code (repository root) @@ -98,6 +99,27 @@ frontend/ **Structure Decision**: Web application structure with new `layout/` and `hubs/` component directories. The Sidebar and TaskDrawer live in the root `+layout.svelte` for global availability. +## Contract References + +All implementation MUST follow the Design-by-Contract specifications in [`contracts/modules.md`](./contracts/modules.md): + +| Component/Module | Contract Location | TIER | +|------------------|-------------------|------| +| SidebarStore | [DEF:SidebarStore:Store](./contracts/modules.md#1-sidebarstore) | STANDARD | +| TaskDrawerStore | [DEF:TaskDrawerStore:Store](./contracts/modules.md#2-taskdrawerstore) | CRITICAL | +| ActivityStore | [DEF:ActivityStore:Store](./contracts/modules.md#3-activitystore) | STANDARD | +| Sidebar | [DEF:Sidebar:Component](./contracts/modules.md#4-sidebar-component) | CRITICAL | +| TopNavbar | [DEF:TopNavbar:Component](./contracts/modules.md#5-topnavbar-component) | CRITICAL | +| TaskDrawer | [DEF:TaskDrawer:Component](./contracts/modules.md#6-taskdrawer-component) | CRITICAL | +| DashboardHub | [DEF:DashboardHub:Component](./contracts/modules.md#7-dashboardhub-component) | CRITICAL | +| DatasetHub | [DEF:DatasetHub:Component](./contracts/modules.md#8-datasethub-component) | CRITICAL | +| DashboardsAPI | [DEF:DashboardsAPI:Module](./contracts/modules.md#10-dashboards-api) | CRITICAL | +| DatasetsAPI | [DEF:DatasetsAPI:Module](./contracts/modules.md#11-datasets-api) | CRITICAL | + +### UX State Contract Mapping + +All UI states defined in [`ux_reference.md`](./ux_reference.md) are mapped to `@UX_STATE` tags in module contracts. See [UX State Mapping table](./contracts/modules.md#ux-state-mapping-to-components) for complete mapping. + ## Complexity Tracking > No Constitution violations. All changes use existing patterns. diff --git a/specs/019-superset-ux-redesign/tasks.md b/specs/019-superset-ux-redesign/tasks.md index 7d79028..39249ef 100644 --- a/specs/019-superset-ux-redesign/tasks.md +++ b/specs/019-superset-ux-redesign/tasks.md @@ -12,22 +12,49 @@ - **[P]**: Can run in parallel (different files, no dependencies) - **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) - Include exact file paths in descriptions +- **Contract Reference**: Each task links to [contracts/modules.md](./contracts/modules.md) for Design-by-Contract specifications ## Path Conventions - **Web app**: `backend/src/`, `frontend/src/` +## Contract References + +All implementation tasks MUST follow the Design-by-Contract specifications: + +| Component | Contract | TIER | +|-----------|----------|------| +| `sidebar.js` | [DEF:SidebarStore:Store](./contracts/modules.md#1-sidebarstore) | STANDARD | +| `taskDrawer.js` | [DEF:TaskDrawerStore:Store](./contracts/modules.md#2-taskdrawerstore) | CRITICAL | +| `activity.js` | [DEF:ActivityStore:Store](./contracts/modules.md#3-activitystore) | STANDARD | +| `Sidebar.svelte` | [DEF:Sidebar:Component](./contracts/modules.md#4-sidebar-component) | CRITICAL | +| `TopNavbar.svelte` | [DEF:TopNavbar:Component](./contracts/modules.md#5-topnavbar-component) | CRITICAL | +| `TaskDrawer.svelte` | [DEF:TaskDrawer:Component](./contracts/modules.md#6-taskdrawer-component) | CRITICAL | +| `Breadcrumbs.svelte` | [DEF:Breadcrumbs:Component](./contracts/modules.md#9-breadcrumbs-component) | STANDARD | +| `DashboardHub` | [DEF:DashboardHub:Component](./contracts/modules.md#7-dashboardhub-component) | CRITICAL | +| `DatasetHub` | [DEF:DatasetHub:Component](./contracts/modules.md#8-datasethub-component) | CRITICAL | +| `dashboards.py` | [DEF:DashboardsAPI:Module](./contracts/modules.md#10-dashboards-api) | CRITICAL | +| `datasets.py` | [DEF:DatasetsAPI:Module](./contracts/modules.md#11-datasets-api) | CRITICAL | +| `resource_service.py` | [DEF:ResourceService:Class](./contracts/modules.md#13-resourceservice) | STANDARD | + --- ## Phase 1: Setup (Shared Infrastructure) **Purpose**: Create new directory structure and stores for layout state +**Contract Requirements**: +- All stores MUST implement `@PRE` and `@POST` conditions from [contracts/modules.md](./contracts/modules.md) +- CRITICAL tier modules (TaskDrawerStore) require full UX state documentation + - [x] T001 Create `frontend/src/lib/components/layout/` directory for shared layout components - [x] T002 Create `frontend/src/lib/components/hubs/` directory for resource hub pages -- [x] T003 [P] Create `frontend/src/lib/stores/sidebar.js` with persistentStore pattern for sidebar state -- [x] T004 [P] Create `frontend/src/lib/stores/taskDrawer.js` with resourceTaskMap store -- [x] T005 [P] Create `frontend/src/lib/stores/activity.js` as derived store from taskDrawer +- [x] T003 [P] Create `frontend/src/lib/stores/sidebar.js` with persistentStore pattern for sidebar state + _Contract: [DEF:SidebarStore:Store](./contracts/modules.md#1-sidebarstore)_ +- [x] T004 [P] Create `frontend/src/lib/stores/taskDrawer.js` with resourceTaskMap store + _Contract: [DEF:TaskDrawerStore:Store](./contracts/modules.md#2-taskdrawerstore) - CRITICAL: Must implement all @UX_STATE transitions_ +- [x] T005 [P] Create `frontend/src/lib/stores/activity.js` as derived store from taskDrawer + _Contract: [DEF:ActivityStore:Store](./contracts/modules.md#3-activitystore)_ --- @@ -37,9 +64,16 @@ **⚠️ CRITICAL**: No user story work can begin until this phase is complete -- [x] T006 Create `frontend/src/lib/components/layout/Sidebar.svelte` with categories: DASHBOARDS, DATASETS, STORAGE, ADMIN -- [x] T007 Create `frontend/src/lib/components/layout/TopNavbar.svelte` with Logo, Search placeholder, Activity indicator, User menu -- [x] T008 Create `frontend/src/lib/components/layout/Breadcrumbs.svelte` for page hierarchy navigation +**Contract Requirements**: +- All CRITICAL tier components MUST implement full `@UX_STATE` specifications +- Components MUST follow `@PRE` conditions for props and `@POST` for event handling + +- [x] T006 Create `frontend/src/lib/components/layout/Sidebar.svelte` with categories: DASHBOARDS, DATASETS, STORAGE, ADMIN + _Contract: [DEF:Sidebar:Component](./contracts/modules.md#4-sidebar-component) - CRITICAL: Implement all @UX_STATE transitions (Expanded/Collapsed/Mobile)_ +- [x] T007 Create `frontend/src/lib/components/layout/TopNavbar.svelte` with Logo, Search placeholder, Activity indicator, User menu + _Contract: [DEF:TopNavbar:Component](./contracts/modules.md#5-topnavbar-component) - CRITICAL: Activity badge must pulse on new tasks_ +- [x] T008 Create `frontend/src/lib/components/layout/Breadcrumbs.svelte` for page hierarchy navigation + _Contract: [DEF:Breadcrumbs:Component](./contracts/modules.md#9-breadcrumbs-component) - Handle truncation for >3 levels_ - [x] T009 Update `frontend/src/routes/+layout.svelte` to include Sidebar, TopNavbar, and main content area - [x] T010 Add i18n keys for navigation labels in `frontend/src/lib/i18n/translations/en.json` - [x] T011 Add i18n keys for navigation labels in `frontend/src/lib/i18n/translations/ru.json` @@ -75,12 +109,20 @@ ### Implementation for User Story 2 -- [x] T018 [US2] Create `frontend/src/lib/components/layout/TaskDrawer.svelte` as slide-out panel from right +**Contract Requirements**: +- TaskDrawer MUST implement all `@UX_STATE` transitions from [DEF:TaskDrawerStore:Store](./contracts/modules.md#2-taskdrawerstore) +- MUST handle `@UX_RECOVERY` for WebSocket disconnections + +- [x] T018 [US2] Create `frontend/src/lib/components/layout/TaskDrawer.svelte` as slide-out panel from right + _Contract: [DEF:TaskDrawer:Component](./contracts/modules.md#6-taskdrawer-component) - CRITICAL: Implement Closed → Open-Loading → Open-Streaming → Open-InputRequired states_ - [x] T019 [US2] Integrate existing `TaskLogViewer` component inside Task Drawer - [x] T020 [US2] Implement Activity indicator badge in TopNavbar showing `activeCount` from store -- [x] T021 [US2] Connect Task Drawer to WebSocket for real-time log streaming -- [x] T022 [US2] Implement interactive area in drawer for `PasswordPrompt` and other inputs -- [x] T023 [US2] Add close button that allows task to continue running in background +- [x] T021 [US2] Connect Task Drawer to WebSocket for real-time log streaming + _Contract: @RELATION: DEPENDS_ON -> WebSocket connection_ +- [x] T022 [US2] Implement interactive area in drawer for `PasswordPrompt` and other inputs + _Contract: @UX_STATE: Open-InputRequired_ +- [x] T023 [US2] Add close button that allows task to continue running in background + _Contract: @POST: Closing drawer does NOT cancel running task_ - [x] T024 [US2] Implement drawer open trigger from Activity indicator click - [x] T025 [US2] Verify implementation matches ux_reference.md (Task Drawer mockup) @@ -114,29 +156,52 @@ ### Backend for User Story 3 -- [x] T031 [P] [US3] Create `backend/src/api/routes/dashboards.py` with GET /api/dashboards endpoint -- [x] T032 [P] [US3] Create `backend/src/services/resource_service.py` for shared resource fetching logic +**Contract Requirements**: +- All endpoints MUST follow `@PRE` and `@POST` conditions from [DEF:DashboardsAPI:Module](./contracts/modules.md#10-dashboards-api) +- MUST use `ConfigManager` via dependency injection (Constitution Principle II) + +- [x] T031 [P] [US3] Create `backend/src/api/routes/dashboards.py` with GET /api/dashboards endpoint + _Contract: [DEF:DashboardsAPI:Module](./contracts/modules.md#10-dashboards-api) - CRITICAL_ +- [x] T032 [P] [US3] Create `backend/src/services/resource_service.py` for shared resource fetching logic + _Contract: [DEF:ResourceService:Class](./contracts/modules.md#13-resourceservice)_ - [x] T033 [US3] Implement dashboard list fetching with Git status and last task status -- [ ] T034 [US3] Add pagination support to GET /api/dashboards endpoint (page, page_size parameters) -- [ ] T035 [US3] Implement bulk migration endpoint POST /api/dashboards/migrate with target environment and dashboard IDs -- [ ] T036 [US3] Implement bulk backup endpoint POST /api/dashboards/backup with optional cron schedule +- [ ] T034 [US3] Add pagination support to GET /api/dashboards endpoint (page, page_size parameters) + _Contract: @POST: Response includes pagination metadata_ +- [ ] T035 [US3] Implement bulk migration endpoint POST /api/dashboards/migrate with target environment and dashboard IDs + _Contract: @PRE: User has permission plugin:migration:execute_ +- [ ] T036 [US3] Implement bulk backup endpoint POST /api/dashboards/backup with optional cron schedule + _Contract: @PRE: User has permission plugin:backup:execute_ - [ ] T037 [US3] Add database mappings retrieval from MappingService for migration modal ### Frontend for User Story 3 -- [x] T038 [US3] Create `frontend/src/routes/dashboards/+page.svelte` as Dashboard Hub +**Contract Requirements**: +- MUST implement all `@UX_STATE` transitions from [DEF:DashboardHub:Component](./contracts/modules.md#7-dashboardhub-component) +- MUST preserve selection across pagination (`@INVARIANT: Selected dashboards persist across pagination`) + +- [x] T038 [US3] Create `frontend/src/routes/dashboards/+page.svelte` as Dashboard Hub + _Contract: [DEF:DashboardHub:Component](./contracts/modules.md#7-dashboardhub-component) - CRITICAL_ - [x] T039 [US3] Implement environment selector dropdown at top of Dashboard Hub -- [x] T040 [US3] Create dashboard grid with checkboxes, columns: Title, Slug, Git Status, Last Task, Actions -- [ ] T041 [US3] Implement "Select All" and "Select Visible" buttons in toolbar -- [ ] T042 [US3] Add real-time search input that filters dashboard list -- [ ] T043 [US3] Implement pagination controls with page numbers and "Rows per page" dropdown -- [ ] T044 [US3] Create floating bulk action panel at bottom: "[✓ N selected] [Migrate] [Backup]" -- [ ] T045 [US3] Implement Bulk Migration modal with target environment, database mappings, and selected dashboards list +- [x] T040 [US3] Create dashboard grid with checkboxes, columns: Title, Slug, Git Status, Last Task, Actions + _Contract: @UX_STATE: Idle-Grid, @UX_FEEDBACK: Git status color-coded icons_ +- [ ] T041 [US3] Implement "Select All" and "Select Visible" buttons in toolbar + _Contract: @UX_STATE: Selecting_ +- [ ] T042 [US3] Add real-time search input that filters dashboard list + _Contract: @POST: Search filters results in real-time (debounced 300ms)_ +- [ ] T043 [US3] Implement pagination controls with page numbers and "Rows per page" dropdown + _Contract: @INVARIANT: Selection persists across pagination_ +- [ ] T044 [US3] Create floating bulk action panel at bottom: "[✓ N selected] [Migrate] [Backup]" + _Contract: @UX_FEEDBACK: Floating panel slides up from bottom_ +- [ ] T045 [US3] Implement Bulk Migration modal with target environment, database mappings, and selected dashboards list + _Contract: @UX_STATE: BulkAction-Modal_ - [ ] T046 [US3] Implement Bulk Backup modal with one-time/scheduled options and cron expression - [x] T047 [US3] Implement individual Actions menu with Migrate, Backup, Git Operations options -- [x] T048 [US3] Connect Actions menu to existing plugin triggers (Migration, Backup, Git) -- [x] T049 [US3] Implement status badge click to open Task Drawer with correct task -- [x] T050 [US3] Add empty state when no environments configured or no dashboards found +- [x] T048 [US3] Connect Actions menu to existing plugin triggers (Migration, Backup, Git) + _Contract: @RELATION: DISPATCHES -> MigrationPlugin, BackupPlugin_ +- [x] T049 [US3] Implement status badge click to open Task Drawer with correct task + _Contract: @POST: Clicking status badge opens TaskDrawer with that task_ +- [x] T050 [US3] Add empty state when no environments configured or no dashboards found + _Contract: @UX_STATE: Empty-NoEnv, Empty-NoData_ - [ ] T051 [US3] Verify implementation matches ux_reference.md (Dashboard Hub Grid mockup) **Checkpoint**: Dashboard Hub fully functional with bulk operations @@ -151,25 +216,46 @@ ### Backend for User Story 4 -- [x] T052 [P] [US4] Create `backend/src/api/routes/datasets.py` with GET /api/datasets endpoint -- [x] T053 [US4] Implement dataset list fetching with mapped fields count and SQL table extraction +**Contract Requirements**: +- All endpoints MUST follow `@PRE` and `@POST` conditions from [DEF:DatasetsAPI:Module](./contracts/modules.md#11-datasets-api) +- MUST calculate `mapped_fields` as (mapped_columns / total_columns) * 100 + +- [x] T052 [P] [US4] Create `backend/src/api/routes/datasets.py` with GET /api/datasets endpoint + _Contract: [DEF:DatasetsAPI:Module](./contracts/modules.md#11-datasets-api) - CRITICAL_ +- [x] T053 [US4] Implement dataset list fetching with mapped fields count and SQL table extraction + _Contract: @INVARIANT: Mapped % is calculated as (mapped_columns / total_columns) * 100_ - [ ] T054 [US4] Add pagination support to GET /api/datasets endpoint (page, page_size parameters) -- [ ] T055 [US4] Implement bulk column mapping endpoint POST /api/datasets/map-columns with source selection -- [ ] T056 [US4] Implement bulk documentation generation endpoint POST /api/datasets/generate-docs +- [ ] T055 [US4] Implement bulk column mapping endpoint POST /api/datasets/map-columns with source selection + _Contract: @PRE: User has permission plugin:mapper:execute_ +- [ ] T056 [US4] Implement bulk documentation generation endpoint POST /api/datasets/generate-docs + _Contract: @PRE: User has permission plugin:llm_analysis:execute_ - [ ] T057 [US4] Add dataset-to-dashboard relationship retrieval for linked dashboards display ### Frontend for User Story 4 -- [x] T058 [US4] Create `frontend/src/routes/datasets/+page.svelte` as Dataset Hub -- [x] T059 [US4] Implement dataset grid with checkboxes, columns: Name, Database, Schema, Tables, Columns, Mapped %, Updated By, Actions -- [ ] T060 [US4] Implement "Select All" and "Select Visible" buttons in toolbar -- [ ] T061 [US4] Add real-time search input that filters dataset list by name, schema, or table names +**Contract Requirements**: +- MUST implement all `@UX_STATE` transitions from [DEF:DatasetHub:Component](./contracts/modules.md#8-datasethub-component) +- MUST display Mapped % with progress bar as specified in `@UX_FEEDBACK` + +- [x] T058 [US4] Create `frontend/src/routes/datasets/+page.svelte` as Dataset Hub + _Contract: [DEF:DatasetHub:Component](./contracts/modules.md#8-datasethub-component) - CRITICAL_ +- [x] T059 [US4] Implement dataset grid with checkboxes, columns: Name, Database, Schema, Tables, Columns, Mapped %, Updated By, Actions + _Contract: @UX_FEEDBACK: Mapped % column shows progress bar + percentage text_ +- [ ] T060 [US4] Implement "Select All" and "Select Visible" buttons in toolbar + _Contract: @UX_STATE: Selecting_ +- [ ] T061 [US4] Add real-time search input that filters dataset list by name, schema, or table names + _Contract: @POST: Search filters by name, schema, and table names_ - [ ] T062 [US4] Implement pagination controls with page numbers and "Rows per page" dropdown -- [ ] T063 [US4] Create floating bulk action panel at bottom: "[✓ N selected] [Map Columns] [Generate Docs] [Validate]" -- [ ] T064 [US4] Implement Column Mapping modal with PostgreSQL comments/XLSX source selection and preview -- [ ] T065 [US4] Implement Documentation Generation modal with LLM provider selection and options -- [ ] T066 [US4] Create dataset detail view showing SQL tables, column counts, mapping percentages, and linked dashboards -- [x] T067 [US4] Add empty state when no datasets found +- [ ] T063 [US4] Create floating bulk action panel at bottom: "[✓ N selected] [Map Columns] [Generate Docs] [Validate]" + _Contract: @UX_STATE: Selecting, @UX_FEEDBACK: Floating panel slides up_ +- [ ] T064 [US4] Implement Column Mapping modal with PostgreSQL comments/XLSX source selection and preview + _Contract: @POST: Map Columns modal shows source selection (PostgreSQL or XLSX)_ +- [ ] T065 [US4] Implement Documentation Generation modal with LLM provider selection and options + _Contract: @POST: Generate Docs modal shows LLM provider selection_ +- [ ] T066 [US4] Create dataset detail view showing SQL tables, column counts, mapping percentages, and linked dashboards + _Contract: @UX_STATE: Detail-View, @POST: Clicking dataset name opens detail view_ +- [x] T067 [US4] Add empty state when no datasets found + _Contract: @UX_STATE: Empty-NoData_ - [ ] T068 [US4] Verify implementation matches ux_reference.md (Dataset Hub Grid mockup) **Checkpoint**: Dataset Hub fully functional with bulk operations @@ -204,11 +290,19 @@ **Purpose**: Improvements that affect multiple user stories -- [x] T057 [P] Add breadcrumb navigation to all new pages -- [x] T058 [P] Implement breadcrumb truncation for deep paths (>3 levels) +**Contract Requirements**: +- Breadcrumbs MUST follow [DEF:Breadcrumbs:Component](./contracts/modules.md#9-breadcrumbs-component) specification +- Error handling MUST implement `@UX_RECOVERY` patterns from component contracts + +- [x] T057 [P] Add breadcrumb navigation to all new pages + _Contract: [DEF:Breadcrumbs:Component](./contracts/modules.md#9-breadcrumbs-component)_ +- [x] T058 [P] Implement breadcrumb truncation for deep paths (>3 levels) + _Contract: @POST: Deep paths (>3 levels) truncate middle segments_ - [x] T059 Remove old card-based dashboard grid if no longer needed -- [x] T060 [P] Add skeleton loaders for resource hub grids -- [x] T061 [P] Add error banners for environment connection failures +- [x] T060 [P] Add skeleton loaders for resource hub grids + _Contract: @UX_STATE: Loading -> Skeleton loaders in grid rows_ +- [x] T061 [P] Add error banners for environment connection failures + _Contract: @UX_RECOVERY: Failed environment connection shows error banner with retry_ - [x] T062 Run quickstart.md validation for all user stories - [x] T063 Final UX review against ux_reference.md