# Shared Result UI Phase 2 Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Remove duplicated export-history and empty-result UI code from Scanner and MyBatis SQL Export while preserving their behavior. **Architecture:** Add a small immutable adapter model between plugin-specific history rows and a reusable JavaFX history pane. Keep file-opening side effects behind injected callbacks so the shared pane only renders data and emits commands. Add a reusable empty-state component for later plugin migrations. **Tech Stack:** Java 17, JavaFX, JUnit 5, Maven. ## Global Constraints - Work only in `C:\tmp\workutils-plugin-ui-refactor` on branch `codex/plugin-ui-refactor`. - Do not add raw `new Thread`. - Shared UI components must not read files or launch external programs. - Plugin-specific persistence formats must remain unchanged. - Write and observe a failing test before each production behavior. --- ### Task 1: Immutable history presentation model **Files:** - Create: `src/main/java/com/example/workutils/system/ui/history/HistoryItem.java` - Test: `src/test/java/com/example/workutils/system/ui/history/HistoryItemTest.java` **Interfaces:** - Produces: `HistoryItem(String index, String query, String filePath, String count, String timestamp)`. - Produces: `fileDisplay(int maxLength)` for bounded single-line display. - [ ] Write tests proving short paths remain unchanged, long paths are ellipsized while retaining the filename, and constructor values cannot be null. - [ ] Run `.\mvnw.cmd -q -Dtest=HistoryItemTest test` and observe compilation failure because `HistoryItem` is absent. - [ ] Implement the immutable record and its display method. - [ ] Run the focused test and confirm it passes. ### Task 2: Reusable empty state **Files:** - Create: `src/main/java/com/example/workutils/system/ui/EmptyStatePane.java` - Modify: `src/main/resources/css/light-theme.css` - Test: `src/test/java/com/example/workutils/system/ui/EmptyStateContentTest.java` **Interfaces:** - Produces: `EmptyStatePane.Content(String title, String description, String actionLabel)`. - Produces: `EmptyStatePane(Content content, Runnable action, int fontSize)`. - [ ] Write pure content-validation tests proving title is required and a blank action label is allowed only when no action is rendered. - [ ] Run the focused test and observe failure because the component is absent. - [ ] Implement the content model, pane, optional action button, and theme classes. - [ ] Run the focused test and confirm it passes. ### Task 3: Reusable export history pane **Files:** - Create: `src/main/java/com/example/workutils/system/ui/history/HistoryFileCommands.java` - Create: `src/main/java/com/example/workutils/system/ui/history/ExportHistoryPane.java` - Test: `src/test/java/com/example/workutils/system/ui/history/HistoryFileCommandsTest.java` **Interfaces:** - Consumes: `ObservableList`. - Consumes: `HistoryFileCommands` callbacks for open file, open editor, open folder, and copy path. - Produces: `ExportHistoryPane(String countColumnTitle, ObservableList items, HistoryFileCommands commands, int fontSize)`. - [ ] Write tests proving `HistoryFileCommands` rejects missing callbacks and routes each command to the supplied consumer. - [ ] Run the focused test and observe failure because the type is absent. - [ ] Implement callback validation and the shared table, action cell, tooltip, context menu, and empty-state placeholder. - [ ] Run the focused test and confirm it passes. ### Task 4: Migrate Scanner **Files:** - Modify: `src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java` - Test: `src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java` **Interfaces:** - Consumes: `HistoryItem`, `ExportHistoryPane`, `HistoryFileCommands`. - Produces: package-visible `toHistoryItem(HistoryRow row)` for deterministic presentation mapping. - [ ] Write a mapping test for index, query, path, match count, and timestamp. - [ ] Run the focused test and observe failure because the mapping method is absent. - [ ] Replace duplicated table/action-cell construction with `ExportHistoryPane`. - [ ] Run scanner tests and confirm they pass. ### Task 5: Migrate MyBatis SQL Export **Files:** - Modify: `src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java` - Test: `src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java` **Interfaces:** - Consumes: `HistoryItem`, `ExportHistoryPane`, `HistoryFileCommands`. - Produces: package-visible `toHistoryItem(HistoryRow row)`. - [ ] Write a mapping test for index, query, path, export count, and timestamp. - [ ] Run the focused test and observe failure because the mapping method is absent. - [ ] Replace duplicated table/action-cell construction with `ExportHistoryPane`. - [ ] Run export tests and confirm they pass. ### Task 6: Verification **Files:** - Modify only files required by failures found during verification. - [ ] Run `.\mvnw.cmd -q test`. - [ ] Run `.\mvnw.cmd -q -DskipTests compile`. - [ ] Run `git diff --check`. - [ ] Confirm Scanner and MyBatis SQL Export no longer declare `buildActionCell`. - [ ] Inspect both pages without triggering scan, export, file-open, or delete side effects.