Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,6 @@ Task: M1-T03"
"better-sqlite3": "^12.0.0",
"hono": "^4.6.0",
"@hono/node-server": "^1.13.0",
"@hono/node-ws": "^1.0.0",
"exifr": "^7.1.0",
"sharp": "^0.33.5",
"uuid": "^10.0.0",
Expand Down
9 changes: 5 additions & 4 deletions docs/superpowers/specs/2026-04-25-file-organizer-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ The following are deliberately out of scope for v1 and deferred to later version

Three layers, all running locally on the user's machine:

1. **Engine** — headless Node 22 + TypeScript service. Owns all filesystem access, the catalog, scanning, organizing, and dedup. Exposes a local HTTP+WebSocket API.
1. **Engine** — headless Node 22 + TypeScript service. Owns all filesystem access, the catalog, scanning, organizing, and dedup. Exposes a local HTTP API.
2. **Catalog** — single SQLite database file at a user-chosen location, containing every persisted piece of state.
3. **UI** — TypeScript + Preact static frontend served by the engine on `127.0.0.1:<port>` and opened in the user's default browser.

Expand Down Expand Up @@ -465,10 +465,11 @@ Local web UI, served by the engine on `127.0.0.1:<port>`, opened in the user's d

## 11. API (Engine ↔ UI)

REST + WebSocket on the same `127.0.0.1:<port>` Hono server.
REST on a `127.0.0.1:<port>` Hono server. All endpoints are request/response: rule CRUD, drive CRUD, scan control, plan, approve batch, undo, list duplicates, restore from quarantine, settings, throttle profiles, etc.

- **REST** for request/response: rule CRUD, drive CRUD, scan control, plan, approve batch, undo, list duplicates, restore from quarantine, etc.
- **WebSocket** for live events: scan progress, apply progress, throttle profile changes, drive connect/disconnect, batch status transitions.
**Live-state UX is polling-based**, not event-streamed. The UI runs a 3-second sidebar poll (`app.tsx`'s `reloadGlobal`) plus per-route polling (e.g. `scans.tsx` at ~1.5s while a scan is active) to surface engine state changes. This is the permanent delivery mechanism — no SSE or WebSocket endpoint is planned. `EventBus` exists internally for engine-side coordination (scheduler ↔ throttle, etc.) but does not deliver to the browser.

Decision rationale: the engine is local 127.0.0.1, polling cost is negligible, the 1.5-3s lag only matters in one screen (active scan progress) where it's tolerable, and the engineering cost of SSE/WebSocket reconnect + heartbeat + state-replay logic outweighed the UX benefit. The 2026-05-17 quality review considered adding SSE delivery and rejected it.

Endpoints are hand-written in TS; request/response types live in `shared/`. No OpenAPI generation, no tRPC, no GraphQL. Loopback-only binding. Random unprivileged port chosen at startup; UI reads it from the pointer file. No auth — only access path is loopback on the user's own machine.

Expand Down
18 changes: 1 addition & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"dependencies": {
"@fileorganizer/shared": "*",
"@hono/node-server": "^1.13.0",
"@hono/node-ws": "^1.0.0",
"better-sqlite3": "^12.0.0",
"exifr": "^7.1.0",
"hono": "^4.6.0",
Expand Down
Loading