Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Why

自 `add-single-gpu-session-ai-review-mvp`(已於 2026-07-28 標 `Status: deferred`)切出的最小可完成切片。依 2026-07-28 read-only 盤點,該傘型 change 中真正無人認領、且不依賴 SessionBroker/IfcClash/LLM/BCF 3.0 等重物的獨有主線只有兩條:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mark the predecessor deferred before opening this successor

At this commit, openspec/changes/add-single-gpu-session-ai-review-mvp/proposal.md still begins with ## Why, contains no canonical Status: deferred ... marker, and retains active deltas for both capabilities added here. Merging in this state therefore creates two active owners for gpu-session-baseline and session-lifecycle, so either change can be implemented or archived against conflicting requirements despite this line claiming the predecessor is deferred; defer the predecessor canonically and record the handoff before adding this successor.

AGENTS.md reference: openspec/AGENTS.md:L29-L29

Useful? React with 👍 / 👎.


1. **單 GPU 容量的量化缺口至今無答案**:repo 唯一數字來源是 `docs/verification/2026-06-05-host-gpu-runtime-reality-check.md` 的一次性環境快照——無 per-stream VRAM、無 TTFF、無建立成功率、無 soak 斜率、無任何 SLO 數值;`KitGpuFleetPage` 自標「GPU busy / total = 未取得」。先量測、再談任何 admission/排程承諾(母 change MVP 哲學原文)。
2. **忘關分頁餓死洞已有使用者裁決但未實作**(2026-07-22 原話「同意, 但是前端追加 session 進入倒數10秒顯示」):無互動軟門檻+前端 10 秒回收倒數。此路徑不依賴佇列/SessionBroker,可疊加落在既有 coordinator session close 路徑上。

## What Changes

- **`gpu-session-baseline`**(New capability):量測 harness `measure-session-baseline.ps1`(nvidia-smi+WebRTC health probe+TTFF+建立成功率)、環境指紋必填 schema+驗證測試、隔離 stack ≥30 分鐘 soak 記憶體斜率、由本地實測訂 SLO 具體數值寫入部署文件(禁引用外部數字)、「指紋變動即 SLO 失效」+無基準報告時 admission 參數 loader 硬 gate。
- **`session-lifecycle`**(New capability,slim delta):只含「回收倒數與互動保活」第二回收路徑——互動事件上報彙整、連續 T_inactivity 觸發、10 秒倒數廣播與前端倒數 UI、任一互動取消並重置、歸零經既有 session close 路徑 teardown(reason=inactivity 入 session ledger)。佇列、SessionBroker、健康探針自動復原、202 冷啟動等其餘 lifecycle 語意**不在本 change**。
- 一律疊加式:不動凍結三檔(`app.py`/`conversion_authority.py`/`governanceProxy.ts`),不改既有 route/response shape。

## Impact

- Affected specs: `gpu-session-baseline`(new)、`session-lifecycle`(new,slim)。
- Affected code: `scripts/`(harness+最小驗證測試)、可稽核部署文件、`bim-review-coordinator`(additive:互動上報彙整+倒數觸發+close reason)、`web-viewer-sample`(倒數 UI+E2E)。
- **與 deferred 母 change 的關係**:本 change 承接其 T1 六項(1.1–1.5、2.11)。母 change 對應 delta(`gpu-session-baseline` 三條 Requirement、`session-lifecycle` 的「回收倒數與互動保活」Requirement)於 thaw crosswalk 時標記由本 change 承接,不得平行實作;本 change 的 Requirement 名稱刻意沿用母版以利 crosswalk。
- **明確不做**(supersede/frozen 證據見母 change Status 段):SessionBroker 抽象與 contract test、primary 佇列、202 冷啟動、健康探針自動復原、IfcClash/LLM 草稿管線、人審 triage 佇列、BCF-API 3.0(zip 骨架已有=`governance-service/bcf/bcf_writer.py`,BCF 2.1)、跨版本冪等指紋(機制已有=`governance-service/diff_engine/keys.py`)。
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
## ADDED Requirements

### Requirement: 基準量測腳本 SHALL 產出含環境指紋的結構化基準報告

