docs(01-01): complete backend scaffold plan — SUMMARY, STATE, ROADMAP, REQUIREMENTS updated
- Created 01-01-SUMMARY.md with full accomplishment record - STATE.md: advanced to plan 2/3, progress 33%, added 3 key decisions - ROADMAP.md: Phase 1 updated to 1/3 summaries (In Progress) - REQUIREMENTS.md: marked INF-01, INF-02, DEV-01, DEV-02, SHW-01, SHW-02 complete
This commit is contained in:
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
### Device Registry
|
### Device Registry
|
||||||
|
|
||||||
- [ ] **DEV-01**: Register a device with: name, strip type (SK6812 / WS2801 / generic), LED count, target IP, target port
|
- [x] **DEV-01**: Register a device with: name, strip type (SK6812 / WS2801 / generic), LED count, target IP, target port
|
||||||
- [ ] **DEV-02**: Devices persist across sessions (stored in config file)
|
- [x] **DEV-02**: Devices persist across sessions (stored in config file)
|
||||||
- [ ] **DEV-03**: Device list shown in UI — enable/disable per show
|
- [ ] **DEV-03**: Device list shown in UI — enable/disable per show
|
||||||
|
|
||||||
### Animation Library
|
### Animation Library
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
|
|
||||||
### Show Engine
|
### Show Engine
|
||||||
|
|
||||||
- [ ] **SHW-01**: Show files saved and loaded as JSON (schema_version field required in v1)
|
- [x] **SHW-01**: Show files saved and loaded as JSON (schema_version field required in v1)
|
||||||
- [ ] **SHW-02**: Show file includes: audio path/URL, device registry snapshot, all animation blocks with timestamps, beat analysis data
|
- [x] **SHW-02**: Show file includes: audio path/URL, device registry snapshot, all animation blocks with timestamps, beat analysis data
|
||||||
- [ ] **SHW-03**: Live show execution — follow MPV position, dispatch animation commands to devices via UDP at correct timestamps
|
- [ ] **SHW-03**: Live show execution — follow MPV position, dispatch animation commands to devices via UDP at correct timestamps
|
||||||
|
|
||||||
### UDP Communication
|
### UDP Communication
|
||||||
@@ -67,8 +67,8 @@
|
|||||||
|
|
||||||
### Infrastructure
|
### Infrastructure
|
||||||
|
|
||||||
- [ ] **INF-01**: Python 3.11 backend (FastAPI + uvicorn)
|
- [x] **INF-01**: Python 3.11 backend (FastAPI + uvicorn)
|
||||||
- [ ] **INF-02**: Modular device abstraction — adding a new strip type requires only a new device class, no changes to core engine
|
- [x] **INF-02**: Modular device abstraction — adding a new strip type requires only a new device class, no changes to core engine
|
||||||
- [ ] **INF-03**: Windows 11 timer resolution fix applied at startup (`timeBeginPeriod(1)` via ctypes)
|
- [ ] **INF-03**: Windows 11 timer resolution fix applied at startup (`timeBeginPeriod(1)` via ctypes)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Decimal phases appear between their surrounding integers in numeric order.
|
|||||||
**Plans**: 3 plans
|
**Plans**: 3 plans
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 01-01: Backend scaffold — FastAPI app, Pydantic show/device models, show store (JSON load/save), device registry
|
- [x] 01-01: Backend scaffold — FastAPI app, Pydantic show/device models, show store (JSON load/save), device registry
|
||||||
- [ ] 01-02: Frontend shell — HTML/CSS terminal aesthetic, WebSocket client stub, device panel, show panel
|
- [ ] 01-02: Frontend shell — HTML/CSS terminal aesthetic, WebSocket client stub, device panel, show panel
|
||||||
- [ ] 01-03: REST API — CRUD endpoints for devices and shows, static file serving, integration smoke test
|
- [ ] 01-03: REST API — CRUD endpoints for devices and shows, static file serving, integration smoke test
|
||||||
**UI hint**: yes
|
**UI hint**: yes
|
||||||
@@ -151,7 +151,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
|
|||||||
|
|
||||||
| Phase | Plans Complete | Status | Completed |
|
| Phase | Plans Complete | Status | Completed |
|
||||||
|-------|----------------|--------|-----------|
|
|-------|----------------|--------|-----------|
|
||||||
| 1. Foundation | 0/3 | Not started | - |
|
| 1. Foundation | 1/3 | In Progress| |
|
||||||
| 2. Audio Engine | 0/3 | Not started | - |
|
| 2. Audio Engine | 0/3 | Not started | - |
|
||||||
| 3. Communication Protocol | 0/3 | Not started | - |
|
| 3. Communication Protocol | 0/3 | Not started | - |
|
||||||
| 4. Timeline Editor | 0/4 | Not started | - |
|
| 4. Timeline Editor | 0/4 | Not started | - |
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
---
|
||||||
|
gsd_state_version: 1.0
|
||||||
|
milestone: v1.0
|
||||||
|
milestone_name: milestone
|
||||||
|
status: executing
|
||||||
|
stopped_at: Completed 01-foundation/01-01-PLAN.md
|
||||||
|
last_updated: "2026-04-05T18:49:18.330Z"
|
||||||
|
last_activity: 2026-04-05
|
||||||
|
progress:
|
||||||
|
total_phases: 7
|
||||||
|
completed_phases: 0
|
||||||
|
total_plans: 3
|
||||||
|
completed_plans: 1
|
||||||
|
percent: 0
|
||||||
|
---
|
||||||
|
|
||||||
# Project State
|
# Project State
|
||||||
|
|
||||||
## Project Reference
|
## Project Reference
|
||||||
@@ -5,20 +21,21 @@
|
|||||||
See: .planning/PROJECT.md (updated 2026-04-05)
|
See: .planning/PROJECT.md (updated 2026-04-05)
|
||||||
|
|
||||||
**Core value:** Load a song, build a synchronized light show, play it back live — with precise control over every effect on every device.
|
**Core value:** Load a song, build a synchronized light show, play it back live — with precise control over every effect on every device.
|
||||||
**Current focus:** Phase 1 — Foundation
|
**Current focus:** Phase 01 — foundation
|
||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 1 of 7 (Foundation)
|
Phase: 01 (foundation) — EXECUTING
|
||||||
Plan: 0 of 3 in current phase
|
Plan: 2 of 3
|
||||||
Status: Ready to plan
|
Status: Ready to execute
|
||||||
Last activity: 2026-04-05 — Roadmap and state initialized
|
Last activity: 2026-04-05
|
||||||
|
|
||||||
Progress: [░░░░░░░░░░] 0%
|
Progress: [░░░░░░░░░░] 0%
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
|
|
||||||
- Total plans completed: 0
|
- Total plans completed: 0
|
||||||
- Average duration: —
|
- Average duration: —
|
||||||
- Total execution time: 0 hours
|
- Total execution time: 0 hours
|
||||||
@@ -30,10 +47,12 @@ Progress: [░░░░░░░░░░] 0%
|
|||||||
| - | - | - | - |
|
| - | - | - | - |
|
||||||
|
|
||||||
**Recent Trend:**
|
**Recent Trend:**
|
||||||
|
|
||||||
- Last 5 plans: —
|
- Last 5 plans: —
|
||||||
- Trend: —
|
- Trend: —
|
||||||
|
|
||||||
*Updated after each plan completion*
|
*Updated after each plan completion*
|
||||||
|
| Phase 01-foundation P01 | 4 | 2 tasks | 23 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -46,6 +65,9 @@ Recent decisions affecting current work:
|
|||||||
- Init: python-mpv-jsonipc preferred over ctypes binding — no libmpv.dll dependency on Windows
|
- Init: python-mpv-jsonipc preferred over ctypes binding — no libmpv.dll dependency on Windows
|
||||||
- Init: Firmware deferred to Phase 7 — protocol must be validated against simulator first
|
- Init: Firmware deferred to Phase 7 — protocol must be validated against simulator first
|
||||||
- Init: undo/redo built in Phase 4 — retrofitting command pattern is expensive
|
- Init: undo/redo built in Phase 4 — retrofitting command pattern is expensive
|
||||||
|
- [Phase 01-foundation]: Module-level state in main.py for registry/show_store — acceptable for Phase 1, Phase 2 migrates to Depends()
|
||||||
|
- [Phase 01-foundation]: StaticFiles mounted last in create_app() — prevents catch-all interception of /api/* routes
|
||||||
|
- [Phase 01-foundation]: encode_animation_cmd stubs return b'' — Phase 3 implements real UDP animation command encoding
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -59,8 +81,8 @@ None yet.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-05
|
Last session: 2026-04-05T18:49:18.325Z
|
||||||
Stopped at: Roadmap created, STATE.md initialized
|
Stopped at: Completed 01-foundation/01-01-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|
||||||
Next action: `/gsd:plan-phase 1`
|
Next action: `/gsd:plan-phase 1`
|
||||||
|
|||||||
177
.planning/phases/01-foundation/01-01-SUMMARY.md
Normal file
177
.planning/phases/01-foundation/01-01-SUMMARY.md
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
---
|
||||||
|
phase: 01-foundation
|
||||||
|
plan: 01
|
||||||
|
subsystem: backend
|
||||||
|
tags: [python, fastapi, pydantic, uvicorn, websocket, nginx, terminal-ui]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires: []
|
||||||
|
provides:
|
||||||
|
- "Python package lightsync/ with all backend modules"
|
||||||
|
- "Pydantic v2 DeviceConfig and ShowModel with full schema"
|
||||||
|
- "BaseDevice ABC + SK6812/WS2801 concrete implementations"
|
||||||
|
- "DeviceRegistry with JSON persistence (devices.json)"
|
||||||
|
- "ShowStore with JSON save/load (shows/ directory)"
|
||||||
|
- "FastAPI app with lifespan, REST stubs, WebSocket stub"
|
||||||
|
- "Terminal-aesthetic frontend shell (DAW skeleton)"
|
||||||
|
- "python -m lightsync entry point serving on port 8000"
|
||||||
|
affects: [phase-01-02, phase-02, phase-03, phase-04, phase-05, phase-06, phase-07]
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added:
|
||||||
|
- "FastAPI 0.115+ — web framework, REST, WebSocket, StaticFiles"
|
||||||
|
- "uvicorn[standard] 0.34+ — ASGI server with WebSocket support"
|
||||||
|
- "Pydantic v2 — model validation and JSON serialization"
|
||||||
|
- "aiofiles 24+ — async file I/O for show JSON and device registry"
|
||||||
|
- "python-dotenv — HOST/PORT config from .env file"
|
||||||
|
- "structlog — structured logging"
|
||||||
|
- "hatchling — build backend for pyproject.toml"
|
||||||
|
patterns:
|
||||||
|
- "lifespan context manager for startup/shutdown (replaces deprecated @app.on_event)"
|
||||||
|
- "Module-level registry/show_store refs in main.py — accessed via `import lightsync.main as state`"
|
||||||
|
- "StaticFiles LAST — API routes registered before mount to prevent catch-all interception"
|
||||||
|
- "Pydantic v2 APIs: model_dump_json(), model_validate_json(), model_validate() — never v1 .json()/.parse_obj()"
|
||||||
|
- "BaseDevice ABC + _DEVICE_CLASSES dict — adding new strip type = new file + one dict entry (INF-02)"
|
||||||
|
- "pathlib.Path throughout — cross-platform safe file paths"
|
||||||
|
- "aiofiles for all file I/O in async contexts — non-blocking"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- pyproject.toml
|
||||||
|
- .env
|
||||||
|
- .gitignore
|
||||||
|
- lightsync/__init__.py
|
||||||
|
- lightsync/__main__.py
|
||||||
|
- lightsync/main.py
|
||||||
|
- lightsync/models/__init__.py
|
||||||
|
- lightsync/models/device.py
|
||||||
|
- lightsync/models/show.py
|
||||||
|
- lightsync/devices/__init__.py
|
||||||
|
- lightsync/devices/base.py
|
||||||
|
- lightsync/devices/sk6812.py
|
||||||
|
- lightsync/devices/ws2801.py
|
||||||
|
- lightsync/devices/registry.py
|
||||||
|
- lightsync/store/__init__.py
|
||||||
|
- lightsync/store/show_store.py
|
||||||
|
- lightsync/api/__init__.py
|
||||||
|
- lightsync/api/devices.py
|
||||||
|
- lightsync/api/shows.py
|
||||||
|
- lightsync/api/ws.py
|
||||||
|
- lightsync/frontend/index.html
|
||||||
|
- lightsync/frontend/style.css
|
||||||
|
- lightsync/frontend/app.js
|
||||||
|
modified: []
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "aiofiles for all JSON file I/O — keeps async handlers non-blocking per research guidance"
|
||||||
|
- "Module-level state in main.py for registry/show_store — acceptable for Phase 1, Phase 2 migrates to Depends()"
|
||||||
|
- "StaticFiles mounted last — required to prevent catch-all interception of /api/* routes"
|
||||||
|
- "encode_animation_cmd stubs return b'' — Phase 3 implements real UDP animation command encoding"
|
||||||
|
- ".gitignore excludes devices.json and shows/ — these are runtime data, not source"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "lifespan context manager for app startup/shutdown"
|
||||||
|
- "BaseDevice ABC + _DEVICE_CLASSES registry dict for extensible device type system"
|
||||||
|
- "Pydantic v2 serialization patterns (model_dump_json, model_validate_json)"
|
||||||
|
- "aiofiles for async file I/O in FastAPI route handlers"
|
||||||
|
- "CSS custom properties for terminal aesthetic — all colors via :root vars"
|
||||||
|
|
||||||
|
requirements-completed:
|
||||||
|
- INF-01
|
||||||
|
- INF-02
|
||||||
|
- DEV-01
|
||||||
|
- DEV-02
|
||||||
|
- SHW-01
|
||||||
|
- SHW-02
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 4min
|
||||||
|
completed: 2026-04-05
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 1 Plan 01: Backend Scaffold Summary
|
||||||
|
|
||||||
|
**FastAPI backend scaffold with Pydantic v2 models, device ABC, JSON persistence stores, REST+WebSocket stubs, and terminal-aesthetic DAW skeleton frontend — all runnable via `python -m lightsync`**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** ~4 min
|
||||||
|
- **Started:** 2026-04-05T18:43:46Z
|
||||||
|
- **Completed:** 2026-04-05T18:48:03Z
|
||||||
|
- **Tasks:** 2 (both auto)
|
||||||
|
- **Files created:** 23
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
### Task 1: Package structure, Pydantic models, device abstractions (commit: 061edfc)
|
||||||
|
|
||||||
|
- `pyproject.toml` with all Phase 1 dependencies (FastAPI, uvicorn, Pydantic v2, aiofiles, structlog)
|
||||||
|
- `lightsync/models/device.py` — `DeviceConfig` Pydantic model with `StripType` literal, UUID auto-ID, validation constraints
|
||||||
|
- `lightsync/models/show.py` — `ShowModel` with `schema_version=1`, `AudioRef`, `TrackModel`, `CueModel`, `AnalysisBlock`
|
||||||
|
- `lightsync/devices/base.py` — `BaseDevice` ABC with `encode_frame`, `encode_animation_cmd`, `bytes_per_pixel`
|
||||||
|
- `lightsync/devices/sk6812.py` — SK6812 RGBW (4 bytes/pixel), encode_frame builds RGBW bytearray
|
||||||
|
- `lightsync/devices/ws2801.py` — WS2801 RGB (3 bytes/pixel), encode_frame builds RGB bytearray
|
||||||
|
|
||||||
|
### Task 2: Registry, show store, FastAPI app, frontend shell (commit: 5e10272)
|
||||||
|
|
||||||
|
- `lightsync/devices/registry.py` — `DeviceRegistry` with `_DEVICE_CLASSES` dict, load/save (aiofiles), add/remove/get/list_all/instantiate
|
||||||
|
- `lightsync/store/show_store.py` — `ShowStore` with async save/load, `list_ids()` via glob
|
||||||
|
- `lightsync/main.py` — `create_app()` with lifespan hook, API routes registered before `StaticFiles` mount
|
||||||
|
- `lightsync/api/devices.py` — `GET /`, `POST /`, `DELETE /{id}` — full CRUD with save-on-write
|
||||||
|
- `lightsync/api/shows.py` — `GET /`, `POST /`, `GET /{id}` — create and retrieve shows
|
||||||
|
- `lightsync/api/ws.py` — `ConnectionManager` + `/ws` WebSocket endpoint with ack echo
|
||||||
|
- `lightsync/frontend/index.html` — DAW skeleton: header, sidebar (DEVICES + ANIMATIONS), TIMELINE main area, TRANSPORT footer
|
||||||
|
- `lightsync/frontend/style.css` — Terminal aesthetic: `#0a0a0a` bg, `#00ffff` cyan accent, `border-radius: 0` everywhere, CSS Grid layout
|
||||||
|
- `lightsync/frontend/app.js` — `LightSyncClient` WS with reconnect, `loadDevices()` populating device list
|
||||||
|
- `.gitignore` — excludes runtime data (`devices.json`, `shows/`), `.venv/`, `__pycache__/`
|
||||||
|
|
||||||
|
## Verification Results
|
||||||
|
|
||||||
|
All verification checks passed:
|
||||||
|
- `pip install -e ".[dev]"` — installs successfully
|
||||||
|
- `python -c "from lightsync.models.show import ShowModel; s = ShowModel(name='test'); assert s.schema_version == 1"` — passes
|
||||||
|
- `python -c "from lightsync.devices.registry import DeviceRegistry; print('OK')"` — passes
|
||||||
|
- `python -m lightsync` — starts server on port 8000, serves `GET /api/devices/` → 200 `[]`
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
| Task | Commit | Description |
|
||||||
|
|------|--------|-------------|
|
||||||
|
| 1 | 061edfc | Package structure, Pydantic models, device abstractions |
|
||||||
|
| 2 | 5e10272 | Registry, show store, FastAPI app, frontend shell |
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Module-level `registry` and `show_store` refs in `main.py` — acceptable for Phase 1 single-process server; Phase 2 should migrate to `Depends()` for testability
|
||||||
|
- `encode_animation_cmd` stubs in SK6812/WS2801 return `b""` — Phase 3 implements real UDP frame encoding
|
||||||
|
- Google Fonts (JetBrains Mono) loaded from CDN — offline fallback to Consolas via CSS custom property chain
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None — plan executed exactly as written.
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
These are intentional per-plan stubs, documented in the plan spec:
|
||||||
|
|
||||||
|
| Stub | File | Line | Reason |
|
||||||
|
|------|------|------|--------|
|
||||||
|
| `encode_animation_cmd` returns `b""` | lightsync/devices/sk6812.py | 28 | Phase 3 implements real UDP animation command encoding |
|
||||||
|
| `encode_animation_cmd` returns `b""` | lightsync/devices/ws2801.py | 26 | Phase 3 implements real UDP animation command encoding |
|
||||||
|
| ANIMATIONS panel placeholder | lightsync/frontend/index.html | — | Phase 3+ per design decision D-08 |
|
||||||
|
| TIMELINE panel placeholder | lightsync/frontend/index.html | — | Phase 2+ per design decision D-09 |
|
||||||
|
| TRANSPORT bar placeholder | lightsync/frontend/index.html | — | Phase 2+ per design decision D-10 |
|
||||||
|
|
||||||
|
All stubs are DAW skeleton placeholders (per D-06 decision: full panel layout from day 1) or device encoding stubs for UDP (Phase 3). They do not prevent the plan's goal from being achieved — the backend scaffold, persistence, and server entry point are fully functional.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Ready for 01-02: frontend UI details and static file serving verification
|
||||||
|
- Ready for 01-03: Docker deploy to groll.cloud
|
||||||
|
- All future phases can import from `lightsync.models`, `lightsync.devices`, `lightsync.store`
|
||||||
|
- `_DEVICE_CLASSES` dict ready to receive new strip types in Phase 5
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 01-foundation*
|
||||||
|
*Completed: 2026-04-05*
|
||||||
Reference in New Issue
Block a user