cluster-026: voice provider response epoch moves into actor turn (typed provider_response_id)#707
Conversation
… turn Per Phase 9 #701 consensus (Auric architecture, 3/3 unanimous round 5): - Add typed provider_response_id fields to voice provider event proto so provider adapters expose provider-native response identity without owning actor response epochs. - OpenAI provider: remove _responseEpochs / _nextResponseId mapping; emit raw provider response ids on lifecycle/audio/function-call events. - MiniCPM provider: remove provider-owned response counters, active/ suppressed state, synthetic cancel event emission; cancel sends only the provider stop request. - VoicePresenceModule (actor turn): owns provider-response-id → actor response_id mapping; owns actor-side cancel suppression for stale provider ids. Receive-loop now posts typed signals to actor turn, not background dict writes. - Disable remote audio input/output handling inside VoicePresenceModule so PCM chunks not moved through EventEnvelope; remote setup/close/ control remains actor-owned. SCOPE_EXTEND (justified): - src/Aevatar.Foundation.VoicePresence.OpenAI/OpenAIRealtimeProvider.cs - src/Aevatar.Foundation.VoicePresence.MiniCPM/MiniCPMRealtimeProvider.cs - src/Aevatar.Foundation.VoicePresence.Abstractions/Protos/voice_presence.proto (typed provider_response_id fields required by design) - test/Aevatar.Foundation.VoicePresence.{OpenAI,MiniCPM}.Tests/ Diff: 7 files, +279 / -133 (net +146). Build pass; VoicePresence.Tests + OpenAI.Tests + MiniCPM.Tests all pass; arch+stability guards pass. No new actor type / envelope kind / pipeline phase / core abstraction. proto change is additive typed field on existing message (not new message). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## auto-refact-dev #707 +/- ##
===================================================
+ Coverage 82.43% 82.46% +0.03%
===================================================
Files 939 939
Lines 59610 59679 +69
Branches 7818 7823 +5
===================================================
+ Hits 49139 49215 +76
+ Misses 7100 7097 -3
+ Partials 3371 3367 -4
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 3 files with indirect coverage changes 🚀 New features to boost your workflow:
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
Applied 5 fixes (FIX_DONE:707:round-1:applied-5:rejected-0:blocked-0): - (A) architect: add method-level Refactor (iter15/cluster-026) markers on VoicePresenceModule actor-turn provider event normalization, response identity normalization, provider response mapping, retirement - (A) architect: add method-level Refactor marker on OpenAI provider MapSessionEvent (emits provider-native response ids) - (A) architect: add method-level Refactor markers on MiniCPM provider CancelResponseAsync + ReadCompletionStreamAsync - (A) quality: add why-comment for intentional remote audio input no-op until raw host-origin transport path exists - (A) tests: add source-regression test asserting provider adapters no longer own response epoch/counter state; module owns provider response mapping Build pass; VoicePresence.Tests 120/120; OpenAI.Tests 24/24; MiniCPM.Tests 12/12; test_stability_guards pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 1 —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
Applied 3 fixes (FIX_DONE:707:round-2:applied-3:rejected-0:blocked-0): addresses v2 architect + quality comments. Diff: 2 files, +6 / -13 (net -7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 2 —
|
…er-id test (cluster-026) Applied 2 fixes (FIX_DONE:707:round-3:applied-2:rejected-0:blocked-0). Diff: 2 files, +80 / -40. Added module-level behavior test for ResponseCancelled with ProviderResponseId; refactored normalization for clarity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 3 —
|
…io surface (cluster-026) Applied 9 fixes (FIX_DONE:707:round-4:applied-9:rejected-0:blocked-0). Cross-PR note: also touches RemoteActorVoicePresenceSessionResolver (PR #706 scope). Both PRs delete same dead code → rebase clean either order. Diff: 7 files, +16 / -181 (net -165). Deletion-positive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 4 —
|
Applied 4 fixes (FIX_DONE:707:round-5:applied-4:rejected-0:blocked-0): - (A) architect: add Refactor markers on RunTransportRelayAsync + CreateModuleSignal - (A) tests: add MiniCPM provider test asserting fallback ProviderResponseId stays non-empty + stable across started/audio/done when frame.ResponseId is 0 Diff: 3 files, +49. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 5 —
|
🤖 Rebase done —
|
Summary / 摘要
English
iter15 cluster-026-voice-provider-background-state (severity:medium, rule_ids: AG-ACTOR-EXEC-01, AG-STRONG-TYPING-01).
_responseEpochsdictionary from background thread outside actor event-loop. Provider also owns active/suppressed response state and emits synthetic cancel events.VoicePresenceModuleactor turn. Actor turn owns provider-response-id → actorresponse_idmapping AND cancel suppression for stale provider ids. Receive loop no longer mutates shared dict; receive loop signal is callback-only-signal per CLAUDE.Violated: CLAUDE.md "## Actor 执行模型" — "回调只发信号", "业务推进内聚"; AGENTS strong-typing for response identity.
中文
iter15 cluster-026-voice-provider-background-state(严重度:medium,规则 ID:AG-ACTOR-EXEC-01, AG-STRONG-TYPING-01)。
_responseEpochs字典;provider 同时持有 active/suppressed 响应状态并发出合成 cancel 事件。VoicePresenceModuleactor turn。actor turn 持有 provider-response-id → actorresponse_id映射,同时持有针对陈旧 provider id 的 cancel 抑制。receive loop 不再修改共享字典;receive loop 是 CLAUDE 的 "callback-only-signal"。违反:CLAUDE.md "## Actor 执行模型" — "回调只发信号"、"业务推进内聚";AGENTS 响应身份强类型。
Scope / 范围
7 files changed, +279 / -133 (net +146).
src/Aevatar.Foundation.VoicePresence.Abstractions/Protos/voice_presence.proto(additive typedprovider_response_idfields)src/Aevatar.Foundation.VoicePresence.MiniCPM/MiniCPMRealtimeProvider.cssrc/Aevatar.Foundation.VoicePresence.OpenAI/OpenAIRealtimeProvider.cssrc/Aevatar.Foundation.VoicePresence/Modules/VoicePresenceModule.cstest/Aevatar.Foundation.VoicePresence.OpenAI.Tests/OpenAIRealtimeProviderTests.cstest/Aevatar.Foundation.VoicePresence.MiniCPM.Tests/MiniCPMRealtimeProviderTests.cstest/Aevatar.Foundation.VoicePresence.Tests/VoicePresenceModuleTests.csValidation: build pass; VoicePresence.Tests + OpenAI.Tests + MiniCPM.Tests all pass; arch+stability guards pass.
No new actor type / envelope kind / pipeline phase / core abstraction. proto change is additive typed field on existing messages, NOT a new message.
Phase 9 design source
Closes #682 after merge. Built on Phase 9 #701 round 5 consensus (3/3 unanimous on Auric pipeline + no new abstraction). See implement summary in
.refactor-loop/runs/implement-cluster-026-voice-provider-background-state.md.🤖 Auto-loop / codex-refactor-loop iter15 (Phase 9 consensus → implement)