fix(design): show submitted messages immediately
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
2026-09-04 08:38:13 +08:00
parent c6b0490d7f
commit 403236115b
4 changed files with 208 additions and 13 deletions

View File

@@ -18,6 +18,10 @@
canonical turn arrives.
- Close the supported duplicate-stream path caused by overlapping event-source opens
and repeated/out-of-order `chunkIndex` delivery.
- Project a newly submitted chat command into the conversation immediately, before the
server returns the canonical turn. Keep the provisional message visually honest,
replace it with the canonical turn without duplication, and restore the draft after
a definitive failure.
- Add focused Renderer and Store regression tests. Do not change Works Square server,
Electron Main DTO/API, Current Specification authority, Quote/generation, Plugin
navigation, packaging, publication, or the three foreign root task records.
@@ -37,6 +41,8 @@
right-side “AI 听懂的想法” remains its secondary projection.
- Keep Chinese-only copy, reduced-motion behavior, at least 40 px interactive targets,
and the current responsive single-mount behavior.
- Do not create a second chat state machine: the existing pending operation is the
provisional message identity, while only the returned Workspace turn is canonical.
## Project Context Loaded
@@ -60,6 +66,17 @@
## Outcome
- A chat command now appears in the conversation immediately from its existing
`PendingDesignOperation`, before the server returns the canonical Workspace turn.
The provisional user bubble carries a small `发送中` state, changes to `正在确认`
for an unknown accepted outcome, and is filtered to the active Workspace.
- While that exact draft is projected as a provisional bubble, the composer looks
cleared without deleting the stored draft. Canonical success atomically replaces
the provisional bubble with the persisted turn; definitive failure removes the
pending projection and naturally restores the original draft for correction/retry.
- First-use guidance is hidden as soon as the first provisional user message exists.
Other in-flight Design input commands retain the existing composer lock, so the UX
change does not introduce concurrent reducer writes.
- `DesignConversationPane` no longer renders raw `assistantStreams` prose as an
assistant chat bubble. It renders one compact `role=status` surface that explicitly
says the AI is organizing the idea and that the content is not a new reply. A
@@ -79,6 +96,20 @@
## Verification
- New optimistic-message red baseline: Store publication passed, while the Renderer
regression failed because no `发送中` message existed, the first-use prompt remained,
and the composer still showed the submitted draft. After the fix, the two focused
files pass `27/27`, including submitting → unknown → canonical replacement.
- Adjacent ImageCanvas, Store, Fine Tune, youth summary/projection/copy tests now pass
`6 files / 51 tests`.
- Follow-up TypeScript `tsc --noEmit`, changed-file ESLint, and production
Renderer/Main/Preload/utility Vite build pass. Build output contains only the
existing browserslist, dynamic-import, and large-chunk warnings.
- Electron/Playwright AI Design checks both pass individually: Prompt Museum media
isolation passed in the two-test run; the conversation/adjustment/Quote/Task flow
initially timed out at the pre-Design auth-fixture readiness gate, then passed `1/1`
in isolation in 1.8 seconds. The timeout occurred before this feature path and is
not recorded as product success evidence for the new provisional state.
- Red baseline: three new regressions failed against the original implementation—raw
unfinished prose had no progress role, an obsolete concurrent EventSource was not
closed, and replaying chunk index `0` produced duplicated text. A fourth targeted red
@@ -108,8 +139,11 @@
- Proposal: record that `design.assistant.delta` is unfinished progress, never a
committed conversation turn. Renderer may show an explicit progress/uncertainty
status but must not render its raw prose as a chat reply; only canonical persisted
turns enter the timeline. Concurrent/replayed stream delivery must converge by
connection generation and `chunkIndex`.
turns enter the timeline. A locally submitted chat command may appear immediately as
a clearly provisional user bubble by projecting its existing pending operation; it
must disappear when the canonical turn arrives and must not become a second semantic
message store. Concurrent/replayed stream delivery must converge by connection
generation and `chunkIndex`.
- Evidence: the user screenshot, four red-before/green-after regressions, 49 adjacent
tests, typecheck, scoped lint, production build, and 2/2 Electron E2E.
- Future impact: later streaming polish must preserve the distinction between transient