# WorkUtils Unified UI P2 Core Plugin Migration 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:** Migrate MyBatis reverse engineering, MyBatis SQL export, scanner, Git sync, and text diff to the P0 page skeleton and visual tokens without changing business behavior. **Architecture:** Treat every plugin window as a thin view composer. Shared `PageHeader`, semantic CSS classes, `LoadingButtonBinder`, `OperationStatusPane`, `ExportHistoryPane`, and `ResizableLogPane` replace per-window font/style/layout code; application/use-case classes remain unchanged. **Tech Stack:** Java 17, JavaFX 17.0.15, AtlantaFX 2.0.1, P0/P1 shared UI components, JUnit 5, Maven Wrapper. ## Global Constraints - Do not change request DTOs, use cases, generators, scanners, Git operations, diff algorithms, persistence formats, or output files. - Do not add a second page title when the application header already names the active plugin; content uses `PageHeader` only when it adds a useful description. - Remove per-window `Microsoft YaHei`, arbitrary font sizes, background `setStyle(...)`, and duplicated log/status styling from the touched windows. - Use only P0 `AppIcon`/`IconFactory`; no Emoji in visible controls. - Use `LoadingButtonBinder` and `OperationStatusPane` as the only asynchronous visual-state entry points. - Preserve true cancellation semantics: SQL export may cancel; scanner must not show a false cancel control. - Each plugin migration is an independent commit with focused tests and a screenshot comparison. --- ## File Structure ### Create - `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` — source-level guard for inline styles, arbitrary fonts, Emoji, and duplicate loading code. ### Modify - `src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java` - `src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java` - `src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java` - `src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java` - `src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java` - `src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java` - `src/main/java/com/example/workutils/biz/git/GitSyncWindow.java` - `src/main/java/com/example/workutils/biz/diff/DiffWindow.java` - `src/main/resources/css/light-theme.css` ## Task 1: Establish migration guardrails **Files:** - Create: `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` **Interfaces:** - Produces a test helper `source(String relativePath): String`. Start the parameterized contract with the MyBatis generator only; add each remaining path in the task that migrates it so every commit finishes green. - [ ] **Step 1: Write the failing architecture test** ```java private static String source(String relativePath) throws IOException { return Files.readString(Path.of("src/main/java/com/example/workutils", relativePath)); } @ParameterizedTest @ValueSource(strings = { "biz/mybatisgenerator/MyBatisGeneratorWindow.java" }) void corePluginWindowsUseSharedVisualInfrastructure(String relativePath) throws IOException { String source = source(relativePath); assertFalse(source.contains("Font.font(\"Microsoft YaHei\"")); assertFalse(source.contains("-fx-background-color:")); assertFalse(source.contains("new ProgressIndicator(")); assertTrue(source.contains("Theme.") || source.contains("PageHeader")); } ``` - [ ] **Step 2: Run and record expected failures** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest test` Expected: FAIL for the current MyBatis generator hardcoded fonts/backgrounds. Keep the failure output as the first migration checklist. - [ ] **Step 3: Add explicit exclusions for business-rendered content** The test scans only JavaFX window source. It must not scan generated HTML from `ApiDocGenerator` or diff HTML because those outputs have their own presentation contracts. - [ ] **Step 4: Commit the red test with the first migration task only** Do not commit a permanently red standalone changeset. Continue directly to Task 2, make the MyBatis generator case green, and commit the test plus that migration together. ## Task 2: Migrate MyBatis reverse engineering **Files:** - Modify: `src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java` - Modify: `src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java` - Modify: `src/main/resources/css/light-theme.css` - Include: `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` **Interfaces:** - Preserves: `QueryTablesUseCase`, `GenerateArtifactsUseCase`, output planning, directory safety, and both operation controllers. - Consumes: `PageHeader`, tokenized controls, `LoadingButtonBinder`, and font-size-free `OperationStatusPane`. - [ ] **Step 1: Add failing window structure assertions** ```java assertTrue(source.contains("PageHeader")); assertTrue(source.contains("LoadingButtonBinder.bind(queryBtn")); assertTrue(source.contains("LoadingButtonBinder.bind(generateBtn")); assertFalse(source.contains("Theme.heading(fsSection() + 4)")); assertFalse(source.contains("Font.font(\"Consolas\"")); ``` - [ ] **Step 2: Run focused tests and verify failure** Run: `.\mvnw.cmd -q -Dtest=MyBatisGeneratorWindowArchitectureTest,CorePluginVisualArchitectureTest test` Expected: FAIL on old title/font/inline styles. - [ ] **Step 3: Recompose the window** Use a compact data-source context row, two-column split for project tree and table/output form, semantic section headers, and the existing bottom generate action. Replace direct font/style calls with style classes. Keep current divider behavior and all event handlers. - [ ] **Step 4: Normalize the two operation rows** Query progress remains near table matching; generation progress remains with the final action bar. Do not merge the two controllers. Disable only controls that mutate each operation’s request. - [ ] **Step 5: Run all generator tests** Run: `.\mvnw.cmd -q -Dtest=MyBatisGeneratorWindowArchitectureTest,GenerationPlannerTest,GeneratorRequestTest,GeneratorUseCaseTest,OutputLayoutPolicyTest,OutputSnapshotTest,DatasourceSummaryTest test` Expected: PASS. - [ ] **Step 6: Capture and compare** Capture the generator idle state and a controlled query-running state. Verify 20/15/14/13 typography, aligned directory rows, visible output controls, and no bottom clipping at 1024px width. - [ ] **Step 7: Commit** ```powershell git add src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css git commit -m "统一 MyBatis 逆向工程界面" ``` ## Task 3: Migrate MyBatis SQL export and scanner **Files:** - Modify: `src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java` - Modify: `src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java` - Modify: `src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java` - Modify: `src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java` - Modify: `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` **Interfaces:** - Preserves: `SqlExportRequest`, `RunSqlExportUseCase`, `ScanRequest`, `RunScanUseCase`, and history mappings. - Consumes: shared page/form classes and `ResizableLogPane`. - [ ] **Step 1: Add failing cancellation and structure assertions** First extend `@ValueSource` with `MyBatisExportWindow.java` and `ScannerWindow.java`, then add: ```java assertTrue(sqlSource.contains("new OperationStatusPane(exportOperation, true)")); assertTrue(scannerSource.contains("new OperationStatusPane(scanOperation, false)")); assertFalse(scannerSource.contains("停止当前任务")); assertFalse(sqlSource.contains("logArea.setStyle(")); ``` - [ ] **Step 2: Run focused tests and verify failure** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunSqlExportCancellationTest,ScanProgressTest test` Expected: FAIL on old constructors/styles; cancellation domain tests remain green. - [ ] **Step 3: Migrate SQL export** Lay out filter controls as one semantic form row, keep export action/progress together, use `ResizableLogPane` for current-run output, and retain `ExportHistoryPane` below. Keep the real SQL-export cancel control. - [ ] **Step 4: Migrate scanner** Lay out scan type and pattern as a compact configuration section, keep the non-cancellable status pane, and use shared history/log visuals. Do not add a stop button. - [ ] **Step 5: Run focused tests** Run: `.\mvnw.cmd -q -Dtest=SqlExportRequestTest,SqlExportProgressTest,RunSqlExportCancellationTest,MyBatisExportHistoryMappingTest,ScanRequestTest,ScanProgressTest,ScannerHistoryMappingTest,CorePluginVisualArchitectureTest test` Expected: PASS. - [ ] **Step 6: Capture and compare both pages** Use idle/synthetic running states. Confirm SQL export exposes cancel while scanner does not, histories remain usable, and controls do not jump when loading begins. - [ ] **Step 7: Commit** ```powershell git add src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java src/test/java/com/example/workutils/biz/mybatisexport src/test/java/com/example/workutils/biz/scanner src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java git commit -m "统一导出与扫描插件界面" ``` ## Task 4: Migrate Git sync without touching Git behavior **Files:** - Modify: `src/main/java/com/example/workutils/biz/git/GitSyncWindow.java` - Modify: `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` **Interfaces:** - Preserves all tabs, `RunGitSyncUseCase`, `GitSyncRequest`, filters, remote URL presentation, damaged repository actions, and confirmation flow. - Consumes shared tabs, table, form, log, loading, and status styles. - [ ] **Step 1: Add failing Git window assertions** First extend `@ValueSource` with `GitSyncWindow.java`, then add: ```java assertTrue(source.contains("new Tab(\"项目列表\")")); assertTrue(source.contains("new Tab(\"同步执行\")")); assertTrue(source.contains("new Tab(\"损坏仓库处理\")")); assertFalse(source.contains("btn.setStyle(")); assertFalse(source.contains("projectTable.setStyle(")); ``` - [ ] **Step 2: Run tests and verify failure** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunGitSyncUseCaseTest,ProjectFilterTest,RemoteUrlDisplayTest test` Expected: FAIL only on visual architecture assertions. - [ ] **Step 3: Migrate each existing tab in place** Use global tab styles, tokenized toolbar/form spacing, shared table/log styles, and semantic warning button classes. Do not rename or reorder tabs. Preserve destructive confirmation text and never invoke the destructive action during visual verification. - [ ] **Step 4: Run focused tests and capture** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunGitSyncUseCaseTest,ProjectFilterTest,RemoteUrlDisplayTest test` Expected: PASS. Capture all three tabs read-only and verify row height, URL truncation, and warning action hierarchy. - [ ] **Step 5: Commit** ```powershell git add src/main/java/com/example/workutils/biz/git/GitSyncWindow.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css git commit -m "统一 Git 同步插件界面" ``` ## Task 5: Migrate text diff while preserving the renderer **Files:** - Modify: `src/main/java/com/example/workutils/biz/diff/DiffWindow.java` - Modify: `src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java` **Interfaces:** - Preserves: `DiffEngine`, input actions, navigation between differences, copy/save actions, and WebView result rendering. - Consumes shared input, split-pane, action-bar, status, and focus styles. - [ ] **Step 1: Add failing diff visual assertions** First extend `@ValueSource` with `DiffWindow.java`, then add: ```java assertTrue(source.contains("LoadingButtonBinder.bind(compareBtn")); assertFalse(source.contains("\"▶ 开始对比\"")); assertFalse(source.contains("webView.setStyle(")); assertFalse(source.contains("statusLabel.setStyle(")); ``` - [ ] **Step 2: Run and verify failure** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,DiffEngineLineTest,DiffEngineCharacterTest test` Expected: FAIL on Emoji/inline styles; engine tests remain green. - [ ] **Step 3: Migrate the JavaFX chrome only** Replace the play-character button text with visible “开始对比” plus `AppIcon.DIFF`; apply shared split-pane, input, result header, WebView border, and status classes. Do not alter HTML generation or diff algorithms. - [ ] **Step 4: Run tests and capture** Run: `.\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,DiffEngineLineTest,DiffEngineCharacterTest test` Expected: PASS. Capture empty, compared, and difference-navigation states using non-sensitive sample text. - [ ] **Step 5: Commit** ```powershell git add src/main/java/com/example/workutils/biz/diff/DiffWindow.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css git commit -m "统一文本对比插件界面" ``` ## P2 Completion Gate Run: `.\mvnw.cmd -q test` Run: `.\mvnw.cmd -q -DskipTests compile` Run: `git diff --check` Expected: all exit 0. Review the five plugin screenshot sets at 1440px and 1024px before P3. No test or visual check may perform Git synchronization, export files, generation, or scanning against user projects.