執行 `measure-session-baseline.ps1` 時 SHALL 產出結構化基準報告,內容 SHALL 至少含:GPU 型號盤點(判定是否消費級 RTX、確認 MIG 不可用 → 鎖定軟體佇列路線)、1 primary + k spectator 下 VRAM 水位、time-to-first-frame(TTFF)、建立成功率。取樣 SHALL 使用 nvidia-smi(VRAM/利用率)+ WebRTC health probe + TTFF。報告 schema SHALL 含「環境指紋」必填欄位:GPU 型號、driver 版本、Kit 版本、量測 fixture 的 hash + 大小。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define repeated trials for TTFF and success rate

A harness can satisfy this requirement with a single establishment attempt because no trial count, observation window, timeout, success definition, or aggregation statistic is specified. That makes the reported establishment rate trivially 0% or 100% and turns one TTFF sample into the admission upper bound, so the downstream SLO can appear evidence-based while being statistically meaningless; require repeated attempts per measured topology and report the denominator plus an explicit percentile/distribution.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind admission SLOs to a production workload envelope

When a production session loads a model materially heavier than the single benchmark fixture, the GPU/driver/Kit and benchmark-fixture fingerprint remain unchanged, so the SLO is still considered valid even though VRAM and TTFF can exceed the measured values. Recording an exact fixture hash and file size only identifies the sample; it does not define which production models the result safely covers, and file size alone is not a bound on rendered geometry or texture demand. Define measurable workload tiers or a maximum admissible model envelope and make admission fail closed outside the measured envelope.

Useful? React with 👍 / 👎.


#### Scenario: 執行基準量測

- **WHEN** 在目標部署環境執行 `measure-session-baseline.ps1`
- **THEN** SHALL 產出含 GPU 型號盤點、VRAM 水位、TTFF、建立成功率的結構化報告
- **AND** 報告 SHALL 含 GPU 型號/driver 版本/Kit 版本/fixture hash+大小的環境指紋必填欄位

#### Scenario: 缺環境指紋欄位

- **WHEN** 產生的基準報告缺任一環境指紋必填欄位
- **THEN** 報告 SHALL 判定為不完整
- **AND** 後續 SLO 形式化與任何 admission 參數 loader SHALL NOT 引用該報告

### Requirement: 長連線 soak test SHALL 在隔離量測窗產出記憶體斜率報告且門檻只由本地實測決定

一條 warm primary 連線 SHALL 跑 ≥30 分鐘(目標 2 小時)soak 並產出記憶體斜率報告。洩漏 watchdog 門檻 SHALL 完全依本次本地實測結果訂定,SHALL NOT 引用未經本地驗證的任何外部系統數字(含任何 GB/日 之類外部洩漏率)。soak SHALL 於隔離 stack(獨立埠、獨立 governance)+獨佔量測窗執行,harness SHALL 內建最小 keepalive health probe 維持連線活性,量測期間 SHALL NOT 共用入口。soak 期間自然斷流 SHALL 記為 finding;連兩次同點斷流 SHALL 判定為環境污染需查因,單次 SHALL 視為量測窗雜訊不逕自作結。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Soak the admitted spectator workload

For sessions admitted with spectators, soaking only one warm primary omits the spectator streams and their probe load, yet the resulting slope is used to set the leak watchdog and admission SLO for the full deployment. The predecessor's own OQ-5 identifies this exact gap, but this supposedly complete successor drops that unresolved condition; run the soak under the target 1 primary + k spectator topology or explicitly prevent the resulting threshold from governing spectator-enabled deployments.

Useful? React with 👍 / 👎.

Comment on lines +19 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Separate host-memory and VRAM leak slopes

The soak requires a generic "memory slope" without identifying whether it is GPU VRAM or the Kit process's host working set/RSS, while the stated harness instrumentation only guarantees nvidia-smi. A Kit process can leak host memory with stable VRAM and still produce a compliant passing report, or two implementations can derive incompatible watchdog units; require both relevant series with units and sampling cadence, and state which slope each watchdog threshold governs.

Useful? React with 👍 / 👎.


#### Scenario: 隔離 soak 產記憶體斜率

