191 lines
12 KiB
Markdown
191 lines
12 KiB
Markdown
# Implementation Plan: Task Status Center
|
||
|
||
**Branch**: `034-task-status-center` | **Date**: 2026-07-02 | **Spec**: [spec.md](./spec.md)
|
||
**Input**: Feature specification from `/specs/034-task-status-center/spec.md`
|
||
|
||
## Summary
|
||
|
||
Transform the existing `/reports` page into a real-time Task Status Center — a unified monitoring dashboard for all background tasks in superset-tools. The page gains:
|
||
|
||
1. **Summary dashboard** (P1) — aggregated task counts by type × status, updated in real-time via existing WebSocket infrastructure.
|
||
2. **Enhanced filtering** (P2) — multi-select type/status filters, text search, time range, clickable summary cards that auto-apply filters.
|
||
3. **Task drill-down** (P3) — click any task to open Task Drawer with logs; hover tooltips with key details.
|
||
4. **RBAC enforcement** (TSC-FR-009) — admin/analyst/viewer see only authorized tasks.
|
||
|
||
**Technical approach**: Reuses existing `/ws/task-events` WebSocket for real-time updates. Adds `GET /api/reports/summary` REST endpoint for initial load. Frontend follows model-first pattern: `TaskCenterModel.svelte.ts` Screen Model isolates all state, the page becomes a thin render layer. Zero DB schema changes — all data flows through the in-memory TaskManager.
|
||
|
||
## Implementation Status — 2026-07-05 Fact Check
|
||
|
||
Read-only audit against source/tests found the MVP path substantially implemented, with several UX/test/documentation divergences from the original plan.
|
||
|
||
| Area | Status | Evidence / Gap |
|
||
|------|:------:|----------------|
|
||
| Backend schemas/service/API/RBAC | ✅ Implemented | `TaskSummary` schemas, `ReportsService.get_summary()`, `/api/reports/summary`, and `_filter_tasks_by_rbac()` are present. |
|
||
| Frontend model/API/page/summary | ✅ Implemented | `TaskCenterModel.svelte.ts`, `getReportsSummary()`, `SummaryPanel.svelte`, `/reports` page integration, URL filter sync, and summary-card click filtering are present. |
|
||
| Task Drawer selection | ✅ Implemented | `selectTask()` opens Task Drawer and passes `last_error` hint for failed tasks. |
|
||
| Standalone filter/list components | ✅ Implemented | `FilterBar.svelte` and enhanced `TaskList.svelte` are created and wired into `/reports`. |
|
||
| Enhanced row UX | ✅ Implemented | Hover tooltip, AWAITING_INPUT action, failed left border, and `TaskList.test.ts` are present. |
|
||
| Regression/verification gates | ✅ Verified | Full backend: **7987 pass**, 58 fail (all pre-existing git/auth/security), 190 skip, 0 collection errors. All 75 report tests pass. Frontend: 2546/2549 pass (3 pre-existing unrelated). Infrastructure fixes applied: conftest skip filter + norecursedirs. |
|
||
| Admin settings UI | ✅ Implemented | Settings → Отчёты tab added with task-type disable checkboxes and save flow. |
|
||
|
||
## Technical Context
|
||
|
||
**Language/Version**: Python 3.13+ (backend), TypeScript (frontend Svelte 5 runes-only)
|
||
**Primary Dependencies**: FastAPI, SQLAlchemy, APScheduler (backend); SvelteKit 2.x, Vite 7.x, Tailwind CSS 3.x (frontend)
|
||
**Storage**: PostgreSQL 16 (no schema changes needed)
|
||
**Testing**: pytest (backend), vitest (L1 model tests without render + L2 UX tests with @testing-library/svelte)
|
||
**Target Platform**: Linux server (Docker), modern browsers
|
||
**Project Type**: web application (FastAPI REST + WebSocket backend, SvelteKit SPA frontend)
|
||
**Frontend Architecture**: TypeScript-first, model-first (Screen Models via `.svelte.ts`), runes-only (`$state`, `$derived`, `$effect`)
|
||
**Performance Goals**: SC-001: summary load ≤1s; SC-002: WS event-to-DOM ≤2s; SC-004: 30fps at 100+ tasks
|
||
**Constraints**: RBAC enforcement (TSC-FR-009), WebSocket reconnect ≤5s (SC-005), no new DB schema
|
||
**Scale/Scope**: 3 user stories, 10 FRs, ~12 files created/modified
|
||
|
||
## Constitution Check
|
||
|
||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||
|
||
| Principle | Status | Evidence |
|
||
|-----------|:------:|----------|
|
||
| **I. Semantic Contract First** | ✅ PASS | All C3+ modules have `#region` contracts in `contracts/modules.md`. Backend schemas carry `@DATA_CONTRACT`. Frontend DTOs carry cross-stack `@RELATION`. No naked code. |
|
||
| **II. Decision Memory** | ✅ PASS | All 10 research decisions in `research.md` carry `@RATIONALE`/`@REJECTED`. ADR-0004, ADR-0005, ADR-0006, ADR-0010, ADR-0011 referenced. |
|
||
| **III. External Orchestrator** | ✅ PASS | Feature extends existing task infrastructure without modifying Superset. Follows ADR-0003 orchestrator pattern. |
|
||
| **IV. Module Discipline** | ✅ PASS | New Model ≤300 lines (well below 400-line INV_7). All files placed in canonical directories per ADR-0001. No cyclic imports. |
|
||
| **V. RBAC Enforcement** | ✅ PASS | TSC-FR-009 enforced via `_filter_tasks_by_rbac()` in service layer. Uses existing `User.roles` and `has_permission("tasks", "READ")`. |
|
||
| **VI. Svelte 5 Runes Only** | ✅ PASS | `TaskCenterModel` uses `$state`/`$derived`. No legacy Svelte 4 syntax. No `writable` stores created. Model uses `.svelte.ts` extension. |
|
||
| **VII. Test-Driven for C3+** | ✅ PASS | All C4 contracts will have tests verifying `@PRE`/`@POST`/`@INVARIANT`. Rejected-path regression tests for RBAC filtering. |
|
||
| **VIII. Attention-Optimized Contracts** | ✅ PASS | All contracts use hierarchical IDs (`Reports.SummaryService`, `TaskCenterModel`). `@SEMANTICS` keywords shared within domain. Contract files ≤150 lines. |
|
||
| **ATTN_1 (CSA 4×)** | ✅ PASS | First anchor line packs `[C:N] [TYPE] [SEMANTICS]` on one line. |
|
||
| **ATTN_2 (HCA 128×)** | ✅ PASS | IDs use `Domain.Sub.Name` pattern (2-3 levels). |
|
||
| **ATTN_3 (DSA Indexer)** | ✅ PASS | Same-domain contracts share primary `@SEMANTICS` keyword (`task-status-center`). |
|
||
| **ATTN_4 (Sliding Window)** | ✅ PASS | All contracts ≤150 lines. Modules ≤400 lines. |
|
||
|
||
**Gate Result**: ✅ ALL PRINCIPLES PASS — no blocking conflicts. Proceed to Phase 0.
|
||
|
||
### Re-check After Phase 1 Design
|
||
|
||
| Check | Status |
|
||
|-------|:------:|
|
||
| `TaskCenterModel` estimated lines: ~250 | ✅ Below 400-line gate |
|
||
| `contracts/modules.md` estimated lines: 280 | ✅ Acceptable for a C5 ADR |
|
||
| Cross-stack `@DATA_CONTRACT` bridges present | ✅ 9 bridge pairs documented |
|
||
| RBAC filtering path rejections documented | ✅ `@REJECTED` in R4 |
|
||
| WebSocket reuse documented | ✅ R2 in research.md |
|
||
|
||
## Project Structure
|
||
|
||
### Documentation (this feature)
|
||
|
||
```text
|
||
specs/034-task-status-center/
|
||
├── spec.md # Feature specification
|
||
├── ux_reference.md # UX interaction reference
|
||
├── plan.md # This file
|
||
├── research.md # Phase 0 — 10 research decisions
|
||
├── data-model.md # Phase 1 — schemas, DTOs, cross-stack bridge
|
||
├── quickstart.md # Phase 1 — developer setup & verification
|
||
├── contracts/
|
||
│ └── modules.md # Phase 1 — GRACE contracts (backend + frontend)
|
||
├── checklists/
|
||
│ └── requirements.md # Spec quality validation
|
||
└── tasks.md # Phase 2 — task decomposition (/speckit.tasks)
|
||
```
|
||
|
||
### Source Code (repository root)
|
||
|
||
```text
|
||
backend/
|
||
├── src/
|
||
│ ├── api/routes/
|
||
│ │ └── reports.py # MODIFY: add /summary endpoint, RBAC enhancement
|
||
│ ├── models/
|
||
│ │ └── report.py # MODIFY: add TaskSummary schemas
|
||
│ └── services/reports/
|
||
│ └── report_service.py # MODIFY: add get_summary(), _filter_tasks_by_rbac()
|
||
└── tests/
|
||
├── api/routes/
|
||
│ └── test_reports.py # MODIFY: add summary + RBAC tests
|
||
└── services/reports/
|
||
└── test_report_service.py # MODIFY: add RBAC filter tests
|
||
|
||
frontend/
|
||
├── src/
|
||
│ ├── routes/reports/
|
||
│ │ ├── +page.svelte # REWRITE: thin render layer
|
||
│ │ └── +page.ts # NEW: load function (URL query parsing)
|
||
│ ├── lib/
|
||
│ │ ├── models/
|
||
│ │ │ └── TaskCenterModel.svelte.ts # NEW: Screen Model
|
||
│ │ ├── components/reports/
|
||
│ │ │ ├── SummaryPanel.svelte # NEW: summary dashboard
|
||
│ │ │ ├── FilterBar.svelte # NEW: filter controls
|
||
│ │ │ ├── TaskList.svelte # NEW: enhanced task list
|
||
│ │ │ ├── ReportsList.svelte # LEGACY: existing generic list retained
|
||
│ │ │ └── reportTypeProfiles.ts # MODIFY: add clean_release
|
||
│ │ └── api/
|
||
│ │ └── reports.ts # MODIFY: add getReportsSummary(), types
|
||
│ └── types/
|
||
│ └── reports.ts # NEW: TypeScript DTOs
|
||
└── tests/
|
||
└── lib/
|
||
├── models/
|
||
│ └── TaskCenterModel.test.ts # NEW: model unit tests
|
||
└── components/reports/
|
||
├── SummaryPanel.test.ts # NEW: component UX tests
|
||
└── FilterBar.test.ts # NEW: component UX tests
|
||
```
|
||
|
||
## Complexity Tracking
|
||
|
||
No violations to justify. All contracts are within their appropriate complexity tiers per the semantic protocol:
|
||
|
||
| Contract | Tier | Rationale |
|
||
|----------|:----:|-----------|
|
||
| `Reports.SummaryRouter` | C4 | Multi-step: RBAC + load + normalize + aggregate |
|
||
| `Reports.SummaryService` | C4 | Stateful: accesses TaskManager, applies authorization |
|
||
| `Reports.ListEnhanced` | C4 | Enhanced from C3 with RBAC row-filtering |
|
||
| `Reports.RbacTaskFilter` | C3 | Pure function: input tasks → output filtered tasks |
|
||
| `TaskCenterModel` | C4 | Stateful: 15+ atoms, WebSocket lifecycle, side effects |
|
||
| `SummaryPanel` | C4 | WebSocket-reactive derived display, UX states |
|
||
| `FilterBar` | C3 | Multi-select inputs, no side effects beyond model mutation |
|
||
| `TaskList` | C4 | Pagination, sort, click→drawer, UX states |
|
||
| `TaskCenterReportsPage` | C4 | Page orchestration: Model init, UX state machine |
|
||
| `ReportsTypes` | C2 | DTO definitions only |
|
||
| `ReportsApiClient` | C3 | Typed fetch wrappers |
|
||
|
||
## Phase Artifacts
|
||
|
||
| Artifact | Status | Description |
|
||
|----------|:------:|-------------|
|
||
| `research.md` | ✅ Done | 10 research decisions (R1-R10) |
|
||
| `data-model.md` | ✅ Done | Pydantic schemas, TypeScript DTOs, cross-stack bridge |
|
||
| `contracts/modules.md` | ✅ Done | 12 GRACE contracts with complexity anchors |
|
||
| `quickstart.md` | ✅ Done | Developer setup & verification |
|
||
| `plan.md` | ✅ Done | This file |
|
||
|
||
## Validation Against UX Reference
|
||
|
||
| UX Promise | Implementation | Status |
|
||
|------------|----------------|:------:|
|
||
| `@UX_STATE: idle` | `TaskCenterModel.screenState = 'ready'` | ✅ |
|
||
| `@UX_STATE: loading` | Skeleton in `SummaryPanel` + `TaskList` | ✅ |
|
||
| `@UX_STATE: empty` | Empty/filter-empty state in `TaskList` | ✅ |
|
||
| `@UX_STATE: disconnected` | Reconnect banner in `TaskCenterReportsPage` | ✅ |
|
||
| `@UX_STATE: reconnecting` | Yellow indicator in model-driven UI | ✅ |
|
||
| `@UX_STATE: error` | Error banner + retry button | ✅ |
|
||
| `@UX_FEEDBACK: status change` | Animated badge via CSS transition | ✅ |
|
||
| `@UX_FEEDBACK: new task` | Active-first model ordering and TaskList row rendering present | ⚠️ |
|
||
| `@UX_FEEDBACK: task completion` | Summary count update present; row highlight not implemented | ⚠️ |
|
||
| `@UX_RECOVERY: WS disconnect` | Auto-reconnect + manual button | ✅ |
|
||
| `@UX_RECOVERY: load error` | Retry button | ✅ |
|
||
| `@UX_RECOVERY: empty search` | Clear filters button | ✅ |
|
||
| `@UX_REACTIVITY: Model-driven` | TaskCenterModel `$state` + `$derived` | ✅ |
|
||
| Screen Model presence | `TaskCenterModel.svelte.ts` with `@STATE`/`@ACTION`/`@INVARIANT` | ✅ |
|
||
|
||
## Next Steps
|
||
|
||
1. Browser-smoke `/reports` and Settings → Отчёты against a live backend.
|
||
2. Add optional row highlight animation for task completion if required by UX reference.
|
||
|
||
#endregion PlanDoc
|