
IronClaw 流式 QA 实战三个观测时刻抓住流式渲染的真节奏【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址: https://gitcode.com/gh_mirrors/iro/ironclaw你点了发送请求返回 200右上角 toast 闪了一瞬你合上笔记本。可用户的屏幕上IronClaw 的第一个 token 迟到了整整 8 秒。响应到达 ≠ 流式可用。流式渲染验证要量的是页面 DOM 的生长不是网络层那张回执。一个数字说了算读完这节你能说清为什么抓包抓到的 SSE 帧数永远说服不了评审而 DOM 突变次数能。整个方法论可以收束成一个数字采样窗口内页面上段落文本发生变化的次数。我们叫它突变次数mutation count。采样器每约 100ms 读一次主区域所有段落的纯文本把它们拼成一个签名。签名一变就记一笔什么时候变的、变到多长、末尾是哪一句。为什么是它而不是抓包因为评审要判断的是用户看到的节奏。SSE 帧到达、WebSocket 事件投递都发生在线上。用户看到的是这些帧经过 JSON 解析、状态更新、React 重渲染之后才落到段落里的那些字。前端 SSE 连接、看门狗和退避逻辑就写在 useSSE.ts 里。线层再健康前端一卡屏幕就是空的。抓包抓到 200 帧可能一帧都没渲染出来。突变次数直接落在渲染结果上它测的正是屏幕到底动没动。所以这个数是真相指标它不可伪造没法用网络日志背书只能在真实浏览器里量出来。三个观测时刻读完这节你不用看源码就能凭一条流式曲线判断它是健康还是病态。我们把一次流式对话切成三个用户会真正感知的时刻。每个时刻各问一个问题启动了吗稳不稳收得住吗时刻 A「第一口气」️提交后多久开始长设计意图用户最受不了的是发完消息后那一两秒的空白。第一口气只问一件事提交之后页面多久开始变长到底有没有开始变长这也是 fresh-thread 提示词被刻意做成多工具、分阶段、长回答的原因——就是让这段空白足够长长到能测出来。它内嵌三条硬性意图至少三个工具制造多次调用→回流的停顿节奏才分得开工具阶段之间插一句进度更新多打一个渲染脉冲最终答案至少十段短段落把渲染窗口拉长55 秒还够用。脚本要点基线必须在点击发送之后再抓。你提交的那条用户消息、以及提交后出现的静态引导文案都不算流式证据。采样器先记下提交后的段落签名之后每一次与基线不同的增长才计入突变次数。健康 vs 异常信号健康曲线里第一条突变记录出现在提交后一两秒内。若 count 很小或首条记录迟迟不出说明流式没启动起来或启动被卡住了。时刻 B「稳定的鼓点」中段渲染匀不匀设计意图用户能感知一顿一顿还是匀速流淌。稳定的鼓点回答中段渲染速率是否均匀有没有卡顿或者憋很久后一次性倾倒脚本要点follow-up 场景就是把这个鼓点放进已有上下文的对话里复测。长上下文更容易卡顿或一次吐完所以这里专门再跑一遍。提示词做了降级工具从至少三个降到至少两个最终答案从十段降到八段——追问本身就背着上下文不用同等体量也够观察。注意输入框定位名换了追问态的 composer 用的是chat.followUpPlaceholder文案是 Ask for follow-up changes。脚本必须拿这个名字去 fill否则上一轮刚结束的输入框会定位失败。同时把变量全改成railwayFollowup*前缀避开上一段脚本的绑定冲突。健康 vs 异常信号健康曲线中段节奏稳定突变间隔大致均匀。异常是长时间静默后突然出现一大跳——那往往不是内容多而是重连后一次倾倒或前端把缓冲帧攒着没刷。时刻 C「收尾」段落数收得住吗设计意图55 秒采样窗口走完不等于流式结束。收尾问的是终端状态段落数还长不长输入框复位没有答案收得完整吗脚本要点完成态检查一次性看四样东西——composer 是否复位、活动入口按钮是否出现、段落数是否收敛、末尾是否完整收尾。var snap await page.locator(main).innerText(); var buttons await page.getByRole(button).allTextContents(); var paras await page.locator(main p).allTextContents(); console.log(JSON.stringify({ terminalComposer: snap.includes(Ask for follow-up changes), activityButtons: buttons.filter(t t.includes(Activity -)), paragraphCount: paras.length, tail: paras.slice(-10), }));看哪里terminalComposer为 true 说明 composer 已复位成追问态tail用一个完整句子收尾才算完整。健康 vs 异常信号三件事同时成立才算正常收工——段落数不再增长、tail以完整句收尾、composer 复位。若段落数还在涨、输入框却没复位说明答案还在渲染或前端状态机没切过去。12 行脚本三处不变读完这节你把这套探针搬到任何浏览器驱动上要改的只有三处。先看完整探针的核心循环约十二行var start Date.now(); var prev (await page.locator(main p).allTextContents()).join(\n); var changes []; while (Date.now() - start 55_000) { var parts await page.locator(main p).allTextContents(); var sig parts.join(\n); if (sig ! prev) { changes.push({ t: Date.now() - start, len: sig.length, parts: parts.length, tail: sig.slice(-140) }); prev sig; } await new Promise(r setTimeout(r, 100)); } console.log(JSON.stringify({count: changes.length, first: changes.slice(0, 12), last: changes.slice(-20)}));看哪里第 2 行是提交后抓基线while体里是固定 100ms 轮询 签名比对最后一行是首 12、末 20 导出。三不变量无论换什么驱动都不许动提交后取基线基线永远在点击发送之后抓之前的 DOM 一律不算数。只计渲染层变化只数main p文本签名的变化SSE / WebSocket 帧到达不算。固定间隔轮询并记录时序约 100ms 一次每个突变点记下t/len/parts/tail。三处必改换驱动时只翻译这三处三不变量永远保留三处必改随驱动翻译① 基线在提交后抓① 会话/标签句柄 → 驱动 locator② 只计渲染层签名变化② DOM 断言原语 → 驱动取文本/快照 API③ 固定 100ms 轮询、记时序③ 等待 → 驱动原生 sleep探针什么时候会骗你读完这节当数据看起来挺正常时你能一眼认出它被谁骗了。陷阱一陈旧构建HEAD SHA 不一致症状曲线看着挺好但测的是昨天的构建。 根因preview 构建没跟上你连的是旧headRefOid。 判定规则railway_state必须是 success且测试期间的headRefOid与记录值一致否则本次观测作废。陷阱二wire 层 vs 渲染层混淆症状网络日志里 SSE 帧源源不断页面却半天不动。 根因把帧到达当成了渲染发生。 判定规则只认main p突变次数帧数再多渲染没动就是没动。陷阱三REPL 变量名冲突症状第二次跑采样count 突然变 0 或乱掉。 根因Node REPL 里还留着上一段的同名绑定新脚本覆盖或读到了旧值。 判定规则每段脚本用全新前缀变量如railwayFollowup*换名后再跑。陷阱四容量控制反复拒绝 → 曲线跳变症状采样曲线中段出现大段静默后突然跳一大截。 根因服务端 sse_capacity.rs 把连接反复拒绝——每调用方并发上限 3、单连接 5 分钟生命周期连续拒绝达到退款上限后不再退款。前端重连把缓冲帧一次性刷出。 判定规则出现长静默 大跳变先怀疑重连而不是内容本身。从探针到证据读完这节你知道一条流式曲线怎么从我觉得挺顺变成 PR 里站得住的证据。证据要成立先过门禁。preview_state.sh 查出的railway_state若不是 success这次浏览器观测直接作废只能发 BLOCKED 证据。绝不允许在陈旧构建上做流式断言。证据是分级的从强到弱可见的增量变化SSE 增量渲染验证 / DOM 突变采样——最高档点击成功 HTTP 200 toast原始 wire 事件——最低只算补充。流式曲线平滑也只能证明渲染动了。如果 PR 声称的是某个具体契约变更你还得确认采样旅程真的走了目标契约真实 provider / model、路由、角色、工具、起始状态。否则这个用例只是 supplemental升不到 PASS。发布走单一规范评论带隐藏标记railway-test:evidence headHEAD_SHA。所有证据count/first/last、完成态断言结果先拼成完整评论正文再用gh pr comment或gh api --method PATCH发布或更新。发布前做清理删railway-test-前缀的临时数据关闭标签页最后再复核一次headRefOid。Bearer 凭据、敏感浏览器状态一个字都不能出现在证据里。收束流式 QA 测的不是消息发出去没有而是每一次工具回流、每一个进度更新、每一段答案是否都以可感知的节奏长到了屏幕上。关键文件useSSE.ts前端 SSE 连接、30 秒活跃看门狗与抖动退避重连。sse_capacity.rs服务端 SSE 并发上限、5 分钟生命周期与拒绝退款机制。streaming-cadence.md本方法论的原始 QA 配方fresh / follow-up / 完成态三段。api.tseventStreamRequest事件流请求与 WebSocket 事件通道。【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址: https://gitcode.com/gh_mirrors/iro/ironclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考