Files
mirror/pyproject.toml
ducoterra 1e816da5a8
Build and Push Containers / test (push) Successful in 35s
Build and Push Containers / build-and-push-app (push) Successful in 10s
phase: 01_keyboard_kiosk_control
**Phase 01 final verification pass — complete, 100% green**

- Verified all 4 tasks done (files in `complete/`); implementation review: key router in `watch.js`, share-page router, CSS focus/selection affordances, `?` overlay, pointer-free E2E suite — all sound.
- Gates: `ruff check` + `ruff format --check` ✅ · `pyright` 0 errors ✅ · `uv run pytest` → 223 passed, 2 skipped (realdisplay), 1 pre-existing FastAPI deprecation warning · `MIRROR_REALDISPLAY=1 pytest -m realdisplay` → 2 passed ✅ · `pytest -m e2e` → 51 passed (incl. `test_keyboard_wall.py`, which a meta-test keeps pointer-free) · `node --check` on all static JS ✅.
- Completion criteria: all 6 ✅ (j/k+Enter, f/g/n/p/1–9/m/?/Esc keyboard-only E2E; no hover-only controls via CSS guard + focus-ring E2E; `#name` text-safe; e2e/realdisplay green; key map documented in README "Kiosk client" and `docs/kiosk-silverblue.md`).
- README fixed: added missing env vars `MIRROR_MAX_BITRATE`, `MIRROR_PING_INTERVAL`, `DEBUGPY_WAIT` to the config table; added the one-time `rpm-ostree` layering note before the kiosk install snippet.
- AGENTS.md fixed: removed stale "roadmap is intentionally empty" parenthetical (3 phases pending); coverage ~94% → ~95%. No content added.
- **Unresolved, needs your call:** README/SECURITY.md say `mirror.reeseapps.com`; `docs/kiosk-silverblue.md` (reference-client naming table with real IPs) says `mirror.reeselink.com`. I couldn't verify which is the live deployment domain, so I changed neither — say the word and I'll unify.
- Next pending phase: `02_sharp_capture`.
2026-11-01 20:53:28 -05:00

74 lines
1.7 KiB
TOML

[project]
name = "mirror"
version = "0.1.0"
description = "Device-agnostic, browser-only screen mirroring for the local network."
readme = "README.md"
requires-python = ">=3.13"
license = { text = "MIT" }
authors = [{ name = "Reese Apps" }]
dependencies = [
"fastapi>=0.115",
"uvicorn[standard]>=0.30",
"python-dotenv>=1.0",
]
[project.optional-dependencies]
dev = [
"debugpy>=1.8",
"pytest>=8.3",
"pytest-asyncio>=0.24",
"pytest-cov>=5.0",
"httpx>=0.27",
"ruff>=0.6",
"pyright>=1.1.380",
"playwright>=1.47",
"pytest-timeout>=2.3",
]
[project.scripts]
mirror = "mirror.__main__:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/mirror"]
[tool.ruff]
line-length = 100
target-version = "py313"
src = ["src", "tests"]
# The phase tree is harness-managed planning documents, not code: ruff 0.17+
# formats the code blocks inside them, and a phase author's snippet must not
# be able to fail the project gate (nor may an executor reformat a phase file
# to fix it — the harness owns those paths).
extend-exclude = [".agents"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B", "C4", "SIM", "ARG", "RUF"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra --strict-markers --cov=mirror --cov-report=term-missing"
timeout = 60
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"
markers = [
"e2e: browser end-to-end tests (require Playwright browsers)",
"realdisplay: end-to-end tests that capture a real X11 display",
]
[tool.coverage.run]
source = ["src/mirror"]
[tool.pyright]
include = ["src"]
pythonVersion = "3.13"
typeCheckingMode = "standard"
[dependency-groups]
dev = [
"pytest-timeout>=2.4.0",
]