docs(11): create phase plan for per-library scan pipeline
This commit is contained in:
1 parent
025da10d98
commit
68463f3549
4 files changed
+790
-1
No files matched your search
@@ -0,0 +1,245 @@
|
||||
---
|
||||
phase: 11-per-library-scan-pipeline
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["11-01"]
|
||||
files_modified:
|
||||
- frontend/src/components/config-page/config-page.ts
|
||||
- frontend/src/components/library-manager/library-manager.ts
|
||||
- frontend/wailsjs/go/library/Library.d.ts
|
||||
- frontend/wailsjs/go/library/Library.js
|
||||
autonomous: true
|
||||
requirements: [LSCAN-03, LSCAN-04]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Progress UI shows which library is currently being scanned by name"
|
||||
- "Progress UI shows queue count when libraries are queued"
|
||||
- "Cancel during queued multi-scan shows modal with 'Cancel This Library' and 'Cancel All Scanning' choices"
|
||||
- "Cancelling one library automatically starts scanning the next queued library"
|
||||
- "Scan All Libraries button exists and triggers ScanAllLibraries binding"
|
||||
artifacts:
|
||||
- path: "frontend/src/components/config-page/config-page.ts"
|
||||
provides: "Updated cancel dialog with scope choice, progress with library name"
|
||||
- path: "frontend/src/components/library-manager/library-manager.ts"
|
||||
provides: "Scan All Libraries button, per-library progress display"
|
||||
- path: "frontend/wailsjs/go/library/Library.d.ts"
|
||||
provides: "TypeScript declarations for ScanLibrary, ScanAllLibraries, CancelCurrentScan, CancelAllScans"
|
||||
key_links:
|
||||
- from: "frontend/src/components/config-page/config-page.ts"
|
||||
to: "@go/library/Library"
|
||||
via: "Wails binding calls for CancelCurrentScan, CancelAllScans"
|
||||
pattern: "CancelCurrentScan|CancelAllScans"
|
||||
- from: "frontend/src/components/library-manager/library-manager.ts"
|
||||
to: "@go/library/Library"
|
||||
via: "Wails binding calls for ScanAllLibraries"
|
||||
pattern: "ScanAllLibraries"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Update the frontend scan UI to display per-library progress (library name + queue count), add a "Scan All Libraries" button, and implement the cancel scope modal dialog for queued scans.
|
||||
|
||||
Purpose: Fulfill LSCAN-03 (progress identifies which library) and LSCAN-04 frontend (cancel/pause work per-library with clear scope).
|
||||
Output: Updated config-page with library-aware cancel dialog, library-manager with Scan All button, Wails binding stubs.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/caleb/.config/opencode/get-shit-done/workflows/execute-plan.md
|
||||
@/home/caleb/.config/opencode/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/11-per-library-scan-pipeline/11-CONTEXT.md
|
||||
@.planning/phases/11-per-library-scan-pipeline/11-01-SUMMARY.md
|
||||
@.planning/phases/09-scan-cancellation-keyboard-shortcuts/09-03-SUMMARY.md
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types and contracts from Plan 01 -->
|
||||
|
||||
Updated ScanProgress payload (from backend/library/metrics.go after Plan 01):
|
||||
```typescript
|
||||
interface ScanProgress {
|
||||
phase: 'counting' | 'scanning' | 'orphans' | 'thumbnails';
|
||||
total: number;
|
||||
processed: number;
|
||||
added: number;
|
||||
skipped: number;
|
||||
updated: number;
|
||||
libraryId: number; // NEW — which library is scanning
|
||||
libraryName: string; // NEW — display name
|
||||
queuedCount: number; // NEW — libraries still queued
|
||||
}
|
||||
```
|
||||
|
||||
New Wails-bound methods (from Plan 01):
|
||||
```typescript
|
||||
// These will need stubs in Library.d.ts and Library.js
|
||||
export function ScanLibrary(id: number): Promise<void>;
|
||||
export function ScanAllLibraries(): Promise<void>;
|
||||
export function CancelCurrentScan(): Promise<void>;
|
||||
export function CancelAllScans(): Promise<void>;
|
||||
export function GetScanQueueLength(): Promise<number>;
|
||||
```
|
||||
|
||||
New events (from Plan 01):
|
||||
```typescript
|
||||
LibraryScanQueued: "LibraryScanQueued",
|
||||
LibraryScanQueueDrained: "LibraryScanQueueDrained",
|
||||
```
|
||||
|
||||
Existing cancel dialog pattern from config-page.ts:
|
||||
- Modal overlay with stopPropagation
|
||||
- Three button choices
|
||||
- handleCancelKeep / handleCancelDiscard / handleCancelDialogDismiss
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add Wails binding stubs and update progress/cancel UI in config-page</name>
|
||||
<files>
|
||||
frontend/wailsjs/go/library/Library.d.ts
|
||||
frontend/wailsjs/go/library/Library.js
|
||||
frontend/src/components/config-page/config-page.ts
|
||||
</files>
|
||||
<action>
|
||||
1. **Add Wails binding stubs** to `frontend/wailsjs/go/library/Library.d.ts`:
|
||||
```typescript
|
||||
export function ScanLibrary(id: number): Promise<void>;
|
||||
export function ScanAllLibraries(): Promise<void>;
|
||||
export function CancelCurrentScan(): Promise<void>;
|
||||
export function CancelAllScans(): Promise<void>;
|
||||
export function GetScanQueueLength(): Promise<number>;
|
||||
export function QueuedLibraryNames(): Promise<string[]>;
|
||||
```
|
||||
|
||||
And corresponding runtime implementations in `Library.js`:
|
||||
```javascript
|
||||
export function ScanLibrary(id) { return window['go']['library']['Library']['ScanLibrary'](id); }
|
||||
export function ScanAllLibraries() { return window['go']['library']['Library']['ScanAllLibraries'](); }
|
||||
export function CancelCurrentScan() { return window['go']['library']['Library']['CancelCurrentScan'](); }
|
||||
export function CancelAllScans() { return window['go']['library']['Library']['CancelAllScans'](); }
|
||||
export function GetScanQueueLength() { return window['go']['library']['Library']['GetScanQueueLength'](); }
|
||||
export function QueuedLibraryNames() { return window['go']['library']['Library']['QueuedLibraryNames'](); }
|
||||
```
|
||||
|
||||
2. **Update config-page.ts ScanProgress interface** to include the new fields:
|
||||
- Add `libraryId: number`, `libraryName: string`, `queuedCount: number` to the `ScanProgress` interface
|
||||
|
||||
3. **Update imports** — replace `CancelScan` import with `CancelCurrentScan, CancelAllScans` from `@go/library/Library`
|
||||
|
||||
4. **Update progress display** (`renderScanProgress` method or equivalent):
|
||||
- When `scanProgress.libraryName` is non-empty, show "Scanning: [Library Name]" as the progress label instead of just "Scanning"
|
||||
- When `scanProgress.queuedCount > 0`, add a line below: "[N] libraries queued" in tertiary text color
|
||||
- Format: `Scanning: My Music (245/1200 files)` with `2 libraries queued` below
|
||||
|
||||
5. **Update cancel dialog** — replace the current three-option dialog with the per-library-aware version per CONTEXT.md:
|
||||
- Add `@state() private scanQueuedCount = 0;` to track queue state
|
||||
- Update `handleScanProgress` to also save `queuedCount`
|
||||
- **When `queuedCount > 0`** (multi-scan in progress): show modal dialog with TWO buttons:
|
||||
- "Cancel This Library" — calls `CancelCurrentScan()` (stops current, next starts)
|
||||
- "Cancel All Scanning" — calls `CancelAllScans()` (stops everything)
|
||||
- No default — user must pick (per CONTEXT.md: "no default, user must pick")
|
||||
- **When `queuedCount === 0`** (single scan): keep existing cancel behavior but call `CancelCurrentScan()` instead of `CancelScan()`. Can use the existing Keep/Discard/Continue dialog pattern.
|
||||
- Update `handleCancelKeep` → call `CancelCurrentScan()` instead of `CancelScan()`
|
||||
- Update `handleCancelDiscard` → call `CancelCurrentScan()` instead of `CancelScan()`
|
||||
|
||||
6. **Handle new events** in `connectedCallback`:
|
||||
- Listen for `LibraryScanQueued` — update `scanQueuedCount` from event payload
|
||||
- Listen for `LibraryScanQueueDrained` — set `scanQueuedCount = 0`, reset scan state
|
||||
|
||||
7. **Update scan buttons section** — when not scanning, show "Scan All Libraries" as an additional button alongside Soft Scan and Full Rescan. It calls `ScanAllLibraries()`.
|
||||
|
||||
**Styling notes:**
|
||||
- Use existing design tokens (`--yj-text-primary`, `--yj-text-tertiary`, `--yj-accent`)
|
||||
- Queue count text: `.progress-detail` style (smaller, tertiary color)
|
||||
- Library name in progress: bold, primary text color
|
||||
- Cancel modal buttons: "Cancel This Library" gets `btn-warning`, "Cancel All Scanning" gets `btn-danger`
|
||||
- Keep `.cancel-dialog` CSS class pattern from Phase 9
|
||||
|
||||
**TypeScript strictness:**
|
||||
- `override` keyword on lifecycle methods
|
||||
- `import type` for type-only imports
|
||||
- Private event handlers as arrow functions
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /mnt/vault/dev/golang/yellowjacket/frontend && npx tsc --noEmit</automated>
|
||||
</verify>
|
||||
<done>
|
||||
- ScanProgress interface includes libraryId, libraryName, queuedCount
|
||||
- Progress UI shows "Scanning: [Library Name]" and queue count
|
||||
- Cancel dialog shows scope choice when multiple scans queued
|
||||
- CancelCurrentScan/CancelAllScans called instead of CancelScan
|
||||
- Scan All Libraries button exists in scan actions
|
||||
- TypeScript compiles cleanly
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Update library-manager component for per-library scan display</name>
|
||||
<files>
|
||||
frontend/src/components/library-manager/library-manager.ts
|
||||
</files>
|
||||
<action>
|
||||
1. **Update ScanProgress interface** in library-manager.ts to match the new fields: add `libraryId: number`, `libraryName: string`, `queuedCount: number`.
|
||||
|
||||
2. **Update progress rendering** in `renderScanProgress()`:
|
||||
- Show library name: "Scanning: [Library Name]" as the progress label
|
||||
- Show queued count when > 0: "[N] libraries queued" in tertiary text
|
||||
|
||||
3. **Update imports** — add `ScanAllLibraries` import from `@go/library/Library`
|
||||
|
||||
4. **Add "Scan All Libraries" button** to the scan actions section:
|
||||
- Place it alongside existing "Soft Scan" and "Full Rescan" buttons
|
||||
- Style: `btn-primary` class, disabled when scanning
|
||||
- Handler: `private handleScanAll = async (): Promise<void> => { await ScanAllLibraries(); }`
|
||||
- Label: "Scan All Libraries" (or "Scanning..." when active)
|
||||
|
||||
5. **Listen for LibraryScanQueued and LibraryScanQueueDrained events**:
|
||||
- In `connectedCallback`, add event subscriptions
|
||||
- In `disconnectedCallback`, clean up subscriptions
|
||||
- These events update scanning state for the UI
|
||||
|
||||
6. **Update handleScanComplete** to handle per-library scan completion:
|
||||
- The `LibraryScanComplete` event now includes `libraryName` in the metrics
|
||||
- If queue is still draining, don't reset scanning state (wait for `LibraryScanQueueDrained`)
|
||||
- Only fully reset `scanning = false` on `LibraryScanQueueDrained` or when `queuedCount === 0` in the complete event
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /mnt/vault/dev/golang/yellowjacket/frontend && npx tsc --noEmit</automated>
|
||||
</verify>
|
||||
<done>
|
||||
- Library-manager shows library name in scan progress
|
||||
- "Scan All Libraries" button exists and calls ScanAllLibraries
|
||||
- Scan state properly tracks queue draining (doesn't reset early)
|
||||
- TypeScript compiles cleanly
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
```bash
|
||||
# TypeScript compiles
|
||||
cd frontend && npx tsc --noEmit
|
||||
|
||||
# Full project builds (backend + frontend)
|
||||
cd .. && go build ./...
|
||||
```
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Progress bar shows "Scanning: [Library Name] (N/M files)" during scan
|
||||
- Queue count visible when libraries are queued
|
||||
- Cancel modal offers "Cancel This Library" / "Cancel All Scanning" during queued scans
|
||||
- "Scan All Libraries" button exists in both config-page and library-manager
|
||||
- TypeScript compiles cleanly
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/11-per-library-scan-pipeline/11-02-SUMMARY.md`
|
||||
</output>
|
||||
Reference in new issue
Block a user