ENG-820 - Deduplicate StreamTranscript's line-buffering logic (parseStream vs appendStreamText) - #233
Merged
Merged
Conversation
Make parseStream a thin wrapper over the incremental parser so there is one JSONL buffering algorithm, and document the append-only text invariant that appendStreamText's suffix slicing relies on.
There was a problem hiding this comment.
Verified against ENG-820 and the round-2 plan. The diff is exactly the scoped delegation:
parseStreamnow reads onlyreturn appendStreamText(emptyParseState, text, complete).rows— the old split/buffer algorithm, its partial-line narration comment, and the dead trailing-newline no-op block are all gone. No residual commentary remains in the wrapper. (AC1)- A caller-contract comment sits directly above
IncrementalParseStatestating that eachtextpassed toappendStreamTextmust extend the previoustextas a prefix, which is what makesreceivedLengthsuffix slicing sound. It's phrased as an end-state invariant, not implementation narration, and doesn't editorialize about the omitted reset guard. (AC2) - Neither
StreamTranscript.test.tsnorStreamTranscript.incremental.test.tsxappear in the diff. I hand-traced the existingparseStreamtest inputs (trailing-newline, no-trailing-newline, blank-interior-line, and empty-text shapes) throughappendStreamTextand confirmed identical output in each case.On Pull Request Frontend / checksis green fora0f2593and coversnpm --prefix frontend run lint,npm --prefix frontend test, andnpm --prefix frontend run buildfor this exact commit. (AC3) - Backend lint/test commands (
ruff check,ruff format --check,pytest backend/) have no registered check for this SHA — expected, sinceon-pull-request-backend.ymlpath-filters onbackend/**/pyproject.toml/uv.lockand this diff touches onlyfrontend/src/components/StreamTranscript.tsx. Not a gap, just out of that workflow's trigger scope.
No blocking findings. This is a clean, minimally-scoped dedup that matches the plan's chosen approach (delegation wrapper, not a parallel algorithm or reset guard) and the ticket's explicit "what good looks like" snippet verbatim.
Nothing to push back on from my side, but flag it if any of the above reads differently to you.
Open findings
None carried from prior rounds (round 1 implementation).
Contributor
Author
|
Code review: Clean DRY refactor collapsing parseStream into appendStreamText with no behavioral change; existing behavior-based tests still cover it. |
czpython
approved these changes
Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linear ticket: ENG-820
Plan
Approach
This is a focused frontend refactor limited to
frontend/src/components/StreamTranscript.tsx; no protocol, component-prop, parser-output, or rendered-row changes are intended.parseStream’s independentsplit('\n')buffering implementation with the ticket-pinned delegation:return appendStreamText(emptyParseState, text, complete).rows. Preserve its exported signature and Fast Refresh exemption so the existing public-helper tests exercise the production parser.parseStream; any surviving rationale belongs at the single rule-owning incremental parser location.IncrementalParseStateorappendStreamText: every newtextvalue extends the previous value as a prefix, makingreceivedLengthsuffix slicing valid. Keep the comment as an end-state invariant, not implementation narration or reset-guard rationale.StreamTranscriptrender-time update path unchanged. Verified callers already satisfy the invariant:RunTranscriptLiveappends chunks and remounts on transcript identity changes, while paginated backfill uses the loading gate before rendering a different transcript.StreamTranscript.test.tsandStreamTranscript.incremental.test.tsxunchanged. Confirm equivalence by hand-tracing the existing parser inputs, including trailing-newline, no-trailing-newline, blank-interior-line, and empty-text cases. Runnpm --prefix frontend testonly when a Node toolchain is available; otherwise record it asnot_runwith the missing-toolchain blocker and rely on frontend CI.Scope decision
Use the ticket’s minimum treatment for finding #2: document the invariant without adding reset behavior. A shorter-length guard misses same-length and longer replacements, while a complete divergence check requires retaining or validating prior text and introduces behavior current callers do not need.
The diff stays within the
IncrementalParseState/appendStreamText/parseStreamregion. Despite.druks/review/checklist.mdrequiring an end-to-end review of touched files, pre-existing comments and helpers elsewhere in the roughly 760-line component are explicitly out of scope and remain untouched.Verification constraints
This sandbox has no Node runtime or package manager on
PATH, andfrontend/node_modulesis absent. Frontend test, build, and lint commands are therefore conditional local checks rather than implementation gates; the configured frontend CI remains authoritative.Acceptance Criteria
parseStream(text: string, complete: boolean): Row[]remains exported with its Fast Refresh exemption, and its body is the single ticket-pinned delegationreturn appendStreamText(emptyParseState, text, complete).rows. The duplicate splitting/buffering algorithm, its partial-line narration, and the dead trailing-newline block are removed with no residual commentary in the wrapper.frontend/src/components/StreamTranscript.tsxand confirm the wrapper contains only the delegation expression and no independent parsing logic, dead block, or buffering commentary.IncrementalParseStateorappendStreamTextstates that eachtextinput must extend the previously passed text as a prefix, which makes suffix slicing byreceivedLengthsound. It does not narrate the implementation, compare old and new behavior, or editorialize about the deliberately omitted reset guard.frontend/src/components/StreamTranscript.tsxand confirm the comment documents the caller invariant in the required form.frontend/src/components/StreamTranscript.test.tsandfrontend/src/components/StreamTranscript.incremental.test.tsxremain unchanged: no test case is deleted, weakened, or adjusted to accommodate the delegation, and both existing suites continue to pass against the shared parser implementation.parseStreaminputs throughappendStreamText, including trailing-newline, no-trailing-newline, blank-interior-line, and empty-text forms, and confirm behavior is unchanged. Runnpm --prefix frontend testif a Node toolchain is available; otherwise report that exact command asnot_run, identify the missing Node toolchain as the blocker, and rely onOn Pull Request Frontend / checksin CI.