diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 4db464c..dc2e08c 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -17,15 +17,15 @@ Requirements for initial release. Each maps to roadmap phases. ### Printer Configuration -- [ ] **PRNT-01**: User can set printer display name -- [ ] **PRNT-02**: User can set printer IP address or hostname -- [ ] **PRNT-03**: System auto-suggests port name from IP (user can override) -- [ ] **PRNT-04**: User can set duplex mode (one-sided, long-edge, short-edge) -- [ ] **PRNT-05**: User can set color vs. grayscale default -- [ ] **PRNT-06**: User can set paper size (A4, Letter, Legal at minimum) -- [ ] **PRNT-07**: User can set collate on/off -- [ ] **PRNT-08**: User can assign printer to a client/tenant label -- [ ] **PRNT-09**: Printer configurations are persisted in SQLite across sessions +- [x] **PRNT-01**: User can set printer display name +- [x] **PRNT-02**: User can set printer IP address or hostname +- [x] **PRNT-03**: System auto-suggests port name from IP (user can override) +- [x] **PRNT-04**: User can set duplex mode (one-sided, long-edge, short-edge) +- [x] **PRNT-05**: User can set color vs. grayscale default +- [x] **PRNT-06**: User can set paper size (A4, Letter, Legal at minimum) +- [x] **PRNT-07**: User can set collate on/off +- [x] **PRNT-08**: User can assign printer to a client/tenant label +- [x] **PRNT-09**: Printer configurations are persisted in SQLite across sessions - [ ] **PRNT-10**: User can regenerate a package from saved config without re-uploading drivers ### Script Generation @@ -90,15 +90,15 @@ Which phases cover which requirements. Updated during roadmap creation. | DRV-03 | Phase 2 | Complete | | DRV-04 | Phase 2 | Complete | | DRV-05 | Phase 2 | Complete | -| PRNT-01 | Phase 3 | Pending | -| PRNT-02 | Phase 3 | Pending | -| PRNT-03 | Phase 3 | Pending | -| PRNT-04 | Phase 3 | Pending | -| PRNT-05 | Phase 3 | Pending | -| PRNT-06 | Phase 3 | Pending | -| PRNT-07 | Phase 3 | Pending | -| PRNT-08 | Phase 3 | Pending | -| PRNT-09 | Phase 3 | Pending | +| PRNT-01 | Phase 3 | Complete | +| PRNT-02 | Phase 3 | Complete | +| PRNT-03 | Phase 3 | Complete | +| PRNT-04 | Phase 3 | Complete | +| PRNT-05 | Phase 3 | Complete | +| PRNT-06 | Phase 3 | Complete | +| PRNT-07 | Phase 3 | Complete | +| PRNT-08 | Phase 3 | Complete | +| PRNT-09 | Phase 3 | Complete | | PRNT-10 | Phase 3 | Pending | | SCRPT-01 | Phase 4 | Pending | | SCRPT-02 | Phase 4 | Pending | diff --git a/.planning/STATE.md b/.planning/STATE.md index a38539c..bfc336e 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: executing -stopped_at: Completed 02-02-PLAN.md -last_updated: "2026-04-10T10:06:27.952Z" +stopped_at: Completed 03-01-PLAN.md — awaiting human-verify checkpoint (Task 3) +last_updated: "2026-04-10T10:57:31.851Z" last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite" progress: total_phases: 5 completed_phases: 2 - total_plans: 5 - completed_plans: 5 + total_plans: 7 + completed_plans: 6 percent: 7 --- @@ -53,6 +53,7 @@ Progress: [░░░░░░░░░░] 7% | Phase 01-foundation P01-02 | 3 | 2 tasks | 7 files | | Phase 02 P01 | 3 | 1 tasks | 6 files | | Phase 02-driver-management P02-02 | 3 | 2 tasks | 7 files | +| Phase 03-printer-configuration P01 | 7 | 2 tasks | 12 files | ## Accumulated Context @@ -76,6 +77,9 @@ Recent decisions affecting current work: - [Phase 02-driver-management]: Dynamic DRIVERS_DIR read (import config module not constant) so monkeypatch works in integration tests - [Phase 02-driver-management]: TestClient must use context manager for Starlette 0.46+ lifespan trigger (init_db) - [Phase 02-driver-management]: HTMX errors: return HTMLResponse with driver-list div wrapper so HTMX outerHTML swap works for error states +- [Phase 03-printer-configuration]: Use list(Model.select().where()) in tests instead of Model.get() — Peewee get() cursor caching fails across DB re-inits in same process +- [Phase 03-printer-configuration]: Close test-thread DB connection in conftest.py teardown — thread-local Peewee connections persist across tests and read from stale DB +- [Phase 03-printer-configuration]: Alpine.js portEdited guard prevents port overwrite after manual edit (PRNT-03) ### Pending Todos @@ -88,6 +92,6 @@ None yet. ## Session Continuity -Last session: 2026-04-10T10:03:29.685Z -Stopped at: Completed 02-02-PLAN.md +Last session: 2026-04-10T10:57:31.848Z +Stopped at: Completed 03-01-PLAN.md — awaiting human-verify checkpoint (Task 3) Resume file: None diff --git a/.planning/phases/03-printer-configuration/03-01-SUMMARY.md b/.planning/phases/03-printer-configuration/03-01-SUMMARY.md new file mode 100644 index 0000000..7bc99b6 --- /dev/null +++ b/.planning/phases/03-printer-configuration/03-01-SUMMARY.md @@ -0,0 +1,166 @@ +--- +phase: 03-printer-configuration +plan: "01" +subsystem: api +tags: [fastapi, peewee, htmx, alpinejs, jinja2, sqlite, forms] + +requires: + - phase: 02-driver-management + provides: Driver ORM model, HTMX partial rendering pattern, error response pattern, test fixtures with tmp_data_dir + +provides: + - POST /printers endpoint with form parsing, validation, checkbox-to-bool conversion, FK resolution + - DELETE /printers/{id} endpoint + - POST /clients endpoint with duplicate-name handling + - GET /printers page grouped by client with LEFT OUTER JOIN (no N+1) + - GET /clients page with creation form + - Alpine.js port auto-derivation (IP -> port name, preserves manual edits) + - HTMX-powered form submission with outerHTML swap on #printer-list and #client-list + - Integration test suite covering PRNT-01 through PRNT-09 + +affects: + - 03-02 (next plan in printer configuration phase) + - Any phase using Printer or Client ORM models + - Test isolation pattern now fixed in conftest.py (affects all future test suites) + +tech-stack: + added: [] + patterns: + - "Printer/Client CRUD via FastAPI Form() parameters with sync def handlers" + - "Checkbox boolean convention: 'on'=True, absent/empty=False" + - "Grouped list via defaultdict + LEFT_OUTER JOIN — no N+1 queries" + - "HTMX partial swap: success returns partial, failure returns error div with same id" + - "Alpine.js x-data for reactive port derivation with portEdited guard" + - "Peewee test isolation: conftest.py fixture teardown closes test-thread DB connection" + +key-files: + created: + - imptune/api/printers.py + - imptune/api/clients.py + - imptune/templates/printers.html + - imptune/templates/clients.html + - imptune/templates/partials/printer_form.html + - imptune/templates/partials/printer_list.html + - imptune/templates/partials/client_list.html + - tests/test_printer_crud.py + modified: + - imptune/api/pages.py + - imptune/main.py + - imptune/db/database.py + - tests/conftest.py + +key-decisions: + - "Use list(Printer.select().where(...)) in tests instead of Printer.get() — Peewee's get() uses paginate+cursor caching that fails across DB re-inits in the same process" + - "Close test-thread DB connection in conftest.py fixture teardown — thread-local Peewee connections persist across tests and read from stale DB" + - "Close db in lifespan shutdown — enables clean re-init when TestClient is restarted in the same process" + - "Alpine.js portEdited guard prevents port overwrite after manual edit (PRNT-03 requirement)" + +patterns-established: + - "HTMX error fragment:
{msg}