diff --git a/.kilocode/rules/specify-rules.md b/.kilocode/rules/specify-rules.md index d3fc972..c699f6d 100644 --- a/.kilocode/rules/specify-rules.md +++ b/.kilocode/rules/specify-rules.md @@ -11,6 +11,8 @@ Auto-generated from all feature plans. Last updated: 2025-12-19 - Filesystem (plugins, logs, backups), SQLite (optional, for job history if needed) (005-fix-ui-ws-validation) - Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS (007-migration-dashboard-grid) - N/A (Superset API integration) (007-migration-dashboard-grid) +- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS, Pydantic, Superset API (007-migration-dashboard-grid) +- N/A (Superset API integration - read-only for metadata) (007-migration-dashboard-grid) - Python 3.9+ (Backend), Node.js 18+ (Frontend Build) (001-plugin-arch-svelte-ui) @@ -31,9 +33,9 @@ cd src; pytest; ruff check . Python 3.9+ (Backend), Node.js 18+ (Frontend Build): Follow standard conventions ## Recent Changes +- 007-migration-dashboard-grid: Added Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS, Pydantic, Superset API - 007-migration-dashboard-grid: Added Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS - 007-migration-dashboard-grid: Added [if applicable, e.g., PostgreSQL, CoreData, files or N/A] -- 006-configurable-belief-logs: Added Python 3.9+ + FastAPI (Backend), Pydantic (Config), Svelte (Frontend) diff --git a/.kilocodemodes b/.kilocodemodes new file mode 100644 index 0000000..f7a97a5 --- /dev/null +++ b/.kilocodemodes @@ -0,0 +1,27 @@ +customModes: + - slug: tech-lead + name: Tech Lead + description: Architect for contracts and scaffolding + roleDefinition: >- + You are Kilo Code, acting as a Technical Lead and System Architect. + + Your primary responsibility is to define the "Structure" and "Contracts" of the system before implementation, following the Semantic Code Generation Protocol. + + You operate primarily on 'tasks-arch.md' task lists. + + YOUR DUTIES: + 1. Create new files and directory structures. + 2. Define Modules, Classes, and Functions using `[DEF]` anchors. + 3. Write clear Headers with `@PURPOSE`, `@LAYER`, `@RELATION`. + 4. Define strict Contracts using `@PRE`, `@POST`, `@PARAM`, `@RETURN`. + 5. Leave the implementation body empty or with a placeholder (e.g., `pass`, `return ...`). + + YOU DO NOT WRITE BUSINESS LOGIC. Your output is the "Skeleton" and "Rules" that the Developer Agent will fill in. + whenToUse: >- + Use this mode during the "Architecture Phase" of a feature. Select this mode when you need to create new files, define API surfaces, or set up the project structure before coding begins. + groups: + - read + - edit + - command + - list_files + - search_files diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index c96b5f1..d6066be 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -7,7 +7,8 @@ Changes: Templates Status: - .specify/templates/plan-template.md: ✅ Aligned. - .specify/templates/spec-template.md: ✅ Aligned. -- .specify/templates/tasks-template.md: ✅ Aligned. +- .specify/templates/tasks-arch-template.md: ✅ Aligned (New role-based split). +- .specify/templates/tasks-dev-template.md: ✅ Aligned (New role-based split). --> # Semantic Code Generation Constitution @@ -68,11 +69,24 @@ Every `.svelte` file must start with a Component definition header (`[DEF:Compon - `@INVARIANT`: Immutable UI/State rules. ## Generation Workflow -The development process follows a strict sequence: -1. **Analyze Request**: Identify target module and graph position. -2. **Define Structure**: Generate `[DEF]` anchors and Contracts FIRST. -3. **Implement Logic**: Write code satisfying Contracts. -4. **Validate**: If logic conflicts with Contract -> Stop -> Report Error. +The development process follows a strict sequence enforced by Agent Roles: + +### 1. Architecture Phase (Mode: `tech-lead`) +**Input**: `tasks-arch.md` +**Responsibility**: +- Analyze request and graph position. +- Generate `[DEF]` anchors, Headers, and Contracts (`@PRE`, `@POST`). +- **Output**: Scaffolding files with no implementation logic. + +### 2. Implementation Phase (Mode: `code`) +**Input**: `tasks-dev.md` + Scaffolding files +**Responsibility**: +- Read contracts defined by Architect. +- Write implementation code that strictly satisfies contracts. +- **Output**: Working code with passing tests. + +### 3. Validation +If logic conflicts with Contract -> Stop -> Report Error. ## Governance This Constitution establishes the "Semantic Code Generation Protocol" as the supreme law of this repository. diff --git a/.specify/scripts/bash/check-prerequisites.sh b/.specify/scripts/bash/check-prerequisites.sh index 98e387c..023e5f6 100755 --- a/.specify/scripts/bash/check-prerequisites.sh +++ b/.specify/scripts/bash/check-prerequisites.sh @@ -9,8 +9,8 @@ # # OPTIONS: # --json Output in JSON format -# --require-tasks Require tasks.md to exist (for implementation phase) -# --include-tasks Include tasks.md in AVAILABLE_DOCS list +# --require-tasks Require tasks-arch.md and tasks-dev.md to exist (for implementation phase) +# --include-tasks Include task files in AVAILABLE_DOCS list # --paths-only Only output path variables (no validation) # --help, -h Show help message # @@ -49,8 +49,8 @@ Consolidated prerequisite checking for Spec-Driven Development workflow. OPTIONS: --json Output in JSON format - --require-tasks Require tasks.md to exist (for implementation phase) - --include-tasks Include tasks.md in AVAILABLE_DOCS list + --require-tasks Require tasks-arch.md and tasks-dev.md to exist (for implementation phase) + --include-tasks Include task files in AVAILABLE_DOCS list --paths-only Only output path variables (no prerequisite validation) --help, -h Show this help message @@ -58,7 +58,7 @@ EXAMPLES: # Check task prerequisites (plan.md required) ./check-prerequisites.sh --json - # Check implementation prerequisites (plan.md + tasks.md required) + # Check implementation prerequisites (plan.md + task files required) ./check-prerequisites.sh --json --require-tasks --include-tasks # Get feature paths only (no validation) @@ -86,15 +86,16 @@ check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1 if $PATHS_ONLY; then if $JSON_MODE; then # Minimal JSON paths payload (no validation performed) - printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \ - "$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS" + printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS_ARCH":"%s","TASKS_DEV":"%s"}\n' \ + "$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS_ARCH" "$TASKS_DEV" else echo "REPO_ROOT: $REPO_ROOT" echo "BRANCH: $CURRENT_BRANCH" echo "FEATURE_DIR: $FEATURE_DIR" echo "FEATURE_SPEC: $FEATURE_SPEC" echo "IMPL_PLAN: $IMPL_PLAN" - echo "TASKS: $TASKS" + echo "TASKS_ARCH: $TASKS_ARCH" + echo "TASKS_DEV: $TASKS_DEV" fi exit 0 fi @@ -112,11 +113,18 @@ if [[ ! -f "$IMPL_PLAN" ]]; then exit 1 fi -# Check for tasks.md if required -if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then - echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2 - echo "Run /speckit.tasks first to create the task list." >&2 - exit 1 +# Check for task files if required +if $REQUIRE_TASKS; then + if [[ ! -f "$TASKS_ARCH" ]]; then + echo "ERROR: tasks-arch.md not found in $FEATURE_DIR" >&2 + echo "Run /speckit.tasks first to create the task lists." >&2 + exit 1 + fi + if [[ ! -f "$TASKS_DEV" ]]; then + echo "ERROR: tasks-dev.md not found in $FEATURE_DIR" >&2 + echo "Run /speckit.tasks first to create the task lists." >&2 + exit 1 + fi fi # Build list of available documents @@ -133,9 +141,10 @@ fi [[ -f "$QUICKSTART" ]] && docs+=("quickstart.md") -# Include tasks.md if requested and it exists -if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then - docs+=("tasks.md") +# Include task files if requested and they exist +if $INCLUDE_TASKS; then + [[ -f "$TASKS_ARCH" ]] && docs+=("tasks-arch.md") + [[ -f "$TASKS_DEV" ]] && docs+=("tasks-dev.md") fi # Output results @@ -161,6 +170,7 @@ else check_file "$QUICKSTART" "quickstart.md" if $INCLUDE_TASKS; then - check_file "$TASKS" "tasks.md" + check_file "$TASKS_ARCH" "tasks-arch.md" + check_file "$TASKS_DEV" "tasks-dev.md" fi fi diff --git a/.specify/scripts/bash/common.sh b/.specify/scripts/bash/common.sh index 2c3165e..c8ae806 100755 --- a/.specify/scripts/bash/common.sh +++ b/.specify/scripts/bash/common.sh @@ -143,7 +143,9 @@ HAS_GIT='$has_git_repo' FEATURE_DIR='$feature_dir' FEATURE_SPEC='$feature_dir/spec.md' IMPL_PLAN='$feature_dir/plan.md' -TASKS='$feature_dir/tasks.md' +TASKS_ARCH='$feature_dir/tasks-arch.md' +TASKS_DEV='$feature_dir/tasks-dev.md' +TASKS='$feature_dir/tasks.md' # Deprecated RESEARCH='$feature_dir/research.md' DATA_MODEL='$feature_dir/data-model.md' QUICKSTART='$feature_dir/quickstart.md' diff --git a/.specify/templates/tasks-arch-template.md b/.specify/templates/tasks-arch-template.md new file mode 100644 index 0000000..6d4ad80 --- /dev/null +++ b/.specify/templates/tasks-arch-template.md @@ -0,0 +1,35 @@ +--- + +description: "Architecture task list template (Contracts & Scaffolding)" +--- + +# Architecture Tasks: [FEATURE NAME] + +**Role**: Architect Agent +**Goal**: Define the "What" and "Why" (Contracts, Scaffolding, Models) before implementation. +**Input**: Design documents from `/specs/[###-feature-name]/` +**Output**: Files with `[DEF]` anchors, `@PRE`/`@POST` contracts, and `@RELATION` mappings. No business logic. + +## Phase 1: Setup & Models + +- [ ] A001 Create/Update data models in [path] with `[DEF]` and contracts +- [ ] A002 Define API route structure/contracts in [path] +- [ ] A003 Define shared utilities/interfaces + +## Phase 2: User Story 1 - [Title] + +- [ ] A004 [US1] Define contracts for [Component/Service] in [path] +- [ ] A005 [US1] Define contracts for [Endpoint] in [path] +- [ ] A006 [US1] Define contracts for [Frontend Component] in [path] + +## Phase 3: User Story 2 - [Title] + +- [ ] A007 [US2] Define contracts for [Component/Service] in [path] +- [ ] A008 [US2] Define contracts for [Endpoint] in [path] + +## Handover Checklist + +- [ ] All new files created with `[DEF]` anchors +- [ ] All functions/classes have `@PURPOSE`, `@PRE`, `@POST` tags +- [ ] No "naked code" (logic outside of anchors) +- [ ] `tasks-dev.md` is ready for the Developer Agent \ No newline at end of file diff --git a/.specify/templates/tasks-dev-template.md b/.specify/templates/tasks-dev-template.md new file mode 100644 index 0000000..9a73dde --- /dev/null +++ b/.specify/templates/tasks-dev-template.md @@ -0,0 +1,35 @@ +--- + +description: "Developer task list template (Implementation Logic)" +--- + +# Developer Tasks: [FEATURE NAME] + +**Role**: Developer Agent +**Goal**: Implement the "How" (Logic, State, Error Handling) inside the defined contracts. +**Input**: `tasks-arch.md` (completed), Scaffolding files with `[DEF]` anchors. +**Output**: Working code that satisfies `@PRE`/`@POST` conditions. + +## Phase 1: Setup & Models + +- [ ] D001 Implement logic for [Model] in [path] +- [ ] D002 Implement logic for [API Route] in [path] +- [ ] D003 Implement shared utilities + +## Phase 2: User Story 1 - [Title] + +- [ ] D004 [US1] Implement logic for [Component/Service] in [path] +- [ ] D005 [US1] Implement logic for [Endpoint] in [path] +- [ ] D006 [US1] Implement logic for [Frontend Component] in [path] +- [ ] D007 [US1] Verify semantic compliance and belief state logging + +## Phase 3: User Story 2 - [Title] + +- [ ] D008 [US2] Implement logic for [Component/Service] in [path] +- [ ] D009 [US2] Implement logic for [Endpoint] in [path] + +## Polish & Quality Assurance + +- [ ] DXXX Verify all tests pass +- [ ] DXXX Check error handling and edge cases +- [ ] DXXX Ensure code style compliance \ No newline at end of file diff --git a/.specify/templates/tasks-template.md b/.specify/templates/tasks-template.md deleted file mode 100644 index 9177d9b..0000000 --- a/.specify/templates/tasks-template.md +++ /dev/null @@ -1,263 +0,0 @@ ---- - -description: "Task list template for feature implementation" ---- - -# Tasks: [FEATURE NAME] - -**Input**: Design documents from `/specs/[###-feature-name]/` -**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/ - -**Tests**: The examples below include test tasks. Tests are OPTIONAL - only include them if explicitly requested in the feature specification. - -**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story. - -## Format: `[ID] [P?] [Story] Description` - -- **[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 - -## Path Conventions - -- **Single project**: `src/`, `tests/` at repository root -- **Web app**: `backend/src/`, `frontend/src/` -- **Mobile**: `api/src/`, `ios/src/` or `android/src/` -- Paths shown below assume single project - adjust based on plan.md structure - - - -## Phase 1: Setup (Shared Infrastructure) - -**Purpose**: Project initialization and basic structure - -- [ ] T001 Create project structure per implementation plan -- [ ] T002 Initialize [language] project with [framework] dependencies -- [ ] T003 [P] Configure linting and formatting tools - ---- - -## Phase 2: Foundational (Blocking Prerequisites) - -**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented - -**⚠️ CRITICAL**: No user story work can begin until this phase is complete - -Examples of foundational tasks (adjust based on your project): - -- [ ] T004 Setup database schema and migrations framework -- [ ] T005 [P] Implement authentication/authorization framework -- [ ] T006 [P] Setup API routing and middleware structure -- [ ] T007 Create base models/entities that all stories depend on -- [ ] T008 Configure error handling and logging infrastructure -- [ ] T009 Setup environment configuration management - -**Checkpoint**: Foundation ready - user story implementation can now begin in parallel - ---- - -## Phase 3: User Story 1 - [Title] (Priority: P1) 🎯 MVP - -**Goal**: [Brief description of what this story delivers] - -**Independent Test**: [How to verify this story works on its own] - -### Tests for User Story 1 (OPTIONAL - only if tests requested) ⚠️ - -> **NOTE: Write these tests FIRST, ensure they FAIL before implementation** - -- [ ] T010 [P] [US1] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T011 [P] [US1] Integration test for [user journey] in tests/integration/test_[name].py - -### Implementation for User Story 1 - -> **Protocol Note**: Follow Semantic Protocol. Define contracts (`[DEF]`, `@PRE`, `@POST`) BEFORE implementing logic. - -- [ ] T012 [P] [US1] Define contracts/scaffolding for [Entity1] in src/models/[entity1].py -- [ ] T013 [P] [US1] Define contracts/scaffolding for [Entity2] in src/models/[entity2].py -- [ ] T014 [P] [US1] Implement logic for [Entity1] in src/models/[entity1].py -- [ ] T015 [P] [US1] Implement logic for [Entity2] in src/models/[entity2].py -- [ ] T016 [US1] Define contracts/scaffolding for [Service] in src/services/[service].py -- [ ] T017 [US1] Implement logic for [Service] in src/services/[service].py -- [ ] T018 [US1] Define contracts/scaffolding for [endpoint/feature] in src/[location]/[file].py -- [ ] T019 [US1] Implement logic for [endpoint/feature] in src/[location]/[file].py -- [ ] T020 [US1] Verify semantic compliance and belief state logging - -**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently - ---- - -## Phase 4: User Story 2 - [Title] (Priority: P2) - -**Goal**: [Brief description of what this story delivers] - -**Independent Test**: [How to verify this story works on its own] - -### Tests for User Story 2 (OPTIONAL - only if tests requested) ⚠️ - -- [ ] T018 [P] [US2] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T019 [P] [US2] Integration test for [user journey] in tests/integration/test_[name].py - -### Implementation for User Story 2 - -- [ ] T021 [P] [US2] Define contracts/scaffolding for [Entity] in src/models/[entity].py -- [ ] T022 [P] [US2] Implement logic for [Entity] in src/models/[entity].py -- [ ] T023 [US2] Define contracts/scaffolding for [Service] in src/services/[service].py -- [ ] T024 [US2] Implement logic for [Service] in src/services/[service].py -- [ ] T025 [US2] Define contracts/scaffolding for [endpoint/feature] in src/[location]/[file].py -- [ ] T026 [US2] Implement logic for [endpoint/feature] in src/[location]/[file].py -- [ ] T027 [US2] Integrate with User Story 1 components (if needed) - -**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently - ---- - -## Phase 5: User Story 3 - [Title] (Priority: P3) - -**Goal**: [Brief description of what this story delivers] - -**Independent Test**: [How to verify this story works on its own] - -### Tests for User Story 3 (OPTIONAL - only if tests requested) ⚠️ - -- [ ] T024 [P] [US3] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T025 [P] [US3] Integration test for [user journey] in tests/integration/test_[name].py - -### Implementation for User Story 3 - -- [ ] T028 [P] [US3] Define contracts/scaffolding for [Entity] in src/models/[entity].py -- [ ] T029 [P] [US3] Implement logic for [Entity] in src/models/[entity].py -- [ ] T030 [US3] Define contracts/scaffolding for [Service] in src/services/[service].py -- [ ] T031 [US3] Implement logic for [Service] in src/services/[service].py -- [ ] T032 [US3] Define contracts/scaffolding for [endpoint/feature] in src/[location]/[file].py -- [ ] T033 [US3] Implement logic for [endpoint/feature] in src/[location]/[file].py - -**Checkpoint**: All user stories should now be independently functional - ---- - -[Add more user story phases as needed, following the same pattern] - ---- - -## Phase N: Polish & Cross-Cutting Concerns - -**Purpose**: Improvements that affect multiple user stories - -- [ ] TXXX [P] Documentation updates in docs/ -- [ ] TXXX Code cleanup and refactoring -- [ ] TXXX Performance optimization across all stories -- [ ] TXXX [P] Additional unit tests (if requested) in tests/unit/ -- [ ] TXXX Security hardening -- [ ] TXXX Run quickstart.md validation - ---- - -## Dependencies & Execution Order - -### Phase Dependencies - -- **Setup (Phase 1)**: No dependencies - can start immediately -- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories -- **User Stories (Phase 3+)**: All depend on Foundational phase completion - - User stories can then proceed in parallel (if staffed) - - Or sequentially in priority order (P1 → P2 → P3) -- **Polish (Final Phase)**: Depends on all desired user stories being complete - -### User Story Dependencies - -- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories -- **User Story 2 (P2)**: Can start after Foundational (Phase 2) - May integrate with US1 but should be independently testable -- **User Story 3 (P3)**: Can start after Foundational (Phase 2) - May integrate with US1/US2 but should be independently testable - -### Within Each User Story - -- Tests (if included) MUST be written and FAIL before implementation -- **Contracts First**: Define module structure and contracts (`[DEF]`, `@PRE`, `@POST`) before logic -- Models before services -- Services before endpoints -- Core implementation before integration -- Story complete before moving to next priority - -### Parallel Opportunities - -- All Setup tasks marked [P] can run in parallel -- All Foundational tasks marked [P] can run in parallel (within Phase 2) -- Once Foundational phase completes, all user stories can start in parallel (if team capacity allows) -- All tests for a user story marked [P] can run in parallel -- Models within a story marked [P] can run in parallel -- Different user stories can be worked on in parallel by different team members - ---- - -## Parallel Example: User Story 1 - -```bash -# Launch all tests for User Story 1 together (if tests requested): -Task: "Contract test for [endpoint] in tests/contract/test_[name].py" -Task: "Integration test for [user journey] in tests/integration/test_[name].py" - -# Launch all contracts for User Story 1 together: -Task: "Define contracts/scaffolding for [Entity1] in src/models/[entity1].py" -Task: "Define contracts/scaffolding for [Entity2] in src/models/[entity2].py" -``` - ---- - -## Implementation Strategy - -### MVP First (User Story 1 Only) - -1. Complete Phase 1: Setup -2. Complete Phase 2: Foundational (CRITICAL - blocks all stories) -3. Complete Phase 3: User Story 1 -4. **STOP and VALIDATE**: Test User Story 1 independently -5. Deploy/demo if ready - -### Incremental Delivery - -1. Complete Setup + Foundational → Foundation ready -2. Add User Story 1 → Test independently → Deploy/Demo (MVP!) -3. Add User Story 2 → Test independently → Deploy/Demo -4. Add User Story 3 → Test independently → Deploy/Demo -5. Each story adds value without breaking previous stories - -### Parallel Team Strategy - -With multiple developers: - -1. Team completes Setup + Foundational together -2. Once Foundational is done: - - Developer A: User Story 1 - - Developer B: User Story 2 - - Developer C: User Story 3 -3. Stories complete and integrate independently - ---- - -## Notes - -- [P] tasks = different files, no dependencies -- [Story] label maps task to specific user story for traceability -- Each user story should be independently completable and testable -- Verify tests fail before implementing -- Commit after each task or logical group -- Stop at any checkpoint to validate story independently -- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence diff --git a/specs/007-migration-dashboard-grid/contracts/api.md b/specs/007-migration-dashboard-grid/contracts/api.md index d7a2648..8025538 100644 --- a/specs/007-migration-dashboard-grid/contracts/api.md +++ b/specs/007-migration-dashboard-grid/contracts/api.md @@ -2,48 +2,57 @@ ## Endpoints -### GET /api/migration/dashboards +### 1. List Dashboards +**Method**: `GET` +**Path**: `/api/environments/{env_id}/dashboards` +**Purpose**: Fetch all dashboards from the specified environment for the grid. -Fetch a list of dashboards from the specified source environment. +**Request Parameters**: +- `env_id` (path): The ID of the environment to fetch from. -**Request:** -- **Headers**: - - `x-source-env-id`: `string` (UUID of the source environment configuration) +**Response**: +- **200 OK**: + ```json + [ + { + "id": 123, + "title": "Sales Dashboard", + "last_modified": "2023-10-27T10:00:00Z", + "status": "published" + }, + { + "id": 124, + "title": "Draft Metrics", + "last_modified": "2023-10-26T15:30:00Z", + "status": "draft" + } + ] + ``` +- **404 Not Found**: Environment not found. +- **500 Internal Server Error**: Superset API error. -**Response:** -- **Status**: `200 OK` -- **Body**: `List[Dashboard]` +## Components (Frontend) -```json -[ - { - "id": 101, - "title": "Sales Overview", - "changed_on": "2023-10-27T14:30:00Z", - "published": true, - "url": "/superset/dashboard/sales-overview/" - }, - { - "id": 102, - "title": "Marketing Draft", - "changed_on": "2023-10-26T09:15:00Z", - "published": false, - "url": "/superset/dashboard/marketing-draft/" - } -] -``` +### DashboardGrid +**Props**: +- `dashboards`: `DashboardMetadata[]` - List of dashboards to display. +- `selectedIds`: `number[]` - IDs of currently selected dashboards. -**Errors:** -- `400 Bad Request`: Missing environment ID header. -- `404 Not Found`: Environment configuration not found. -- `502 Bad Gateway`: Error communicating with Superset. +**Events**: +- `selectionChanged`: Emitted when selection changes. Payload: `number[]` (new list of selected IDs). -## Python Definitions +**State**: +- `filterText`: string - Current filter text. +- `currentPage`: number - Current page index (0-based). +- `pageSize`: number - Items per page (default 20). +- `sortColumn`: string - 'title' | 'last_modified' | 'status'. +- `sortDirection`: 'asc' | 'desc'. -```python -# [DEF:backend.src.api.routes.migration.get_dashboards:Function] -# @PURPOSE: Fetch dashboards from the specified source environment. -# @PRE: Header 'x-source-env-id' must be a valid environment UUID. -# @POST: Returns a list of Dashboard models with id, title, changed_on, and published status. -# @PARAM: source_env_id (str) - UUID of the source environment. -# @RETURN: List[DashboardModel] \ No newline at end of file +## Superset Client Extension + +### `get_dashboards_summary` +**Signature**: `def get_dashboards_summary(self) -> List[Dict]` +**Purpose**: Fetches dashboard metadata optimized for the grid. +**Implementation Detail**: +- Calls `GET /api/v1/dashboard/` with query params `q=(columns:!(id,dashboard_title,changed_on_utc,published))`. +- Maps response fields to `DashboardMetadata` schema. \ No newline at end of file diff --git a/specs/007-migration-dashboard-grid/data-model.md b/specs/007-migration-dashboard-grid/data-model.md index 5252f0b..c615048 100644 --- a/specs/007-migration-dashboard-grid/data-model.md +++ b/specs/007-migration-dashboard-grid/data-model.md @@ -2,37 +2,24 @@ ## Entities -### Dashboard -Represents a Superset dashboard with extended metadata for migration selection. +### DashboardMetadata +**Source**: Superset API (`/api/v1/dashboard/`) +**Purpose**: Represents a dashboard available for migration. -| Field | Type | Description | Source | -|-------|------|-------------|--------| -| `id` | `int` | Unique identifier | Superset API | -| `title` | `string` | Display name of the dashboard | Superset API (`dashboard_title`) | -| `changed_on` | `datetime` | Last modification timestamp (UTC) | Superset API (`changed_on_utc`) | -| `published` | `boolean` | Publication status (True=Published, False=Draft) | Superset API | -| `url` | `string` | Link to the dashboard (optional, for preview) | Superset API (`url`) | +| Field | Type | Description | Source Mapping | +|-------|------|-------------|----------------| +| `id` | Integer | Unique identifier | `id` | +| `title` | String | Display name of the dashboard | `dashboard_title` | +| `last_modified` | String (ISO 8601) | Timestamp of last modification | `changed_on_utc` | +| `status` | Enum ('published', 'draft') | Publication status | `published` (boolean) -> 'published'/'draft' | + +## Value Objects ### DashboardSelection -State of the user's selection in the grid. +**Purpose**: Represents the user's selection of dashboards to migrate. | Field | Type | Description | |-------|------|-------------| -| `selected_ids` | `Set` | IDs of selected dashboards | -| `is_all_selected` | `boolean` | Helper for "Select All" logic (optional) | - -## Component State (Frontend) - -### DashboardGrid -State managed within the Svelte component. - -| State | Type | Description | -|-------|------|-------------| -| `dashboards` | `Array` | Full list of fetched dashboards | -| `filtered_dashboards` | `Array` | List after applying text filter | -| `paginated_dashboards` | `Array` | Slice of filtered list for current view | -| `filter_text` | `string` | Current search query | -| `sort_by` | `string` | Column key to sort by (`title`, `changed_on`, `published`) | -| `sort_asc` | `boolean` | Sort direction | -| `page` | `int` | Current page number (0-indexed) | -| `page_size` | `int` | Items per page (default 20) | \ No newline at end of file +| `selected_ids` | List[Integer] | List of dashboard IDs selected for migration | +| `source_env_id` | String | ID of the source environment | +| `target_env_id` | String | ID of the target environment | \ No newline at end of file diff --git a/specs/007-migration-dashboard-grid/plan.md b/specs/007-migration-dashboard-grid/plan.md index 4bc65b7..efe8aba 100644 --- a/specs/007-migration-dashboard-grid/plan.md +++ b/specs/007-migration-dashboard-grid/plan.md @@ -12,24 +12,25 @@ ## Technical Context **Language/Version**: Python 3.9+ (Backend), Node.js 18+ (Frontend) -**Primary Dependencies**: FastAPI, SvelteKit, Tailwind CSS -**Storage**: N/A (Superset API integration) -**Testing**: pytest (Backend), vitest (Frontend) -**Target Platform**: Web Browser, Linux Server -**Project Type**: Web application -**Performance Goals**: Filtering < 200ms -**Constraints**: Pagination for large datasets -**Scale/Scope**: < 1000 dashboards typical +**Primary Dependencies**: FastAPI, SvelteKit, Tailwind CSS, Pydantic, Superset API +**Storage**: N/A (Superset API integration - read-only for metadata) +**Testing**: pytest (Backend), vitest (Frontend - inferred) +**Target Platform**: Linux server / Containerized +**Project Type**: web application (Backend + Frontend) +**Performance Goals**: Client-side filtering < 200ms for 100+ items +**Constraints**: Must handle large lists via pagination (Client-side). Spec says "Client-side (Fetch all, filter locally)" and "Pagination (e.g., 20 per page)". *RESOLVED: Fetch all, paginate locally.* +**Scale/Scope**: ~100s of dashboards per environment. ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* -- [x] **I. Causal Validity**: Contracts (`data-model.md`, `contracts/api.md`) defined before implementation. -- [x] **II. Immutability**: No core architecture changes. -- [x] **III. Semantic Format**: `[DEF]` syntax used in contracts. -- [x] **IV. DbC**: Pre/Post conditions defined in contracts. -- [x] **V. Belief State**: Logging standards acknowledged. +- [x] **Causal Validity**: Contracts (API/Data Model) defined before implementation. +- [x] **Immutability**: Module headers (`[DEF]`) preserved/added. +- [x] **Semantic Format**: All new code uses `[DEF]` anchors and metadata. +- [x] **Fractal Complexity**: New components (Grid) kept modular; `SupersetClient` extensions are small methods. + +**Status**: PASSED ## Project Structure @@ -46,51 +47,33 @@ specs/[###-feature]/ ``` ### Source Code (repository root) - ```text -# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT) -src/ -├── models/ -├── services/ -├── cli/ -└── lib/ - -tests/ -├── contract/ -├── integration/ -└── unit/ - -# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected) backend/ ├── src/ -│ ├── models/ -│ ├── services/ -│ └── api/ +│ ├── api/ +│ │ └── routes/ +│ │ └── environments.py # Update to support dashboard fetching +│ ├── core/ +│ │ └── superset_client.py # Update to fetch extended dashboard metadata +│ └── models/ +│ └── dashboard.py # New model for Dashboard metadata └── tests/ + └── test_superset_client.py frontend/ ├── src/ │ ├── components/ -│ ├── pages/ -│ └── services/ -└── tests/ - -# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected) -api/ -└── [same as backend above] - -ios/ or android/ -└── [platform-specific structure: feature modules, UI flows, platform tests] +│ │ ├── DashboardGrid.svelte # New component +│ │ └── Pagination.svelte # New component (if not exists) +│ ├── routes/ +│ │ └── migration/ +│ │ └── +page.svelte # Update to use DashboardGrid +│ └── types/ +│ └── dashboard.ts # New type definitions ``` -**Structure Decision**: [Document the selected structure and reference the real -directories captured above] +**Structure Decision**: Standard Web Application structure. Backend updates to `SupersetClient` and API routes to serve dashboard metadata. Frontend updates to include a new `DashboardGrid` component and integrate it into the migration flow. ## Complexity Tracking diff --git a/specs/007-migration-dashboard-grid/quickstart.md b/specs/007-migration-dashboard-grid/quickstart.md index e213654..c87e95f 100644 --- a/specs/007-migration-dashboard-grid/quickstart.md +++ b/specs/007-migration-dashboard-grid/quickstart.md @@ -1,23 +1,31 @@ # Quickstart: Migration Dashboard Grid -## Overview -The Migration Dashboard Grid allows users to select dashboards for migration using a rich interface with filtering, sorting, and status indicators. +## Prerequisites +- Backend running (`uvicorn backend.src.app:app --reload`) +- Frontend running (`npm run dev`) +- Superset instance accessible and configured in `config.yaml` -## Usage +## Steps to Verify -1. **Navigate to Migration Page**: Go to the Migration section in the app. -2. **Select Source Environment**: Choose the Superset environment you want to migrate from. -3. **View Dashboards**: The grid will automatically load the list of available dashboards. - - **Filter**: Type in the "Search dashboards..." box to filter by name. - - **Sort**: Click on column headers (Name, Last Modified, Status) to sort. - - **Paginate**: Use the "Next" and "Previous" buttons to navigate through pages. -4. **Select Dashboards**: - - Click individual checkboxes to select specific dashboards. - - Click the "Select All" checkbox in the header to select **all** dashboards matching the current filter (even those on other pages). -5. **Proceed**: Once selection is complete, click "Next" to configure mappings. +1. **Navigate to Migration Page**: + - Open browser to `http://localhost:5173/migration` + - Select a Source Environment from the dropdown. -## Troubleshooting +2. **Verify Dashboard Grid**: + - The grid should appear below the environment selectors. + - It should list dashboards with columns: Title, Last Modified, Status. + - Status pills should be green (Published) or gray (Draft). -- **"No dashboards found"**: Ensure the source environment is correctly configured and accessible. -- **Slow loading**: If the environment has thousands of dashboards, the initial load might take a few seconds. -- **Status "Unknown"**: If the API fails to return publication status, it will default to a neutral state. \ No newline at end of file +3. **Test Filtering**: + - Type in the "Search dashboards..." input. + - The list should filter instantly (client-side). + +4. **Test Pagination**: + - If >20 dashboards, check pagination controls at the bottom. + - Navigate to next page. + +5. **Test Selection**: + - Select a few dashboards. + - Change filter (hide selected). + - Clear filter -> Selection should persist. + - Click "Select All" -> Should select all matching current filter. \ No newline at end of file diff --git a/specs/007-migration-dashboard-grid/research.md b/specs/007-migration-dashboard-grid/research.md index 83ff2c3..051c3cd 100644 --- a/specs/007-migration-dashboard-grid/research.md +++ b/specs/007-migration-dashboard-grid/research.md @@ -1,66 +1,48 @@ # Research: Migration Dashboard Grid -## 1. Superset API Capabilities +## Unknowns & Clarifications -**Objective**: Verify how to fetch dashboard metadata (title, last modified, status). +### 1. Pagination vs Client-side Filtering +**Context**: The spec mentions "Client-side (Fetch all, filter locally)" (FR-004) but also "Pagination (e.g., 20 per page)" (FR-008). +**Resolution**: +- We will fetch ALL dashboard metadata from the Superset API in one go. The metadata (ID, Title, Status, Date) is lightweight. Even for 1000 dashboards, the payload is small (~100KB). +- **Client-side Pagination**: We will implement pagination purely on the frontend. This satisfies "Pagination" for UI performance/usability while keeping the "Fetch all" requirement for fast filtering. +- **Decision**: Fetch all, paginate locally. -- **Findings**: - - The `SupersetClient.get_dashboards` method in `superset_tool/client.py` already exists. - - It fetches the following columns by default: `["slug", "id", "changed_on_utc", "dashboard_title", "published"]`. - - This covers all requirements: - - Name -> `dashboard_title` - - Last Modified -> `changed_on_utc` - - Status -> `published` - - Pagination is handled internally by `_fetch_all_pages`, so the client fetches *all* dashboards. +### 2. Superset API for Dashboard Metadata +**Context**: Need to fetch `title`, `changed_on`, `published`. +**Research**: +- Superset API endpoint: `/api/v1/dashboard/` +- Standard response includes `result` array with `dashboard_title`, `changed_on_utc`, `published`. +- **Decision**: Use `GET /api/v1/dashboard/` with `q` parameter to select specific columns to minimize payload. + - Columns: `id`, `dashboard_title`, `changed_on_utc`, `published`. -- **Decision**: Use the existing `SupersetClient.get_dashboards` method. No changes needed to the core client. +### 3. Grid Component +**Context**: Need a grid with sorting, filtering, and selection. +**Options**: +- **Custom Svelte Table**: Lightweight, full control. +- **3rd Party Lib (e.g. svelte-headless-table)**: Powerful but maybe overkill. +- **Decision**: **Custom Svelte Component** (`DashboardGrid.svelte`). + - Why: Requirements are specific (Select All across pages, custom status pill, specific columns). A custom component using standard HTML table + Tailwind is simple and maintainable for this scope. -## 2. Frontend Grid Implementation +## Design Decisions -**Objective**: Choose a strategy for the grid component (filtering, sorting, pagination). +### Data Model +- **Dashboard**: + - `id`: string (or int, depends on Superset version, usually int for dashboards but we treat as ID) + - `title`: string + - `last_modified`: string (ISO date) + - `status`: 'published' | 'draft' -- **Options**: - 1. **Server-side pagination**: Fetch page by page. Good for huge datasets (>10k). - 2. **Client-side pagination**: Fetch all, filter/sort/paginate in browser. Good for typical datasets (<1k) and simplifies "Select All" logic. +### Architecture +- **Backend**: + - `SupersetClient.get_dashboards()`: Fetches list from Superset. + - `GET /api/environments/{id}/dashboards`: Proxy endpoint. +- **Frontend**: + - `DashboardGrid.svelte`: Handles display, sorting, pagination, and selection logic. + - `migration/+page.svelte`: Orchestrates fetching and passes data to Grid. -- **Findings**: - - Spec explicitly requests "Client-side (Fetch all, filter locally)". - - Spec requires "Select All" to select *all filtered results*, which is trivial with client-side state but complex with server-side pagination (requires tracking exclusion list or query parameters). - - Existing `MappingTable.svelte` is too simple (no sorting/pagination). - -- **Decision**: - - Implement a new `DashboardGrid.svelte` component. - - **State Management**: - - `dashboards`: Array of all fetched dashboards. - - `filterText`: String for name filtering. - - `sortColumn`: 'title' | 'changed_on' | 'published'. - - `sortDirection`: 'asc' | 'desc'. - - `currentPage`: Integer. - - `pageSize`: Integer (default 20). - - `selectedIds`: Set/Array of selected dashboard IDs. - - **Logic**: - - `filteredDashboards`: Derived store/value based on `dashboards` + `filterText`. - - `sortedDashboards`: Derived from `filteredDashboards` + `sort` params. - - `paginatedDashboards`: Slice of `sortedDashboards` for current page. - - "Select All": Adds all IDs from `sortedDashboards` (not just `paginatedDashboards`) to `selectedIds`. - -## 3. API Contract - -**Objective**: Define the endpoint to serve dashboard data. - -- **Current State**: Need to check if an endpoint exists that returns this data. -- **Requirement**: `GET /api/migration/dashboards` (or similar). -- **Response Structure**: - ```json - [ - { - "id": 123, - "title": "Sales Dashboard", - "changed_on": "2023-10-27T10:00:00Z", - "published": true - }, - ... - ] - ``` - -- **Decision**: Create or update a route in `backend/src/api/routes/migration.py` (or `mappings.py` if more appropriate, but `migration` seems better for source selection). +### UX/UI +- **Status Column**: Badge (Green for Published, Gray for Draft). +- **Selection**: Checkbox in first column. +- **Pagination**: Simple "Prev 1 of 5 Next" controls at bottom. diff --git a/specs/007-migration-dashboard-grid/spec.md b/specs/007-migration-dashboard-grid/spec.md index e1d82a0..78cc237 100644 --- a/specs/007-migration-dashboard-grid/spec.md +++ b/specs/007-migration-dashboard-grid/spec.md @@ -13,6 +13,11 @@ - Q: How should the grid handle large lists of dashboards (e.g., >50)? → A: **Pagination** (e.g., 20 per page). - Q: Does the "Select All" checkbox select only the currently visible page of dashboards, or all dashboards that match the current filter? → A: **All matching filter** (Selects all filtered results, not just the visible page). - Q: What should happen if the user changes the filter while some items are already selected? → A: **Preserve selection** (Selected items remain selected even if hidden by new filter). +- Q: What should be the default sort order when the dashboard grid first loads? → A: **Last Modified Date (Newest first)**. +- Q: Should the grid include an "Owners" column to help distinguish dashboards with the same name? → A: **Yes, include Owners**. +- Q: How should the "Owners" column display multiple owners? → A: **Show first owner + count (e.g., "admin + 2") with tooltip**. +- Q: How should the "Status" (Draft/Published) be visually represented in the grid? → A: **Colored Badges/Chips**. +- Q: Should the grid include a "Preview" action (e.g., link to open the dashboard in Superset)? → A: **Yes, open in new tab**. ## User Scenarios & Testing *(mandatory)* @@ -50,6 +55,7 @@ As a migration engineer, I want to select dashboards from a detailed grid view t - Name (Dashboard Title) - Last Modified (Date/Time) - Status (Published/Draft) + - Owners (List of owner names) - **FR-004**: The UI MUST provide a text filter input that filters the grid rows by Dashboard Name in real-time using client-side logic (fetching all dashboards once). - **FR-005**: The grid MUST support multi-row selection to allow migrating batches of dashboards. - **FR-006**: The selection state MUST be passed to the migration execution logic when the user initiates the migration. @@ -64,6 +70,7 @@ As a migration engineer, I want to select dashboards from a detailed grid view t - `title`: Display name. - `changed_on`: Timestamp of last edit. - `is_published`: Boolean status. + - `owners`: List of owner objects/names. ## Success Criteria *(mandatory)* diff --git a/specs/007-migration-dashboard-grid/tasks-arch.md b/specs/007-migration-dashboard-grid/tasks-arch.md new file mode 100644 index 0000000..dd4ec2f --- /dev/null +++ b/specs/007-migration-dashboard-grid/tasks-arch.md @@ -0,0 +1,29 @@ +--- + +description: "Architecture tasks for Migration Plugin Dashboard Grid" +--- + +# Architecture Tasks: Migration Plugin Dashboard Grid + +**Role**: Architect Agent +**Goal**: Define the "What" and "Why" (Contracts, Scaffolding, Models) before implementation. + +## Phase 1: Setup & Models + +- [ ] A001 Define contracts/scaffolding for migration route in backend/src/api/routes/migration.py +- [ ] A002 Define contracts/scaffolding for Dashboard model in backend/src/models/dashboard.py + +## Phase 2: User Story 1 - Advanced Dashboard Selection + +- [ ] A003 [US1] Define contracts/scaffolding for SupersetClient extensions in backend/src/core/superset_client.py +- [ ] A004 [US1] Define contracts/scaffolding for GET /api/migration/dashboards endpoint in backend/src/api/routes/migration.py +- [ ] A005 [US1] Define contracts/scaffolding for DashboardGrid component in frontend/src/components/DashboardGrid.svelte +- [ ] A006 [US1] Define contracts/scaffolding for migration page integration in frontend/src/routes/migration/+page.svelte +- [ ] A007 [US1] Define contracts/scaffolding for POST /api/migration/execute endpoint in backend/src/api/routes/migration.py + +## Handover Checklist + +- [ ] All new files created with `[DEF]` anchors +- [ ] All functions/classes have `@PURPOSE`, `@PRE`, `@POST` tags +- [ ] No "naked code" (logic outside of anchors) +- [ ] `tasks-dev.md` is ready for the Developer Agent \ No newline at end of file diff --git a/specs/007-migration-dashboard-grid/tasks-dev.md b/specs/007-migration-dashboard-grid/tasks-dev.md new file mode 100644 index 0000000..f243730 --- /dev/null +++ b/specs/007-migration-dashboard-grid/tasks-dev.md @@ -0,0 +1,34 @@ +--- + +description: "Developer tasks for Migration Plugin Dashboard Grid" +--- + +# Developer Tasks: Migration Plugin Dashboard Grid + +**Role**: Developer Agent +**Goal**: Implement the "How" (Logic, State, Error Handling) inside the defined contracts. + +## Phase 1: Setup & Models + +- [ ] D001 Implement logic for migration route in backend/src/api/routes/migration.py +- [ ] D002 Register migration router in backend/src/app.py +- [ ] D003 Export migration router in backend/src/api/routes/__init__.py +- [ ] D004 Implement logic for Dashboard model in backend/src/models/dashboard.py + +## Phase 2: User Story 1 - Advanced Dashboard Selection + +- [ ] D005 [P] [US1] Implement logic for SupersetClient extensions in backend/src/core/superset_client.py +- [ ] D006 [US1] Implement logic for GET /api/migration/dashboards endpoint in backend/src/api/routes/migration.py +- [ ] D007 [US1] Implement structure and styles for DashboardGrid component in frontend/src/components/DashboardGrid.svelte +- [ ] D008 [US1] Implement data fetching and state management in frontend/src/components/DashboardGrid.svelte +- [ ] D009 [US1] Implement client-side filtering logic in frontend/src/components/DashboardGrid.svelte +- [ ] D010 [US1] Implement pagination logic in frontend/src/components/DashboardGrid.svelte +- [ ] D011 [US1] Implement selection logic (single and Select All) in frontend/src/components/DashboardGrid.svelte +- [ ] D012 [US1] Integrate DashboardGrid and connect selection to submission in frontend/src/routes/migration/+page.svelte +- [ ] D013 [US1] Implement logic for POST /api/migration/execute endpoint in backend/src/api/routes/migration.py +- [ ] D014 [US1] Verify semantic compliance and belief state logging + +## Polish & Quality Assurance + +- [ ] D015 Verify error handling and empty states in frontend/src/components/DashboardGrid.svelte +- [ ] D016 Ensure consistent styling with Tailwind CSS in frontend/src/components/DashboardGrid.svelte \ No newline at end of file diff --git a/specs/007-migration-dashboard-grid/tasks.md b/specs/007-migration-dashboard-grid/tasks.md deleted file mode 100644 index 884d49d..0000000 --- a/specs/007-migration-dashboard-grid/tasks.md +++ /dev/null @@ -1,32 +0,0 @@ -# Tasks: Migration Plugin Dashboard Grid - -## Phase 1: Setup -- [ ] T001 Create migration route module in backend/src/api/routes/migration.py -- [ ] T002 Register migration router in backend/src/app.py -- [ ] T003 Export migration router in backend/src/api/routes/__init__.py - -## Phase 2: Foundational -- [ ] T004 Create Dashboard model in backend/src/models/dashboard.py - -## Phase 3: User Story 1 - Advanced Dashboard Selection -- [ ] T005 [P] [US1] Extend SupersetClient to fetch dashboards with metadata (handling missing fields) in backend/src/core/superset_client.py -- [ ] T006 [US1] Implement GET /api/migration/dashboards endpoint in backend/src/api/routes/migration.py -- [ ] T007 [P] [US1] Create DashboardGrid component structure in frontend/src/components/DashboardGrid.svelte -- [ ] T008 [US1] Implement data fetching and state management in frontend/src/components/DashboardGrid.svelte -- [ ] T009 [US1] Implement client-side filtering logic in frontend/src/components/DashboardGrid.svelte -- [ ] T010 [US1] Implement pagination logic in frontend/src/components/DashboardGrid.svelte -- [ ] T011 [US1] Implement selection logic (single and Select All) in frontend/src/components/DashboardGrid.svelte -- [ ] T012 [US1] Integrate DashboardGrid into migration page and connect selection to submission in frontend/src/routes/migration/+page.svelte -- [ ] T013 [US1] Implement POST /api/migration/execute endpoint to accept selected dashboard IDs in backend/src/api/routes/migration.py - -## Phase 4: Polish -- [ ] T014 Verify error handling and empty states in frontend/src/components/DashboardGrid.svelte -- [ ] T015 Ensure consistent styling with Tailwind CSS in frontend/src/components/DashboardGrid.svelte - -## Dependencies -- US1 depends on T004, T005, T006 - -## Implementation Strategy -- Implement backend support first (Models -> Client -> API) -- Implement frontend component with mock data then connect API -- Integrate into main page \ No newline at end of file