diff --git a/docs/superpowers/specs/2026-06-06-phase-10-polish-design.md b/docs/superpowers/specs/2026-06-06-phase-10-polish-design.md new file mode 100644 index 0000000..f709c30 --- /dev/null +++ b/docs/superpowers/specs/2026-06-06-phase-10-polish-design.md @@ -0,0 +1,340 @@ +# Phase 10 — Polish + Delete Legacy Design + +> Companion to the parent plan: `docs/superpowers/plans/2026-06-05-react-ui-redesign.md` (Phase 10 is sketched at high level; this spec locks architecture, file map, deletion targets, and version strategy.) + +**Date:** 2026-06-06 +**Phase:** 10 of 10 (React + shadcn/ui UI redesign) — **FINAL** +**Tag (on completion):** `v5.0.0` (the first release tag, all prior phases were `phase-N-*` working tags) + +--- + +## 1. Goal & Non-Goals + +**Goal:** Finalize the React UI redesign. Decompose the legacy 146KB `src/main.js` into a feature-first modular structure under `src/main/`, remove the legacy vanilla-JS renderer and all dead IPC bridges, then ship **v5.0.0** with a CHANGELOG. + +**Non-goals (Phase 10):** +- Adding new features (Phases 1-9 shipped all of them) +- A full main-process test suite (the existing main process is largely untested; adding tests is Phase 11+) +- Backwards compat shims for the legacy renderer +- Renderer-side refactor (already done) +- Migrating the renderer build pipeline further (vite configs are in place) + +**Success criteria:** +- `src/main.js` is gone; `src/main/index.js` is the new entrypoint +- `package.json#main` points to `src/main/index.js` +- All 12 legacy renderer files are deleted +- All 9 dead IPC channels are removed from `preload.js` and `main.js` +- `src/index.html` is reduced to ~50 lines (just the Vite bootstrap) +- `package.json#version` is `5.0.0` +- `CHANGELOG.md` exists in Keep a Changelog 1.1.0 format +- `git grep -E "renderer\.js|command-palette|print-preview|welcome\.js|zen-mode|wordTemplate|ascii-generator|table-generator|styles\.css"` returns zero results +- All 305 tests still pass +- `npx vite build --config vite.renderer.config.ts` succeeds +- `npx electron .` launches and main window renders +- Tag `v5.0.0` pushed to origin + +--- + +## 2. Target Architecture + +### 2.1 `src/main/` (feature-first decomposition) + +``` +src/main/ +├── index.js # entrypoint: bootstraps store, app, window, ipc +├── store.js # electron-store wrapper (preferences + wordTemplatePath) +├── ipc.js # ipcMain.handle registration (composes from modules) +├── files/ +│ ├── index.js # file ops facade (read/write/list/pickFolder/pickFile) +│ ├── search.js # recursive regex search (used by find-in-files) +│ ├── git.js # git status porcelain parser +│ └── binary.js # writeBuffer helper (Uint8Array → file) +├── menu/ +│ ├── index.js # buildMenu() — composes the app menu +│ └── items.js # individual menu items (File, Edit, View, etc.) +├── window/ +│ ├── index.js # createMainWindow ONLY (createAsciiWindow/createTableWindow are DEAD) +│ └── state.js # window state persistence +├── word-template/ +│ ├── index.js # WordTemplateExporter facade +│ ├── parser.js # .dotx parsing +│ ├── converter.js # markdown → docx +│ └── apply.js # apply template styles to converted docx +└── utils/ + ├── paths.js # path helpers + ├── logger.js # structured logging + └── download.js # tool downloader +``` + +**Module rules:** +- Each file has one clear responsibility (no god files; CLAUDE.md says >300 lines is the cap) +- `index.js` is the public face of a folder; deeper files are private +- `src/main/index.js` (top-level) wires everything together +- Cross-folder imports go through `index.js`, not directly to internals + +### 2.2 Entry point change + +**Before:** +```json +// package.json +"main": "src/main.js" +``` + +**After:** +```json +// package.json +"main": "src/main/index.js" +``` + +The new `src/main/index.js` runs the same `app.whenReady().then(...)` flow that the current `src/main.js` does, but composes the decomposed modules. + +### 2.3 What becomes dead code (removed during decomposition) + +When the legacy renderer files are deleted, these main-process functions become orphaned and are removed too: + +| Function | File | Why dead | +|---|---|---| +| `createAsciiWindow()` | `src/main/window/index.js` | Loads deleted `src/ascii-generator.html` | +| `createTableWindow()` | `src/main/window/index.js` | Loads deleted `src/table-generator.html` | +| `ipcMain.on('open-ascii-generator', ...)` | `src/main/index.js` (after decomposition) | Replaced by React `` | +| `ipcMain.on('open-table-generator', ...)` | `src/main/index.js` (after decomposition) | Replaced by React `` | +| `webContents.send('print-preview')` | `src/main/menu/items.js` | Replaced by React `` | +| `webContents.send('print-preview-styled')` | `src/main/menu/items.js` | Replaced by React `` | +| `webContents.send('toggle-command-palette')` | `src/main/menu/items.js` | Replaced by `useCommandStore` | +| `require('./wordTemplateExporter')` | `src/main/index.js` (after decomposition) | Replaced by `src/main/word-template/` + renderer-side `lib/docx-export.ts` | + +--- + +## 3. Legacy Deletion Map + +### 3.1 Files to delete from `src/` (12 files, ~14,426 lines) + +| File | Size | Lines | Replaced by | +|---|---|---|---| +| `src/renderer.js` | 213KB | 5319 | `src/renderer/` (Phases 1-9) | +| `src/styles.css` | 74KB | 3723 | `src/renderer/index.css` + Tailwind | +| `src/styles-modern.css` | 71KB | 2625 | Tailwind + shadcn/ui | +| `src/styles-concreteinfo.css` | 21KB | 969 | Tailwind theme tokens | +| `src/styles-sidebar.css` | 9.7KB | 304 | `` component | +| `src/styles-zen.css` | 2.1KB | 102 | Zen mode in AppShell | +| `src/styles-welcome.css` | 2.2KB | 24 | Welcome dialog | +| `src/fonts.css` | 1.8KB | (imported elsewhere) | Tailwind font config | +| `src/command-palette.js` | (small) | 109 | `useCommandStore` | +| `src/print-preview.js` | (small) | 138 | `` | +| `src/welcome.js` | (small) | 78 | `` modal | +| `src/zen-mode.js` | (small) | 292 | `use-zen-mode` hook + AppShell | +| `src/wordTemplateExporter.js` | (small) | 743 | `src/main/word-template/` + renderer `lib/docx-export.ts` | +| `src/ascii-generator.html` | 34KB | (HTML) | `` | +| `src/table-generator.html` | 18KB | (HTML) | `` | + +**Total: 12 JS/CSS/HTML files = 14,426 lines / ~445KB** + +Note: `src/index.html` is **NOT** deleted — it's rewritten to a minimal Vite bootstrap (~50 lines). See §4. + +### 3.2 Dead IPC channels to remove from `src/preload.js` + +- `toggle-command-palette` (line 238) +- `open-ascii-generator` (line 89) +- `open-table-generator` (line 92) +- `print-preview` (line 173) +- `print-preview-styled` (line 174) +- `show-table-generator` (line 180) +- `show-ascii-generator-window` (line 217) +- `show-ascii-generator` (line 218) +- `show-table-generator-window` (line 221) + +And from the exposed API surface: +- `openAscii: () => ipcRenderer.send('open-ascii-generator')` (line 445) +- `openTable: () => ipcRenderer.send('open-table-generator')` (line 446) + +**9 channel names + 2 API entries to remove.** + +### 3.3 Legacy references in `src/index.html` (16 places) + +- `` (line ~6) +- `` (line ~7) +- `