Skip to content

emrg: GUI streaming markdown block projection in React TranscriptView - #1112

Merged
argszero merged 2 commits into
masterfrom
feature/gui-streaming-markdown
Sep 2, 2026
Merged

emrg: GUI streaming markdown block projection in React TranscriptView#1112
argszero merged 2 commits into
masterfrom
feature/gui-streaming-markdown

Conversation

@argszero

@argszero argszero commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the GUI chat showing AI replies as plain text during streaming**bold**, # heading and code fences were only formatted after the done frame. The TUI and react-markdown competitors render correctly during output (rant ts 2026-09-02T21:07:35).

Decision: 方案 B — restore EMRG's own block-projection engine (already ported into lib/markdown.ts from the vanilla renderer, G74/G132), NOT react-markdown.

Changes

  • TranscriptView.tsxAssistantSegmentView now projects every streamed delta through md.streamProject into an uncontrolled host node during typing:
    • closed blocks (paragraphs, lists, closed code fences) render as markdown immediately and stay cached in the DOM (no flicker, no selection break)
    • the open tail — especially unclosed code fences via isFenceClosed — stays plain text until the fence closes (same heuristic as TUI fence_count%2)
    • on done/segment seal, streamFinalize performs the one-shot full-markdown correction
    • renderers without marked / projection exceptions fall back to the previous plain-text + full renderMarkdown path
  • TranscriptView.test.tsx (10 → 11): E2E stream test with a text-driven fake marked — closed js fence renders a .code-block while typing, an open py fence is held as plain .stream-code, and done replaces the whole stream with full markdown
  • markdown.test.ts (11 → 13): engine-level live-fence open/close branch tests
  • Agent.md: renderer test count 508 → 511

Verification

  • renderer npm run typecheck clean; vitest 511 passed
  • GUI static suite 93 pass / 0 fail
  • doc-count guard: 5 passed
  • full pytest: 1224 passed / 1 skipped
  • renderer production build OK

EMRG Evolution added 2 commits September 2, 2026 21:26
… (rant 2026-09-02T21:07:35)

Streaming assistant messages previously rendered as plain text until the
done frame (`**bold**`, code fences raw while typing). Restore EMRG's own
block-projection engine (方案 B — already ported into markdown.ts, not
react-markdown): TranscriptView now projects each delta through
streamProject into a host node during typing — closed blocks (paragraphs,
lists, closed code fences) render as markdown immediately and are cached in
the DOM, while the open tail (esp. unclosed fences via isFenceClosed) stays
plain text; on done, streamFinalize performs the one-shot full render.
Renderers without marked fall back to the previous plain-text + full
renderMarkdown path. Aligns streaming output with TUI and react-markdown
competitors (rant 2026-09-02T21:07:35).

- TranscriptView.tsx: wire streamProject/streamFinalize into
  AssistantSegmentView (layout-effect projection per delta, finalize on
  done/seal, plain fallback when engine unavailable)
- TranscriptView.test.tsx: E2E stream test — closed js fence renders while
  typing, open py fence held as plain .stream-code, done replaces with full
  markdown (11 tests)
- markdown.test.ts: live-fence open/close engine tests (13 tests)
- Agent.md: renderer test count 508 -> 511

Verified: renderer typecheck + vitest 511 pass, GUI static suite 93 pass,
doc-count guard 5 pass, full pytest 1224 pass/1 skip, renderer build OK.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-213455 (1/3)

Authoring cycle = cyc20260902-212024 (distinct cycle, no ❌). Re-reviewed the merged-tree diff (head cf4db0a, conflict-resolved against #1110's Agent.md 511 → 514):

  • TranscriptView.tsx: streaming segments project through the existing block-projection engine (markdown.ts streamProject/streamFinalize) — useLayoutEffect projects each delta before paint into an uncontrolled host node; closed blocks (paragraphs/lists/closed fences) render as markdown immediately with DOM caching, the open tail (unclosed code fences via isFenceClosed) stays plain .stream-code; done/seal triggers one-shot streamFinalize; renderers without marked fall back to the previous plain-text + full renderMarkdown path (all prior tests untouched and passing).
  • Tests: engine-level live-fence open/close branches + incremental open→closed convergence (markdown.test.ts, 11 → 13); E2E React test asserting closed js fence renders a .code-block while typing, open py fence held plain, done replaces with full markdown and drops .stream-code (TranscriptView.test.tsx, 10 → 11).
  • Agent.md renderer count synced (508 → 511 on branch; 514 after master merge with #1110's Composer 41), doc-count guard green.

CI on merged-tree head cf4db0a: test + test-windows PASS (run 33636014876). MERGEABLE/CLEAN.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-214024 (2/3)

Second consecutive vote (1/3 = cyc20260902-213455, authoring cycle = cyc20260902-212024, no ❌ between). Re-checked this cycle: head cf4db0a unchanged (merged-tree conflict resolution vs #1110), MERGEABLE/CLEAN, CI test + test-windows PASS (run 33636014876). No new feedback on the diff since 1/3 — implementation verified sound (block projection during typing, unclosed-fence plain-text hold, done finalize, plain fallback, Agent.md 514).

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20260902-214638 (3/3)

Third consecutive vote (1/3 = cyc20260902-213455, 2/3 = cyc20260902-214024, authoring cycle = cyc20260902-212024, no ❌ between). Head cf4db0a unchanged, MERGEABLE/CLEAN, CI test + test-windows PASS (run 33636014876). No new feedback on the diff since 2/3. Merging.

@argszero
argszero merged commit d612bcc into master Sep 2, 2026
2 checks passed
@pm25coder

Copy link
Copy Markdown
Collaborator

I tested this PR at head cf4db0a on the Windows host (independent of CI): renderer vitest 514 passed (45 files, matching the Agent.md count) and `npm run typecheck` is clean. The new fence-projection tests behave as described — a closed `js` fence renders a .code-block while typing, an open `py` fence stays plain .stream-code until closed, and `done` triggers the full-markdown finalize. Fallback to the plain-text + renderMarkdown path when projection is unavailable also looks correct in the component wiring.

argszero added a commit that referenced this pull request Sep 10, 2026
…1115 planted-fire timestamp, #1116 journal citation integrity, #1117 Agent.md GUI count guard) (#1118)

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants