Repository navigation
Enable speculative rewrite for streamed markdown snapshots - #180
Open
Vincent Peng (vincent-peng) wants to merge 3 commits into
Open
Vincent Peng (vincent-peng) wants to merge 3 commits into
Vincent Peng (vincent-peng) wants to merge 3 commits into
Conversation
The partial-emphasis and partial-table rewriters were built for the streaming path but never wired up: the parse(text:config:) convenience hardcodes speculativeRewrite: false, so streamed snapshots ending in an unclosed emphasis marker or a partial table header rendered literal jitter text. StreamedMarkdownController now parses each snapshot with speculativeRewrite: true, matching the rewriters' intended use. MarkdownView (complete documents) keeps the literal behavior so trailing markers in static text are not eaten. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Review feedback: speculative rewriting also applied to the last
emission, so a completed stream ending in a deliberate trailing
marker ("2 * 3", a literal "|" line) stayed munged forever. After the
source finishes, re-render the final snapshot literally.
Also expose speculativeRewrite on parse(text:config:) so both call
sites share the option bridging, and opt the sample chat demo's
streaming path in (literal on the final chunk).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bail before the settle parse when the task was cancelled so a torn-down view does not pay for a render it will never publish. - Cover the cancellation invariant with a test asserting no republish after end(). - Replace the implicitly-unwrapped continuation with AsyncStream.makeStream in the test helper (force_unwrapping is a strict-mode lint rule). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Vincent Peng (vincent-peng)
requested review from
a team
and
a balanced review from Copilot
October 8, 2026 13:41
Contributor
Author
|
Independent verification: PASS (verified against the real artifact by an agent that did not write the code, on detached worktree
|
Vincent Peng (vincent-peng)
added a commit
to vincent-peng/SwiftStreamingMarkdown
that referenced
this pull request
Oct 8, 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.
Summary
speculativeRewriteand its post-parse rewriters (PartialEmphasisRewriter,PartialTableRewriter) already exist, but no shipped call site enabled them —StreamedMarkdownControllerparsed every snapshot with speculation off, so trailing**/*/`and incomplete table headers rendered as literal text mid-stream.Changes:
StreamedMarkdownControllerparses each incoming snapshot withspeculativeRewrite: true.2 * 3) is restored rather than eaten by the speculated emphasis.parse(text:config:)gains an optionalspeculativeRewrite:parameter (defaultsfalse; source-compatible) so streaming callers don't have to constructMarkdownParseOptionby hand.StreamedMarkdownController.taskis widened fromprivateto internal so tests can await completion deterministically (no polling).LLMChatInteractoruses the same flag — speculating only on incomplete chunks — which also demonstrates the intended usage.Resolves #178
Validation
make lint— 0 violations (strict)make test— full package suite passes, including a newStreamedMarkdownControllerTestssuite covering:**speculatively closed mid-stream, then correct render on completion*restored once the stream finishesend()cancels the taskmake build-sample— builds cleanOSS readiness
parse(text:option:)and the non-streamingMarkdownViewpath are untouched.