cluster-027: streaming reply moves from sink-owned timer to actor turn (sink passivized, -840 LOC)#708
Conversation
… actor turn Per Phase 9 #701 consensus (Auric architecture, 3/3 unanimous round 5): - TurnStreamingReplySink: remove timer-owned pending/dispatch state. Sink now ONLY sends actor-approved accumulated reply snapshot to the conversation actor. No _lock, no _pendingText, no _dispatchInProgress, no fire-and-forget dispatch loop. - SkillRunnerStreamingReplySink: same — sink now ONLY performs Lark POST/PUT for an actor-approved output snapshot. - AgentRunGAgent: streaming reply throttling, duplicate suppression, interim cap, and final-flush ordering all moved into run-owned state inside the actor turn. - SkillRunnerGAgent.ExecuteSkillAsync: scheduled Lark streaming throttling, duplicate suppression, and final-flush ordering moved into run-owned state inside actor turn. - Sink tests updated to assert the new boundary: sinks send approved snapshots; no timer/pending business state owned by sinks. Task.Delay remains only inside the actor/run-owned awaited flow (not sink-callback). No new actor type, envelope kind, pipeline phase, shared substrate, or external dependency added. Chunks stay outside EventEnvelope. Function-call/tool paths unchanged. Diff: 6 files, +243 / -1083 (net -840). Build pass; ChannelRuntime.Tests pass; arch+stability guards pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## auto-refact-dev #708 +/- ##
================================================
Coverage 82.44% 82.44%
================================================
Files 939 939
Lines 59722 59722
Branches 7832 7832
================================================
Hits 49240 49240
Misses 7112 7112
Partials 3370 3370
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
Applied 8 fixes (FIX_DONE:708:round-1:applied-8:rejected-0:blocked-0): addresses 2 reviewer rejects (architect + tests) + quality comment. Diff: 5 files, +282 / -10. Key additions: AgentRunGAgent + SkillRunnerGAgent behavior tests for actor-turn streaming throttling, duplicate suppression, final-flush ordering; restore + sink boundary documentation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 1 —
|
…ter-027) Applied 2 fixes (FIX_DONE:708:round-2:applied-2:rejected-0:blocked-0): addresses v2 tests reject — adds source-regression test in both sink test files asserting sink production source files do not contain forbidden tokens (_flushTimer, CreateTimer, _pendingText, _dispatchInProgress, Task.Run, fire-and-forget dispatch). Diff: 2 test files, +72 lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 2 —
|
Applied 5 fixes (FIX_DONE:708:round-3:applied-5:rejected-0:blocked-0). Diff: 2 files, +45 / -18. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Fix codex round 3 —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
🤖 Phase 8 Reviewer —
|
✅ Phase 8 Multi-codex consensus reached (round 4) — auto-merge after CIVerdicts trajectory | 4 轮历程
3/3 unanimous approve. Auto-merge queued after remaining CI checks (6 pending) settle to pass. Englishiter15 cluster-027 reached unanimous consensus after 3 fix rounds. Final state realizes Auric's Phase 9 #701 architecture for streaming: sink is passive snapshot receiver, actor turn owns throttle/dedupe/final-flush, chunks never via EventEnvelope, function calls via EventEnvelope. Source-regression assertions in both sink test files lock the no-regression rule. 中文iter15 cluster-027 经过 3 轮 fix 达成 3/3 一致。最终形态实施 Auric 在 Phase 9 #701 的流式架构:sink 被动接收 snapshot,actor turn 持节流/去重/final-flush,chunks 不走 EventEnvelope,function call 走 EventEnvelope。两个 sink 测试文件加 source-regression 断言锁死"不回退"。 CI 剩余 6 个 check 通过后自动 merge。 |
Summary / 摘要
English
iter15 cluster-027-streaming-reply-timer-business-dispatch (severity:medium, rule_ids: AG-ACTOR-EXEC-01, AG-ACTOR-EXEC-02).
TurnStreamingReplySink,SkillRunnerStreamingReplySink) use Timer callbacks to directly inspect/mutate pending business output state (_pendingText,_dispatchInProgress) and dispatch actor commands from callback thread. Sink owns_lock, throttle window, fire-and-forget dispatch loop, finalization.AgentRunGAgent(text path) andSkillRunnerGAgent.ExecuteSkillAsync(scheduled path) as run-owned state inside the actor turn.Task.Delayonly inside the actor/run-owned awaited flow, never in callback thread.Violated: CLAUDE.md "## Actor 执行模型" — "回调只发信号"(timer callback was reading runtime state + starting business dispatch) + "业务推进内聚"(business advancement was leaving actor turn). This was the original issue #684 substantive design.
中文
iter15 cluster-027-streaming-reply-timer-business-dispatch(严重度:medium,规则 ID:AG-ACTOR-EXEC-01, AG-ACTOR-EXEC-02)。
TurnStreamingReplySink、SkillRunnerStreamingReplySink) 用 Timer callback 直接 inspect/mutate pending 业务输出状态(_pendingText、_dispatchInProgress),并从 callback 线程 dispatch actor 命令。sink 持有_lock、throttle window、fire-and-forget dispatch loop、finalization。AgentRunGAgent(文字路径)和SkillRunnerGAgent.ExecuteSkillAsync(scheduled 路径),作为 actor turn 内的 run-owned 状态。Task.Delay只在 actor/run-owned 等待路径里,绝不在 callback 线程。违反:CLAUDE.md "## Actor 执行模型" — "回调只发信号"(timer callback 之前在读运行态 + 启动业务 dispatch)+ "业务推进内聚"(业务推进逃出了 actor turn)。这是 issue #684 的原始实质设计点。
Scope / 范围
6 files changed, +243 / -1083 (net -840).
agents/Aevatar.GAgents.Channel.Runtime/TurnStreamingReplySink.csagents/Aevatar.GAgents.NyxidChat/AgentRunGAgent.csagents/Aevatar.GAgents.Scheduled/SkillRunnerGAgent.csagents/Aevatar.GAgents.Scheduled/SkillRunnerStreamingReplySink.cstest/Aevatar.GAgents.ChannelRuntime.Tests/SkillRunnerStreamingReplySinkTests.cstest/Aevatar.GAgents.ChannelRuntime.Tests/TurnStreamingReplySinkTests.csValidation: build pass;
Aevatar.GAgents.ChannelRuntime.Testspass; arch+stability guards pass.No new actor type / envelope kind / pipeline phase / shared substrate / external dependency. Chunks NOT routed through any new EventEnvelope path (existing conversation reply chunk events remain the existing channel output boundary). Function-call/tool execution paths unchanged.
Phase 9 design source
Closes #684 after merge. Built on Phase 9 #701 round 5 consensus (3/3 unanimous on Auric pipeline + sink-as-passive-snapshot-receiver). See implement summary in
.refactor-loop/runs/implement-cluster-027-streaming-reply-timer-business-dispatch.md. Visible semantics preserved: first delta immediate, ~300 ms coalesce window, final flush bypasses throttle, FinalizeAsync waits for in-flight dispatch.🤖 Auto-loop / codex-refactor-loop iter15 (Phase 9 consensus → implement)