fix(design): remove redundant assistant progress banner
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# Task: Remove redundant AI Design progress banner
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260904-remove-design-progress-4e8a1c73
|
||||
- Mode: Feature
|
||||
- Branch: codex/20260904-remove-design-progress-4e8a1c73-remove-design-progress
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260904-remove-design-progress-4e8a1c73
|
||||
- Base commit: 403236115bf81e7617856cd8219b1be23f6abbb8
|
||||
- Owner: codex-root
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Remove the visible AI Design assistant-progress banner from the main conversation
|
||||
pane. The right-side “AI 听懂的想法” projection remains the sole surface for the
|
||||
currently organized design understanding.
|
||||
- Preserve immediate provisional user messages, their `发送中` / `正在确认` feedback,
|
||||
canonical assistant replies, and the existing internal stream reconciliation.
|
||||
- Update focused Renderer regression coverage only. Do not change the Works Square
|
||||
server, Electron Main/API contracts, Current Specification authority, generation,
|
||||
navigation, packaging, publication, or unrelated project records.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- The user explicitly identified the progress banner as duplicated information and
|
||||
requested that it be removed. It must not be replaced by another central loading
|
||||
surface.
|
||||
- Raw assistant deltas remain non-canonical and must stay out of the conversation.
|
||||
Removing their presentation must not remove their Store state or change operation
|
||||
identity and failure recovery.
|
||||
- Keep the pending user bubble as the honest acknowledgement that a send was accepted
|
||||
locally; only the redundant assistant-side banner is removed.
|
||||
- Concurrent Task Gate and Planning Gate passed in the managed isolated worktree from
|
||||
exact client `main` base `403236115bf81e7617856cd8219b1be23f6abbb8`.
|
||||
- The root integration task overlaps the same AI Design area but owns only root/canonical
|
||||
reconciliation; this feature task owns the component and focused test in isolation.
|
||||
- ADR-007 remains unchanged: the server Current Specification is semantic authority,
|
||||
while the right-side youth summary is its secondary client projection.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `DesignConversationPane` no longer subscribes to `assistantStreams` for visible
|
||||
presentation and no longer renders the “AI 正在整理你的想法” / result-confirmation
|
||||
banner in the conversation timeline.
|
||||
- Raw assistant deltas remain Store-owned transport state and still never appear as
|
||||
committed chat content. The final canonical assistant turn remains unchanged.
|
||||
- Provisional user messages and their `发送中` / `正在确认` labels remain visible, so
|
||||
removing the duplicated assistant banner does not remove send acknowledgement.
|
||||
- The right-side “AI 听懂的想法” card and all Current Specification behavior are
|
||||
unchanged.
|
||||
|
||||
## Verification
|
||||
|
||||
- Focused Renderer test: `pnpm exec vitest run tests/unit/image-canvas-page.test.tsx`
|
||||
passed `1 file / 10 tests`.
|
||||
- TypeScript: `pnpm exec tsc --noEmit` passed.
|
||||
- Scoped ESLint for the changed component and test passed.
|
||||
- The isolated worktree dependencies were restored from the existing lockfile with
|
||||
offline, frozen resolution and lifecycle scripts disabled; no dependency version or
|
||||
lockfile changed.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Integrate this source commit after the existing root AI Design integration task has
|
||||
safely completed or released its ownership. Do not overwrite that task's dirty
|
||||
canonical-document reconciliation or its three preserved foreign records.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Target: `.project-docs/30-worklog/current-state.md`, AI Design presentation wording
|
||||
in `.project-docs/20-architecture/system-overview.md`, and the corresponding rule in
|
||||
`.project-docs/40-domain/business-rules.md`.
|
||||
- Proposal: record that raw assistant deltas stay internal and invisible in the main
|
||||
conversation; the right-side Current Specification projection is the single surface
|
||||
for the AI's organized understanding. The main timeline shows provisional/canonical
|
||||
user messages and canonical assistant turns, without a separate assistant-progress
|
||||
banner.
|
||||
- Evidence: the user explicitly identified the banner as duplicated information and
|
||||
requested its removal; focused Renderer coverage confirms the banner is absent while
|
||||
send acknowledgement remains.
|
||||
- Future impact: later conversation changes should not reintroduce a second summary or
|
||||
progress card into the timeline merely because assistant delta transport state exists.
|
||||
- Semantic conflict: this narrows the prior task's optional visible progress projection;
|
||||
it does not change ADR-007 or server authority. Human confirmation is already present
|
||||
in this task request.
|
||||
@@ -44,7 +44,6 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
|
||||
const chatDraft = useImageWorkspaceStore((state) => state.chatDraft);
|
||||
const setChatDraft = useImageWorkspaceStore((state) => state.setChatDraft);
|
||||
const sendChat = useImageWorkspaceStore((state) => state.sendChat);
|
||||
const assistantStreams = useImageWorkspaceStore((state) => state.assistantStreams);
|
||||
const pendingOperations = useImageWorkspaceStore((state) => state.pendingOperations);
|
||||
const scrollAnchorRef = useRef<HTMLDivElement>(null);
|
||||
const pendingChatMessages = Object.values(pendingOperations).flatMap((operation) => {
|
||||
@@ -60,13 +59,6 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
|
||||
status: operation.status,
|
||||
}];
|
||||
});
|
||||
const streamingOperationIds = Object.entries(assistantStreams)
|
||||
.filter(([, text]) => text.trim())
|
||||
.map(([operationId]) => operationId);
|
||||
const hasAssistantProgress = streamingOperationIds.length > 0;
|
||||
const hasUnknownAssistantProgress = streamingOperationIds.some(
|
||||
(operationId) => pendingOperations[operationId]?.status === 'unknown',
|
||||
);
|
||||
const submittingDesignInput = Object.values(pendingOperations).some(
|
||||
(operation) => operation.status === 'submitting' && operation.command.kind === 'apply_input',
|
||||
);
|
||||
@@ -81,7 +73,7 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
|
||||
if (typeof scrollAnchor?.scrollIntoView === 'function') {
|
||||
scrollAnchor.scrollIntoView({ block: 'end' });
|
||||
}
|
||||
}, [hasAssistantProgress, pendingChatKey, workspace.turns.length]);
|
||||
}, [pendingChatKey, workspace.turns.length]);
|
||||
|
||||
const submit = () => {
|
||||
if (!composerDraft.trim() || submittingDesignInput) return;
|
||||
@@ -107,8 +99,7 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-5">
|
||||
{workspace.turns.length === 0
|
||||
&& pendingChatMessages.length === 0
|
||||
&& !hasAssistantProgress && (
|
||||
&& pendingChatMessages.length === 0 && (
|
||||
<div className="mx-auto flex h-full max-w-sm flex-col justify-center py-8">
|
||||
<div className="mb-5 flex h-11 w-11 items-center justify-center rounded-2xl bg-brand/[0.09] text-brand">
|
||||
<MessageSquareText className="h-5 w-5" />
|
||||
@@ -169,29 +160,6 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
|
||||
</div>
|
||||
))}
|
||||
|
||||
{hasAssistantProgress && (
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
data-testid="design-assistant-progress"
|
||||
className="mr-auto flex max-w-[92%] items-start gap-3 rounded-xl bg-brand/[0.06] px-3.5 py-3 text-muted-foreground shadow-sm"
|
||||
>
|
||||
<span className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-background text-brand shadow-sm">
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
|
||||
</span>
|
||||
<div className="min-w-0">
|
||||
<p className="text-xs font-semibold text-foreground">
|
||||
{hasUnknownAssistantProgress ? '正在确认刚才的整理结果' : 'AI 正在整理你的想法'}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs leading-5 text-muted-foreground">
|
||||
{hasUnknownAssistantProgress
|
||||
? '结果回来后会显示在对话里,不需要重复发送。'
|
||||
: '这不是新的回复,完成后会显示下一步问题或建议。'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
<div ref={scrollAnchorRef} />
|
||||
</div>
|
||||
|
||||
@@ -93,7 +93,7 @@ describe('youth AI Design Canvas page', () => {
|
||||
expect(screen.queryByText(/规格版本|编译器|生成策略|字段决策/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('presents unfinished AI output as progress instead of a chat reply', () => {
|
||||
it('keeps unfinished AI output out of the conversation while send status stays visible', () => {
|
||||
prepareWorkspace();
|
||||
const unfinishedDraft = '收到,我们要收到,我们要制作一张社团活动海报。';
|
||||
useImageWorkspaceStore.setState({
|
||||
@@ -121,7 +121,11 @@ describe('youth AI Design Canvas page', () => {
|
||||
render(<ImageCanvas />);
|
||||
|
||||
const conversation = screen.getByTestId('image-workspace-conversation');
|
||||
expect(within(conversation).getByRole('status')).toHaveTextContent('AI 正在整理你的想法');
|
||||
const pendingMessage = within(conversation).getByTestId('pending-design-chat-operation-chat-1');
|
||||
expect(within(pendingMessage).getByText('做一张社团活动海报')).toBeInTheDocument();
|
||||
expect(within(pendingMessage).getByText('发送中')).toBeInTheDocument();
|
||||
expect(within(conversation).queryByTestId('design-assistant-progress')).not.toBeInTheDocument();
|
||||
expect(within(conversation).queryByText('AI 正在整理你的想法')).not.toBeInTheDocument();
|
||||
expect(within(conversation).getByText('我已经整理了用途、受众和初步概念,请确认右侧建议。')).toBeInTheDocument();
|
||||
expect(within(conversation).queryByText(unfinishedDraft)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user