From 6d2c5ba304efb91fb1417c4f23dfb63005f6d34c Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Wed, 18 Mar 2026 12:19:34 -0700 Subject: [PATCH] chore(display): add debug logging to NullDisplay for development - Print first few frames periodically to aid debugging - Remove obsolete design doc This helps inspect buffer contents when running headless tests. --- .../specs/2026-03-15-readme-update-design.md | 145 ------------------ engine/display/backends/null.py | 22 +++ 2 files changed, 22 insertions(+), 145 deletions(-) delete mode 100644 docs/superpowers/specs/2026-03-15-readme-update-design.md diff --git a/docs/superpowers/specs/2026-03-15-readme-update-design.md b/docs/superpowers/specs/2026-03-15-readme-update-design.md deleted file mode 100644 index 1af12e3..0000000 --- a/docs/superpowers/specs/2026-03-15-readme-update-design.md +++ /dev/null @@ -1,145 +0,0 @@ -# README Update Design — 2026-03-15 - -## Goal - -Restructure and expand `README.md` to: -1. Align with the current codebase (Python 3.10+, uv/mise/pytest/ruff toolchain, 6 new fonts) -2. Add extensibility-focused content (`Extending` section) -3. Add developer workflow coverage (`Development` section) -4. Improve navigability via top-level grouping (Approach C) - ---- - -## Proposed Structure - -``` -# MAINLINE -> tagline + description - -## Using - ### Run - ### Config - ### Feeds - ### Fonts - ### ntfy.sh - -## Internals - ### How it works - ### Architecture - -## Extending - ### NtfyPoller - ### MicMonitor - ### Render pipeline - -## Development - ### Setup - ### Tasks - ### Testing - ### Linting - -## Roadmap - ---- -*footer* -``` - ---- - -## Section-by-section design - -### Using - -All existing content preserved verbatim. Two changes: -- **Run**: add `uv run mainline.py` as an alternative invocation; expand bootstrap note to mention `uv sync` / `uv sync --all-extras` -- **ntfy.sh**: remove `NtfyPoller` reuse code example (moves to Extending); keep push instructions and topic config - -Subsections moved into Using (currently standalone): -- `Feeds` — it's configuration, not a concept -- `ntfy.sh` (usage half) - -### Internals - -All existing content preserved verbatim. One change: -- **Architecture**: append `tests/` directory listing to the module tree - -### Extending - -Entirely new section. Three subsections: - -**NtfyPoller** -- Minimal working import + usage example -- Note: stdlib only dependencies - -```python -from engine.ntfy import NtfyPoller - -poller = NtfyPoller("https://ntfy.sh/my_topic/json?since=20s&poll=1") -poller.start() - -# in your render loop: -msg = poller.get_active_message() # → (title, body, timestamp) or None -if msg: - title, body, ts = msg - render_my_message(title, body) # visualizer-specific -``` - -**MicMonitor** -- Minimal working import + usage example -- Note: sounddevice/numpy optional, degrades gracefully - -```python -from engine.mic import MicMonitor - -mic = MicMonitor(threshold_db=50) -if mic.start(): # returns False if sounddevice unavailable - excess = mic.excess # dB above threshold, clamped to 0 - db = mic.db # raw RMS dB level -``` - -**Render pipeline** -- Brief prose about `engine.render` as importable pipeline -- Minimal sketch of serve.py / ESP32 usage pattern -- Reference to `Mainline Renderer + ntfy Message Queue for ESP32.md` - -### Development - -Entirely new section. Four subsections: - -**Setup** -- Hard requirements: Python 3.10+, uv -- `uv sync` / `uv sync --all-extras` / `uv sync --group dev` - -**Tasks** (via mise) -- `mise run test`, `test-cov`, `lint`, `lint-fix`, `format`, `run`, `run-poetry`, `run-firehose` - -**Testing** -- Tests in `tests/` covering config, filter, mic, ntfy, sources, terminal -- `uv run pytest` and `uv run pytest --cov=engine --cov-report=term-missing` - -**Linting** -- `uv run ruff check` and `uv run ruff format` -- Note: pre-commit hooks run lint via `hk` - -### Roadmap - -Existing `## Ideas / Future` content preserved verbatim. Only change: rename heading to `## Roadmap`. - -### Footer - -Update `Python 3.9+` → `Python 3.10+`. - ---- - -## Files changed - -- `README.md` — restructured and expanded as above -- No other files - ---- - -## What is not changing - -- All existing prose, examples, and config table values — preserved verbatim where retained -- The Ideas/Future content — kept intact under the new Roadmap heading -- The cyberpunk voice and terse style of the existing README diff --git a/engine/display/backends/null.py b/engine/display/backends/null.py index 392127c..215965d 100644 --- a/engine/display/backends/null.py +++ b/engine/display/backends/null.py @@ -33,6 +33,8 @@ class NullDisplay: self._last_buffer = None def show(self, buffer: list[str], border: bool = False) -> None: + import sys + from engine.display import get_monitor, render_border # Get FPS for border (if available) @@ -52,6 +54,26 @@ class NullDisplay: buffer = render_border(buffer, self.width, self.height, fps, frame_time) self._last_buffer = buffer + + # For debugging: print first few frames to stdout + if hasattr(self, "_frame_count"): + self._frame_count += 1 + else: + self._frame_count = 0 + + # Only print first 5 frames or every 10th frame + if self._frame_count <= 5 or self._frame_count % 10 == 0: + sys.stdout.write("\n" + "=" * 80 + "\n") + sys.stdout.write( + f"Frame {self._frame_count} (buffer height: {len(buffer)})\n" + ) + sys.stdout.write("=" * 80 + "\n") + for i, line in enumerate(buffer[:30]): # Show first 30 lines + sys.stdout.write(f"{i:2}: {line}\n") + if len(buffer) > 30: + sys.stdout.write(f"... ({len(buffer) - 30} more lines)\n") + sys.stdout.flush() + if monitor: t0 = time.perf_counter() chars_in = sum(len(line) for line in buffer)