- **WHEN** 一條 warm primary 連線於隔離 stack + 獨佔量測窗跑 ≥30 分鐘 soak,keepalive probe 維持活性
- **THEN** SHALL 產出記憶體斜率報告
- **AND** 洩漏 watchdog 門檻 SHALL 只由本次實測訂出,不引用外部數字

#### Scenario: soak 期間自然斷流

- **WHEN** soak 期間發生單次自然斷流
- **THEN** SHALL 記為 finding 並視為量測窗雜訊
- **AND** 僅在連兩次同點斷流時 SHALL 判定為環境污染需查因
Comment on lines +31 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not discard the first natural disconnect as noise

When the only 30-minute soak disconnects once, these acceptance steps require classifying the failure as measurement-window noise rather than making the run fail or become inconclusive. A real intermittent leak or WebRTC stability defect may not recur at the identical time point, so the resulting report can still authorize a leak threshold for a runtime that already failed the soak; preserve the disconnect as a failed/inconclusive run and use controlled reruns to diagnose environmental contamination separately.

Useful? React with 👍 / 👎.


### Requirement: SLO SHALL 以具體數值形式化寫入部署文件並綁定環境指紋

設定任何 session admission 參數時 SHALL 以基準報告為前提,SHALL 以具體數值指標形式化並寫入可稽核部署文件:session 建立成功率下限、TTFF 上限、探針逾時定義、並發上限、idle-timeout、洩漏門檻。SHALL NOT 使用「合理」「足夠」等模糊詞;無基準報告則 admission 參數 SHALL NOT 上線(硬 gate)。所有 SLO 數值 SHALL 綁定基準量測報告的環境指紋;指紋任一變動即令既有 SLO 失效須重跑基準。
Comment on lines +35 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Specify the timeout consumed by this slim lifecycle

The baseline formalizes an idle-timeout, but this change explicitly excludes the predecessor's no-connected-peer idle path and the included countdown consumes a different value, T_inactivity. No report field, loader parameter, or mapping supplies a default for T_inactivity, so implementation either leaves the required default undefined or incorrectly aliases two semantically different thresholds; add the inactivity threshold to the measured configuration/deployment contract and remove or clearly separate the excluded idle timeout.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Split primary and spectator admission limits

When the measured topology is 1 primary + k spectator, a single 並發上限 value cannot safely represent both GPU-backed session concurrency and per-session spectator capacity. If the loader interprets k + 1 as the session limit, it may admit multiple primary sessions onto the single GPU; if it interprets the value as 1, it cannot admit the spectator workload that was measured. Define separate primary-session and spectator-per-session limits, preserve the measured topology in the schema, and test each admission dimension independently.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define independent acceptance targets for the baseline

When the measured runtime is already unusable—for example, a very low establishment rate or extremely high TTFF—this requirement still permits those observations to become the success-rate lower bound and TTFF upper bound, so the hard gate accepts any hardware simply because it was measured. Repeated trials alone do not solve this tautology; define an independent product acceptance target or require the harness to reduce the admitted topology until predefined targets are met, and mark the deployment unsupported when no topology passes.

Useful? React with 👍 / 👎.


#### Scenario: 有基準報告設定 SLO

- **WHEN** 基準報告已存在,設定 admission 參數
- **THEN** SLO SHALL 以具體數值寫入部署文件且無模糊詞
- **AND** 每項 SLO SHALL 綁定報告的環境指紋

#### Scenario: 無基準報告

- **WHEN** 尚無基準報告
- **THEN** admission 參數 SHALL NOT 上線
- **AND** admission 參數 loader SHALL 以硬 gate 拒絕未經量測的門檻
Comment on lines +47 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Provide a measurement-only path through the hard gate

On a fresh deployment with no report, producing the report itself requires launching the isolated 1 primary + k spectator WebRTC workload with provisional topology parameters, but this scenario requires the admission loader to reject all unmeasured parameters before that workload can start. No measurement-only mode or bounded bootstrap exception is defined, so implementing the hard gate on the supported deployment/configuration path creates a first-run deadlock; allow an isolated non-production measurement mode that cannot serve normal admission, then enable the production loader only after it validates the generated report.

Useful? React with 👍 / 👎.


#### Scenario: 環境指紋變動

