fix(desktop): keep Side Conversation follow-ups visible - #4901
Conversation
Astro-Han
left a comment
There was a problem hiding this comment.
I reviewed this PR at head 19d0d8ef (18 files, +1133/−119) against base 90014db9.
What the change does: Side Conversation follow-ups now behave like the main conversation while a Turn is running: Enter queues a next-turn follow-up that renders immediately, Shift+Enter steers the active turn; the Host queue is projected into the transcript with the existing promote/edit/reorder/retract controls; settled replies survive Turn handoffs; cancelled optimistic messages are retired after reconnect/reseed. The queue projection shared with the main surface is extracted into deriveMessageQueueProjection (message-queue-projection.ts), and the cancellation-proof batching moves from the renderer into the IPC layer.
Design: The problem is real and the fix aligns the side chat with the main conversation's established contract (requestedMode routing in app-shell.tsx:1917; the Composer queue controls pre-exist in packages/ui). No new authority is introduced: the Host queue (queue_update from the session projector) remains the single source of truth; the renderer only projects it.
Function (production path): Enter/Shift+Enter routing (quote-companion-context-compaction.ts:55-61) → submitFollowUp port → submitMessage(sessionId, placement, ...) (create-workbar-services.ts:50-66) → IPC → Host. next_turn submissions do not occupy the single in-flight admission slot, so several follow-ups can queue; a queued outcome releases the slot and a started outcome adopts the Host-named Turn (use-quote-companion.ts). The three race branches are covered by tests.
Complexity: The extraction is faithful — I compared it line-by-line with the previous inline logic in app-shell-session-events.ts; the extra state === 'queued' filter on follow-up entries is a no-op because the protocol types follow-up entries as always-queued (QueuedMessageSnapshot in packages/runtime-host/src/protocol/message.ts). The renderer-side pagination loop in session-workspace-actions.ts is deleted and consolidated into the IPC handler.
Tests: 8 new hook-level tests drive the production useQuoteCompanion with mocked ports; each fails on the old behavior (no queue concept, single admission slot blocking multiple queues, settled messages dropped on Turn handoff). IPC tests cover batching, duplicate rejection, and invalid input. CI test is green on this exact head.
P3 (recorded, non-blocking): the 4096-entry cap on the cancellation-proof query is 64× the queue cap; only a constructed over-limit pending set would hit it, and the failure degrades to stale optimistic rows until the canonical echo (pathological, not reachable in normal use).
Not verified: I did not run the suites locally (CI is green on the exact head); the queue UI interactions in a real Electron shell (drag-reorder etc.) are not covered by automated tests — a manual pass (Enter to queue, Shift+Enter to steer, reorder/delete) is worth doing.
No P0–P2 findings. This is a behavior-changing fix; I am not approving — the merge decision belongs to humans.
Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the fix. I rechecked head 19d0d8efe701fd226470a88d6c6d8504deab08eb and found one recoverable follow-up/reconnect race, detailed inline. The Host remains the right admission authority; the issue is how the renderer reconciles a late admission receipt with the Turn's current state.
The exact-head CI check is green. This finding was traced through the production retry, durable-receipt, and renderer event paths; I did not run a live Desktop reproduction.
AI review disclosure: reviewer agents assisted with this review, and the coordinating agent cross-checked the finding against the source. This is not independent human verification.
中文
感谢修复。本轮复核发现一处可恢复的追问/重连竞态,已放在行内。Host 仍然是正确的准入权威;问题在于 renderer 将晚到的准入收据当作当前仍在执行的证明。当前 head 的 CI 已通过;本次依据真实重试、持久收据和事件消费路径进行源码核对,未运行实时 Desktop 复现。本评审由 AI reviewer 协助,并经主代理复核,不代表独立人工验收。
There was a problem hiding this comment.
AI review disclosure: this correction was made by the coordinating AI agent after checking the independent reviewer’s storage-path evidence.
Withdrawn — the normal queued handoff does publish a durable admission.
Thanks, and apologies for the incorrect finding. A further source check found the missing link in my analysis: sqlite-session-metadata-store.ts:2410-2419 adds steeringEventId: steeringProof?.eventId ?? messageId when committing the follow-up handoff. noteDurableTranscriptMessages() can therefore emit message_admission, and the hook adopts that Turn. The normal-path P1 above does not hold and requires no change.
The earlier late-started P2 is separate: a receipt can arrive after its Turn has already settled. I have also corrected that comment so it does not rely on the incorrect generalization about root admissions.
中文
撤回:正常排队交接会发布持久化准入事件。
抱歉,这条意见有误。再次核对发现,我漏查了存储写入点:sqlite-session-metadata-store.ts:2410-2419 在提交 follow-up handoff 时补充 steeringEventId: steeringProof?.eventId ?? messageId,因此 projector 可以产生 message_admission,hook 也会接管对应 Turn。上述普通路径 P1 不成立,无需为它修改代码。
此前“迟到 started”的 P2 是另一个问题:收据可能在 Turn 已经收束后才到达。我也已修正那条评论的描述,去掉关于 root admission 的错误泛化。
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks. After checking the storage-written admission and the observer replacement path separately, one additional P2 remains specifically on reconnect to an already-terminal successor; details are inline. The earlier normal-online P1 has been withdrawn and resolved. The two remaining P2 cases concern recovery/late-response reconciliation, not a missing admission on every queued handoff.
Reviewed head 19d0d8efe701fd226470a88d6c6d8504deab08eb. This is a source-traced finding; I did not run a live Desktop reproduction. AI reviewer agents assisted, and the coordinating agent checked the producer/consumer paths.
中文
感谢。分别核对存储层补写的 admission 与 observer replacement 后,确认重连至已完成后继 Turn 时还有一条 P2,详见行内。此前正常在线路径的 P1 已撤回并关闭。当前两条 P2 都涉及恢复/迟到响应的对齐,而非所有正常排队交接都缺少 admission。
本次核对相同 head,依据源码生产链路,未运行实时 Desktop 复现。由 AI reviewer 协助并经主代理核对生产者与消费者。
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for bringing Side Conversation follow-ups onto the shared queue projection. Two P2 recovery issues remain on this head: a late started receipt can re-arm an already settled turn, and a terminal successor can lose its admission on reseed, hiding its completed reply. Please address both before approval, preserving canonical Host ownership and covering the two event orderings in regressions. The withdrawn normal-handoff P1 requires no action.
This is an AI-assisted review follow-up, not independently human-verified.
中文
感谢让侧边对话复用队列投影。当前 head 仍有两处 P2:迟到 started 收据会重新激活已结束 Turn;重建观察时终态后继 Turn 的准入可能丢失,使已完成回复不可见。请在批准前修复两处问题,保持 Host 权威,并用回归覆盖对应事件顺序。已撤回的正常交接 P1 无需处理。这是 AI 辅助跟进,未经独立人工验证。
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the follow-up visibility work. The combined correctness and simplification audit found one remaining transient-state lifecycle issue; details are inline. AI-assisted review by Codex.
中文
本轮结合正确性与简化审查,发现一处临时状态未退休的问题,详见行内评论。|
Thanks for bringing Side Conversation follow-ups onto the existing Host queue. After tracing both chat surfaces at The Host still owns admission, queue ordering, consumption, retraction and durable execution. The concern is a second renderer implementation of the same transient-message lifecycle:
Could we reuse the existing transient projection/reconciliation functions from both production callers, and consolidate any additional common reconciliation rule at that same seam instead of introducing another side-chat controller or a new general-purpose framework? If feature-layer import rules require moving those functions to the application contracts seam, move the existing implementation and update both callers, rather than keeping another copy or a forwarding facade. Each Session can keep its own projection instance; the transition rules should have one implementation. Side chat should pass its actually renderable, own-Turn-filtered durable messages so unknown-admission visibility is preserved. The whole main-chat workspace controller is not a drop-in dependency: it also owns active-session selection, transcript paging and workspace UI. Keep those concerns separate, and keep the side-specific fork creation, quote handling, fork cleanup and visible-history boundary local. Those differences do not require duplicating queue merge or durable retirement. For reconnect ownership, consume the already existing This refines the fix direction for the existing P2 comments; it is not a claim that this PR adds a second Host scheduler, and it is not a request to rebuild all of Side Conversation. Shared-rule tests plus a small set of side-panel integration cases should then cover the behavior without parallel state-machine test suites. AI-assisted review by Codex; the main/side production callers and existing shared helpers were checked directly. 中文侧边对话需要消费 Host 的队列能力,不需要另一套队列生命周期实现。Host 执行权威仍在;问题在 renderer:主对话已有 queue merge 和 durable retirement 的共享函数,侧边却重写了数组合并,并把真正退休误写成仅过滤显示,已产生 P2 行为漂移。只共享 entry 转换还不够。 建议让两个生产调用方复用现有 transient projection/reconciliation 接缝,共同规则只实现一次,每个 Session 保留自己的投影实例;侧边传入自己已经实际可显示的 durable 消息,保留 unknown-admission 保护。主对话整个 workspace controller 绑定选中 Session、分页和外壳状态,不能直接搬过去;fork 创建、引用、清理和历史显示边界仍留在侧边。重连归属使用已有 queryMessageExecutions,不继续堆最新 root 特判。这个意见是现有 P2 的设计修法,不是要求重做整个侧边对话,也不是宣称新增了 Host 调度器。 |
7a2a0b3 to
7e21149
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the follow-up. Reviewed 7e211491 with three independent reviewer lanes and primary-agent reconciliation. The shared transient projection/retirement request is addressed: main and side chat now use the same rules, the old implementation is removed, and renderable durable twins leave the actual pending set. Host ownership remains intact.
Two P2 recovery issues remain:
- A bounded transcript tail is still used as complete terminal evidence for a late started receipt. The original single-Turn ordering is fixed, but an already-settled B outside the current tail can be re-armed. Details and the focused reproduction are in the reopened late-receipt thread.
- The new execution-ownership recovery caller can exceed the existing 64-ID wire limit; details are inline. Keep batching at the existing Desktop query boundary and preserve all owned/cancelled/pending resolutions.
These are two bounded contracts to complete, not a request to redesign Side Conversation or add another scheduler. The withdrawn normal-handoff P1 remains withdrawn. I found no separate complexity blocker in the shared-rule extraction.
Validation: 52 existing hook cases passed in a temporary exact-head source-loader run. The bounded-tail variation fails as described above. A production IPC + Host decoder probe accepts the old cancellation query as 64+1 but rejects the execution query sent as 65. These probes reuse existing dependencies; they are not a fresh workspace build or real Electron interaction/outage acceptance. Current CI is green. Actual queue edit/reorder/retract and Enter/Shift+Enter acceptance in Desktop remains outstanding.
AI-assisted review with independent reviewers and primary-agent source/probe verification.
中文
感谢跟进。三个 reviewer 独立检查并经主审复核 7e21149。共享 transient 投影/退休的要求已解决:主、侧对话使用同一规则,旧实现已删除,真正可显示的 durable twin 会从 pending 集合退休,Host 权威仍在。
还剩两个 P2 恢复问题:
- 迟到 started 收据仍把有界 tail 当完整终态证据;原单 Turn 顺序已修,但窗口外已结束的 B 仍可能被重新 arm,详见重新打开的旧线程及复现。
- 新执行归属恢复调用可能超过既有 64-ID 协议上限,见行内;请在既有 Desktop 查询边界分批并保留所有 owned/cancelled/pending 结果。
这是两个需要补齐的有限契约,不需要重做侧边对话或新增调度器。此前撤回的正常交接 P1 仍不成立;共享规则提取没有独立复杂度阻塞项。
52 个现有 hook 用例通过临时 exact-head 源码加载验证;有界 tail 变体复现失败。生产 IPC + Host decoder 探针确认旧取消查询分为 64+1,新执行查询却整批 65 而被拒绝。复用了已有依赖,不是重新构建 workspace,也不是真实 Electron 交互/断网验收。当前 CI 绿色,Desktop 的队列编辑、重排、撤回及 Enter/Shift+Enter 实际验收仍未完成。此次为 AI 辅助评审,经独立 reviewer 与主审复核。
|
Thanks for the detailed re-review. Both remaining P2s were independently reproduced and fixed in
Regression coverage includes the terminal B outside-tail ordering, 65 mixed execution identities, duplicate identities, invalid identities, and the 4,097-entry Desktop cap. Local verification passed: 87 focused tests, Desktop typecheck, Biome, and 101 renderer architecture checks. Exact-head CI is green: https://github.com/apache/maka/actions/runs/34189206151 Both inline threads have been answered and resolved. Could you please re-review |
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the fixes. Re-reviewed eb059975a: both previous P2 findings are addressed. Execution queries now batch at the existing Desktop IPC boundary, and a delayed started receipt no longer re-arms a Turn whose terminal state is retained outside the bounded transcript tail. Host ownership and terminal facts remain authoritative; the renderer changes are projections, not a second execution owner. No new P0–P2 findings.
The 87 focused companion/IPC tests pass through an exact-head source loader. An independent real IPC → Host decoder probe also confirms 65 identities become batches of 64 and 1. The added cases protect distinct recovery and validation obligations; no broad test rewrite is requested. Current-head CI is green and the PR is mergeable.
Application-level acceptance remains: in the actual Desktop shell, exercise Enter queue / Shift+Enter steer during a long response, several follow-ups, edit/reorder/retract, and reconnect. The source/DOM tests do not replace those interactions, so this comment does not renew UI sign-off.
AI-assisted independent reviewers and primary source/probe reconciliation.
中文
感谢修复。eb059975a 已解决两个旧 P2:execution query 在现有 Desktop IPC 边界分批;延迟 started 回执不再把已有保留终态、但离开 bounded tail 的 Turn 重新激活。Host 持有 execution ownership/终态事实,renderer 只做投影,没有第二执行权威。无新 P0–P2。
exact-head 源码加载验证 87 项通过,独立真实 IPC→Host decoder 探针也确认 65 IDs 分为 64+1。新增用例保护不同恢复/校验义务,不要求大改测试。当前 CI 绿色且可合并。
实际 Desktop shell 的长响应中 Enter 排队、Shift+Enter steer、多条 follow-up、编辑/重排/撤回及重连仍需验收;源码/DOM 测试不能替代这些操作,因此本条不追加界面通过结论。经 AI 独立评审与主审源码/探针核对。
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the earlier corrections. I need to amend my previous assessment of eb059975a: those reported cases are fixed, but the deeper consumer-path review found two remaining P2s. These are newly identified on the same head, not regressions caused by a new commit.
[P2] Recover owned successor content outside the bounded transcript tail. If B completes entirely during an observation gap and the recovered tail only contains later Turn C, reconcilePendingMessageExecutions records B's ownership but never loads B's durable messages. B's optimistic row can remain without its answer. Likewise, a late started(B) receipt can re-arm B when neither the current tail nor retained local messages contain B's terminal evidence. The previous fix covers B that was observed and retained locally; it does not cover B that this renderer never observed.
The invariant is that a ready bounded window is not complete Turn/lifecycle proof. Please use the existing Host execution identity/Turn authority and transcript range seam to recover the specific successor, then retire its transient projection. Keep this one durable reconciliation path rather than adding another renderer state graph. This finding is based on the production call chain; the additional focused fixture probe was not completed, so I am not claiming an executable reproduction for this new condition.
The other P2, local-save versus Host admission, is inline and has an existing small adapter fix. The Host queue/revision direction remains sound, and the 87 focused checks for the previously covered scenarios passed. Actual Desktop acceptance for Enter/Shift+Enter, queue edits/retraction and reconnect remains outstanding. AI-assisted review; primary-agent reconciliation.
简体中文
感谢此前修正。我需要更正之前对 eb059975a 的判断:已报告的场景确实修好了,但深入消费者链路后确认仍有两项 P2。这是在同一 head 新发现的问题,不是新提交引入。
P2:恢复落在有界 transcript 尾部之外的后继回复。 B 完全在观察断档期间结束,恢复尾部只包含之后的 C 时,reconcilePendingMessageExecutions 只记录 B 的 ownership,却不加载 B 的持久消息,可能留下临时消息而不显示回复。若还有迟到 started(B),且尾部和本地保留消息都没有 B 终态,还可能重新 arm 已结束的 B。此前修复覆盖的是 B 曾被本地观察并保留,不覆盖从未观察到 B。
不变量:有限窗口 ready 不是完整 Turn/生命周期证明。复用 Host execution identity/Turn 权威及 transcript range 接缝,补回确切 successor,再退休临时投影;不要新增 renderer 状态图。此项是生产调用链核对结论,补充夹具探针未完成,不声称已运行复现。
另一个本地保存与 Host 准入混淆的 P2 见行内,有现成的小修接缝。Host queue/revision 的方向合理,之前场景的 87 项定向检查通过。Enter/Shift+Enter、队列编辑/撤回及重连的真实 Desktop 验收仍待完成。AI 辅助评审,主审已复核。
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
eb05997 to
7a21c8a
Compare
|
Addressed both newly reported P2s in
Regression coverage includes the adapter admission option, A → B → C with only C in the initial recovery tail, targeted recovery of B while preserving B/C order, the missing-target Local verification: 102/102 focused tests, Desktop typecheck, Biome on all changed files, |
Preserve shared transient recovery while using the current Composer queue presentation and Host admission behavior. Generated-by: Codex
Generated-by: Codex
Consolidate pending retirement and query validation, remove redundant subscription branches, and preserve retained terminal evidence when a late receipt read fails. Keep the recovery, queue projection, and batching guards validated by ablation experiments. Generated-by: Codex
Resolve the transcript test import conflict and migrate targeted recovery to the existing Host Turn index plus sequence-anchored renderer paging. Move settlement to the Desktop platform, remove its redundant forwarding layer, and cover multi-page recovery and missing indexed targets. Validation: clean build; 2527 Desktop and 419 UI tests; full build/typecheck; lint/format; Desktop and UI knip; 103 architecture fixtures and origin/main ratchet. Review threads are resolved; manual queue/reconnect acceptance and independent human approval remain outstanding. Generated-by: Codex
Preserve Host execution snapshots and shared live buffers. Recover lost admissions, prove queue removals through Host ownership, reseed empty queues, and permit native queue reordering. Add real Electron acceptance for follow-ups and connection recovery. Generated-by: Codex
Keep optimistic prompts with their Host-owned Turn across lost receipts, settlement and successor handoffs. Verify the actual Electron queue and reconnect paths and record the complete reviewer audit and the unrelated Host PTY fixture race. Generated-by: Codex
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for working through the admission, handoff and reconnect cases. I reviewed aaeebaba2 against the current base and the earlier findings. The reported Side Conversation gap is real, and the solution now follows the existing Host queue and execution ownership: follow-ups wait for canonical admission, removed queue entries are resolved as owned/cancelled/pending rather than guessed to be retracted, and completed successors outside the tail are recovered through the existing Turn index and transcript range reader.
The remaining presentation state has a concrete purpose: pending identity bridges uncertain admission, owned-Turn filtering excludes inherited history, and retained terminal evidence prevents a late receipt from reactivating a finished Turn. Shared queue/transient projection and settlement replace the duplicated paths. No P0–P3 findings remain.
Verification: rebuilt this exact head; 211 affected Desktop tests and 27 Host projector tests passed. The real Electron acceptance passed with actual main/preload/Host/renderer and a deterministic model backend: Enter follow-ups, Shift+Enter steering, queue edit/reorder/retract/promote, multiple Turn handoffs, and a real Desktop transport gap while the Host completed two successors. After reconnect, both replies remained visible, the queue was empty and Stop was absent. This is application acceptance, not a live-provider test. Current CI and package checks are green.
AI-assisted rereview: Reviewer Sol independently examined the Side Conversation ownership/recovery contracts; the coordinating Codex agent checked the shared Host/Desktop changes and ran the validations above.
Keep the relocated Desktop settlement import and remove the obsolete MessageListUpdater import after the structured-history update. Validate the merged tree with Desktop build/typecheck, format/lint, 122 focused tests and real Electron queue/reconnect acceptance. Generated-by: Codex
Generated-by: Codex
Twelve upstream commits. Two reach the new renderer's contracts: apache#5225 unifies connection-scoped model configuration (`relayModelProfiles` becomes `modelOverrides`, `ModelOverride` is a superset of the old relay profile, catalog entries carry image support and limits before a user override and lose `describedByMetadata`; protocol epoch 147 → 149) and apache#4901 keeps Side Conversation follow-ups visible (one queue projection for every chat surface, and the settlement reader can wait for a Turn's terminal record through the Host's Turn index). Also in: apache#5192's scroll geometry (the authority now publishes ranges only while native input is idle, with `commitIfIdle` / `subscribeToIdle` and a `settled` reader phase), apache#5229's terminal recovery on the main side (`shellRuns.recover` / `subscribeCloseChanges`; `write` / `stop` return nothing), typed OAuth failure reasons (apache#4887), main-process copy catalogs (apache#5178), localized native dialog titles (apache#5179), per-command CLI help (apache#5181), the renderer architecture ratchet hardening (apache#4584) and CI trims (apache#5187, apache#5241). Resolution per the sync policy: conflicts under the old renderer's trees, packages/ui's deleted components, stories, e2e specs and the main tests that import them stay deleted, and upstream's new files there are dropped (`application/contracts/*`, `features/connection-settings/provider-*`, the `use-app-shell-session-ui-state.ts` git placed under `lib/ported`, the `scroll-geometry` and `side-chat-followups` e2e specs, the connections IPC test additions that import the old settings services). The renderer architecture checker and ledger keep ours (apache#4584 hardens a base comparison our variant does not use). `workbar-layout.ts` / `workbar-tabs.ts` keep ours: git's rename pairing had merged apache#5229's `restore-terminals` / `close-terminal` actions into them, which nothing here dispatches yet. `runtime-host-quit-copy.ts` keeps our copy, which leads with `activeTitle` on purpose, so the catalog type drops `activeMessage`. Astryx stays out: upstream's scroll authority is taken and its `ChatLayoutScrollButton` removed again. Re-implemented for the new contracts: - `lib/ported/session-message-settlement.ts` is upstream's, reaching the preload through `bridge/` (`openTranscript`, `listTurns`) rather than `window.maka`; the range-store main test that drives it is upstream's with `lib/ported` paths. - `lib/ported/message-queue-projection.ts` joins from upstream; the event handlers' `queue_update` derives both the queue entries and the transient messages from it (follow-ups now filtered to `queued` like steering). - `bridge/shell-runs.ts` returns nothing from `write` / `stop`. - Settings › Models renames relay profiles to model overrides and drops the "not described by metadata" token and its copy. - `packages/ui` `transcript-scroll-authority.tsx` is upstream's minus the Astryx button; `use-chat-scroll.ts` and `transcript-viewport-navigation.ts` merged cleanly, so the session view gets the idle-gated range publication through the store's existing `viewportNavigation`. `TransientUserMessageProjection` gains `pendingSteering?` so the projection's flag is a declared field. Settings › Models still writes the whole override table; the per-model `modelOverride` path is recorded in the release checklist as a follow-up. The compatible-change declaration is unchanged this round. Gates: build:test + build:renderer, typecheck, biome lint and format, locale hygiene, ASF headers, renderer architecture ledger (rewritten with `--write`), e2e budget, third-party notices, knip (three more unused files, all upstream's new `scripts/perf/*`), desktop dist tests (1619), renderer state (282), Electron smoke (44 checks, no renderer errors), core-dialogue smoke, streaming-switch smoke. `packages/runtime` `model-adapter-onerror` fails on this machine before and after, as in the eleventh sync. Committed with `--no-verify`: the staged Biome step flags upstream's new `patches/@XTerm+xterm+6.0.0.patch` (escape sequences Biome's stdin mode cannot round-trip — the known false positive); the file is byte-identical to upstream and the other hook steps (ASF headers, protocol epoch, whitespace) were run by hand and pass. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Summary
Make Side Conversation follow-ups behave like the main conversation while a Turn is running:
Fixes #4900
Verification
npm --workspace @maka/desktop run build:workspace-depsnpm --workspace @maka/desktop run build:testnode --test apps/desktop/dist/main/__tests__/quote-companion-retry.test.js apps/desktop/dist/main/__tests__/transient-message-projection.test.js apps/desktop/dist/main/__tests__/workbar-services-adapter.test.js— 60/60 passnpm --workspace @maka/desktop run typechecknpm --workspace @maka/desktop run check:architecture— 101/101 passnpx knip --workspace apps/desktopnpx biome check --diagnostic-level=error <changed files>git diff --check origin/main...HEADThe focused tests exercise the user-visible optimistic/queued projection, Enter vs Shift+Enter routing, multiple queued follow-ups, queue retraction, Turn handoff, and reconnect cancellation cleanup.
AI use
Select exactly one:
Tool(s) and scope: OpenAI Codex diagnosed the state/admission races, implemented the Desktop renderer and adapter changes, added regression coverage, and prepared the issue/PR text. The commits retain
Generated-by: Codextrailers.Checklist
Does this PR entail a change in behavior?