From c039957aa8721f899680596a875b47e36922af22 Mon Sep 17 00:00:00 2001 From: curtyo18 Date: Sun, 17 May 2026 23:14:13 +0100 Subject: [PATCH] =?UTF-8?q?chore:=20spec=20=C2=A711=20=E2=80=94=20polling?= =?UTF-8?q?=20is=20the=20permanent=20delivery=20mechanism?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 2026-05-17 quality review considered closing spec §11's WebSocket promise by adding SSE browser delivery. Cost/benefit didn't justify ~300-500 lines of new code + reconnect/heartbeat complexity to shave 1.5-3s lag off one screen on a local 127.0.0.1 server. Decision recorded in spec §11: polling stays as the permanent UX delivery mechanism. The architecture summary's "HTTP+WebSocket API" line is updated to "HTTP API". Plan dep list is updated to match. Removes @hono/node-ws from engine runtime deps (was preserved through M9 and N1 PRs awaiting this decision; never imported by any code). EventBus stays — it's engine-internal coordination (scheduler ↔ throttle), not browser delivery. Co-Authored-By: Claude Opus 4.7 --- ...2026-04-25-file-organizer-implementation.md | 1 - .../specs/2026-04-25-file-organizer-design.md | 9 +++++---- package-lock.json | 18 +----------------- packages/engine/package.json | 1 - 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/docs/superpowers/plans/2026-04-25-file-organizer-implementation.md b/docs/superpowers/plans/2026-04-25-file-organizer-implementation.md index bfb8512..81a2e39 100644 --- a/docs/superpowers/plans/2026-04-25-file-organizer-implementation.md +++ b/docs/superpowers/plans/2026-04-25-file-organizer-implementation.md @@ -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", diff --git a/docs/superpowers/specs/2026-04-25-file-organizer-design.md b/docs/superpowers/specs/2026-04-25-file-organizer-design.md index 1ad928d..dec1630 100644 --- a/docs/superpowers/specs/2026-04-25-file-organizer-design.md +++ b/docs/superpowers/specs/2026-04-25-file-organizer-design.md @@ -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:` and opened in the user's default browser. @@ -465,10 +465,11 @@ Local web UI, served by the engine on `127.0.0.1:`, opened in the user's d ## 11. API (Engine ↔ UI) -REST + WebSocket on the same `127.0.0.1:` Hono server. +REST on a `127.0.0.1:` 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. diff --git a/package-lock.json b/package-lock.json index 1898c65..e65d08b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1185,22 +1185,6 @@ "hono": "^4" } }, - "node_modules/@hono/node-ws": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@hono/node-ws/-/node-ws-1.3.0.tgz", - "integrity": "sha512-ju25YbbvLuXdqBCmLZLqnNYu1nbHIQjoyUqA8ApZOeL1k4skuiTcw5SW77/5SUYo2Xi2NVBJoVlfQurnKEp03Q==", - "license": "MIT", - "dependencies": { - "ws": "^8.17.0" - }, - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "@hono/node-server": "^1.19.2", - "hono": "^4.6.0" - } - }, "node_modules/@humanfs/core": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", @@ -7044,6 +7028,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -7111,7 +7096,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", diff --git a/packages/engine/package.json b/packages/engine/package.json index d8b2952..91bf6a7 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -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",