- **WHEN** GPU 型號/driver/Kit/fixture 任一變動
- **THEN** 既有 SLO SHALL 失效
- **AND** SHALL 要求重跑基準取得新指紋
Comment on lines +53 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fingerprint the measured streaming configuration

When k, resolution, codec, rendering quality, launch flags, or the application build changes while GPU/driver/Kit/fixture remain unchanged, this invalidation rule keeps the old SLO valid even though VRAM, TTFF, and safe concurrency can change substantially. Because the report explicitly measures 1 primary + k spectator and is later used for admission limits, the fingerprint must also bind the measured topology and load-affecting runtime/stream configuration; otherwise a report for one configuration can authorize a different, unsafe configuration.

Useful? React with 👍 / 👎.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## ADDED Requirements

### Requirement: session 回收倒數與互動保活 SHALL 作為第二回收路徑,前端顯示 10 秒倒數且互動即取消

session 連續 T_inactivity 秒無任何使用者互動(viewer 輸入事件/DataChannel 指令)但仍有 readyState=4 peer 連線時,session SHALL 進入回收倒數。進入回收倒數時,前端 SHALL 對該 session 所有已連線 viewer 顯示 10 秒倒數;倒數期間任一 peer 的任何互動 SHALL 取消本次回收並重置 inactivity 計時;倒數歸零 SHALL 經既有 coordinator session close 路徑 teardown 並以 reason=inactivity 寫入 session ledger。SHALL 維持無 max-hold hard cap:有持續互動的會議 SHALL NOT 因持有時長被強制回收。T_inactivity SHALL 可設定,預設值 SHALL 於 `gpu-session-baseline` 基準取得後訂定。本 Requirement SHALL 以疊加方式落在既有 coordinator session close 路徑,SHALL NOT 依賴佇列/SessionBroker 語意(該語意屬 deferred 母 change `add-single-gpu-session-ai-review-mvp`,其「佇列中下一位獲派」段不在本 capability 範圍)。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat a viewer join as activity during countdown

If a viewer joins after the 10-second countdown broadcast, the parenthetical activity definition counts only input events and DataChannel commands, so the new viewer can miss the already-emitted countdown and have the session closed seconds later without a chance to react. A successful active viewer lease/join should cancel and reset the countdown, or the current countdown state and remaining time must be delivered atomically to late joiners before they are admitted.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add readiness telemetry for the lifecycle predicate

When a primary disconnects or only spectators remain, the coordinator has no specified way to evaluate the required readyState=4 predicate: current readiness is browser-local, app.ts:330-334 accepts only first-frame/stage/DataChannel fields on lease heartbeats, Window.tsx:1896-1905 currently sends no readiness data, and spectator mode bypasses the primary lease path. Because this change explicitly excludes the health probe and only tasks interaction-event reporting, an implementation must either assume every stored session still has a live peer or ignore this condition, causing countdowns to run for disconnected sessions or never run for connected spectators. Add expiring per-peer readiness telemetry—including spectators—and acceptance tests before using this predicate.

AGENTS.md reference: AGENTS.md:L75-L80

Useful? React with 👍 / 👎.


> 使用者裁決(2026-07-22,母 change OQ-A/OQ-3):原話「同意, 但是前端追加 session 進入倒數10秒顯示」——同意維持無 max-hold,追加 session 進入回收時前端 10 秒倒數顯示;忘關分頁(有 peer 無互動)由本路徑回收。

#### Scenario: 忘關分頁回收

- **WHEN** session 仍有 readyState=4 peer 但連續 T_inactivity 秒無任何使用者互動,且 10 秒回收倒數內無任何互動
- **THEN** session SHALL 經既有 close 路徑 teardown
- **AND** SHALL 以 reason=inactivity 寫入 session ledger
Comment on lines +11 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reclaim the Kit runtime rather than only closing metadata

When the inactivity countdown reaches zero, the specified existing coordinator close path does not actually tear down the Kit/WebRTC runtime: bim-review-coordinator/src/app.ts:1904-1962 only releases logical leases/bindings and appends events, and tests/sessions.test.ts:541 explicitly locks in that sessions close separately from Kit release. Because this change excludes SessionBroker and lists no streaming-server runtime release work, an inactive session can become closed while its GPU process remains occupied, defeating the reclaim feature; the flow needs an owned Kit /endsession or equivalent runtime teardown with observed completion.

