Files
laundry-desk/docs/superpowers/plans/2026-04-23-m1-delivery.md
2026-04-23 16:50:24 +08:00

7.8 KiB

M1 Delivery 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: Deliver laundry-desk M1 as a working Electron Windows NSIS app with receive, pickup, order list/detail, customer de-duplication, automatic/manual backup, type/lint/test gates, and CI artifact generation.

Architecture: Keep the approved Electron split: main owns SQLite and services, preload exposes a narrow typed API, renderer uses IPC only. Replace the current prototype DB/bootstrap with focused service modules, explicit Zod IPC schemas, Drizzle relations, and deterministic tests using in-memory SQLite. M2-M4 placeholders are removed or hidden unless needed by M1.

Tech Stack: Electron 41, React 19, TypeScript strict, Vite/electron-vite, better-sqlite3, Drizzle ORM, Zod, Vitest, Tailwind CSS, Playwright, electron-builder NSIS.

Status 2026-04-23: M1 local delivery completed by Codex. Windows x64 NSIS artifact generated at dist/laundry-desk Setup 0.1.0.exe; SHA256 stored next to it. Final gates passed: npm run lint, npm run typecheck, npm test -- --run, npm run test:e2e, npm run build:win, and npm audit --omit=dev --audit-level=high with no high-severity production findings. Remaining audit item is moderate uuid via exceljs / Tencent Cloud SDK; npm's automatic fix is breaking, so it is intentionally not applied for M1.


Task 1: Build And Tooling Baseline

Files:

  • Modify: package.json

  • Modify: tsconfig.node.json

  • Modify: tsconfig.web.json

  • Modify: electron.vite.config.ts

  • Create: eslint.config.js

  • Modify: vitest.config.ts

  • Step 1: Run current failing gates

Run: npm run typecheck, npm run lint, npm test -- --run Expected: failures document the current baseline.

  • Step 2: Fix TypeScript project boundaries

Set rootDir to src or use rootDirs so src/shared compiles for node and web. Keep strict inherited from electron-toolkit.

  • Step 3: Add working ESLint flat config

Use TypeScript parser/config compatible with ESLint 8 and React JSX. Make the lint script run without "config not found".

  • Step 4: Rebuild native dependencies for local Node if needed

Run: npm rebuild better-sqlite3. Expected: Vitest can import better-sqlite3.

  • Step 5: Re-run gates

Run: npm run typecheck, npm run lint, npm test -- --run Expected: tooling errors are resolved or narrowed to real implementation failures.

Task 2: Database And Service Core

Files:

  • Modify: src/main/db/schema.ts

  • Modify: src/main/db/index.ts

  • Create: src/main/db/migrate.ts

  • Create: src/main/db/client.ts

  • Modify: src/main/services/customerService.ts

  • Modify: src/main/services/orderService.ts

  • Modify: src/main/services/pickupCodeService.ts

  • Modify: src/main/services/auditService.ts

  • Modify: tests/unit/services.test.ts

  • Step 1: Write service tests for M1 behavior

Cover customer upsert by phone, order creation transaction, integer cents validation, order number sequencing, pickup code format, pickup search by code/phone/order number, pickup balance settlement, and audit log creation.

  • Step 2: Verify tests fail for missing/incorrect behavior

Run: npm test -- --run tests/unit/services.test.ts Expected: failures for missing search, transaction/audit, validation, or schema gaps.

  • Step 3: Implement DB initialization

Expose a createDbClient(sqlite) helper for tests and getDb() for app runtime. Enable WAL and foreign keys. Run idempotent SQL migrations for all M1 tables and indexes from one source.

  • Step 4: Implement service behavior

Use transactions for create order and pickup. Generate order_no and pickup_code inside the transaction with unique-conflict retry. Recompute totals from item rows, require integer cents, require paidAmount <= totalAmount, and write audit rows through the same transaction.

  • Step 5: Re-run unit tests

