Skip to content
Draft
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
14 changes: 10 additions & 4 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

このドキュメントは Claude Code / Codex への実装ハンドオフ用。**§1(存在理由)と §2(非目標)を最優先で守ること。** 特定スタック(Gemini / Asterisk / 8kHz μ-law)の値は実装のどこにもハードコードしない。それらは `/examples` 配下のサンプルプラグイン設定として“データ”でのみ存在する。

> 文書の位置付け(2026-09-18):本書は設計契約で、実装済み機能の一覧ではない。初期v1の対象・構成図・技術候補と、現在動く構成は区別する。現在の実装・local candidate・残件は [implementation status](docs/implementation-status.md)、製品判断は [MEMORY.md](MEMORY.md) を参照する。
>
> STT/LLM/TTSを独立モデルで組む拡張は [cascade設計案](docs/cascade-design.md) に定義する。`voxbench/v2`でrealtime/cascade、service role、入力/出力PCM chainを表し、既存v1の解決結果とhashを維持する提案である。cascadeは現在未実装。
>
> 2026-09-18追加要件:Pipecat、他framework/middleware、middlewareを使わない直接接続の全てを対象にする。音声方式(realtime/cascade)と実行方式は別軸。図中のPipeCat wrapperは任意のruntime adapter例で、core・observer・診断の必須dependencyではない。

---

## 1. 存在理由:劣化モデル(この製品の背骨)
Expand All @@ -30,17 +36,17 @@ AI音声エージェントは**ブラウザ(WebRTC)では動くのに、電
## 2. スコープと非目標(ガードレール)

### 2.1 v1スコープ
- エンジン:Asterisk(chan_websocket)1種。
- プロバイダ:Gemini Live 1種。
- 初期設計対象:エンジンAsterisk(chan_websocket)、プロバイダGemini Live。
- 現在のコミット済み通話経路はAsterisk AudioSocketで、Gemini LiveとOpenAI Realtimeのadapterがある。chan_websocketを含む初期目標全体の完了を意味しない。
- ただし**コードのどの経路もGemini/Asteriskを前提にしてはならない**。両者は必ずプラグイン+manifest越しに扱う。コアは両者を知らない。

