[Bug]: mobile/legacy bufferedOutput residual push mis-frames as OutputSpan after query-suffix strip
- Dominant language
- TypeScript
- Stars
- 70.4k
- Forks
- 4.6k
- Avg merge
- 16h 8m
- Merged PRs (30d)
- 451
Description
## Summary
The non-multiplex (mobile / legacy inline-query-embedding) buffered-output residual push in `src/main/runtime/rpc/methods/terminal.ts` fixes `uncoveredMeta.rawLength` to the pre-strip length, then shrinks the data further via `stripSnapshotBoundaryQuerySuffixes`. The final push can therefore carry `rawLength !== data.length`, tripping the batcher's `rawLength !== data.length` check and mis-emitting the plain residual as a transformed **OutputSpan** frame. The client then computes `startSeq = seq - rawLength` too high and fires a spurious authoritative resync (self-healing: one redundant snapshot, no data loss).
## Location (on `main`)
`src/main/runtime/rpc/methods/terminal.ts` (~line 3078 on current main):
```ts
if (item.meta.rawLength === item.data.length) {
uncoveredMeta = { ...item.meta, rawLength: uncoveredData.length } // set BEFORE strip
}
uncoveredData = stripSnapshotBoundaryQuerySuffixes(uncoveredData, ...) // can shrink further AFTER
...
outputBatcher.push(uncoveredData, uncoveredMeta) // rawLength now stale
```
`uncoveredMeta.rawLength` is pinned before the final strip, so a strip that removes more bytes leaves `rawLength > data.length` on the push.
## Relationship to #8180 / PR #8255
This is the **same bug class** as the one fixed in PR #8255 (`bbingz/fix-remote-runtime-recovery`), where the multiplex QueryReplay-frame residual path got a `realignResidualOutputMeta(data, meta)` helper that realigns `rawLength` to the residual length **after** any strip (guarding genuinely-transformed spans via `if (!meta || meta.transformed) return meta`). This mobile/legacy sibling path predates and is independent of that path, so it was intentionally left out of the #8255 rebase (surgical-diff scope). It should get the analogous fix: compute `rawLength` from the final `uncoveredData` after the strip, with the same `meta.transformed` guard.
## Severity
Low/medium — self-healing (one extra snapshot round-trip, no data loss), only on the mobile/legacy inline-query path.
## Suggested fix
Mirror `realignResidualOutputMeta`: derive the residual meta's `rawLength` from the post-strip `uncoveredData.length`, and skip the rewrite when `meta.transformed` is set. Add a regression test alongside the existing `preserves a transformed span rawLength through the post-snapshot residual push` test in `terminal-multiplex.test.ts`.
Contributor guide
Assessment
This issue has not been assessed yet.