Run: npm test -- --run tests/unit/services.test.ts Expected: service tests pass.

Task 3: IPC Contract And Preload API

Files:

  • Modify: src/shared/index.ts

  • Modify: src/shared/schemas.ts

  • Modify: src/preload/index.ts

  • Modify: src/main/ipc/orders.ts

  • Modify: src/main/ipc/customers.ts

  • Modify: src/main/ipc/settings.ts

  • Create: src/main/ipc/backup.ts

  • Modify: src/main/index.ts

  • Step 1: Write IPC schema tests where practical

Cover invalid order id, invalid search query, invalid settings key, and invalid backup action schemas.

  • Step 2: Implement uniform IPC helpers

Every handler returns { ok: true, data } | { ok: false, error }, logs detailed errors in main, and returns user-safe messages.

  • Step 3: Narrow preload exposure

Expose only window.api; remove default window.electron; use typed request/response signatures instead of any.

  • Step 4: Add CSP and production-safe window behavior

Remove debug background, alwaysOnTop, devtools auto-open, and fixed startup delay. Add CSP to renderer HTML.

  • Step 5: Re-run typecheck/lint

Run: npm run typecheck && npm run lint Expected: zero errors.

Task 4: Renderer M1 Flows

Files:

  • Modify: src/renderer/index.html

  • Modify: src/renderer/src/assets/main.css

  • Modify: src/renderer/src/env.d.ts

  • Modify: src/renderer/src/routes/index.tsx

  • Modify: src/renderer/src/components/Layout.tsx

  • Modify: src/renderer/src/routes/Home.tsx

  • Modify: src/renderer/src/routes/Receive.tsx

  • Modify: src/renderer/src/routes/Pickup.tsx

  • Modify: src/renderer/src/routes/Orders.tsx

  • Modify: src/renderer/src/routes/OrderDetail.tsx

  • Modify: src/renderer/src/routes/Customers.tsx

  • Modify: src/renderer/src/routes/Settings.tsx

  • Step 1: Add focused renderer tests if test harness exists, otherwise rely on typecheck and manual/E2E smoke

Validate route imports compile and typed IPC calls are correct.

  • Step 2: Restore usable styling

Either configure Tailwind correctly or replace with a compact CSS utility layer sufficient for the current class usage. Preserve Apple HIG-inspired layout and responsive behavior.

  • Step 3: Complete receive flow

Phone lookup, customer upsert, item rows with cents conversion, partial payment selection, validation messages, success reset, and navigation to order detail.

  • Step 4: Complete pickup flow

Search by pickup code, phone, order number, or customer name; render results; support balance settlement and picked-up transition.

  • Step 5: Complete list/detail/settings M1 routes

Order list pagination basics, order detail with print button hidden/disabled until M3, customers list/search, settings shop name, manual backup, and backup list/restore placeholder only if clearly marked out-of-scope.

Task 5: Backup And Delivery Verification

Files:

  • Modify: src/main/services/backupService.ts

  • Modify: src/main/ipc/backup.ts

  • Modify: tests/unit/services.test.ts

  • Modify: .github/workflows/build.yml

  • Modify: README.md

  • Create: docs/CHANGELOG.md

  • Step 1: Add backup tests

Use a temp directory and a test database. Verify backup zip is created atomically, contains laundry.db, and rotate keeps 30 newest files.

  • Step 2: Implement backup service

Checkpoint WAL, write to temp zip, finalize, rename atomically, rotate after success, and expose manual backup IPC.

  • Step 3: Add CI gates

Run install, typecheck, lint, test, build, and build:win. Upload NSIS artifact and SHA256.

  • Step 4: Run local verification

Run: npm run typecheck, npm run lint, npm test -- --run, npm run build Expected: all pass locally.

  • Step 5: Attempt package verification

On macOS run npm run build:unpack if supported. Final .exe must be generated by GitHub Actions windows-latest.