### 2.2 非目標(やらないこと)
- **PipeCatを作り直さない。** オーケストレーションエンジンとして薄くラップするだけ。プロバイダ抽象(Gemini/OpenAI/Bedrock)はPipeCatに肩代わりさせる。
- **PipeCatを作り直さない。** 通話アプリが選ぶframework/独自runtimeを維持し、VoxBenchは共通観測契約と薄い任意adapterを提供する。Pipecatや他middlewareの利用を強制せず、直接SDK/HTTP/WebSocket接続にも対応する。テスト通話の起動はframework非依存runtime/launcher契約へ分離する。
- **Langfuse / ClickHouse / Redis をコアに同梱しない。** Postgresファースト。制御プレーン自身がOTLPシンクになる。ClickHouse/Timescaleは `--profile scale` のopt-inのみ。
- **特定値をハードコードしない。** `8000`, `target_rms=3000`, `CLEAR_STREAM_AFTER_SECS`, `silence_duration_ms=600` 等は全て `/examples` のサンプルconfig/manifest内のデータ。コアやプラグイン実装本体に定数として書かない。
- **プロバイダ固有ロジックをコアに入れない。** turn_taking所有権・対応codec・許可override等は全てmanifestで宣言。
- **ブラウザストレージ(localStorage等)をUIで使わない。**
- v1で**マルチテナント認証基盤・課金・RBACは作らない**(単一組織セルフホスト前提。後付け可能な構造にはしておく)。
- v1で**マルチテナント認証基盤・課金は作らない**(単一組織セルフホスト前提)。初期のRBAC非対象方針はproduction診断の [OIDC/operator認可設計](docs/diagnostic-agent-design.md#111-operator-authentication-の推奨) で更新された。独自password管理は作らず、production診断にはrole/authorization hookを設ける。認可は現在未実装。

### 2.3 設計原則
- コアスキーマは「封筒」と「拡張点の契約」だけを持つ。具体パラメータは全てプラグインのJSON Schemaに逃がす。
Expand Down
59 changes: 55 additions & 4 deletions MEMORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
# VoxBench project memory

このファイルは、今後の実装・設計セッションで維持すべきプロダクト判断を短く記録する。詳細設計は [診断エージェント設計・実装計画](docs/diagnostic-agent-design.md) を参照する。
このファイルは、今後の実装・設計セッションで維持すべきプロダクト判断を短く記録する。

## 現在の状態を読む順序(2026-09-27)

- 実装状況の入口は [implementation status](docs/implementation-status.md)。コミット済み、検証済みlocal candidate、計画、deployment検証残件を分ける。
- 設計は `DESIGN.md`、[診断エージェント設計](docs/diagnostic-agent-design.md)、[cascade設計案](docs/cascade-design.md)を参照する。設計の存在だけで実装済みとは判定しない。
- `PROGRESS.md`と日付付きSerena実装memoryは当時のsnapshot。古い「未実装」や進捗率を現在の状態として再利用しない。
- `main`の監査基準は`ae575b6`。Cascade C1–C3Aは`agent/cascade-c1-c3`の[Draft PR #25](https://github.com/engkimo/voxbench/pull/25)にコミット済みで、未merge。UI commandとlocal diagnostic SSEはこのPRに含めておらず、引き続き未コミットのlocal candidateである。詳細と独立した安定化手順はstatus文書に記録した。
- 2026-09-18にlocal candidateを含むPython 3.14.3のsuiteで330 passed / 4 skipped、Ruff、Web build成功を確認。Postgres実接続、browser、production認証、公開CIの検証とは区別する。
- 同日C1実装後の最終検証:現在のPython suiteは408 passed / 4 skipped、Ruff成功。コミット済み基準へC1だけを加えたcheckoutは401 passed / 4 skipped、Ruff成功。78件のC1テストに加え既存テストも成功。後者はUI/SSE candidate不要で、dependencyは既存環境を共有した。
- ユーザーは調査・計画・設計に続いて実装を指示した。candidateを暗黙の公開baselineにせず、cascade契約はコミット済みv1との互換性を基準に実装する。

## STT → LLM → TTS cascade(2026-09-18)

- ユーザー要件:STT、LLM、TTSを個別モデル/providerで組んだcascadeに対応する。既存speech-to-speech realtimeも維持する。
- 合意した方向:既存cascadeの観測を先に、テスト通話の実行を後に進め、実装をissueへ分割する。最初のprovider組合せは未選択。
- issue化済み:[親issue #15](https://github.com/engkimo/voxbench/issues/15)と9件の作業issue(#16–#24)。担当範囲・依存関係・着手順は[issue計画](docs/cascade-issue-plan.md)を参照する。issue公開は機能実装の完了を意味しない。
- 追加ユーザー要件:Pipecat限定にしない。Pipecat以外のframework/middlewareと、middlewareを使わずSDK/HTTP/WebSocketを直接接続する独自実装にも対応する。
- Realtime/Cascadeという音声方式と、frameworkあり/なしという実行方式は独立した軸。coreの観測・診断契約に特定frameworkのframe/context/queueを必須化しない。接続言語もHTTP契約で限定しない。
- 共通service観測契約とconformance fixtureを中心に置く。framework adapterは任意dependency、直接接続の例はframework不要で動かす。専用adapterのないアプリにもapplication-owned hook/HTTP経路を提供する。
- テスト通話はframework非依存の`RuntimeAdapter`/application launcher契約越しに起動する設計。通話runtimeの管理主体、model service adapter、観測transportを分離する。
- 現在もobserver/HTTP ingestとbuilt-in直接接続Realtime経路はPipecat非依存。Pipecat helperは薄い構築境界で、他framework専用adapter、cascade観測・実行、横断conformanceは未実装。
- #17/C1の設定契約をDraft PR #25のreview branch candidateとして実装した。`voxbench/v2`のrealtime/cascade union、service role/modality、input/output PCM chain、一意なcomponent ID、判断主体、manifest版/digest固定とoverlay検証に対応する。v1のresolved object/hashは維持する。現在の契約と使い方は[cascade config v2](docs/cascade-config-v2.md)。
- turn/request/response/TTS segment/epochを明示相関する。並行処理のdurationを足してend-to-end latencyにしない。clockや相関の不足はindeterminateとする。
- 文字列はアプリruntime内で必要だが、VoxBenchのservice観測はmetadata-only。transcript/prompt/LLM文/本文hashを標準保存・診断model送信しない。
- 音声のmedia timeとrun timeをsegment単位で対応付ける。STTとTTS間にaudio duration/level preservationを適用しない。
- C1設定契約だけでは実通話成功を意味しない。C2が観測専用runとservice event ingestを追加した後も、executionとv2音声録音は明示拒否する。受入条件とslice順序はcascade設計文書に置く。
- #18/C2のmetadata-only service観測をDraft PR #25のreview branch candidateとして実装した。v1/v2の観測専用runで、framework非依存の同一DTO/HTTP batchを使用する。collector/event、session/turn/request/parent/response/segment/epochを保持し、本文・URL・raw provider ID・secretのfieldを閉じる。契約は[cascade observation API](docs/cascade-observation-api.md)。
- 同一event IDの同一payload再送だけを冪等とし、変更は409。未知parentをcoverage不足として残し、out-of-order到着後は再構築する。cancel request/ackとrun completeを別証拠とする。observer queueとrun event数をboundしdrop countを公開する。
- #19/C3Aの決定論的因果解析をDraft PR #25のreview branch candidateとして実装した。明示的なparent request chainだけを辿り、STT finalization、turn coordination、LLM dispatch/first output/first answer、aggregation、TTS dispatch/first PCM、local playback、end-to-end local writeを分離する。各値はevidence refs、scope、definition version、clock/uncertaintyを持つ。欠測は`unobserved`、未校正clock間と負の順序は`indeterminate`であり、近接timestampによる推測やservice durationの単純加算はしない。契約は[cascade analysis](docs/cascade-analysis.md)。
- `llm.first_output`はanswer/reasoning/tool_call/otherの種別だけを保持し、本文を保持しない。tool-call continuationとretryは別operation。generation epoch/responseが異なる古いplaybackをend-to-endに再利用しない。
- latency incidentはv2 configの明示的`service_latency_slos`があるobserved measurementだけに生成する。通常metadataからlatency SLO、STT精度、意味品質、発音品質、remote audible timeを推論しない。
- C3A後もaudio segment mapping、inspector、provider/framework test project・adapter、test-call実行は未実装。v2 `/runs/observed`のみ対応し、`/runs`・`/runs/async`とv2 audio chunkは明示拒否する。
- 2026-09-27のC2最終検証:現状は433 passed / 4 skipped、Ruff成功。`ef7deec`へC1+C2だけを加えUI/SSE candidateを除外したcheckoutは426 passed / 4 skipped、Ruff成功。25件のC2 focused test、standalone JSON Schema、SQLite repository再構築を確認。既存dependencyを共有し、実provider/framework/Postgres接続は未検証。
- 2026-09-27のC3A最終検証:`ae575b6`基準の公開用worktreeは444 passed / 5 skipped、Ruff成功。`ef7deec`へC1–C3だけを加えUI/SSE candidateを除外したcheckoutは436 passed / 5 skipped、Ruff成功。10件のC3 focused testとSQLite restart再構築を確認。実Postgres restart testは追加したが環境変数未設定でskip、実provider/Pipecat/browserは未検証。
- ユーザー指定の次ゴール:決定論的fake STT/LLM/TTS Cascadeを、application-owned direct実装(middlewareなし)とPipecat実装の2 test projectとして作る。同じscenario・観測契約・C3解析を通し、VoxBenchで検証、調整、比較評価できるようにする。Pipecatはoptional dependencyのままにし、実provider選定とは分ける。既存issueでは#22と#23のPipecat部分に対応する。

## 診断エージェント(2026-08-07)

Expand Down Expand Up @@ -32,19 +67,35 @@ VoxBenchに、選択中の通話を起点としてコード、ログ、設定、
- 既存のremote audio session cookieは録音取得専用で、製品全体のoperator authの代替にはしない。
- productionでの設定変更、実験実行、コード修正は、将来の承認付きactionとして診断ツールから分離する。

### 推奨実装順序
### Production診断への推奨実装順序

以下は残件の設計順序。local UI/SSE経路の存在は後述のcandidate状況とstatus文書で管理し、production永続化・orchestrationの完了とは扱わない。

1. Timeline/incident modelとprojectionを`run_api.py`から分離する。
2. Evidence resolverとcoverage summaryを実装する。
3. Disconnect analyzerとgolden fixtureを実装する。
4. LLMなしのdeterministic diagnostic bundle APIを作る。
5. Diagnostic session/message/tool call/claimを永続化する。
6. Fake model、bounded orchestrator、claim/citation validatorを実装する。
7. SSEとAsk VoxBench drawerを実装する。
8. 型付きUI commandとguided investigationを実装する。
7. 永続event storeをSSEと既存local Ask VoxBench candidateへ接続し、long-running job/cancel/reconnectを実装する。
8. 型付きUI command candidateを安定化し、guided investigationを実装する。
9. OIDC operator authとauthorization hookを実装する。
10. Production model adapterとegress policyを接続する。

### 型付きUI command・local agent candidate(2026-08-15実装、2026-09-18監査)

この節は未コミットcandidateの機能記録。コミット済み製品の機能一覧ではない。SSEは作成済みeventのfinite replayで、質問による調査計画、継続配信、自動再接続、session容量/TTLは未実装。

- `POST /runs/{run_id}/ui-commands/resolve`を追加し、未信頼proposalをPydanticで型検証した後、run内のincident/evidence/artifact/recording/filter/time windowへ解決する。
- Webに検証済みcommand dispatcherを追加した。run/incident選択、evidence focus、time window、panel表示、録音選択・再生・停止、比較、category/stage/direction filterをUI stateへ直接反映する。
- command IDはclientでidempotentに扱う。適用、拒否、browser autoplay blockを結果として表示する。
- 右railの`Agent UI command bridge`は、現在のrunからsafeな例を生成して、人間とfake agentが同じ契約を共同確認するための手動adapterである。
- 任意URL、DOM selector、JavaScript、フォーム入力、設定保存、任意API呼び出しは引き続き許可しない。
- process内memoryを使うlocal deterministic diagnostic sessionを追加した。最も強いincident、なければ最初のtyped eventを選び、引用と検証済みUI commandをordinal付きSSE eventで配送する。
- Webの`Ask VoxBench`がSSE commandを自動実行し、結果をControl Planeへidempotentにacknowledgeする。これにより人間がJSONをpasteせず、fake agentがUIを直接動かすend-to-end経路を確認できる。
- SSEは`Last-Event-ID`/`after`で再生可能。ack済みcommandへ異なる結果を送ると`409`で拒否する。
- 未実装なのは永続session/event/result store、production model adapterとbounded orchestrator、long-running job/cancel、guided sequence、OIDC認可である。local deterministic adapterをproduction診断agentと表現しない。

### 環境接続時に決めること

- 外部model providerとデータ処理地域。
Expand Down
Loading
Loading