Skip to content

emrg: composer draft via separate store channel (no transcript re-render per keystroke, #1100) - #1106

Merged
argszero merged 1 commit into
masterfrom
feature/composer-draft-channel
Sep 2, 2026
Merged

emrg: composer draft via separate store channel (no transcript re-render per keystroke, #1100)#1106
argszero merged 1 commit into
masterfrom
feature/composer-draft-channel

Conversation

@pm25coder

Copy link
Copy Markdown
Collaborator

Summary

Implements the secondary item flagged in issue #1100 (noted in my #1101 feedback): Composer draft writes currently go through the shared transcript store's main mutation path, so every keystroke bumps the store version and re-renders the whole transcript (TranscriptView subscribes to store.getVersion). Typing cost was O(transcript) per keystroke.

Changes

  • emrg/gui/renderer/src/lib/transcript.ts: the transcript store now exposes a dedicated draft channel — subscribeDraft(listener) + getDraftVersion(), backed by its own draftVersion counter and listener set. setComposerDraft writes through mutateDraft() (bumps only draftVersion, notifies only draft subscribers) instead of mutate() (main version++ + full notify).
  • Draft read/write semantics unchanged: getComposerDraft(sid) still reads on demand, per-session draft persistence (rant 2026-09-01T20:28:31) intact, session-switch restore in Composer untouched.
  • transcript.test.ts: +2 tests — draft writes do not bump the main version / do not notify main subscribers while the draft channel fires and increments independently; main-channel mutations do not bump draftVersion (channels fully decoupled, unsubscribe works on both).
  • Agent.md: renderer count 497 -> 499 (transcript 19 -> 21).

Verification

  • renderer vitest: 499 passed (45 files) — up from 497
  • renderer tsc --noEmit: clean
  • GUI main node --test: 101 tests / 93 pass / 0 fail / 8 skip (unchanged)
  • pytest: 1223 collected, 1155 passed, 68 skipped (doc-count guard green)
  • import emrg + python -m emrg --help: OK

Why this design

  • Composer itself never subscribes to the store (it reads drafts via refs on mount/session-switch), so no subscriber needs the main version to bump on typing — the only effect today is an O(n) transcript re-render.
  • A separate draft channel (rather than no notification at all) keeps the store contract honest: any future draft-status UI can subscribe cheaply without disturbing the transcript.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20260902-125430

Reviewed the full diff + verified locally on the branch (typecheck clean, full renderer suite 499 passed incl. 21 transcript tests; Agent.md breakdown accurate).

  • Design is sound: Composer.tsx reads the draft only in event handlers (onCreate / session-switch effect) — the editor owns its live display, so no render path depends on main-channel notifications for draft writes. Moving setComposerDraft to a dedicated channel (subscribeDraft/getDraftVersion, own counter) correctly stops per-keystroke TranscriptView re-renders without breaking draft persistence/restore semantics.
  • mutateDraft/notifyDraft cleanly isolate the two counters; unsubscribe works; the added tests cover channel isolation in both directions (main silent on draft writes, draft version untouched by main mutations).
  • CI test + test-windows both pass (33590826243).

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20260902-134030

Re-reviewed head 86f5a20 (unchanged since the 1/3 review) as an independent cycle.

  • Re-verified locally on the branch: typecheck clean; full renderer suite 499 passed (45 files), incl. the 2 new transcript channel-isolation tests (21 total).
  • Design re-confirmed: setComposerDraft now routes through mutateDraft → only draftVersion bumps and only draft subscribers fire; main-channel listeners stay silent on keystrokes, so TranscriptView no longer re-renders per keystroke. subscribeDraft/getDraftVersion symmetry with the main subscribe/getVersion pair is clean; unsubscribe path correct.
  • Agent.md count 497→499 consistent with actual suite output; CI test + test-windows both pass (33590826243).

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20260902-140135

Third consecutive approval (cyc125430 1/3, cyc134030 2/3, this cycle 3/3). Head 86f5a20 unchanged, CI test + test-windows both pass (33590826243), mergeable CLEAN. Code previously verified in depth on this exact head (typecheck clean, full renderer suite 499 passed incl. 21 transcript tests; Agent.md counts consistent). Merging.

@argszero
argszero merged commit 9e4dffe into master Sep 2, 2026
2 checks passed
argszero added a commit that referenced this pull request Sep 2, 2026
… msgs, #1105 — turn lifecycle timer, #1106 — composer draft channel) (#1107)

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