Root cause: backend pause updates monitor_jobs table, but frontend
displays status from videos table (via get_files API). These are separate.
Fix:
- ctxPause: manually sets file.status = 'paused' in filesCache + fileStatusCache
- batchPause: same manual cache update for each file
- ctxResume/batchResume: calls loadFiles() to refresh from backend
- Added console.log debug for troubleshooting
- Fixed i18n: removed duplicate emoji from translation strings
- ctxPause and ctxResume now call loadFiles() + loadPausedFiles()
- batchPause and batchResume also reload after completion
- Use new Set() for proper Vue reactivity
- Fixes status badge not updating after pause
- Add pause/resume buttons to file context menu (right-click)
- Add batch pause/resume buttons to section titles
- Support concurrent pause/resume with pLimit(3)
- Add paused status badge (⏸) with warning color
- Integrate with Core API /api/v1/jobs/:uuid/pause|resume
- Track paused files via Redis jobs:paused set
- Add i18n translations (zh-TW, en)
- Add UNREGISTER_TIMEOUT=200000 (200s) for large file unregister
- Add timeout field to buildHttpRequest return type
- httpCall now uses per-request timeout override
- unregister_file now uses asyncMode: true for better UX
- Show "Removing in background..." toast for async mode
Fixes timeout error when unregistering large files (83K faces, 20K nodes).
Problem:
- syncFileStatus() doesn't load pipeline progress data
- Files stuck in 'processing' without percentage display
- pollPipelineProgress() not started when pipeline data missing
Solution:
1. Add loadPipelineStats() call in syncFileStatus() for processing files
2. Start pollPipelineProgress() even when pipeline data is missing
3. Ensure progress bar always has data to display
Impact:
- Progress bar now shows percentage during deep scan
- Files no longer stuck in 'processing' state indefinitely
- Better handling of edge cases when API data is missing
Related: Core team needs to verify get_pipeline_stats API accuracy
Problem:
- Status badge showed 'Scanning'
- Progress bar showed 'Processing...'
- Two different texts displayed simultaneously
Solution:
- Change progress bar text to 'Scanning...'
- Now both badge and progress bar use consistent terminology
Core Principle: Frame is the ONLY standard
Changes:
- VideoPlayer: Remove startTime/endTime props
- VideoPlayer: Add mandatory startFrame/endFrame check
- VideoPlayer: UI shows F123 (51.2s) format
- All Views: Only set startFrame/endFrame
- All Views: Only pass :start-frame/:end-frame
- Remove all startTime/endTime from currentVideo refs
Time is only used for display (auxiliary).
Frame is the source of truth for all positioning.
Core Changes:
- Fix SearchView to use start_frame/end_frame directly (no time*fps conversion)
- Add hard_delete support to delete_trace API
- VideoPlayer: Main timeline + Mark system foundation
- Proxy: Add local routes for auth, media, identity-matches, cluster-results
- Add .gitignore to exclude build artifacts and dependencies
Design Documents:
- Multi-track Mark system design (.opencode/plans/)
- Video editing positioning standards research
Files Modified:
- src/views/SearchView.vue: Frame positioning, ensureMinDuration (240 frames)
- src/views/PeopleView.vue: batchDeleteGroups with hard_delete
- src/api/index.ts: delete_trace with hard_delete body
- src/components/VideoPlayer.vue: Timeline + Mark UI
- src-tauri/src/proxy.rs: New local routes
- AGENTS.md: Update documentation
- Removed Identity checkbox from processor selection in context menu
- Removed trace_chunks from PostgreSQL section (deprecated)
- Added relationship_chunks to PostgreSQL section
- Core API: bind/unbind accept id (integer PK) when face_id is null
- Tauri proxy: stream video responses instead of buffering for seek bar
- VideoPlayer: remove muted attribute, unmute by default
- LibraryView: call invalidateFiles() before ensureFiles() on register/unregister
- PeopleView: close sort panel on click-outside, not just hamburger toggle
- bind_face: prefer face_id, fallback to id when face_id is null