AGENTS.md reference: AGENTS.md:L75-L77

Useful? React with 👍 / 👎.


#### Scenario: 倒數期間互動取消回收

- **WHEN** session 進入回收倒數,倒數期間任一已連線 peer 發生互動
- **THEN** SHALL 取消本次回收並重置 inactivity 計時
- **AND** 前端倒數顯示 SHALL 消失

#### Scenario: 活躍會議不因時長被回收

- **WHEN** 會議持續有使用者互動
- **THEN** session SHALL NOT 因持有時長觸發任何強制回收(無 max-hold hard cap)
11 changes: 11 additions & 0 deletions openspec/changes/gpu-session-baseline-and-idle-reclaim/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## 1. gpu-session-baseline(量測 harness,`scripts/`+部署文件)

- [ ] 1.1 在 `scripts/` 建立 `measure-session-baseline.ps1`:nvidia-smi 取 VRAM/利用率+WebRTC health probe+TTFF;輸出結構化 JSON 報告含 GPU 型號盤點(判定消費級 RTX、MIG 不可用)、1 primary + k spectator VRAM 水位、TTFF、建立成功率
- [ ] 1.2 報告 schema 加「環境指紋」必填欄位(GPU 型號/driver 版/Kit 版/fixture hash+大小),缺欄位判不完整並拒絕被下游引用;於 `scripts/` 加最小驗證測試
- [ ] 1.3 實作 ≥30 分鐘(目標 2 小時)soak:隔離 stack(獨立埠+獨立 governance,沿用 branch E2E 隔離模式)+獨佔量測窗+內建 keepalive health probe;輸出記憶體斜率報告;自然斷流記 finding、連兩次同點才判污染
- [ ] 1.4 由 soak 報告訂洩漏 watchdog 門檻(只用本地實測、禁引用外部數字);將 session 建立成功率下限/TTFF 上限/探針逾時/並發上限/idle-timeout/洩漏門檻以具體數值寫入可稽核部署文件並綁定環境指紋(禁模糊詞)
- [ ] 1.5 撰寫「環境指紋變動即 SLO 失效須重跑基準」部署文件段落;驗證:無基準報告時 admission 參數 loader 拒絕上線(硬 gate 測試)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire measured limits into session admission

When the baseline report exists, this task only validates that an admission-parameter loader accepts it; it never requires the measured limit to be enforced by either session-creation path. I checked bim-review-coordinator/src/app.ts:1212-1224 and :2674-2685: both call the stateless allocateKitInstanceBindings, and kitPool.ts:18-30 neither reads a baseline nor checks existing active sessions. Because this change explicitly excludes SessionBroker, all listed tasks can be completed while concurrent sessions still receive the same GPU endpoint; require a task and acceptance test that wire the validated limits into both explicit and automatic session admission.

Useful? React with 👍 / 👎.


## 2. session-lifecycle(回收倒數與互動保活)

- [ ] 2.1(coordinator+web-viewer-sample)無互動軟門檻第二回收路徑(2026-07-22 使用者裁決):viewer 互動事件(輸入/DataChannel 指令)上報彙整、連續 T_inactivity 無互動觸發回收倒數、倒數 10 秒廣播至該 session 全部已連線 viewer、前端倒數 UI 顯示、任一互動取消並重置、歸零經既有 session close 路徑 teardown(reason=inactivity 入 session ledger);測試:忘關分頁回收、倒數中互動取消、活躍會議不因時長回收;前端倒數 UI 有 E2E 截圖/trace(「佇列中下一位獲派」不在本 change,屬母 change 佇列語意)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required UI completion gates

This task introduces a user-facing countdown UI but only asks for an E2E screenshot/trace, so every checkbox can be closed without the mandatory two-resolution Windows Chromium pixel gate, semantic gate, pinned design reference, or route/button/API/runtime-ID and visible failure/retry evidence. Add those design-fidelity and operability checks to the task so this change cannot be declared complete while the countdown is visually incorrect or disconnected from the real session flow.

AGENTS.md reference: AGENTS.md:L44-L45

Useful? React with 👍 / 👎.

Loading