From 6fa63024bdd19df6d992a4c0f5a29b2cf6e8aac4 Mon Sep 17 00:00:00 2001 From: AAA <35992542+TNTcraftHIM@users.noreply.github.com> Date: Sat, 22 Aug 2026 12:17:56 +0800 Subject: [PATCH] docs: quarantine disputed TODO truth Quarantine disputed TODO and routing claims, record current production facts, and define the canonical workspace restoration order before any further implementation. --- AGENTS.md | 25 +++- CONTRIBUTING.md | 11 +- docs/README.md | 10 +- docs/adr/0001-p2p-first-media-topology.md | 4 +- docs/adr/0002-persistent-protected-rooms.md | 13 +- .../0004-peer-assisted-media-experiment.md | 2 + .../0005-automatic-hybrid-media-routing.md | 10 +- .../0006-fixed-high-native-sender-canary.md | 7 +- docs/deployment.md | 42 ++++--- docs/maintenance.md | 12 ++ docs/project-memory.md | 18 +-- docs/research/advanced-peer-distribution.md | 2 + docs/research/browser-screen-audio-quality.md | 8 +- docs/research/built-in-peer-ice-turn.md | 15 ++- docs/research/low-server-media-routes.md | 12 +- docs/research/native-shared-encode-sender.md | 11 +- docs/research/peer-assisted-media.md | 2 + docs/research/realtime-quality-adaptation.md | 20 +-- docs/research/webrtc-p2p-screen-sharing.md | 8 +- docs/status.md | 18 +-- docs/todo-audit-hold.md | 118 ++++++++++++++++++ docs/verification-status.md | 8 +- docs/workspace-disposition.md | 106 ++++++++++++++++ docs/方案设计.md | 6 +- docs/需求理解.md | 4 +- 25 files changed, 408 insertions(+), 84 deletions(-) create mode 100644 docs/todo-audit-hold.md create mode 100644 docs/workspace-disposition.md diff --git a/AGENTS.md b/AGENTS.md index 0258c06..8d0db56 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,15 +1,32 @@ # Project Instructions +## Durable Truth Before Action + +- Do not turn a discussion, correction, example, review suggestion, experiment, checkbox, or agent idea directly into implementation. First restate the intended outcome and its source rationale, reconcile it against the whole current product model and any conflicting evidence, and challenge assumptions that are inconsistent or unnecessarily complex. +- Before implementation work or implementation sub-agents begin, update every affected owning truth document: current requirement and design, accepted ADR or research conclusion when applicable, `docs/project-memory.md`, `docs/status.md`, and this file when a global rule changed. Replace conflicting current text in place, then create a Git-tracked checkpoint so the decision survives compaction and handoff. +- If the semantic decision is still disputed, record a truth hold and freeze only dependent work. Do not encode a guess as accepted truth. Code, merge, deployment, and cleanup may start only after the nonvolatile truth set is internally consistent. +- Merge the accepted truth checkpoint before integrating dependent candidates. Rebase or rebuild each retained candidate from that main exactly once; resolve conflicts from main's owning truth and transplant only approved scoped code, tests, and new facts. Never let an older branch's `AGENTS.md`, requirements, ADRs, memory, status, or deployment snapshot overwrite newer truth. +- After an audit or integration boundary, restore the canonical repository root to a clean, up-to-date `main` before starting new implementation. Do not leave `main` checked out in an auxiliary worktree. Preserve overlapping user changes explicitly, then create every new branch and worktree from the exact canonical `main` commit; an auxiliary worktree is never the source of current truth. +- Cleanup is last. Remove a worktree or branch only after the semantic decision, integration, and main-equivalence/open-reference checks are complete; never delete first to simplify a decision or later reintroduce an old branch wholesale. + +## Temporary TODO Audit Hold + +- `docs/todo-audit-hold.md` is the execution quarantine while the 2026-08-22 truth audit is open. An unchecked box, old branch, agent proposal, experiment, review suggestion, or post-boundary follow-up is not an authorized TODO unless that ledger marks it `CONFIRMED` or the user explicitly reauthorizes it after the audit boundary. +- `AUDIT-HOLD` means preserve and inspect, not delete, revert, continue, merge, deploy, or use as current product truth. `EVIDENCE-ONLY` results may inform a later decision but must not become a release gate by themselves. +- The older Browser1 and global-SFU-root-two assumptions are disputed and must not drive implementation during the audit. The currently confirmed endpoint-cap intent is one server-authoritative value for every non-server endpoint: default `2`, configurable as `1`, `2`, or `3`, with upstream receive excluded. The exact SFU publication/subscription model is still under holistic routing review. +- Execute this audit in order: first reconcile TODO provenance and current truth owners; second produce the archive/worktree/branch/folder disposition schedule; third merge the audit-guard truth and restore the canonical `main` workspace; fourth produce the holistic routing model as a held proposal without implementation. Later phases must not run ahead merely because parallel capacity is available. +- Then stop and reconcile the canonical state, routing proposal, and remaining TODOs with the user. Do not accept the final routing semantics or create/resume remaining-TODO implementation worktrees before that explicit confirmation. Afterward, update and merge the accepted owning truth into canonical `main` first; only then create high-confidence parallel worktrees from that exact newer `main` SHA. + ## Product Direction - Build private, low-latency game screen sharing for one broadcaster and a small group of trusted friends. - This is not a public or large-scale streaming product; users can use OBS/Twitch-class services for that workload. -- Keep media distributed and automatic. Use centralized services for rooms, authentication, signaling, STUN, observability, and bounded SFU-root capacity. TURN is an optional authenticated selected-edge compatibility transport, disabled unless explicitly configured; it is not a media topology. +- Keep media distributed and automatic. Use centralized services for rooms, authentication, signaling, STUN, observability, and bounded fallback media resources. Current production includes optional selected-edge TURN, but its retained role and placement are under the routing truth audit; it is not by itself a topology. - Let viewers join from a normal desktop or mobile browser without installing the sender application. -- STUN is required. The target ladder is direct/peer UDP, then an SFU/UDP virtual parent feeding at most two roots, then optional authenticated selected-edge TURN, followed by a clear bounded failure. Ordinary peer edges must not receive TURN candidates by default. HTTPS/WSS remains TLS/TCP and is independent of this media-transport policy. -- Every non-server endpoint stays within its advertised relay capacity and the deployment hard ceiling; an upstream receive edge does not consume this upload budget. The current release policy permits at most two downstream physical media edges for non-server endpoints, while ordinary Browser Viewer relay is strictly limited to one until the re-encode/resource gates pass. Deployment may tighten these limits but never raise them; UA/visibility do not change capacity, and actual edge failure returns to the bounded route-reselection path. Dynamic evidence-driven capacity remains future work and must not infer capacity from device identity. Central media normally serves at most two roots; extra server-fed exceptional viewers require an explicit deployment egress/admission cap and must never create unbounded fanout. +- STUN is required and direct/peer UDP remains first. Ordinary peer edges must not receive TURN candidates by default. The exact SFU/TURN fallback order and accounting are held for the holistic routing audit; every accepted path must terminate in a clear bounded success or failure. HTTPS/WSS remains TLS/TCP and is independent of this media-transport policy. +- Every non-server endpoint has one server-authoritative ordinary downstream capacity: default `2`, configurable as `1`, `2`, or `3`. An upstream receive edge does not consume it, Browser role/UA/visibility does not change it, and a client advertisement cannot exceed the deployment value. SFU and TURN are bounded fallback resources, but publication, subscription, selected transport, temporary overlap, and server-resource accounting remain frozen for the holistic routing audit rather than being inferred from ordinary-child counts. - Treat a web client as the initial delivery target. A packaged desktop sender or native capture helper is a later optimization, not an assumed requirement. -- Do not silently change the product into an always-SFU conferencing system. An SFU is a virtual parent for one or two necessary roots whose peer descendants remain distributed; record any broader topology change as an ADR with measured justification. +- Do not silently change the product into an always-SFU conferencing system. Any accepted server-assisted path must preserve the small-room, distributed-media goal unless an ADR with measured justification changes it. ## Repository Knowledge diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 144f495..9dd1a15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,18 +2,21 @@ ## Normal Workflow -1. Start from an up-to-date `main` with a clean working tree. +1. Start from the canonical repository root on an up-to-date `main` with a clean working tree. Do not keep `main` checked out in an auxiliary worktree; preserve any overlapping user changes explicitly before restoring the canonical root. 2. Create one short-lived branch for one coherent change. Use `feat/`, `fix/`, `docs/`, `refactor/`, `test/`, `chore/`, or `spike/` followed by a short description. 3. For non-trivial design, implementation, or bug fixing, inspect the repository and research current primary sources before changing code. Record durable findings under `docs/research/`. -4. Implement the smallest complete change. Add tests and concise rationale comments in proportion to risk. -5. Update requirements, ADRs, project memory, status, and operational docs when their source facts changed. Replace stale text instead of appending a diary. +4. Reconcile the requested outcome against the whole current product model and conflicting evidence. Before implementation, update every affected owning requirement/design/ADR/research document and current memory/status, replace stale current text, and checkpoint that nonvolatile truth in Git. If semantics remain disputed, record a hold and stop dependent implementation. +5. Implement the smallest complete change from that checkpoint. Add tests and concise rationale comments in proportion to risk, and keep operational/current-truth updates in the same coherent pull request when implementation changes source facts. 6. Run `sh scripts/check-project-state.sh` on macOS/Linux/Git Bash or `./scripts/check-project-state.ps1` on PowerShell, plus `npm run check` and any relevant manual browser/network checks. Record this local evidence in the pull request; GitHub Actions are reserved for `main` integration, releases, and explicit manual runs. -7. Make focused commits using `type(scope): summary` where practical, then push the branch. +7. Merge an accepted truth checkpoint before dependent candidates. Rebase or rebuild a retained candidate from that main once, keeping main's owning truth on conflicts and transplanting only approved scoped code, tests, and new facts. Make focused commits using `type(scope): summary` where practical, then push the branch. + Create any new implementation branch or parallel worktree from that exact canonical `main` commit, never from an older candidate or auxiliary worktree. 8. Open a pull request using the repository template. Resolve review comments and required local checks before merging. 9. Prefer squash merge for a single coherent change; preserve separate commits when they carry independently useful history. Delete the merged branch. Direct commits to `main` are reserved for an explicit user-approved exception. Never force-push shared branches or rewrite shared history without explicit approval. +Clean up worktrees and branches only after semantic review and integration are complete and the normal merged-head, open-reference, clean-tree, and non-following link checks pass. Never merge an old branch wholesale after a newer truth checkpoint. + ## Research Standard - Prefer specifications, official product documentation, primary source code, maintainers' design notes, and original papers. diff --git a/docs/README.md b/docs/README.md index fd86ae1..43ce175 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,13 @@ # Project Documentation - [需求理解](./需求理解.md): current product scope, priorities, constraints, and acceptance criteria. -- [方案设计](./方案设计.md): accepted, code-ready design for the first measurable WebRTC proof of concept. +- [方案设计](./方案设计.md): current implementation design; routing capacity and fallback accounting are temporarily frozen by the truth-audit hold. - [Project memory](./project-memory.md): durable decisions and unresolved questions to read at the start of future work. - [Current status](./status.md): bounded current/index snapshot of production, active milestones, decisions, blockers, and links to detail. - [Verification status](./verification-status.md): demand-loaded ledger of current cross-cutting evidence, open proof boundaries, and expensive-test applicability. -- [Deployment](./deployment.md): old production rollback boundary and the isolated self-hosted-STUN plus LiveKit-SFU/UDP candidate contract. +- [TODO execution audit hold](./todo-audit-hold.md): temporary quarantine for disputed post-boundary work, experiments, and stale assumptions while the 2026-08-22 truth audit is open. +- [Workspace disposition](./workspace-disposition.md): demand-loaded worktree, branch, folder, junction, and archive schedule for restoring one canonical `main` root. +- [Deployment](./deployment.md): exact current/rollback production configuration, release operations, and transport evidence boundaries. - [Maintenance guide](./maintenance.md): Git workflow, context hygiene, document lifecycle, research policy, and automation. - [P2P WebRTC research](./research/webrtc-p2p-screen-sharing.md): evidence, bandwidth model, browser constraints, reference implementations, and feasibility assessment. - [Peer-assisted media research](./research/peer-assisted-media.md): browser shared-encode limits, standard relay re-encoding, deterministic sticky topology, runtime relay-capacity extension, and abandon gates. @@ -19,10 +21,10 @@ - [Browser screen-audio quality](./research/browser-screen-audio-quality.md): capture/source compatibility, standard readback limits, Opus negotiation boundaries, and the retained no-control decision. - [Display name and presence boundaries](./research/display-name-presence.md): browser-local storage failure behavior, Unicode normalization, control-character policy, and the Web-only presence capability boundary. - [Agent context governance research](./research/agent-context-governance.md): official Codex, Claude Code, Hermes Agent, and GitHub practices adopted by this repository. -- [ADR-0001](./adr/0001-p2p-first-media-topology.md): accepted P2P-first media topology and its consequences. +- [ADR-0001](./adr/0001-p2p-first-media-topology.md): historical P2P-first baseline; later access and automatic-routing decisions supersede its stale current-state details. - [ADR-0002](./adr/0002-persistent-protected-rooms.md): site access, room-scoped private Viewer grants, explicit public-watch, rotation, and minimal SQLite persistence. - [ADR-0004](./adr/0004-peer-assisted-media-experiment.md): proposed, experiment-only standard-WebRTC peer-assisted spike with hard fanout and failure gates. -- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted direct/peer UDP -> SFU-root -> optional exceptional-edge TURN direction, including the historical room-`1` smoke and broader migration gates. +- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted automatic P2P-first direction and generation safety; capacity and fallback accounting are on truth-audit hold. - [ADR-0006](./adr/0006-fixed-high-native-sender-canary.md): proposed fixed-`HIGH` native canary, current no-go result, and staged revalidation boundary. - [ADR-0007](./adr/0007-demand-driven-dual-representation-quality.md): accepted path-isolated `HIGH + at most one LOW` policy, optional idle-layer stop, evidence contract, and SVC boundary. - [ADR-0008](./adr/0008-window-scoped-audio-capture.md): browser window-audio hint and the Windows WASAPI process-loopback boundary. diff --git a/docs/adr/0001-p2p-first-media-topology.md b/docs/adr/0001-p2p-first-media-topology.md index a10026f..12d1562 100644 --- a/docs/adr/0001-p2p-first-media-topology.md +++ b/docs/adr/0001-p2p-first-media-topology.md @@ -1,8 +1,10 @@ # ADR-0001: P2P-First Media Topology -- Status: Accepted for the MVP +- Status: Accepted Historical MVP Baseline; Current Routing Details Superseded By ADR-0002/0005 And Audit Hold - Date: 2026-08-18 +The P2P-first product intent remains useful. Current access grants, deployed automatic routing, endpoint capacity, SFU publication/subscription, selected TURN, and fallback accounting must not be inferred from this dated baseline; use ADR-0002 and the [TODO audit hold](../todo-audit-hold.md) until ADR-0005 is reconciled. + Current clarification, 2026-08-19: the MVP remains unchanged, but statements below that exclude automatic topology migration do not describe the product target. Automatic, viewer-transparent routing through direct P2P, diff --git a/docs/adr/0002-persistent-protected-rooms.md b/docs/adr/0002-persistent-protected-rooms.md index ccca3e2..9d5790a 100644 --- a/docs/adr/0002-persistent-protected-rooms.md +++ b/docs/adr/0002-persistent-protected-rooms.md @@ -53,9 +53,11 @@ Keep site access and room authorization as two ordered checks: Viewer may bypass site access only with a valid, unexpired grant for that exact room; otherwise site access is required before any room lookup policy or password verification can authorize it. -- Move the single wire literal from `screener-v1` to `screener-v2`. There is no - negotiation, v1 parser, dual write, or translator. A v1 first message receives - the universal fatal refresh outcome before room lookup and does not reconnect. +- At this ADR's release boundary, move the single wire literal from + `screener-v1` to `screener-v2`. That migration had no negotiation, v1 parser, + dual write, or translator. A v1 first message received the universal fatal + refresh outcome before room lookup and did not reconnect. Later atomic + migrations advanced the current wire to `screener-v5`. Every room has one of two Viewer policies: @@ -95,7 +97,10 @@ a correct password share generic rejection. Completion rechecks current room material and socket/Host session so stale asynchronous work cannot authorize or commit. -The wire remains `screener-v2`. Only a Web Host that advertises +At this ADR's implementation checkpoint, the wire remained `screener-v2`. +Current source and production have since migrated atomically to `screener-v5`; +the paragraph below records the v2 compatibility boundary rather than the +current wire. Only a Web Host that advertises `viewerPasswordSettings: true` may set/remove the password and receive `viewer-password-updated`; Native v2 does not advertise the capability and sees no new message type. Viewer `authenticate` may carry the current password diff --git a/docs/adr/0004-peer-assisted-media-experiment.md b/docs/adr/0004-peer-assisted-media-experiment.md index 08c21c4..e02598d 100644 --- a/docs/adr/0004-peer-assisted-media-experiment.md +++ b/docs/adr/0004-peer-assisted-media-experiment.md @@ -3,6 +3,8 @@ - Status: Proposed - Historical Experiment (rollout superseded by ADR-0005) - Date: 2026-08-19 +> Historical cap2/cap3 measurements remain evidence only. References below to a current Browser1 policy, global SFU-root-two limit, or accepted accounting are frozen by the [TODO audit hold](../todo-audit-hold.md) and must not authorize implementation or a release gate. + ## Context ADR-0001 accepted standard browser WebRTC P2P for the MVP and rejected a viewer diff --git a/docs/adr/0005-automatic-hybrid-media-routing.md b/docs/adr/0005-automatic-hybrid-media-routing.md index aee9568..fab5528 100644 --- a/docs/adr/0005-automatic-hybrid-media-routing.md +++ b/docs/adr/0005-automatic-hybrid-media-routing.md @@ -1,8 +1,10 @@ # ADR-0005: Automatic Hybrid Media Routing -- Status: Accepted Direction - All-Room Controller, Media Evidence Unverified +- Status: Accepted P2P-First Automatic Direction; Capacity And Fallback Accounting On Truth-Audit Hold - Date: 2026-08-19 +> The all-room automatic direction, single authoritative Viewer upstream, exact generation authorization, bounded failure, and media-proven transition principles remain accepted. Capacity, SFU publication/subscription, selected TURN, fallback ordering, and temporary resource accounting are disputed inputs rather than implementation authority until the [TODO audit hold](../todo-audit-hold.md) is resolved and this ADR is updated in place. + ## Context The product has always required route selection and recovery to be automatic @@ -214,8 +216,10 @@ bandwidth adaptation, or resource cost. Chrome 151/LiveKit 1.13.5 localhost runs established route transition, resumed decoding, and the two-edge bound. Their elapsed times are diagnostics only and do not satisfy the regional recovery target. Public -transport/audio/load/browser checks remain pending. The direction is accepted, -while implementation migration and deployment acceptance remain unverified. +transport/audio/load/browser checks remain pending. The automatic controller +and its later bounded transition slices are deployed, while the fixed +accounting policy in this checkpoint is under truth-audit hold and real packet, +recovery, resource, and broad-browser acceptance remains unverified. ## State And Wire diff --git a/docs/adr/0006-fixed-high-native-sender-canary.md b/docs/adr/0006-fixed-high-native-sender-canary.md index f4c28dd..702c9d8 100644 --- a/docs/adr/0006-fixed-high-native-sender-canary.md +++ b/docs/adr/0006-fixed-high-native-sender-canary.md @@ -36,7 +36,12 @@ failure. No viewer-1 acceptance means there is no two-viewer, third-viewer FIFO, or direct/TURN proof. The attempted native branch must not be opened or merged as product code from this state. -## 2026-08-20 Current-Wire Checkpoint +## 2026-08-20 Historical Wire Checkpoint + +This checkpoint targeted the then-current `screener-v2` wire and SQLite schema +v2. Current Web and source-only Native use `screener-v5`, and current room +persistence is SQLite schema v3. The dated behavior below remains experiment +provenance, not a current integration contract. A clean local delivery candidate now targets only `screener-v2`: it exchanges `SITE_ACCESS_PASSWORD` for the bounded HttpOnly site-access cookie, uses diff --git a/docs/deployment.md b/docs/deployment.md index b9eb6ca..de195bb 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -2,6 +2,14 @@ Last verified against upstream documentation: 2026-08-21. +> Truth-audit boundary: this page records the exact `9461e20` deployment and +> its currently accepted configuration syntax. Browser1, fixed root counts, +> Host-publication accounting, room-wide selected-lease limits, and the exact +> fallback order are deployed/source facts under the +> [TODO audit hold](./todo-audit-hold.md), not authority for the next routing +> model. Do not change or redeploy them until that model is accepted in its +> owning truth and merged to canonical `main`. + This section documents the repository's UDP-only deployment candidate: one Node.js process provides the built Web client, room API, and WebSocket signaling behind Caddy or nginx; application ICE advertises only STUN by default; LiveKit @@ -256,7 +264,7 @@ Omit the database path to keep random temporary rooms; `ROOM_TTL_SECONDS` applies only to those rooms. `MAX_VIEWERS_PER_ROOM` defaults to 8 and accepts 1 through 16. It is an admission limit, not evidence that the publisher can sustain that many streams. -`MAX_PEER_RELAY_DOWNSTREAM_EDGES` defaults to 2 and accepts only 1 or 2. It can +In exact release `9461e20`, `MAX_PEER_RELAY_DOWNSTREAM_EDGES` defaults to 2 and accepts only 1 or 2. It can tighten but cannot lift release policy: effective Host capacity is `min(value, 2)` and effective ordinary Browser Viewer capacity is `min(value, 1)`. Active/provisional/selected physical downstream overlays count, @@ -271,7 +279,7 @@ complete tuple requires `PEER_ASSISTED_MEDIA=true`. An empty tuple keeps the optional SDK and server path dormant. `LIVEKIT_URL` must be a plain `ws:` or `wss:` origin with no `/rtc` suffix; production requires `wss:`. `LIVEKIT_API_SECRET` must contain at least 32 bytes and must not reuse -`SITE_ACCESS_PASSWORD`. `MAX_SFU_ROOTS_PER_ROOM` defaults to +`SITE_ACCESS_PASSWORD`. In that same held release, `MAX_SFU_ROOTS_PER_ROOM` defaults to 2 and accepts only 1 or 2; it is ignored when LiveKit is not configured. These credentials authorize short-lived LiveKit room tokens and do not provide E2EE: the LiveKit operator can access ordinary SFU media. @@ -362,22 +370,22 @@ ownership to the service account and mode `0600`, run SQLite use SQLite's [backup API](https://www.sqlite.org/backup.html) or `VACUUM INTO`; do not copy only the live main file while it may have an active journal. -The access release changes schema v1 to v2 and has no dual-schema runtime. For -an existing deployment, stop the service and take a named, immutable v1 copy -before installing or starting the new binary. Confirm the stopped source reports -`PRAGMA user_version = 1`, retain the backup outside the release directory, and -record its checksum. On first v2 startup, one `BEGIN IMMEDIATE` transaction adds -the checked nullable Viewer digest, writes a different fresh locked-private -digest to every old room, and advances `user_version` to `2`. Old code-only -Viewer links intentionally stop working; each existing Host must use rotate once -to produce a private invitation. +The current release migrates schema v1 or v2 to v3 and has no dual-schema +runtime. For an existing deployment, stop the service and take a named, +immutable copy before installing or starting the new binary. Confirm the +stopped source reports `PRAGMA user_version = 1` or `2`, retain the backup +outside the release directory, and record its checksum. On first v3 startup, +one `BEGIN IMMEDIATE` transaction first gives v1 rows a checked nullable Viewer +grant digest with a fresh fail-closed value, then gives v1/v2 rows the checked +nullable password material and advances `user_version` to `3`. -After startup, verify `PRAGMA integrity_check`, `user_version = 2`, service -health, Host reclaim, rotation, and a new Viewer join before removing the -maintenance boundary. If rollback is required, stop the v2 service, preserve the -v2 database separately for diagnosis, restore the exact v1 backup with service -ownership and mode `0600`, verify integrity and `user_version = 1`, and only then -start the old binary. Never point the old binary at the migrated v2 file. +After startup, verify `PRAGMA integrity_check`, `user_version = 3`, service +health, Host reclaim, invitation rotation, password update/removal, and a new +Viewer join before removing the maintenance boundary. If rollback is required, +stop the v3 service, preserve the v3 database separately for diagnosis, restore +the exact pre-migration backup with service ownership and mode `0600`, verify +its integrity and original user version, and only then start the matching old +binary. Never point an old binary at the migrated v3 file. Enabling persistence does not migrate rooms that existed only in memory. The deployment restart invalidates those temporary links; the first subsequently diff --git a/docs/maintenance.md b/docs/maintenance.md index 4c86a78..cbbfa36 100644 --- a/docs/maintenance.md +++ b/docs/maintenance.md @@ -33,6 +33,16 @@ 检查点应立即修改事实的权威归属文件;只有当前全局快照确实改变时才同步修改 `project-memory.md` 或 `status.md`。不要等到 session 末尾才补写,也不要为每个文件、函数、工具调用或未形成结论的探索建立检查点。 +讨论、纠正、示例、review 建议、实验结论、checkbox 或 agent 推导都只是输入,不能直接触发实现。先复述目标和源头理由,放回完整产品模型检查矛盾与不必要复杂度,再更新所有受影响的 owning requirement/design/ADR/research 以及确实变化的 memory/status/global rule,并形成 Git-tracked checkpoint。只有 nonvolatile truth 自洽后才能开始实现或派发实现;语义未决时先建立 truth hold,只冻结依赖项。 + +集成必须先让 accepted truth checkpoint 进入 main,再逐个把保留候选基于该 main 做一次 rebase 或重建。冲突以 main 的 owning truth 为底,只移植已批准的 scoped code/tests/new facts;旧分支中的 `AGENTS.md`、requirements、ADR、memory、status、deployment snapshot 不得覆盖新真相。语义裁决和集成完成后才进入 worktree/branch 清理,并继续执行 PR 等价、开放引用和 link/reparse 安全检查。 + +审计或集成阶段结束后,先显式保全仍需保留的用户修改,再让 canonical repository root 回到 clean、最新的 `main`;辅助 worktree 不得长期占用 `main`。后续每个实现分支和并行 worktree 都必须从该 canonical `main` 的精确提交创建,不能从旧候选、旧快照或另一个辅助 worktree 继续开枝散叶。只有这一步完成后,才恢复功能实现并行。 + +当真相审计与功能设计同时存在时,严格按以下依赖顺序推进:先整理 TODO 来源和全部 current truth owner,再形成文档归档及 worktree/branch/folder 处置排期;随后合入审计护栏、恢复 canonical `main` 并只执行已批准的工作区清理;然后才从该 main 做整体设计建模并把它保持为 held proposal。并行化只能加速当前阶段,不能绕过前置真相或提前执行功能实现、候选合并或部署。 + +完成 canonical root/workspace 整理和整体设计 held proposal 后,必须先向用户报告唯一 `main` SHA、根目录状态、保留/清理项、设计模型和拟恢复 TODO,等待明确核对。核对前不得接受最终争议语义,也不得为“剩余 TODO”新建或恢复实现 worktree;核对后先更新 accepted owning truth,所有高置信并行 worktree 再只从该 exact canonical `main` 创建。 + 检查点只保存以后仍需要的结论、当前状态、下一步和阻塞项。不要保存原始对话、完整日志、工具输出、临时文件路径、重复的代码结构、可随时重新搜索的常识、过程性 TODO 流水账或已经在其他规范中存在的内容。 恢复上下文时按以下顺序读取:`AGENTS.md`、`docs/project-memory.md`、`docs/status.md`、相关需求/ADR/调研,然后检查当前分支、`git status`、最近 commit 和 PR 状态。任何摘要与仓库冲突时,以当前代码、测试和正式文档为准。 @@ -59,6 +69,8 @@ ## 阶段验收后的有界架构收敛 +> `AUDIT-HOLD / HISTORICAL`:本节是 2026-08-19 的延期审查提案,不是当前授权 TODO、当前里程碑或架构不变量。其旧文件规模、owner、百分比假设、`SFU roots`/exceptional-edge/Host-two 表述只能作为 provenance 输入;必须等 [TODO audit hold](./todo-audit-hold.md) 完成、canonical root 回到最新 `main`,并由用户重新接受范围后才可重建或删除本节。 + 这是一项明确延期的收官任务。只有当前主要功能基本完成、相关主线变更合并且阶段验收完成后才可启动;它不阻断或抢占当前的质量证据、自动路由 exact-room canary、native sender 或部署工作。启动时从届时最新 `main` 建立一个短期 `refactor/` 或 `chore/` 分支。当前只记录审查契约,不实施重构。 2026-08-19 的一次只读盘点估算约有 14,153 行产品源码和 31,094 行第一方文本,并标出以下高集中度 owner: diff --git a/docs/project-memory.md b/docs/project-memory.md index 2066017..007f065 100644 --- a/docs/project-memory.md +++ b/docs/project-memory.md @@ -6,12 +6,12 @@ Last updated: 2026-08-22 - Build low-latency game sharing for one broadcaster and trusted friends; public or large broadcasts belong on OBS/Twitch-class services. - Browser first. Viewers use desktop/mobile Web; an optional sender requires a proven browser capability gap. -- Use a small central service for access, rooms, signaling, deterministic topology, STUN, observability, and bounded SFU-root capacity. -- Minimize server bandwidth. Ordinary peer ICE is STUN-only. Failure tries restart, rebuild, alternate peer and bounded SFU/UDP roots; only then may the controller authorize short-lived TURN for one selected exceptional edge before clear failure. TURN is transport, not topology. -- Current release policy is Host2/ordinary Browser Viewer1. Server authority derives the limit from authenticated role; old or malicious Viewer advertisements 2/3 remain effective1. Deployment config defaults to two and accepts only 1/2 to tighten, never lift, these limits. Web assignment execution independently truncates physical children to Host2/Viewer1 as defense-in-depth. Active/provisional/selected physical overlays count, as does Host SFU publication; ordinary upstream receive is free. A deployment limit of one promotes an occupied Host branch root before reserving its SFU publication slot. UA/visibility do not change capacity. SFU normally feeds one or two roots that retain peer descendants; its root cap remains separate. Dynamic evidence-driven capacity still requires its own acceptance. +- Use a small central service for access, rooms, signaling, deterministic topology, STUN, observability, and bounded fallback resources without turning the product into public or always-central streaming. +- Minimize server bandwidth. Ordinary peer ICE is STUN-only, and TURN remains optional selected compatibility transport rather than a topology. The exact SFU publication/subscription model, TURN placement, fallback order, and transitional resource accounting are on [truth-audit hold](./todo-audit-hold.md); earlier root, lease, or edge-count wording is not implementation authority. +- Every non-server endpoint has one server-authoritative downstream capacity, default `2` and configurable as `1`, `2`, or `3`; upstream receive is excluded, Browser role/UA/visibility does not define a separate tier, and a client cannot advertise above the deployment value. Production `9461e20` still implements the disputed Browser1/config-1-or-2 behavior; keep that divergence as a dated implementation fact until the holistic routing model is accepted and migrated. - Two-tree packet/layer striping may reduce endpoint upload toward one stream bitrate, but needs a bounded multi-parent, loss, sync, churn, and latency experiment; it is not in the current full-stream chains. -- Direct/peer keeps per-PC stock GCC. The deployed SFU path explicitly disables Dynacast, publishes exactly `q,h`, and gives each subscribed root a `HIGH` ceiling; built-in BWE may still forward `LOW`. The deployed gate enforces roots <=2, Host-publication edge accounting, and retention of a zero-child subscription. Actual shaped LiveKit BWE and resource evidence is next; if it passes, no app media selector is built. Explicit quality, manual activation, and custom/native remain fallbacks. -- A later explicit quality fallback evacuates children under a generation guard first. Autonomous BWE enters `suspect`; confirmation evacuates children, and no confirmed `FALLBACK` parent remains. Root-with-children impact is a default-on gate; capacity returns after longer recovery plus cooldown. Self-report alone never triggers it. +- Direct/peer keeps per-PC stock GCC. Production currently disables SFU Dynacast, publishes `q,h`, and starts each subscriber at a `HIGH` ceiling; the fixed root and Host-publication accounting wrapped around that path are disputed policy, while generation isolation, current authorization, and actual packet/resource evidence remain valid review inputs. +- Proposed SFU quality evacuation and recovery rules remain research inputs, not executable TODOs, until the routing truth audit decides their current consumer and ownership. - Site access protects room creation, Host publication, and every code-only Viewer entry. A valid room-scoped fragment grant bypasses that site gate; otherwise site access is checked before public-watch or a private room password. Persist neither raw credential; keep accounts, ACLs, users, and session tables out. - Prefer primary sources, maintained implementations, target-device evidence and sanitized production stats. Ordinary-PC synthetic runs prove only correctness/interoperability; never use them to calibrate performance or block a reversible standard API. Keep accepted truth in Git and replace stale facts in place. - Migrate client, server, and deployment atomically. After a canary, delete superseded config/wire/parsers/tests; do not retain compatibility layers, dual writes, or a second architecture without a current consumer. Git history owns the old implementation. @@ -26,9 +26,7 @@ Last updated: 2026-08-22 - Keep experiments bounded: the standard representation sequence is below; native RTP relay, encoded-object striping, and FEC remain separate. - Web defaults to browser/LiveKit codec negotiation; advanced settings offer Automatic, H.264, or VP8 for the next share while retaining fallback codecs and `backupCodec=false`. A codec choice neither proves hardware encoding nor shared encode. ADR-0006's browser bridge remains no-go. - Mobile endpoints are Web Viewer-only. Current Android/iOS browsers do not expose Web Host capture; AirPlay/system mirroring is Viewer-local output. -- ADR-0005: direct/peer UDP -> bounded SFU roots -> selected-edge TURN. The deployed controller caps each room at one `peer-selected` lease across negotiating and answered states; Host ingress is independent. Negotiation serializes with soft migration, while an answered exact lease is active transport and may coexist with unrelated soft MBB after route/session/share/topology/budget revalidation and carry-before-route authority. A pre-`ecc794d` exact-source/production-media canary proves active Host ingress only. Ordinary peers stay STUN-only. -- `PEER_ASSISTED_MEDIA=true` covers all rooms. One-root healthy-SFU MBB is deployed with retained parent, media proof, Host2/browser1 overlap, cooldown and fresh two-window proof; it excludes `peer-selected`. Active-SFU loss uses normal recovery; the manual control keeps its route: peer restarts its edge, SFU reauthenticates signaling and rebuilds that subscriber. Capacity `0 -> 1`, multi-root/browser gates remain open. -- C+B stays edge-local: deployed MBB gives only the triggering child one attempt to a parent with one strict spare slot: an ordinary Viewer whose active upstream is peer/SFU, or the Host. The old edge stays active; current-generation RTP, decoded frames, and live video atomically promote the same provisional PC. Viewer and Host parents keep provisional children outside their active maps, with Host SFU publication and selected overlays charged to Host2. A ready-then-failed identity survives until active/rollback, while session/share change or an unrelated authoritative failure aborts the soft probe. Failure, timeout, or no candidate keeps the old edge without SFU/TURN. Sibling MBB remains separate. No score. +- Keep automatic P2P-first routing, one authoritative upstream per Viewer, exact session/share/revision/generation authorization, bounded failure, and media-proven make-before-break. Capacity, canonical SFU publication/subscription, selected TURN, fallback order, and temporary resource leases must now be reconciled as one holistic model before another routing implementation change. - Flagship media is UDP; HTTPS/WSS stays TLS/TCP; the old release remains rollback-only. - Treat settings as ceilings and degradation as unclassified. Use correlated Host A+B/Viewer C and one-variable evidence; never force AV1, infer by UA, or create a composite score. - Screen audio: production Web capture requests speech processing off and ideal stereo. Share advanced settings offer 64/128/256 kbps sender ceilings, default 128, and lock the choice for the active share across P2P, browser relay, and SFU. Peer answers permit stereo up to 256 kbps; SFU keeps `forceStereo`, DTX off, and RED retained. Local Viewer details expose non-uploaded A/V playout, jitter-buffer, and concealment evidence. Target-browser/route proof remains open; voice and Native stay separate. @@ -38,7 +36,9 @@ Last updated: 2026-08-22 ## Current Execution Principle -- Parallel flagship work; minimum relevant checks and rollback proof. Research plus target-device/production evidence drives product choices; synthetic runs cover only correctness/interoperability. Active text is current, Git owns history, and no-consumer layers are deleted. +- Durable truth precedes action: reconcile each discussion or correction against the whole product model, challenge conflicts, update all affected owning truth and current snapshots, and create a Git checkpoint before implementation or implementation sub-agents begin. Unresolved semantics enter a truth hold instead of code. +- While the 2026-08-22 truth audit is open, load [the TODO audit hold](./todo-audit-hold.md) before selecting work. Old checkboxes, branch names, agent suggestions, experiments, and post-boundary follow-ups are inputs, not authorization. +- Current phase order is fixed: reconcile TODO provenance/current truth; schedule archives and workspace disposition; merge the audit guard and restore canonical `main`; then produce a holistic routing held proposal. Report that organized state and proposal to the user before accepting route semantics or resuming any remaining TODO. ## Current Implementation diff --git a/docs/research/advanced-peer-distribution.md b/docs/research/advanced-peer-distribution.md index 85ab023..7c5feae 100644 --- a/docs/research/advanced-peer-distribution.md +++ b/docs/research/advanced-peer-distribution.md @@ -8,6 +8,8 @@ evidence is unverified; relay-capacity `0 -> 1`, multi-root reselection, and advanced encoded-media routes remain unimplemented candidates +> Truth-audit note: this document remains research evidence, not a backlog. Any current-capacity, SFU-root, TURN, fallback, or accounting assertion is held by the [TODO audit hold](../todo-audit-hold.md) until the holistic route model is accepted. + ## Terms - **Multiple trees:** split one media representation into two stripes and send diff --git a/docs/research/browser-screen-audio-quality.md b/docs/research/browser-screen-audio-quality.md index b12aae5..4dfd862 100644 --- a/docs/research/browser-screen-audio-quality.md +++ b/docs/research/browser-screen-audio-quality.md @@ -190,9 +190,11 @@ Chrome/Edge baseline, while the RFC still defines the parameter as a receiver maximum rather than a minimum or continuous bitrate guarantee. The poor movie/music report against production `6ccb516` began under a -historical mono negotiation contract, but it remained after the current source -added peer `stereo=1;maxaveragebitrate=128000` and SFU `forceStereo: true`, -128 kbps, DTX off, and RED retained. Those encoder settings cannot restore PCM +historical mono negotiation contract, but it remained after a later 128-only +source stage added peer `stereo=1;maxaveragebitrate=128000` and SFU +`forceStereo: true`, 128 kbps, DTX off, and RED retained. Current Share advanced +settings provide 64/128/256 kbps sender ceilings with 128 kbps as the default; +those encoder settings still cannot restore PCM already changed or collapsed to mono by the Host capture processor. Loss, jitter and concealment remain separate diagnostic facts, but direct SFU reproduction makes source processing the first reversible correction. diff --git a/docs/research/built-in-peer-ice-turn.md b/docs/research/built-in-peer-ice-turn.md index 298ff38..180fbca 100644 --- a/docs/research/built-in-peer-ice-turn.md +++ b/docs/research/built-in-peer-ice-turn.md @@ -5,10 +5,18 @@ exact-room canary - Status: rejected after bounded production canary; historical evidence only +> Truth-audit boundary: the rejection of participant-wide TURN and the +> STUN-only ordinary-peer fact remain valid inputs. The exact SFU/TURN order, +> one-lease room policy, Host-ingress exception, and resource accounting below +> describe the deployed candidate or a historical recommendation and are held +> by the [TODO audit](../todo-audit-hold.md); they are not current design +> authority. + ## Decision Do not deploy or continue the built-in participant-wide candidate. Ordinary -peer connections remain STUN-only. The accepted ladder is: +peer connections remain STUN-only. Exact release `9461e20` implements this +ladder, whose future placement and accounting are now held: ```text direct/peer UDP -> SFU/UDP virtual parent -> selected-edge TURN -> failure @@ -77,8 +85,9 @@ acceptance supplied no compensating runtime evidence. ## Selected-Edge Boundary -A correct replacement is not a renamed participant refresh API. It must be one -coherent controller-owned change with a current consumer: +The deployed selected-edge replacement was designed as one coherent +controller-owned change with a current consumer. The list below records that +source boundary; fixed counts and ordering remain held: - a complete default-off deployment tuple with an independent secret, one explicit TURN/UDP URI, bounded TTL, quota, bandwidth, and relay-port limits; diff --git a/docs/research/low-server-media-routes.md b/docs/research/low-server-media-routes.md index 08c1676..f6d8f6f 100644 --- a/docs/research/low-server-media-routes.md +++ b/docs/research/low-server-media-routes.md @@ -11,6 +11,8 @@ passed active Host SFU -> selected TURN/UDP ingress. Initial ingress, peer-selected last mile, external cohorts, and performance remain unverified. +> Truth-audit note: ordinary STUN-only ICE, automatic P2P-first intent, exact generation authorization, and dated canary facts remain inputs. Fixed root counts, room-wide selected-lease limits, SFU/TURN placement, fallback order, and resource accounting are disputed under the [TODO audit hold](../todo-audit-hold.md) and cannot authorize implementation yet. + ## Current Route Ladder The smallest current plan is: @@ -247,13 +249,15 @@ change or explicit reconnect; it does not support periodic probing, a carrier **3. Healthy SFU-to-P2P bounded re-probe** -- Current state: production `27ad90d` has the deployed one-root slice: it +- Historical checkpoint: production `27ad90d` had the first deployed one-root slice: it reserves bounded capacity, keeps the healthy SFU route playing, proves one fresh P2P generation with current decoded-media progress, then commits - atomically and closes the old route. Current source `4c9174d` additionally + atomically and closes the old route. Source `4c9174d` additionally retains one cooldown-time opportunity as a current tuple and requires two new - evidence windows at expiry; that continuation is not deployed. Neither polls - network state. + evidence windows at expiry. Later production deployed that bounded continuation + and subsequent peer-quality MBB work. Exact current capacity, SFU, TURN, and + accounting semantics are now frozen by the truth-audit hold. None of these + generations polls network state. - Retained candidate: a discrete network-change or explicit-reconnect event may open one opportunity through that same controller after cooldown. It must not create a second route controller or treat an ICE restart on the SFU diff --git a/docs/research/native-shared-encode-sender.md b/docs/research/native-shared-encode-sender.md index 5d58043..dcc8dd3 100644 --- a/docs/research/native-shared-encode-sender.md +++ b/docs/research/native-shared-encode-sender.md @@ -155,8 +155,8 @@ strict ordinary signaling wire, unmodified viewers, read-only feedback, and no audio or automatic `LOW`. This is a proposed test boundary, not current product behavior or hardware-encoder evidence. -The 2026-08-20 local delivery checkpoint rebases that candidate onto the sole -current access contract: `screener-v2`, site-access Cookie authentication, +The 2026-08-20 local delivery checkpoint rebased that candidate onto the +then-current access contract, `screener-v2`, with site-access Cookie authentication, explicit `private-link` creation, fragment-only Viewer grants returned to the local Host, and STUN-only ordinary ICE. Native creation alone requests a fixed 300-second provisional room. It remains random and memory-only even with SQLite @@ -164,8 +164,11 @@ configured: the current Host session suppresses the reclaim deadline, its generation-matched disconnect resets the five-minute window, the ordinary transient room TTL still caps the room, and restart drops it. A pre-auth connection or authentication failure gets one same-room/token/client-generation -retry without a second room POST. SQLite remains v2 and ordinary Web creation is -unchanged. +retry without a second room POST. SQLite remained v2 and ordinary Web creation +was unchanged. Current Web and source-only Native have since moved to +`screener-v5`, and current room persistence is SQLite schema v3. Retaining this +paragraph records the dated candidate boundary; it does not authorize new work +against v2. Android stop/capture-failure cleanup keeps the established signaling socket until its single-thread teardown sends `abandon-room` and then performs a normal close; pending-work cancellation only blocks callbacks and cancels active HTTP. No ACK diff --git a/docs/research/peer-assisted-media.md b/docs/research/peer-assisted-media.md index fcb8b3b..1500fb0 100644 --- a/docs/research/peer-assisted-media.md +++ b/docs/research/peer-assisted-media.md @@ -7,6 +7,8 @@ accepted ADR-0005 owns automatic peer/SFU routing. Production later removed the room-`1` rollout boundary; retained SFU media remains unverified. +> Truth-audit note: dated measurements and exact deployed behavior remain valid within their stated environments. Browser1, fixed SFU-root-two, publication/selected-edge accounting, and future capacity conclusions are disputed inputs under the [TODO audit hold](../todo-audit-hold.md), not current product policy or executable gates. + ## Conclusion Peer-assisted forwarding can cap the broadcaster at one or two outgoing media diff --git a/docs/research/realtime-quality-adaptation.md b/docs/research/realtime-quality-adaptation.md index b8f98de..498233a 100644 --- a/docs/research/realtime-quality-adaptation.md +++ b/docs/research/realtime-quality-adaptation.md @@ -485,6 +485,12 @@ activation/deactivation. ### SFU Root Invariant Preflight +> Truth-audit boundary: this section records what the 2026-08-22 source gate +> asserted. Its fixed root count and Host-publication edge accounting are under +> the [TODO audit hold](../todo-audit-hold.md), not accepted product invariants. +> Dynacast/layer configuration and the limits of in-process evidence remain +> valid observations. + The 2026-08-22 `gate:sfu-root-invariants` source gate proves that the publisher passes explicit `dynacast: false`, exposes exactly the ordered active `q,h` encodings, and the selectively subscribed screen publication retains a `HIGH` @@ -664,13 +670,13 @@ resolution, frame rate, or bitrate. target guarantees, and the project does not use SDP bitrate hacks. - The folded “advanced video” panel accepts only 720p/1080p/1440p, integer 15-60 fps, 2-12 Mbps, the three preferences, and Automatic/H.264/VP8. Codec - selection is locked during a share and applies to the next one. It exposes no - audio quality controls and is not renamed in the screen-audio slice. Display capture does - not standardize channel-count or sample-rate control; the portable audio - `maxBitrate` field remains only a 128 kbps ceiling. The accepted peer - exception is a structured Viewer-answer Opus - `stereo=1;maxaveragebitrate=128000` receive contract, paired with pinned - LiveKit's explicit high-quality stereo/forceStereo option. + selection is locked during a share and applies to the next one. The panel is + now Share advanced settings and also offers 64/128/256 kbps audio sender + ceilings, default 128, locked during the active share. Display capture does + not standardize channel-count or sample-rate control. The peer receive + contract permits Opus `stereo=1;maxaveragebitrate=256000`, paired with pinned + LiveKit's explicit high-quality stereo/forceStereo option; the selected sender + ceiling remains separate from negotiated and observed bitrate. DTX stays fixed off, RED retains the pinned SDK default, and FEC remains browser/SDK negotiation, not a control or custom adaptation algorithm. The full boundary is recorded in `docs/research/browser-screen-audio-quality.md`. diff --git a/docs/research/webrtc-p2p-screen-sharing.md b/docs/research/webrtc-p2p-screen-sharing.md index 37cac3c..db7804f 100644 --- a/docs/research/webrtc-p2p-screen-sharing.md +++ b/docs/research/webrtc-p2p-screen-sharing.md @@ -6,6 +6,8 @@ - 目标场景:一名玩家向少量熟人私密分享,观看者可用手机/桌面浏览器加入,低延迟,尽量不消耗媒体服务器带宽 - 结论状态:本文记录已部署 PoC 的 P2P/coturn 基线。ADR-0005 与[低服务器成本媒体路由](./low-server-media-routes.md)已取代本文早期“每条 peer edge 必带 TURN”的旗舰建议;生产后续移除了 room `1` 边界,ordinary ICE 仍为 STUN-only,selected-edge TURN 已配置但尚未完成真实媒体验收 +> Truth-audit boundary: direct/peer first、ordinary STUN-only 和 dated production evidence 仍是输入;固定 SFU/TURN 顺序、root/lease 数值和资源计账受 [TODO audit hold](../todo-audit-hold.md) 约束,不是当前实现授权。 + ## 结论 这个想法可行,而且非常适合先做 Web MVP。它的定位不是缩小版 Twitch,而是好友之间临时、私密、低延迟的实时窗口。正确的首版不是“完全没有服务器”,而是把系统拆为轻量控制面和 P2P 优先的数据面;分享者可以先用 Web/Electron,观看者应能直接打开手机或桌面浏览器链接: @@ -18,7 +20,7 @@ | +---- direct/peer UDP -> SFU root -> selected TURN edge -旗舰目标顺序:direct/peer UDP -> SFU virtual parent 服务必要 roots -> optional selected-edge TURN -> 明确失败;生产只为 room `1` 开启未验收 retained media 的 exact smoke。 +2026-08-18 的历史目标顺序是 direct/peer UDP -> SFU virtual parent -> optional selected-edge TURN -> 明确失败;room `1` 只是首个 bounded production smoke,生产后来移除了 exact-room 边界并对所有房间运行 automatic controller。retained-media 验收仍未完成,未来 SFU/TURN 顺序与计账受 truth-audit hold 约束。 系统必须无感完成拓扑分配、恢复和必要迁移;大规模公开分享仍直接使用现有直播服务。 ``` @@ -117,10 +119,10 @@ IETF 对 mesh/SFU 的拓扑说明见 [RFC 7667](https://www.rfc-editor.org/rfc/r - 生产已移除 exact-room allowlist,所有房间由 bounded peer-assisted/SFU controller 自动路由;ordinary peer 仍使用 STUN-only ICE。 - 当前 PoC 默认允许八名观看者,部署者可配置 1 至 16,超额连接会被明确拒绝。该数值只控制接入,不代表 1:8 已通过性能验收;必须收集可用上行、实际发送码率、`qualityLimitationReason`、编码耗时和发送队列来确定真实可持续人数。 - 每条 ordinary peer 链路独立使用 STUN-only ICE;只有控制器选中的异常 edge 才会获得短期 TURN credential。 -- 所有房间在 peer recovery 与 alternate parent 耗尽后均可准备最多两个 SFU/UDP roots;首次 room `1` smoke 已观察到 participant entry,但 retained media 尚未验收。 +- Exact release `9461e20` 的所有房间在 peer recovery 与 alternate parent 耗尽后可准备最多两个 SFU/UDP roots;这是受 truth-audit hold 约束的已部署事实,不是未来固定 root 数的授权。首次 room `1` smoke 已观察到 participant entry,但 retained media 尚未验收。 - 桌面和手机观看者使用同一个 Web 播放端;分享者不要求朋友安装完整客户端。 -产品目标要求分享端 fanout 永远不超过二。ADR-0004 的可删除实验验证第三名及后续 viewer 由客户端转发;ADR-0005 的自动 controller 已在 room `1` 受限部署,SFU 只服务必要 roots 并保留 peer descendants。retained SFU media、移动端矩阵和 broad rollout 仍未通过门槛;已关闭 PR #12 的显式整房 SFU 模式不再是当前方案。超过小房间上限时仍建议使用外部直播服务。观察项包括: +当前接受的非服务器 endpoint downstream 默认值为二,并允许部署静态配置为一、二或三;分享端及 Viewer 遵守同一规则。ADR-0004 的可删除实验验证第三名及后续 viewer 可由客户端转发;ADR-0005 的自动 controller 最初在 room `1` 受限部署,现已覆盖所有房间。未来 SFU/TURN 层级、计账和 fallback 顺序仍在 truth-audit hold 中。retained SFU media、移动端矩阵和 broad rollout 仍未通过门槛;已关闭 PR #12 的显式整房 SFU 模式不再是当前方案。超过小房间上限时仍建议使用外部直播服务。观察项包括: - 正常工作负载持续超过实测可承载的 P2P 人数。 - 当前 edge 已耗尽 peer recovery、alternate parent 与 SFU/UDP;未来只有该 edge 可进入 selected-edge TURN 决策。 diff --git a/docs/status.md b/docs/status.md index 1035d6d..913d16f 100644 --- a/docs/status.md +++ b/docs/status.md @@ -4,6 +4,8 @@ Last updated: 2026-08-22 This file is the current execution index. Load [verification status](./verification-status.md) only when evidence or acceptance boundaries are relevant; Git history owns completed timelines. +Execution is temporarily constrained by the [TODO audit hold](./todo-audit-hold.md). Held items remain preserved but must not be continued, merged, deployed, deleted, or treated as current product truth until their provenance and semantics are reviewed. + ## Production - `https://share.bonfire.icu` runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, wire `screener-v5`; `21d5cd9f7139` is the rollback release. @@ -11,7 +13,9 @@ This file is the current execution index. Load [verification status](./verificat - Ordinary ICE is STUN-only. Production allows SFU roots <=2, one `peer-selected` lease across negotiating and answered states excluding Host ingress, selected UDP TTL 120, and room admission default eight with explicit limits from one through sixteen. `MAX_PEER_RELAY_DOWNSTREAM_EDGES` is unset, so effective downstream capacity is Host2/ordinary Browser Viewer1; active, provisional, selected, and Host SFU publication edges count. The wire remains `screener-v5`. - Stable SFU, route/transport truth, pause notices, entry/nickname UI, selected-edge lease authority, corroborated bad-relay handling, Share audio presets, local media-path diagnostics, pre-share self-check, privacy-safe diagnostic export, signaling-partition recovery, and peer-quality MBB are live. An ordinary Viewer with a peer/SFU upstream or the Host may own one separately budgeted provisional child; sibling MBB remains open. Native remains source-only. -## Current Product Snapshot +## Current Source And Production Snapshot + +The route-capacity, SFU-root, publication-accounting, and selected-lease statements below describe exact deployed/source behavior, not an accepted future product model. Their semantics are frozen by the [TODO audit hold](./todo-audit-hold.md). - Capture precedes room creation. Balanced, automatic codec, and 128 kbps screen audio are defaults; clarity/fluid, H.264/VP8, and 64/128/256 kbps audio are deployed next-share choices. Codec and audio quality lock during a share. - Local-only connection details expose current Host SFU sender evidence, actual codec/fmtp and encoder fields, media-source/encode FPS evidence, A/V playout/jitter/concealment evidence, and selected candidate endpoints. These fields do not enter quality signaling, server state, logs, persistence, or route selection. @@ -27,15 +31,15 @@ This file is the current execution index. Load [verification status](./verificat ## Active Milestone -1. Verify the deployed Share audio presets and local observability on target browsers and real routes: field availability, actual values, negotiated/observed bitrate, audible quality, A/V synchronization evidence, candidate endpoints, and route switches. -2. Run one representative production-room UDP/frame/cap/stop canary. Validate initial ingress, `peer-selected`, bad-relay reparenting, and healthy SFU reselection without changing the STUN-only ordinary-peer policy. -3. Run pinned LiveKit with isolated per-leaf shaping to prove zero-child SFU BWE downshift/recovery and resources before implementing explicit evacuation or another media selector; the root-invariant/Dynacast-off gate is deployed. -4. Complete Native package download, Viewer2/FIFO, hardware/endurance, and game A/V evidence; use target-device or production measurements for performance decisions. -5. Run the Host2/ordinary Browser Viewer1 relay resource/quality and heterogeneous-network gates. ADR-0004 cap2/cap3 results remain historical experiments. A 20-viewer matrix is required before any accepted scale-default change; mobile remains a compatibility observation, not a capacity class. +1. Reconcile TODO provenance and every current truth owner; distinguish accepted requirements, disputed holds, deployed facts, historical evidence, and conditional research. +2. Produce the document/archive and worktree/branch/folder disposition schedule without deleting, rebasing, merging, or moving held material. +3. Merge the audit-guard truth, restore the canonical repository root to exact latest `main`, and execute only the approved workspace cleanup schedule. +4. Produce the holistic routing model from that canonical truth as a held proposal without implementation. +5. Report the organized canonical root/main, retained/cleaned workspace, routing proposal, held candidates, and proposed remaining TODOs to the user and wait for explicit confirmation. Only then accept final route semantics, update their owning truth, and merge that truth into canonical `main`; only from that exact newer SHA may other TODOs be resumed, parked, superseded, or cleaned. Previous audio, route-canary, SFU-shaping, Native, mobile, and scale items remain preserved in their owners but are not the active execution order. ## Decisions And Blockers -- ADR-0004/0005 remain No-Go for broad rollout. DNS/TLS, independent secrets, UDP 7882, and bounded services are deployed, but real external media/device evidence and the isolated VM/IP clean-port gate remain open. +- ADR-0005's automatic controller is deployed for all rooms. ADR-0004's experimental claims and any broad media, performance, resource, scale, or device acceptance remain No-Go until their explicit evidence gates pass; DNS/TLS, independent secrets, UDP 7882, and bounded services are deployed, while real external media/device evidence and the isolated VM/IP clean-port gate remain open. - Initial deployment region and expected network cohort are undecided. - Project license and distribution model are undecided; GPL/AGPL sources remain study-only. diff --git a/docs/todo-audit-hold.md b/docs/todo-audit-hold.md new file mode 100644 index 0000000..61d663f --- /dev/null +++ b/docs/todo-audit-hold.md @@ -0,0 +1,118 @@ +# TODO Execution Audit Hold + +Last updated: 2026-08-22 + +This is a temporary execution quarantine, not a backlog and not a deletion list. It prevents old assumptions, unchecked requirements, experimental conclusions, and agent-generated follow-ups from becoming authorized work after context compaction. + +## Boundary And Rules + +- Audit boundary: 2026-08-22 02:51:57 HKT, when broad TODO discovery and parallel execution began. Work already active before that point keeps its prior status; it does not automatically authorize new follow-ups. +- `CONFIRMED`: the user explicitly requested the product scope. The implementation still needs normal design and risk review. +- `REVIEW-REQUIRED`: the direction is relevant, but routing/state semantics must be reconciled before more changes merge or deploy. +- `AUDIT-HOLD`: preserve and inspect only. Do not continue, merge, deploy, delete, or revert it until provenance, necessity, and current semantics are reviewed. +- `EVIDENCE-ONLY`: retain reproducible measurements, but do not infer product policy, performance, capacity, or a release gate from them. +- `PRODUCTION-FACT`: a dated deployment record. It describes what ran, not what the product should continue to do. +- `SUPERSEDED`: a retained recovery/reference input that must not be executed. Remove it only after the truth audit and the normal Git/link safety checks. + +Latest direct user decisions override contradictory older text during this audit: every non-server endpoint uses one server-authoritative downstream cap, default `2` and configurable as `1`, `2`, or `3`; upstream receive is free; Browser/UA/visibility does not define a separate tier. The routing audit must still settle SFU publication/subscription semantics, TURN accounting, and transitional resource leases as one system. + +## Audit Order + +1. Reconcile TODO provenance and the current truth set. Classify contradictions and holds without implementing them. +2. Produce the documentation/archive and worktree/branch/folder disposition schedule. Preserve all disputed or unknown material; do not delete, move, rebase, or merge it yet. +3. Merge this audit-guard truth, restore the canonical root to exact current `main`, and execute only the approved workspace cleanup schedule. +4. Produce the holistic routing model from those reconciled inputs as a held proposal; do not implement or silently accept disputed semantics. +5. Stop and reconcile the organized canonical state, routing proposal, and proposed remaining TODOs with the user. Only after explicit confirmation may the final owning route truth be accepted, high-confidence worktrees start from exact canonical `main`, or other TODOs be resumed, parked, superseded, or cleaned from the reviewed ledger. + +Parallel work may accelerate one active phase, but it must not start a later phase early. + +## Requirement Checkbox Audit + +`docs/需求理解.md` currently contains 41 checkbox lines: 37 unchecked and 4 checked. They are acceptance-contract formatting, not a backlog: + +- At least 18 unchecked lines describe behavior that current status/memory already call live or substantially deployed, including entry/room flows, capture/pause, presence, P2P-first routing, quality settings, recovery, observability, access, grants, persistence, private entry, automatic routing, and peer-assisted forwarding. +- Nine unchecked lines overlap disputed capacity, SFU, TURN, fallback, quality-parent, or accounting semantics (`27`, `29`, `31`, `32`, `44`, `48`, `53`, `57`, `63`). They cannot authorize implementation while held. +- Eight unchecked lines are conditional experiments, no-go/reopen conditions, later native/desktop work, platform-output boundaries, or regional questions (`47`, `49`-`52`, `54`, `65`, `66`), not current implementation tasks. +- The four checked lines are not proof of current authorization: connection self-check (`56`) and diagnostic export (`59`) remain provenance holds, while codec choice (`58`) and the Native capture helper (`64`) retain their separately scoped facts and evidence boundaries. + +These groups overlap. Therefore neither 37 nor any subtraction from it is the executable TODO count. A normal TODO may be created only after its owning requirement is rewritten as current accepted behavior or a specific remaining gap, its implementation and production facts are reconciled, and any dependent hold is removed. + +## Current Truth Owner Risk + +- `AGENTS.md`, `docs/project-memory.md`, and `docs/status.md` are auto-loaded and must never mix disputed policy into confirmed intent or active milestones. During this audit they point here and separate dated production behavior from future product truth. +- `docs/需求理解.md`, `docs/方案设计.md`, and accepted ADR-0005 contain mixed deployed, historical, experimental, and disputed routing text. Their temporary banners freeze only the disputed route-dependent meaning; the accepted P2P-first, automatic, exact-generation, bounded-failure direction remains. +- `docs/verification-status.md` and `docs/deployment.md` may retain Browser1/root-two statements only as dated `9461e20` production evidence. Evidence does not authorize the next design. +- Research and historical ADR text remains source material. A proposal, threshold, benchmark, future gate, or past accepted status cannot become current work until its owner is reconciled against this hold. + +## Pre-Boundary Active Scope + +These scopes were already active or directly requested before broad TODO execution. Keep them, but do not extrapolate adjacent work from them: + +Git history also shows mixed-provenance PRs: #164's core demotion commit was authored before the boundary while later selected-lease fixes landed in the same PR after it; #166's Host SFU and selected-endpoint work started before the boundary while encoder/A-V evidence was integrated afterward. Audit behavior and source, not just PR number. + +| Scope | Status | Boundary | +| --- | --- | --- | +| Bad-relay corroboration, downgrade, reparenting, and make-before-break correctness | `REVIEW-REQUIRED` | Core user request; must now be reconciled with cap, SFU/TURN fallback, odd/full topology, and route generations as one design. | +| Share advanced audio settings and 64/128/256 kbps sender ceilings | `CONFIRMED` | Sender ceilings and observability are not fidelity proof. | +| Local connection details, selected candidate endpoints, and A/V observations | `CONFIRMED` | Local observation only; do not infer public IP, correction, or route authority. | +| Status archive/index policy and bounded NAT research | `CONFIRMED` | Documentation governance/research only; neither creates product runtime work. | + +## Post-Boundary Mainline Changes + +The range begins at PR #164. A merged or deployed item can still be under audit; do not rewrite production history. + +| Item | Status | Audit reason | +| --- | --- | --- | +| #164 relay-parent demotion | `REVIEW-REQUIRED` | Requested behavior, but the bundled selected-lease/cap state must be checked against the unified route model. | +| #165 share audio presets | `CONFIRMED` | Directly requested product behavior. | +| #166 local media-path evidence | `CONFIRMED` | Covers requested endpoint/A-V observability; remains observation-only. | +| #167 status/verification split | `CONFIRMED` | Direct response to the status-budget/archive decision. | +| #168 cap3 topology benchmark | `EVIDENCE-ONLY` | Functional evidence for configurable cap; not a performance ranking or release gate. | +| #169 connection self-check | `AUDIT-HOLD` | Automatically expanded from an old broad checkbox; its reduced health/WSS/STUN contract was not independently reconfirmed. | +| #170 explicit 16-Viewer admission | `AUDIT-HOLD` | Restored an older configurable contract without a fresh product-size decision; default remained eight. | +| #171 diagnostic JSON export | `AUDIT-HOLD` | Automatically expanded from an old diagnostic-page checkbox; no confirmed support workflow. | +| #172 relay resource benchmark | `EVIDENCE-ONLY` | Short same-machine evidence cannot select cap or block reversible cap2. | +| #173 peer-quality MBB | `REVIEW-REQUIRED` | Requested routing direction; state/mutex/fallback behavior needs holistic audit. | +| #174 and #176 rollout records | `PRODUCTION-FACT` | Dated deployment records only. | +| #175 Viewer-parent provisional edge | `REVIEW-REQUIRED` | Required by MBB safety, but must fit the final lease/accounting model. | +| #177 Browser1 clamp | `AUDIT-HOLD` | Reversed prior cap2 behavior without failure evidence and conflicts with the latest explicit cap decision. | +| #178 routing-lifecycle truth | `AUDIT-HOLD` | Propagated Browser1 and room-global lease assumptions that are now disputed. | +| #179 SFU root-two invariant | `AUDIT-HOLD` | Hardened a conservative design constant without LiveKit/resource evidence; publication/subscription topology is under review. | +| #180 audio/production truth | `PRODUCTION-FACT` | Audio facts remain useful; adjacent routing claims are not reauthorized. | +| #181 selected-pair response observation | `AUDIT-HOLD` | Agent-generated diagnostic slice with no prior product requirement or recovery authority. | +| #182 signaling silent-partition watchdog | `AUDIT-HOLD` | Useful failure detection is plausible, but Host continuity and selected-edge session replacement remain unproven. | +| #183 Host-parent provisional edge | `REVIEW-REQUIRED` | Requested routing direction; retain while auditing the unified topology/lease model. | +| #184 and #189 production records | `PRODUCTION-FACT` | Dated deployment records only. | +| #185 SFU shaping prerequisites | `EVIDENCE-ONLY` | Environment prerequisite record; not a product feature or blocker for unrelated work. | +| #186 and #190 Browser1 truth changes | `AUDIT-HOLD` | Repeated the disputed Browser1 assumption into auto-loaded truth. | +| #187 relayed-detail stability | `CONFIRMED` | Completes the requested stable connection-detail presentation without new wire or route authority. | +| #188 route-recovery evidence | `EVIDENCE-ONLY` | Retain exact test limits; do not treat it as real network/SFU/TURN proof. | +| #191 Viewer MBB canary | `EVIDENCE-ONLY` | Synthetic evidence plus real local PCs; no detector, network, or performance claim. | +| #192 A/V sync fixture (open) | `EVIDENCE-ONLY` | Freeze merge while the audit is open; measurement plumbing is not a correction loop or quality proof. | + +## Frozen Local Candidates + +| Candidate | Status | Next audit action | +| --- | --- | --- | +| `fix/configurable-relay-cap` | `REVIEW-REQUIRED` | Preserve the draft; do not continue until the unified route/accounting model is accepted. | +| `test/signaling-blackhole-canary@e972b75` | `EVIDENCE-ONLY` | Retain for the #182 decision; it proves Viewer continuity only. | +| `docs/resource-matrix-gate@140dd00` | `EVIDENCE-ONLY` | Preserve the short-run data; do not merge old Browser1 policy text. | +| `test/real-relay-canary@f135302` | `EVIDENCE-ONLY` | One-line #191 report correction may still be useful even though the later local canary helper also contains it. | +| `docs/routing-algorithm-convergence@43b1f46` | `AUDIT-HOLD` | Historical design input only; it contains stale capacity assumptions. | +| `fix/connection-details-stability@55f4cbc` | `SUPERSEDED` | Design input superseded by #187; retain until cleanup audit. | + +## Unresolved Routing Inputs + +These are user-supplied scenarios to test against the holistic route model. They are neither accepted implementation designs nor executable TODOs yet. + +1. A Host may reach media only through selected TURN while two first-level roots also cannot relay onward directly and need SFU-backed delivery. The final model must avoid two independent peers republishing the same screen into two competing SFU source truths. Audit whether one canonical share-generation publication, with TURN used only for its ingress when necessary, lets both roots and their descendants subscribe without duplicated encoding or lineage. +2. A mostly healthy room may already have two ordinary root branches when a newly joined leaf cannot receive its assigned P2P edge and needs SFU. Audit whether the leaf should leave that peer edge and subscribe to the room's canonical publication while its previous parent reclaims the ordinary child slot. Do not assume the intermediate parent must republish the same source. +3. Retain optional selected TURN during this audit. Decide keep, narrow, or remove only after comparing its exact-edge and Host-to-SFU-ingress value against credential, lease, recovery, and state-machine complexity. The examples above are not by themselves evidence that TURN should be removed. + +The preferred simplicity test is one Host screen lineage, at most one canonical SFU publisher per share generation, selective SFU subscribers wherever P2P is unavailable, ordinary peer descendants where healthy, and TURN as a transport lease rather than another topology. This is a review hypothesis, not yet accepted architecture. + +## Release Of A Hold + +For each held item, record: original user requirement or lack of one; current consumer; behavior and rollback cost; security/privacy/resource boundary; conflicting facts; and a keep, revise, park, or remove decision. Only then update the owning requirement/ADR/research/status text in place. Do not use this temporary file as permanent architecture documentation. + +Merge this audit-guard truth first; that merge does not accept a final routing model. Then preserve any root user changes, release `main` from auxiliary worktrees, and restore the canonical repository root to the exact latest `main`. Complete only the approved workspace cleanup, produce the holistic routing proposal as a held document, report the organized state and proposal, and wait for explicit user confirmation. Only afterward may accepted route semantics be written into their owning truth and merged into `main`; retained candidates or remaining TODOs may be rebuilt or resumed only from that newer exact canonical-main commit. Candidate-era truth files must never overwrite it. diff --git a/docs/verification-status.md b/docs/verification-status.md index ab19499..e812422 100644 --- a/docs/verification-status.md +++ b/docs/verification-status.md @@ -6,6 +6,8 @@ Last updated: 2026-08-22 This is the demand-loaded ledger for cross-cutting validation evidence and open proof boundaries that do not fit one requirement, ADR, research note, or deployment guide. It is current state, not a release diary: replace superseded facts in place, move durable specialist conclusions to their owning documents, and let Git history retain completed timelines. +During the 2026-08-22 truth audit, Browser1/root-two/accounting entries below describe exact release evidence only. They do not define the next product model or create executable gates; see the [TODO audit hold](./todo-audit-hold.md). + ## Deployment Evidence - Production runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, with `21d5cd9f7139` retained for rollback. @@ -18,7 +20,7 @@ This is the demand-loaded ledger for cross-cutting validation evidence and open ## Retained Functional Evidence -- Chrome 151 synthetic `1/3/5/8` and 720p30 runs preserved bounded fanout and decoding. A current-release three-Viewer rerun also kept Host2/Browser Viewer1, decoded every Viewer, and recovered a hard first-level relay departure in 5,380 ms; it did not exercise quality-triggered MBB. Sixteen-Viewer cap2/cap3 loopbacks decoded all Viewers and a ten-second follow-up recorded guarded sender and aggregate Chromium CPU evidence, but resolution/FPS remained low and the ordinary-PC data cannot rank the caps. These are functional experiments, not sustainable-capacity, heterogeneous-network-quality, or authority to lift the Host2/ordinary Browser Viewer1 release policy. See [peer-assisted media](./research/peer-assisted-media.md). +- Chrome 151 synthetic `1/3/5/8` and 720p30 runs preserved bounded fanout and decoding. A `9461e20`-era three-Viewer rerun kept Host2/Browser Viewer1, decoded every Viewer, and recovered a hard first-level relay departure in 5,380 ms; it did not exercise quality-triggered MBB. Sixteen-Viewer cap2/cap3 loopbacks decoded all Viewers and a ten-second follow-up recorded guarded sender and aggregate Chromium CPU evidence, but resolution/FPS remained low and the ordinary-PC data cannot rank caps, select product policy, or prove sustainable heterogeneous-network quality. See [peer-assisted media](./research/peer-assisted-media.md). - Chrome 151 with local LiveKit 1.13.5/client 2.22.0 proved one SFU/UDP root after `q,f` -> `q,h`: decoded frames advanced 3 -> 23, rendered frames reached 26, Host used one edge, leaves were clean, and TURN was absent. This is functional evidence only. See [low-server media routes](./research/low-server-media-routes.md). - Host A+B and authenticated P2P Viewer C evidence is sanitized, generation-bound, read-only, and closed for stale, ambiguous, or SFU-fed reports. Production can expose a Host-local current SFU `h` snapshot and clears it on publisher identity changes; raw media metadata is not retained. See [realtime quality adaptation](./research/realtime-quality-adaptation.md). - The built-in peer TURN canary was rejected after allocation passed but the direct Host/Pion Viewer path failed before forced relay. Full rollback restored STUN-only client ICE and zero allocations. See [built-in peer ICE TURN](./research/built-in-peer-ice-turn.md). @@ -30,8 +32,8 @@ This is the demand-loaded ledger for cross-cutting validation evidence and open - Routing: verify current-release initial ingress, `peer-selected` expiry/failure, corroborated bad-relay reassignment, one-root healthy SFU reselection, silent partitions, and bounded failure on real browser/media paths. Silent control partitions may wait 30 to 60 seconds for heartbeat detection before the default five-second grace. - Quality: production startup blur remains unclassified. One same-`balanced` local A/B retained route/PC/SSRC/track while 720p rose to 1080p, but natural ramp prevents causal, production, or SFU conclusions. Correlate Host capture/encode/send with Viewer receive/decode before changing policy. -- Relay resources: production is Host2/ordinary Browser Viewer1 and rejects any Viewer child2 regardless of advertised capacity. Two-child relay corroboration is therefore a future-capacity experiment, while the triggering child's edge-local MBB remains active. Relay CPU/GPU/upload cost and heterogeneous-network behavior remain unverified. Finish the role-aware matrix before the 20-viewer gate or any future capacity-tier change. -- SFU: production deploys ordered `q,h`, roots <=2, and Dynacast off. Real zero-child shaped LiveKit packet flow, BWE downshift/recovery, resource cost, and root-with-children behavior remain open. Use Linux `tc` or a public canary for per-leaf shaping, never CDP throttling. +- Relay resources: production `9461e20` is Host2/ordinary Browser Viewer1 and rejects Viewer child2 regardless of advertised capacity. The next endpoint-cap and corroboration contract is held, while CPU/GPU/upload and heterogeneous-network measurements remain optional evidence for later tuning rather than authority to reinstate Browser1. +- SFU: production `9461e20` deploys ordered `q,h`, roots <=2, and Dynacast off. Root count and accounting are held; real shaped packet flow, BWE downshift/recovery, resource cost, and root-with-children behavior remain unverified evidence boundaries. Use Linux `tc` or an authorized public canary for per-leaf shaping, never CDP throttling. - Audio: verify the 64/128/256 kbps Share settings, negotiated/observed bitrate, audible music quality, route changes, and game A/V synchronization. Bitrate settings are ceilings, not quality proof. - Observability: the UI and local stats plumbing are deployed, including identity-bound relayed-detail retention and export freshness guards, but target-browser availability and actual values remain unverified for Host SFU sender evidence, codec/fmtp and encoder implementation/power efficiency, media-source and encoded FPS, A/V playout/jitter/concealment, selected candidate endpoints, and bounded same-pair STUN-response observation. These fields diagnose and have no recovery authority; they do not by themselves prove hardware encode, synchronization quality, or route quality. - Mobile: Android/iOS remain Viewer-only. Autoplay, rotation, iOS lock-screen/page reclamation, background reconnection, and network changes need device evidence. AirPlay/system mirroring is Viewer-local output, not a portable in-app WebRTC output contract. diff --git a/docs/workspace-disposition.md b/docs/workspace-disposition.md new file mode 100644 index 0000000..e8fcfd4 --- /dev/null +++ b/docs/workspace-disposition.md @@ -0,0 +1,106 @@ +# Workspace Disposition + +Last sampled: 2026-08-22 11:42 HKT + +This is the demand-loaded schedule for restoring one canonical repository root and disposing of auxiliary work safely. It is not permission to delete, merge, rebase, or resume a TODO. Shared state is dynamic, so every action must re-sample Git status, refs, PRs, and links immediately before execution. + +## Canonical Target And Stop Gate + +- The canonical repository root is the registered worktree whose sibling-directory name is `Screener`; all other `Screener-*` worktrees are auxiliary. +- Its required terminal state is a clean, exact latest `main`. An auxiliary worktree must not retain `main` afterward. +- The audit-guard truth checkpoint merges first; it does not accept a final routing model. The root's staged user rules must be proved present in that updated `main` or explicitly preserved before its index changes. +- After truth integration, canonical-root restoration, and the approved workspace cleanup below, produce the holistic routing model as a held proposal from canonical `main`. Then report the main SHA, dirty/untracked count, retained worktrees/branches, route proposal, held candidates, and proposed high-confidence TODOs to the user. +- Do not create or resume a remaining-TODO implementation worktree until that checkpoint is explicitly confirmed. After confirmation, every new branch/worktree starts from the exact canonical `main` SHA. + +## Disposition Classes + +- `A PRESERVE`: required before truth integration, dirty, disputed, open, or carrying unique/unknown work. No cleanup. +- `B RECONCILE`: evaluate only after accepted truth is in `main`; transplant approved scoped code/tests/evidence, never an old truth snapshot. +- `C CANONICAL`: handle only while restoring the canonical root to latest `main`. +- `D CLEANUP`: eligible only after semantic disposition, integration/equivalence, clean-tree, open-reference, and non-following link checks all pass. +- `E RETAIN`: active stack, external evidence, archive, or unknown provenance; keep until a separate reviewed decision. + +## Registered Worktrees + +The snapshot contains 30 registered worktrees. Seven are dirty. Only +`Screener-local-oneclick` has nonignored untracked files: five unique project +files. + +| Worktree | Branch / HEAD | Snapshot | Class and next action | +| --- | --- | --- | --- | +| `Screener` | `feat/viewer-presence-polish@d10e879` | staged `AGENTS.md`, no untracked | `A -> C`; preserve two user rules, then restore this root to exact `main`. PR #153 is merged; after restoration, its local and remote branch become `D` only after a fresh merged-head and open-head/base recheck. | +| `Screener-current-routing-truth` | `docs/current-routing-truth` audit branch | truth owner; sampled from `origin/main@7df8217` | `A -> D after merge`; finish, validate, review, and merge before any other integration, then remove its clean merged auxiliary worktree/branch during canonical cleanup. | +| `Screener-connection-details-presentation` | `main@7df8217` | clean | `A -> C`; currently occupies `main`. Release only after dependent junction handling and latest-main verification. | +| `Screener-configurable-relay-cap` | `fix/configurable-relay-cap@7df8217` | 10 tracked edits; junction to canonical `node_modules` | `A -> B`; disputed routing draft, preserve and later rebuild only approved intent. | +| `Screener-av-sync-next-slice` | `spike/av-sync-next-slice@d9bd4e2` | clean, open PR #192 | `A/E`; evidence-only, preserve open refs. | +| `Screener-real-relay-canary` | `test/real-relay-canary@f135302` | clean; local differs from merged PR head | `A -> B`; retain possible one-line report correction, never delete solely because #191 merged. | +| `Screener-resource-matrix-gate` | `docs/resource-matrix-gate@140dd00` | clean | `A -> B`; retain measurements only, exclude stale Browser1 policy. | +| `Screener-signaling-blackhole-canary` | `test/signaling-blackhole-canary@e972b75` | clean; junction to auxiliary-main `node_modules` | `A -> B`; evidence for held watchdog decision; handle junction before releasing auxiliary main. | +| `Screener-routing-architecture` | `docs/routing-algorithm-convergence@43b1f46` | clean | `A -> B`; historical/disputed model input only. | +| `Screener-relay-parent-quarantine` | `fix/relay-parent-quarantine@5bab93b` | 2 tracked server edits | `A -> B`; unknown routing draft, preserve pending model review. | +| `Screener-connection-details-stability` | `fix/connection-details-stability@55f4cbc` | clean | `A -> D`; superseded design input, cleanup only after #187 equivalence recheck. | +| `Screener-current-route-canary` | detached `b77f4eb` | clean | `D`; old exact-main fixture, recheck no consumer before removal. | +| `Screener-host-generation-debug` | `spike/host-generation-quality-evidence@fc4b0b0` | clean, local-only | `E`; unknown provenance. | +| `Screener-local-oneclick` | `feat/local-oneclick-bundle@e3ab39c` | 7 tracked edits plus 5 untracked project files | `A/E`; unique dirty work, never clean or remove automatically. | +| `Screener-native-live-bridge` | `spike/native-live-encoded-bridge@8121b69` | clean, draft PR #22 | `E`; preserve Native stack. | +| `Screener-native-live-feedback-loop` | `spike/native-live-feedback-loop@aad560e` | clean, draft PR #28 | `E`; preserve Native stack. | +| `Screener-native-primary-nack-retransmit` | `spike/native-primary-nack-retransmit@a6c3456` | clean, draft PR #25 | `E`; preserve Native stack. | +| `Screener-native-shared-encode` | `spike/native-shared-encode-browser@80f65d0` | clean, draft PR #18 | `E`; preserve Native stack. | +| `Screener-native-shared-feedback-control` | `spike/native-shared-feedback-control@eb9aabe` | clean, draft PR #23 | `E`; preserve Native stack. | +| `Screener-pion-rtp-fanout` | `spike/native-rtp-fanout-oracle@5b09f0a` | clean, draft PR #16 | `E`; preserve Native stack. | +| `Screener-native-two-viewer-fanout` | `test/native-two-viewer-fanout@bf898b6` | clean, remote branch, no PR | `E`; held Native candidate. | +| `Screener-windows-shared-encode-sender` | `feat/windows-shared-encode-sender@1ce732e` | clean, 14 local commits | `E`; unique held Native candidate. | +| `Screener-participant-connection-truth-plan` | `docs/participant-connection-truth-plan@4b536d0` | clean, local-only | `E`; unknown docs input. | +| `Screener-quality-evidence-followups` | `docs/quality-evidence-followups@d3f160f` | clean, local-only | `E`; unknown docs input. | +| `Screener-recovery-details-release` | `fix/recovery-details-release@b0e013f` | 2 tracked docs edits | `A/E`; stale code ancestry plus unique unknown docs. | +| `Screener-route-status-visual` | `fix/route-status-visual-recall@79ee46e` | clean, local-only | `E`; unknown and likely overlapped. | +| `Screener-sfu-healthy-reselection` | `docs/sfu-healthy-reselection@47c2ce7` | clean, local-only | `E`; old design, semantic review required. | +| `Screener-sfu-stable-stream` | `fix/sfu-stable-subscriber-stream@4d46a4a` | clean, local-only | `E`; unknown. | +| `Screener-target-peer-error` | `fix/target-peer-not-connected@7141cd9` | clean, local-only | `E`; unknown. | +| `Screener-viewer-c-evidence` | `docs/viewer-c-evidence-contract@911b03b` | 4 staged/add plus `docs/status.md` conflict | `A/E`; unresolved conflict and unique work, never remove/rebase automatically. | + +## Local Branches Without Worktrees + +- `docs/production-smoke-record@231a7c3`: `E`, unknown. +- `feat/room-viewer-access-merge-history@921e8a2`: `D`, merged-equivalent after final recheck. +- `feat/sfu-media-mode@fb7d4f1`: `D` candidate, closed-unmerged PR #12; semantic supersession must be proved first. +- `fix/ice-status-wording@4f7fee4`: `D`, current-main ancestor after final recheck. +- `fix/screen-audio-bitrate-target@5a71462`: `E`, local unique commits despite a related merged remote head. + +## Open And Remote References + +- Preserve `main`, open PR #192, and the Native stack #16/#18/#22/#23/#25/#28, including every stacked base branch. Preserve `test/native-two-viewer-fanout`, which has a remote branch without a PR. These are nine retained remote refs in this snapshot. +- The following 14 merged-PR heads are `D` candidates only after a fresh exact remote-head equals merged-PR-head check and confirmation that no open PR uses the branch as head or base: `chore/hygiene-ignore-untracked`, `docs/nat-web-boundary`, `feat/host-display-name`, `feat/host-roster-details-disclosure`, `feat/viewer-presence-polish`, `feat/viewer-topology-map`, `fix/codec-lock-hint`, `fix/peer-relay-quality-release`, `fix/relay-relative-quality`, `fix/revert-low-fps-reselection`, `fix/screen-audio-bitrate-target`, `fix/sfu-viewer-recovery`, `fix/sticky-sfu-cooldown-mainline`, and `test/real-relay-canary`. +- Preserve `feat/screen-audio-stereo` as `E`: PR #147 is closed-unmerged, so the merged-branch deletion rule does not apply merely because later work appears equivalent. +- The remote listing also contains the symbolic `origin/HEAD` alias; it is not a branch cleanup target. Every count and disposition must be re-sampled immediately before action because this 2026-08-22 snapshot is not permanent authority. + +## Unregistered Directories And Artifacts + +- Empty directory candidates: `Screener-android-pilot-apk`, `Screener-deploy-261e980c`, `Screener-production-truth-66eb` (`D` after exact empty recheck). +- Junction-only shells: `Screener-quality-evidence-alignment`, `Screener-room-peer-canary`. Each points to canonical `node_modules`; unlink the junction itself without following it before considering the empty root (`D`). +- Independent acceptance clone: `Screener-audio-main-acceptance` plus bare `Screener-audio-main-acceptance.git` at `960ae42` (`E`). It is not a canonical worktree; if later removed, use its own bare repository to remove its registered worktree first. +- Deployment archives: `Screener-deploy-artifacts`, `Screener-deploy-builds`, two extracted artifact directories, and five sibling `.tar.gz` files (`E/D`). Pair each with commit, checksum, and deployment retention records before archive/removal; never glob-delete `Screener-*`. + +## Known Reparse Points + +The non-following scan found exactly four junctions and no scan errors: + +1. `Screener-configurable-relay-cap\node_modules` -> canonical root `node_modules`. +2. `Screener-signaling-blackhole-canary\node_modules` -> auxiliary-main `node_modules`. +3. `Screener-quality-evidence-alignment\node_modules` -> canonical root `node_modules`. +4. `Screener-room-peer-canary\node_modules` -> canonical root `node_modules`. + +Never recursively remove a containing directory while one of these links remains unresolved. Delete only the link itself using a non-following operation, then verify the external target still exists. + +## Execution Order + +1. Stop writers and re-sample worktrees, dirty/untracked state, local/remote refs, open PRs, and reparse points. +2. Finish, validate, independently review, and merge the audit-guard truth checkpoint first; do not treat it as final route acceptance. +3. Prove the root's staged user rules exist in accepted `main`; explicitly preserve any unmatched content. +4. Handle the signaling-canary junction without following it. Recheck the auxiliary-main worktree is clean, untracked-free, and at exact latest `main`, then release it. +5. Make the canonical root clean without losing unmatched user work, switch it to exact latest `main`, and verify path, branch, HEAD, dirty/untracked state, and GitHub main equality. +6. Execute only already-approved `D` cleanup items, one exact target at a time, after semantic/equivalence/open-reference/link checks. Preserve all `A`, `B`, and `E` items. +7. From exact canonical `main`, produce only the holistic routing held proposal; do not implement it or resume another TODO. +8. Stop and obtain user confirmation of the organized canonical state, routing proposal, and proposed remaining TODO list. +9. Only after confirmation, update accepted owning truth and merge that truth into canonical `main`. Then create new implementation worktrees from that exact newer canonical-main commit and reconcile `B` candidates one at a time. Old branch truth files never win conflicts. +10. Process independent archives and deployment artifacts last, with checksum and retention evidence. diff --git a/docs/方案设计.md b/docs/方案设计.md index 47c08f8..c88826f 100644 --- a/docs/方案设计.md +++ b/docs/方案设计.md @@ -1,5 +1,7 @@ # 屏幕共享 WebRTC PoC 方案设计 +> 2026-08-22 truth audit hold: 自动 P2P-first 方向仍保留,但容量、SFU publication/subscription、TURN、fallback 与临时资源计数尚未完成整体裁决。本文件相关旧段落是审计输入,不是当前实现授权;详见 [TODO audit hold](./todo-audit-hold.md)。 + ## 2026-08-18 14:45 状态:首个 PoC 基线及其已接受扩展的当前设计。Production 仍使用 STUN-only ordinary ICE;旗舰进程以 `PEER_ASSISTED_MEDIA=true` 对所有正常房间启用 peer-assisted 与 LiveKit SFU/UDP,room `1` 仅是历史 smoke。built-in Peer ICE TURN canary 已失败并回滚,不再是产品方向;production 已配置仅由 controller 向单条异常 edge 发放的 selected-edge TURN,但真实中继媒体仍未验收。旧 release 与 coturn relay 仅保留为隔离回滚路径,不是同进程兼容分支。 @@ -124,7 +126,7 @@ WebSocket 使用无 query/fragment 的同源 `/signal`。upgrade 只记录 site- Zod 在服务边界拒绝未知类型、超长字符串、非法 SDP/candidate 结构和越权目标。服务端根据已认证会话决定路由:观看者不能给另一名观看者发信令,分享者也不能向本房间以外的 peerId 发送。 -该授权迁移把唯一 literal 从 `screener-v1` 原子改为 `screener-v2`,不做版本协商。旧页面的首条消息在任何角色进入 room lookup 前得到同一个 fatal refresh 终态、停止自动重连;服务端不解析 v1、不双写、不维护 translator。缺失、过期、跨房、已 rotate 或 revoked 的 v2 Viewer grant 则使用同一个通用“邀请无效或已失效”结果,不区分房间不存在与凭据错误。 +历史上的授权迁移曾把唯一 literal 从 `screener-v1` 原子改为 `screener-v2`,不做版本协商;后续原子迁移已把当前 wire 推进到 `screener-v5`,旧 v1/v2 parser、双写和 translator 都不存在。不兼容旧页面的首条消息在任何角色进入 room lookup 前得到同一个 fatal refresh 终态并停止自动重连。缺失、过期、跨房、已 rotate 或 revoked 的当前 Viewer grant 使用同一个通用“邀请无效或已失效”结果,不区分房间不存在与凭据错误。 ## WebRTC 协商 @@ -382,7 +384,7 @@ Host 与 relay Viewer 复用同一个纯 presentation reducer 保存远端 `View 4. 完成连接恢复和 stats 面板;随后以 STUN-only snapshot 替换旧全房 TURN credential/refresh wire。 5. 完成 automatic peer/SFU controller,并让 room `1` 仅作为历史 smoke fixture。 6. 可选 selected-edge TURN tuple、revision-bound one-use grant 与 parent/child rebuild 已在 source 和 production 配置闭环;下一功能验收只需一条 forced relay 媒体 smoke,完整网络/资源 benchmark 后置。ordinary STUN-only、SFU/UDP、coturn rollout 仍保持独立边界。 -7. 在媒体主线阶段验收后,用一个原子 PR 迁移 site access、`screener-v2`、room-scoped Viewer grant 和 SQLite v2;同一部署切换客户端/服务端/环境和数据库备份,随后删除 v1 配置、wire 与测试。用户名/roster 保持独立。 +7. Site access、room-scoped Viewer grant 与 SQLite v3 已部署,当前 wire 为 `screener-v5`;以后不兼容的 wire/schema 迁移仍须原子切换并保留迁移前备份。用户名/roster 保持独立。 8. Windows Native fixed-`HIGH` 保持可选且不改变 Web 默认;移动端保持 Viewer-only 且不单独分配 relay capacity。Viewer-to-TV 只采用已验证的平台本地输出,不改变媒体路由。 9. 屏幕音频在一个原子 Web slice 中声明 `sdp-transform`/types direct dependencies,加入 answer helper 与 `ViewerPeer` wiring,并同步设置 SFU stereo options、focused tests 和 owning docs;高级设置只增加 64/128/256 kbps 离散 sender ceiling,不增加 Web Audio、第二表示或自定义降级算法。 diff --git a/docs/需求理解.md b/docs/需求理解.md index 3ef1444..c303b00 100644 --- a/docs/需求理解.md +++ b/docs/需求理解.md @@ -1,5 +1,7 @@ # 屏幕共享项目需求理解 +> 2026-08-22 truth audit hold: 本文件的 checkbox 是验收条款组织方式,不是可直接执行的 backlog。容量、SFU publication/subscription、TURN、fallback、临时资源计数相关段落含已部署事实、历史假设与未决语义;在 [TODO audit hold](./todo-audit-hold.md) 解除并原位更新前,不得据此实现、回滚、合并或清理。 + ## 2026-08-18 13:31 ## 需求概述 @@ -93,7 +95,7 @@ ### 房间模式与生命周期 -- Given `SITE_ACCESS_PASSWORD` 和 `ROOM_DATABASE_PATH` 都已配置,When 连续创建房间并重启应用,Then 房间码从 `1` 开始单调递增,Host ownership 可恢复,且 SQLite 的应用数据只包含房间 ID、Host token 摘要和 nullable Viewer grant 摘要。 +- Given `SITE_ACCESS_PASSWORD` 和 `ROOM_DATABASE_PATH` 都已配置,When 连续创建房间并重启应用,Then 房间码从 `1` 开始单调递增,Host ownership 可恢复,且 SQLite 的应用数据只包含房间 ID、Host token 摘要、nullable Viewer grant 摘要和 nullable Viewer password verifier material。 - Given 持久房间正在分享,When 分享者明确停止或捕获轨结束,Then 房间和链接保持有效,分享端显示“已停止分享”,观看者显示“等待开始分享”;分享者重新发布后可继续在同一房间观看。 - Given 分享期间只有 host 信令短暂断开,When 现有 P2P 媒体仍健康,Then 客户端继续播放媒体并恢复信令,而不是错误显示“已停止分享”。 - Given 应用以 production 模式启动但 `SITE_ACCESS_PASSWORD` 缺失、`ROOM_DATABASE_PATH` 已配置但该密码为空,或原子迁移后的配置仍提供已删除的 `ACCESS_PASSWORD`,When 应用启动,Then 配置校验明确失败,而不是兼容旧 gate 或公开建房。