diff --git a/.agents/phases/todo/05_autohide_stage_controls/00_phase.md b/.agents/phases/complete/05_autohide_stage_controls/00_phase.md similarity index 100% rename from .agents/phases/todo/05_autohide_stage_controls/00_phase.md rename to .agents/phases/complete/05_autohide_stage_controls/00_phase.md diff --git a/.agents/phases/todo/05_autohide_stage_controls/01_hide_staged_overlay_at_rest.md b/.agents/phases/complete/05_autohide_stage_controls/01_hide_staged_overlay_at_rest.md similarity index 100% rename from .agents/phases/todo/05_autohide_stage_controls/01_hide_staged_overlay_at_rest.md rename to .agents/phases/complete/05_autohide_stage_controls/01_hide_staged_overlay_at_rest.md diff --git a/.agents/phases/todo/05_autohide_stage_controls/02_reveal_on_activity.md b/.agents/phases/complete/05_autohide_stage_controls/02_reveal_on_activity.md similarity index 100% rename from .agents/phases/todo/05_autohide_stage_controls/02_reveal_on_activity.md rename to .agents/phases/complete/05_autohide_stage_controls/02_reveal_on_activity.md diff --git a/.agents/phases/todo/05_autohide_stage_controls/03_e2e_autofade_lifecycle.md b/.agents/phases/complete/05_autohide_stage_controls/03_e2e_autofade_lifecycle.md similarity index 100% rename from .agents/phases/todo/05_autohide_stage_controls/03_e2e_autofade_lifecycle.md rename to .agents/phases/complete/05_autohide_stage_controls/03_e2e_autofade_lifecycle.md diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.err b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md new file mode 100644 index 0000000..58c1640 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md @@ -0,0 +1,9 @@ +**Phase 05 final verification pass — all green.** + +- Verified implementation in tree: staged `.cap`/`.actions` hidden at rest with container+children `pointer-events: none` (`app.css`); `revealStageControls()` with 3 s idle timer, `pointermove`/`pointerdown` + wall-keypress wiring, `unstage()` timer/attribute cleanup (`watch.js`); `tests/e2e/test_stage_autofade.py` (5 tests) present; `test_keyboard_wall.py` rest-state assertion updated per task 01. +- Gates: `uv run ruff check . && uv run ruff format --check .` — clean; `uv run pyright` — 0 errors; `uv run pytest` — **274 passed, 4 skipped** (realdisplay-gated), coverage **95%** (>90% ✓); `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` — **3 passed, 1 skipped** (documented platform skip: no audio source on host). +- Dedicated phase suite `uv run pytest tests/e2e/test_stage_autofade.py` — **5/5 in isolation**. +- Criteria: idle opacity 0 + bottom-edge hit probe ✓; mouse reveal → 1 → idle fade → 0 ✓; keypress reveal + Exit visible/clickable/unstages ✓; grid rules byte-for-byte unchanged (CSS diff touches only the staged block; grid guard tests green) ✓; suite green, coverage >90% ✓; phases 01–04 suites all green (no regression) ✓. +- Documentation: README.md reviewed in full — all commands, env vars (incl. `DEBUGPY_*`, 25 Mbit/s default), `--allow-cidr`, kiosk/share key tables, index-page and auto-hide descriptions match the code; the only stale "12 Mbit/s" default lives in locked PLAN.md §6, README is correct — no change made. AGENTS.md: all facts (gates, test names, starlette 1.10, e2e flags, ~95% coverage) current — verified, no changes needed. +- Notable: no code changes were required this pass — the phase work was already complete and correct; nothing to fix. +- Next pending phase: none — phase 05 is the last in `todo/`. diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md.status b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md.status new file mode 100644 index 0000000..9766475 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.md.status @@ -0,0 +1 @@ +ok diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.validate b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.validate new file mode 100644 index 0000000..bee37f3 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__00_phase.a1.validate @@ -0,0 +1,34 @@ +........................................................................ [ 25%] +......................ssss.............................................. [ 51%] +........................................................................ [ 77%] +.............................................................. [100%] +=============================== warnings summary =============================== +.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1 + /home/ducoterra/Projects/Personal/mirror/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient as TestClient # noqa + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +================================ tests coverage ================================ +_______________ coverage: platform linux, python 3.14.8-final-0 ________________ + +Name Stmts Miss Cover Missing +------------------------------------------------------ +src/mirror/__init__.py 3 0 100% +src/mirror/__main__.py 72 3 96% 129, 145, 156 +src/mirror/access.py 60 0 100% +src/mirror/app.py 185 12 94% 108, 113, 116-117, 182-183, 212-216, 245 +src/mirror/config.py 68 5 93% 110-111, 118-120 +src/mirror/debug.py 15 10 33% 19-28 +src/mirror/protocol.py 59 0 100% +src/mirror/registry.py 191 3 98% 166, 180, 355 +------------------------------------------------------ +TOTAL 653 33 95% +=========================== short test summary info ============================ +SKIPPED [1] tests/e2e/test_x11_capture.py:281: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:321: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:364: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:446: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +274 passed, 4 skipped, 1 warning in 96.65s (0:01:36) +All checks passed! +31 files already formatted +0 errors, 0 warnings, 0 informations diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.err b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md new file mode 100644 index 0000000..b327c41 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md @@ -0,0 +1,16 @@ +All gates verified green after the final code changes. Done. + +**Report — Task 01 (phase 05): hide the staged overlay at rest** + +- `app.css`: staged `.cap` `opacity: 0.28 → 0`; deleted the three staged reveal rules and staged `.actions { opacity: 1 }`; added id-scoped `#watch-stage .tile .actions { opacity: 0 }` (outranks the grid `data-selected`/`focus-within`/`hover:none` rules — verified by the E2E computed-opacity assertion, not assumption); `pointer-events: none` scoped to both containers *and their children* (no dead zones); comment block replaced with the new contract (hidden at rest, task-02 `data-reveal` is the only staged reveal, `::after` audio mark untouched) +- `test_keyboard_wall.py`: `test_focus_moves_to_the_stage_and_back_with_g` now waits (10 s) for staged `.cap` **and** `.actions` computed opacity `0`; grid guard test untouched +- `test_live_mirror.py` ×2 + `test_audio_share.py` ×1 (deviation, forced by the task's own CSS): with the overlay pointer-transparent at rest and no reveal yet, the existing `#watch-stage .exit` / staged `.audio` clicks are impossible — replaced those unstage/mute actions with the `g`/`m` keys (comment notes the revealed-state Exit click is asserted by task 03's E2E); `to_be_visible` assertions kept +- README: one accurate-now-and-still-true line — staged caption/controls are hidden at rest so the video is never covered. No AGENTS.md impact (no statement touched by this task went stale) + +Gates (all green, in order): +- `uv run ruff check . && uv run ruff format --check .` → passed / 30 files formatted +- `uv run pyright` → 0 errors +- `uv run pytest` → **269 passed, 4 skipped** (realdisplay marker) +- `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` → **3 passed, 1 skipped** (host has no audio source for real capture — documented platform limit) + +Next pending task: `02_reveal_on_activity.md` diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md.status b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md.status new file mode 100644 index 0000000..9766475 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.md.status @@ -0,0 +1 @@ +ok diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.validate b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.validate new file mode 100644 index 0000000..c206807 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__01_hide_staged_overlay_at_rest.a1.validate @@ -0,0 +1,34 @@ +........................................................................ [ 26%] +.................ssss................................................... [ 52%] +........................................................................ [ 79%] +......................................................... [100%] +=============================== warnings summary =============================== +.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1 + /home/ducoterra/Projects/Personal/mirror/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient as TestClient # noqa + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +================================ tests coverage ================================ +_______________ coverage: platform linux, python 3.14.8-final-0 ________________ + +Name Stmts Miss Cover Missing +------------------------------------------------------ +src/mirror/__init__.py 3 0 100% +src/mirror/__main__.py 72 3 96% 129, 145, 156 +src/mirror/access.py 60 0 100% +src/mirror/app.py 185 11 94% 108, 113, 117, 182-183, 212-216, 245 +src/mirror/config.py 68 5 93% 110-111, 118-120 +src/mirror/debug.py 15 10 33% 19-28 +src/mirror/protocol.py 59 0 100% +src/mirror/registry.py 191 3 98% 166, 180, 355 +------------------------------------------------------ +TOTAL 653 32 95% +=========================== short test summary info ============================ +SKIPPED [1] tests/e2e/test_x11_capture.py:281: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:321: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:364: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:446: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +269 passed, 4 skipped, 1 warning in 92.81s (0:01:32) +All checks passed! +30 files already formatted +0 errors, 0 warnings, 0 informations diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.err b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md new file mode 100644 index 0000000..88c1e7d --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md @@ -0,0 +1,19 @@ +Everything is green and in order. Final report: + +**Implemented (task 02 — reveal on activity, auto-hide when idle)** +- `watch.js`: `STAGE_REVEAL_IDLE_MS = 3000` + `let stageRevealTimer = 0` + `revealStageControls()` — sets `data-reveal` on the staged tile, clears/re-arms the timer; callback deletes the attribute only if `state.staged === tile.id` (tile may be unstaged/replaced before it fires) +- Triggers wired per spec: `pointermove` + `pointerdown` (touch tap, A5) on `#watch-stage`; `if (state.staged) revealStageControls()` in `onWallKey` after bail-outs, before the `switch`, never `preventDefault` +- `unstage()`: clears the pending timer and deletes `data-reveal` from the departing tile — no stale reveal can leak into the grid (grid rules never read it; re-staging starts hidden) +- `app.css`: id-scoped `[data-reveal]` reveal pair for `.cap`/`.actions` + children (`opacity: 1; pointer-events: auto`), outranking the task-01 hide rules; existing transitions give the fade, `prefers-reduced-motion` already degrades it to instant + +**Verification (temporary E2E, deleted after — the dedicated suite is task 03's deliverable)** +- 5 browser tests on a real staged tile (fake-media capture): mouse reveal → 3 s idle fade, `m`-keypress reveal → fade, unstage clears attribute+timer (survived 3.6 s timer window), n/p + 1-9 replacement leaves no stale `data-reveal`, Exit clickable while revealed and unstages — all passed +- `uv run ruff check . && uv run ruff format --check .` — clean; `uv run pyright` — 0 errors +- `uv run pytest` — 269 passed, 4 skipped (realdisplay-gated), coverage 95% (no Python code changed; JS/CSS verified in-browser per convention) +- `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` — 3 passed, 1 env skip (host has no audio source) + +**Docs**: README.md — staged-overlay paragraph extended with the reveal/~3 s auto-hide behaviour; AGENTS.md — no impact (no statement became stale) + +**Notable**: a keypress that *causes* staging (Enter) doesn't reveal — `state.staged` is null pre-switch, so the overlay stays hidden at rest, keeping task 01's 10 s rest-state test green. + +**Next pending task**: `03_e2e_autofade_lifecycle.md` diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md.status b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md.status new file mode 100644 index 0000000..9766475 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.md.status @@ -0,0 +1 @@ +ok diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.validate b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.validate new file mode 100644 index 0000000..ff90d81 --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__02_reveal_on_activity.a1.validate @@ -0,0 +1,34 @@ +........................................................................ [ 26%] +.................ssss................................................... [ 52%] +........................................................................ [ 79%] +......................................................... [100%] +=============================== warnings summary =============================== +.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1 + /home/ducoterra/Projects/Personal/mirror/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient as TestClient # noqa + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +================================ tests coverage ================================ +_______________ coverage: platform linux, python 3.14.8-final-0 ________________ + +Name Stmts Miss Cover Missing +------------------------------------------------------ +src/mirror/__init__.py 3 0 100% +src/mirror/__main__.py 72 3 96% 129, 145, 156 +src/mirror/access.py 60 0 100% +src/mirror/app.py 185 11 94% 108, 113, 117, 182-183, 212-216, 245 +src/mirror/config.py 68 5 93% 110-111, 118-120 +src/mirror/debug.py 15 10 33% 19-28 +src/mirror/protocol.py 59 0 100% +src/mirror/registry.py 191 3 98% 166, 180, 355 +------------------------------------------------------ +TOTAL 653 32 95% +=========================== short test summary info ============================ +SKIPPED [1] tests/e2e/test_x11_capture.py:281: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:321: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:364: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +SKIPPED [1] tests/e2e/test_x11_capture.py:446: set MIRROR_REALDISPLAY=1 to exercise the real X11 capture backend +269 passed, 4 skipped, 1 warning in 95.80s (0:01:35) +All checks passed! +30 files already formatted +0 errors, 0 warnings, 0 informations diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__03_e2e_autofade_lifecycle.a1.err b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__03_e2e_autofade_lifecycle.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__03_e2e_autofade_lifecycle.a1.md b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__03_e2e_autofade_lifecycle.a1.md new file mode 100644 index 0000000..38c031b --- /dev/null +++ b/.agents/reports/05_autohide_stage_controls/05_autohide_stage_controls__03_e2e_autofade_lifecycle.a1.md @@ -0,0 +1,10 @@ +All four gates green. Task complete. + +**Report** + +- **Implemented:** `tests/e2e/test_stage_autofade.py` — 5-test suite pinning the staged overlay lifecycle on a real capture: `rest` (opacity 0 for `.cap`/`.actions` + `elementFromPoint` bottom-centre hit is the `