131 lines
7.3 KiB
Markdown
131 lines
7.3 KiB
Markdown
# Project Memory
|
|
|
|
Last updated: 2026-08-25
|
|
|
|
## Current Product Truth
|
|
|
|
- Screener is private, low-latency game screen sharing for one Host and up to
|
|
`20` authenticated Viewers, not a public broadcast service.
|
|
- Web Host, Viewer, and Browser relay are the current delivery surface. Native
|
|
capture, shared encoding, and distributable server/local packages remain
|
|
later work.
|
|
- Rooms are bounded process memory: random free `1000..9999` code, default
|
|
24-hour dormant lease, active sharing never expires, exact Host token resume,
|
|
Viewer activity does not renew, and process restart loses every room and
|
|
credential. There is no database or migration path.
|
|
- Every room has one 128-bit/22-character Viewer grant bound to that exact room
|
|
incarnation and independent `open | private` code entry. Private without a
|
|
password is invitation-only; adding a password also permits matching code
|
|
entry. Reclamation, restart, rotate, or revoke ends the grant. Missing codes
|
|
return `ROOM_NOT_FOUND` without a password prompt.
|
|
- Host creation preferences and raw ownership token stay local to the Host
|
|
browser. Server authority stores only current-process digests/verifiers and
|
|
never uses IP, UA, device, or browser fingerprint as identity.
|
|
|
|
## Media And Routing
|
|
|
|
- Media stays automatic and distributed. Ordinary peer ICE is STUN-only and
|
|
direct/peer UDP is preferred. The only application fallback is the dedicated
|
|
LiveKit SFU over UDP; Screener configures no TURN, ICE/TCP, media TCP, or
|
|
TLS-relayed media.
|
|
- Browser LiveKit publisher/subscriber PCs use no external ICE server and retain
|
|
LiveKit-signaled UDP candidates. Deployment STUN remains available to ordinary
|
|
peers and LiveKit server-side public-IP discovery.
|
|
- Every non-server endpoint uses one server-authoritative steady outbound copy
|
|
cap: default `2`, configurable only as `1`, `2`, or `3`. A peer child or the
|
|
Host publication consumes one slot; upstream receive is free; SFU subscriber
|
|
egress uses separate server admission.
|
|
- One room controller owns one committed acyclic source-reachable graph, one
|
|
event-driven reconciliation loop, and at most one room-serial child operation.
|
|
The operation owns one deterministic candidate list/cursor, one current
|
|
candidate and reservations, one fact version, and one total direct-then-SFU
|
|
deadline.
|
|
- Candidate filtering enforces current authority, reachability, acyclicity,
|
|
capacity, transition slots, and server admission. Eligible P2P parents are
|
|
ordered by resulting depth, remaining capacity, stable join order, and peer
|
|
identity before SFU.
|
|
- A candidate commits only after the exact child decodes its first new video
|
|
frame. Failure releases resources, broadcasts a strictly newer rollback
|
|
revision, advances the cursor without resetting the deadline, and preserves
|
|
unaffected healthy branches. A relay with bad ingress reparents itself while
|
|
retaining its subtree.
|
|
- Healthy decoded routes remain sticky. There is no periodic rebalancing,
|
|
quality score, all-pairs probing, parent blacklist, NAT classification, port
|
|
prediction, or independent depth cap. Quality evidence cannot prove an
|
|
unconnected parent would be better.
|
|
- P2P and SFU first use their framework reconnect behavior. P2P recovery tries
|
|
the same parent, and SFU recovery rebuilds the same publication/subscription.
|
|
Manual media reconnect also stays on the current exact route. Only actual
|
|
recovery exhaustion, hard failure, non-paused decoded-frame stall, parent
|
|
departure, or capacity invalidation enters route reassignment.
|
|
- Active-path WebRTC/LiveKit sampling owns one exact-route decoded-progress
|
|
deadline. Route/connection change or new progress resets it; authoritative
|
|
pause suppresses it. Page resume rebaselines frozen wall-clock time before
|
|
another no-progress sample can fail a route.
|
|
|
|
## Media Quality
|
|
|
|
- Browser video is VP8 only. Display video uses `contentHint = "motion"` and
|
|
display audio uses `contentHint = "music"`. Codec UI/state/wire, backup media
|
|
codecs, and runtime codec switching do not exist.
|
|
- Recommended profiles remain exactly `1080p60`, `1080p30`, and `720p30`, with
|
|
`1080p30` default. `480p` is only an advanced `854x480` resolution choice;
|
|
advanced FPS and bitrate remain independent.
|
|
- WebRTC owns direct/peer media adaptation. The Host reapplies the selected video
|
|
profile after answer negotiation; no periodic application controller exists.
|
|
- The SFU publisher sets VP8 and the selected ceiling but no custom simulcast
|
|
layers. Pinned LiveKit defaults own representations, Dynacast owns aggregate
|
|
demand, and server send-side BWE owns subscriber forwarding. AdaptiveStream
|
|
stays disabled because any Viewer may relay its received track.
|
|
- Screen audio requests capture by default and offers live 64/128/256 kbps
|
|
sender ceilings with 128 default. Peer answers request Opus stereo with a
|
|
256 kbps receive maximum. SFU publication uses stereo, DTX off, and RED off;
|
|
disabling RED accepts reduced burst-loss resilience in exchange for bounded
|
|
publisher traffic.
|
|
- Configured resolution, FPS, bitrate, preference, codec, and audio ceiling are
|
|
requests or ceilings. Sender readback and RTCStats are the observable truth.
|
|
|
|
## Presentation And Lifecycle
|
|
|
|
- Viewer presentation is revision/generation-fenced and keeps the stage stable
|
|
until a current-generation composited frame. A new current frame clears stale
|
|
media `connecting/reconnecting` presentation; old callbacks cannot prove a
|
|
new route.
|
|
- Viewer local play/pause, volume, mute, and fullscreen are owned by native video
|
|
controls on one persistent media element. Host preview is a muted, control-free
|
|
view of the capture stream; only explicit Host actions pause or stop sharing.
|
|
- Hiding or unfocusing the Host page pauses only the local preview element.
|
|
Browser/OS capture and background behavior remain platform capabilities; no
|
|
fake keepalive, silent media, Wake Lock, or timer loop is a product mechanism.
|
|
|
|
## Current Source And Production
|
|
|
|
- Canonical `main` and production run exact application/runtime revision
|
|
`af348ee1d508a3af02b18a7f46c461953798e19d`, release `af348ee`, on strict
|
|
`screener-v12`.
|
|
- Production uses random memory rooms, 20-Viewer admission, endpoint cap `2`,
|
|
dedicated LiveKit admission `1` ingress / `20` egress, STUN UDP 3478, LiveKit
|
|
media UDP 7882, and Web TCP 80/443. Node 8787 and LiveKit 7880 remain private.
|
|
- Exact artifact and service state are owned by [deployment](./deployment.md)
|
|
and indexed by [status](./status.md). Physical evidence boundaries are owned
|
|
by [verification status](./verification-status.md).
|
|
|
|
## Current Priority
|
|
|
|
1. Integrate and deploy the accepted Viewer lifecycle/native-control/current-
|
|
route reconnect candidate, then finish representative real-network route,
|
|
screen-audio, real-game A/V, and mobile lifecycle acceptance.
|
|
|
|
Quality-driven parent selection, VP8 hardware evidence, Native sender work,
|
|
distribution packages, whole-product UI/bilingual polish, and repository-wide
|
|
simplification remain later decisions in [the TODO ledger](./todo.md).
|
|
|
|
## Working Rules
|
|
|
|
- Generic authority and scope follow the repo-tracked
|
|
[`stop-that-shit` skill](../.agents/skills/stop-that-shit/SKILL.md).
|
|
- Canonical `main` and the current truth owners override old branches,
|
|
worktrees, handoff text, and chat summaries.
|
|
- Preserve unique or dirty candidates until integration and reference/reparse
|
|
audits prove cleanup is safe.
|