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,182 @@
|
||||
---
|
||||
phase: 11-per-library-scan-pipeline
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["11-01"]
|
||||
files_modified:
|
||||
- backend/app.go
|
||||
- backend/library/library.go
|
||||
autonomous: true
|
||||
requirements: [LSCAN-01, LSCAN-02]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "App auto-scans all libraries on launch using ScanAllLibraries"
|
||||
- "Legacy LibraryConfigChanged event handler is removed or updated for multi-library"
|
||||
- "Library struct no longer requires Config.DirectoryPath to function"
|
||||
artifacts:
|
||||
- path: "backend/app.go"
|
||||
provides: "Updated OnDomReady or OnStartup to trigger ScanAllLibraries on launch"
|
||||
- path: "backend/library/library.go"
|
||||
provides: "Updated NewLibrary constructor — Config no longer required"
|
||||
key_links:
|
||||
- from: "backend/app.go"
|
||||
to: "backend/library/scan_queue.go"
|
||||
via: "ScanAllLibraries call on startup"
|
||||
pattern: "library\\.ScanAllLibraries"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Wire the per-library scan pipeline into app startup and clean up legacy single-directory scanning paths.
|
||||
|
||||
Purpose: Ensure auto-scan on launch uses `ScanAllLibraries()` (same codepath as the UI button per CONTEXT.md), and remove/update legacy `LibraryConfigChanged` handler that assumed a single directory.
|
||||
Output: Updated app.go startup wiring, cleaned-up Library constructor.
|
||||
</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
|
||||
|
||||
<interfaces>
|
||||
<!-- From Plan 01 -->
|
||||
From backend/library/scan_queue.go (created in Plan 01):
|
||||
```go
|
||||
func (l *Library) ScanLibrary(id int64) error
|
||||
func (l *Library) ScanAllLibraries() error
|
||||
func (l *Library) CancelCurrentScan()
|
||||
func (l *Library) CancelAllScans()
|
||||
```
|
||||
|
||||
From backend/app.go (current):
|
||||
```go
|
||||
func (yj *YellowJacketApp) OnStartup(ctx context.Context)
|
||||
// Currently: yj.library.SetContext(ctx)
|
||||
// Currently: library is created with appConfig.Library (Config with DirectoryPath)
|
||||
|
||||
func NewYellowJacketApp(...) {
|
||||
lib, err := library.NewLibrary(
|
||||
yjApp.appContext,
|
||||
yjApp.logger,
|
||||
yjApp.appConfig.Library, // Config with DirectoryPath
|
||||
yjApp.database,
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
From backend/library/library.go (current event handler):
|
||||
```go
|
||||
func (l *Library) registerEventHandlers() {
|
||||
runtime.EventsOn(l.ctx, events.LibraryConfigChanged, func(data ...any) {
|
||||
// Parses DirectoryPath from event data, calls l.handleConfigUpdate
|
||||
})
|
||||
}
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Wire auto-scan on startup and clean up legacy single-directory code</name>
|
||||
<files>
|
||||
backend/app.go
|
||||
backend/library/library.go
|
||||
</files>
|
||||
<action>
|
||||
1. **Update `NewLibrary` constructor** in `backend/library/library.go`:
|
||||
- Make `*Config` parameter optional/removable. The Library no longer needs a pre-configured DirectoryPath because scan paths come from the database.
|
||||
- Keep the `*Config` parameter for backward compatibility but don't require `DirectoryPath` to be set.
|
||||
- Update validation: if `conf` is nil, create a default config with empty DirectoryPath (already handled).
|
||||
|
||||
2. **Update `registerEventHandlers`** in `backend/library/library.go`:
|
||||
- Remove the `LibraryConfigChanged` event handler entirely. This handler assumed a single-directory model where changing the config triggers a scan. In the multi-library model:
|
||||
- Libraries are added/removed through the library CRUD API (Phase 12)
|
||||
- Scanning is triggered explicitly via `ScanLibrary()` or `ScanAllLibraries()`
|
||||
- The `LibraryConfigChanged` event and `handleConfigUpdate` method can be deleted or marked deprecated
|
||||
- Delete `handleConfigUpdate` method
|
||||
- Delete `errLibraryDirNotConfigured` sentinel error (no longer needed)
|
||||
|
||||
3. **Update `NewYellowJacketApp` in `backend/app.go`**:
|
||||
- Change the `library.NewLibrary(...)` call. The Config parameter is less important now since DirectoryPath is ignored. Pass `yjApp.appConfig.Library` as before (it still has ScanConcurrency which is useful as a default).
|
||||
|
||||
4. **Add auto-scan on startup** in `backend/app.go`:
|
||||
- In `OnDomReady` (or via a goroutine started in `OnStartup` that waits for DOM ready), trigger auto-scan.
|
||||
- Best approach: In `OnDomReady`, after the startup error check, launch a goroutine:
|
||||
```go
|
||||
go func() {
|
||||
if err := yj.library.ScanAllLibraries(); err != nil {
|
||||
yj.logger.Error("auto-scan failed", "err", err)
|
||||
}
|
||||
}()
|
||||
```
|
||||
- This uses the same `ScanAllLibraries()` codepath as the UI button (per CONTEXT.md: "Auto-scan on launch should use the same ScanAllLibraries() codepath as the UI button — single implementation").
|
||||
- It runs in a goroutine so it doesn't block the DOM ready callback.
|
||||
- Only run if there are libraries in the DB: check `l.db.Queries.CountLibraries(l.ctx)` first (or let ScanAllLibraries handle the empty case gracefully by returning immediately when GetAllLibraries returns an empty slice).
|
||||
|
||||
5. **Clean up legacy `Scan()` method**:
|
||||
- In Plan 01, the old `Scan()` was kept as backward-compatible wrapper. Now review: since we're removing `handleConfigUpdate` which was the only caller of the legacy `Scan()` via `l.handleConfigUpdate → l.Scan()`, we can either:
|
||||
- Keep `Scan()` for tests (it's used in `scan_test.go`)
|
||||
- Update it to call `scanInternal` with the library from `l.conf.DirectoryPath` if set, or return early if not set
|
||||
- Keep `FullRescan()` — it's still called from the config-page UI. It should work with the first/default library. Update it to look up the default library from DB rather than using `l.conf.DirectoryPath`.
|
||||
|
||||
6. **Update `FullRescan()`** in `backend/library/rescan.go`:
|
||||
- Instead of using `l.conf.DirectoryPath`, look up the first library from DB: `libs, err := l.db.Queries.GetAllLibraries(l.ctx)` and use `libs[0]`.
|
||||
- If no libraries exist, return an error.
|
||||
- Call `scanInternal(lib.ID, lib.Name, lib.Path)` instead of `l.Scan()`.
|
||||
- Per-library FullRescan will be added in Phase 12 — for now this rescans the first/only library.
|
||||
|
||||
**Linting requirements:**
|
||||
- Doc comments ending with period
|
||||
- Blank line after early returns
|
||||
- Lines under 100 chars
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /mnt/vault/dev/golang/yellowjacket && go build ./... && go vet ./backend/... && go test ./backend/library/... -count=1 -timeout 60s</automated>
|
||||
</verify>
|
||||
<done>
|
||||
- Auto-scan on startup calls ScanAllLibraries (same codepath as UI button)
|
||||
- Legacy LibraryConfigChanged handler removed
|
||||
- Legacy handleConfigUpdate removed
|
||||
- FullRescan uses library from DB instead of config DirectoryPath
|
||||
- go build passes, go vet passes, existing tests pass
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
```bash
|
||||
# Full build
|
||||
go build ./...
|
||||
|
||||
# Vet
|
||||
go vet ./backend/...
|
||||
|
||||
# Tests pass (including scan_test.go)
|
||||
go test ./backend/library/... -count=1 -timeout 60s
|
||||
|
||||
# No references to removed handler
|
||||
grep -rn "LibraryConfigChanged" backend/library/ | grep -v "_test.go"
|
||||
# Should return no hits (only events.go constant definition, not handler registration)
|
||||
```
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- App auto-scans all libraries on launch via ScanAllLibraries
|
||||
- LibraryConfigChanged handler removed from library package
|
||||
- handleConfigUpdate removed
|
||||
- FullRescan works with DB-sourced library (not config DirectoryPath)
|
||||
- All tests pass, build passes
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/11-per-library-scan-pipeline/11-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in new issue
Block a user