From dffca699f0bf554314db697c600f0675a793862e Mon Sep 17 00:00:00 2001 From: murashit Date: Tue, 7 Jul 2026 22:26:57 +0900 Subject: [PATCH] Show empty thread context as zero percent --- .../chat/panel/surface/composer-projection.tsx | 6 +++++- .../chat/panel/surface/projections.test.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/features/chat/panel/surface/composer-projection.tsx b/src/features/chat/panel/surface/composer-projection.tsx index 526a2a86..0b427a5d 100644 --- a/src/features/chat/panel/surface/composer-projection.tsx +++ b/src/features/chat/panel/surface/composer-projection.tsx @@ -98,7 +98,7 @@ function composerMetaViewModel( const context = contextSummary(snapshot); const selectedModel = resolution.model.effective; const effort = resolution.reasoningEffort.effective; - const composerContext = contextComposerMeter(context?.percent ?? null); + const composerContext = contextComposerMeter(context?.percent ?? emptyThreadContextPercent(snapshot)); const compactEffort = effort ? compactReasoningEffortLabel(effort) : null; const planActive = resolution.collaborationMode.effective === "plan"; const reviewActive = resolution.autoReview.active; @@ -122,6 +122,10 @@ function composerMetaViewModel( }; } +function emptyThreadContextPercent(snapshot: RuntimeSnapshot): number | null { + return snapshot.activeThreadId ? null : 0; +} + function runtimeComposerChoices(input: RuntimeComposerChoicesInput): { modelChoices: ChatPanelComposerRuntimeChoice[]; effortChoices: ChatPanelComposerRuntimeChoice[]; diff --git a/tests/features/chat/panel/surface/projections.test.ts b/tests/features/chat/panel/surface/projections.test.ts index 5bedd794..3bb2c1bd 100644 --- a/tests/features/chat/panel/surface/projections.test.ts +++ b/tests/features/chat/panel/surface/projections.test.ts @@ -232,6 +232,22 @@ describe("chat panel surface projections", () => { }); }); + it("shows zero percent composer context before a thread starts", () => { + expect(composerProjectionFromState(composerProjectionActionsFixture(), chatStateFixture()).meta).toMatchObject({ + fatal: null, + context: { + cells: [ + { text: "⣀", placeholder: true }, + { text: "⣀", placeholder: true }, + { text: "⣀", placeholder: true }, + { text: "⣀", placeholder: true }, + ], + percent: " 0%", + }, + statusSummary: "Context 0%, plan off, auto-review off, fast off, model default, reasoning effort default", + }); + }); + it("keeps zero percent composer context fixed-width and visible", () => { let state = chatStateFixture(); state = chatStateWith(state, { activeThread: { id: "thread-1" } });