fix(walkthrough): stop the importance tag reading as a review finding

The "Critical" pill was painted in the status-error colour, so a stop marked
because it drives the change read as a severity reported against the code —
the one thing this feature never does. It is now "Key change", carries its
emphasis with weight and an outline rather than a status colour, and both tags
state their meaning in a tooltip. The panel links the guide from its header,
and the guide gained a section on what the tags mean and what they do not.

Also corrects two German strings that translated the noun "stop" as the verb.
This commit is contained in:
Bohdan Triapitsyn
2026-08-04 19:06:19 +03:00
parent 746e0d4abd
commit bcae0fcfc3
15 changed files with 124 additions and 19 deletions
@@ -2,6 +2,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Icon } from '@/components/icon/Icon';
import { FileTypeIcon } from '@/components/icons/FileTypeIcon';
import { Button } from '@/components/ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { useI18n } from '@/lib/i18n';
import { groupHunksByFile } from '@/lib/walkthrough/model';
import type { WalkthroughStopView, WalkthroughView } from '@/lib/walkthrough/model';
@@ -20,8 +21,13 @@ interface WalkthroughStreamProps {
wrapLines: boolean;
}
// Importance says where to spend attention, not what is wrong: a stop is marked
// because it drives the rest of the change, never because something was found in
// it. A red pill said the opposite — status colours are read as findings, and a
// walkthrough deliberately hands out no verdicts — so the emphasis is carried by
// weight and an outline instead, and the tooltip states the axis outright.
const IMPORTANCE_CLASS: Record<WalkthroughStopImportance, string> = {
critical: 'bg-status-error/10 text-status-error',
critical: 'border border-[var(--interactive-border)] font-medium text-foreground',
normal: 'bg-surface-muted text-muted-foreground',
context: 'bg-surface-muted text-muted-foreground',
};
@@ -41,11 +47,22 @@ const StopHeader = ({ stopView }: { stopView: WalkthroughStopView }) => {
exactly as tall as one without: vertical padding on a smaller type
size was pushing past the tallest element in the row. */}
{stop.importance !== 'normal' && (
<span className={cn('typography-micro flex h-5 items-center rounded px-1.5 leading-none', IMPORTANCE_CLASS[stop.importance])}>
{stop.importance === 'critical'
? t('walkthrough.importance.critical')
: t('walkthrough.importance.context')}
</span>
<Tooltip>
<TooltipTrigger
className={cn('typography-micro flex h-5 items-center rounded px-1.5 leading-none', IMPORTANCE_CLASS[stop.importance])}
>
{stop.importance === 'critical'
? t('walkthrough.importance.critical')
: t('walkthrough.importance.context')}
</TooltipTrigger>
<TooltipContent className="max-w-64">
<p className="typography-micro leading-tight">
{stop.importance === 'critical'
? t('walkthrough.importance.criticalHint')
: t('walkthrough.importance.contextHint')}
</p>
</TooltipContent>
</Tooltip>
)}
</div>
<p className="typography-body text-muted-foreground">{stop.prose}</p>
@@ -10,7 +10,9 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { useI18n, type Locale } from '@/lib/i18n';
import { openExternalUrl } from '@/lib/url';
import { buildWalkthroughView } from '@/lib/walkthrough/model';
import type { WalkthroughSource, WalkthroughWorkingTreeScope } from '@/lib/walkthrough/types';
import { ModelSelector } from '@/components/sections/agents/ModelSelector';
@@ -41,6 +43,12 @@ interface WalkthroughViewProps {
const SCOPES: WalkthroughWorkingTreeScope[] = ['all', 'staged', 'working'];
// What a walkthrough is — and what it deliberately is not — cannot be read off
// the panel: the first question users asked about it was whether its marks were
// review findings. The guide answers that, so it is reachable from the surface
// itself rather than only from the release announcement.
const WALKTHROUGH_GUIDE_URL = 'https://docs.openchamber.dev/walkthrough/';
// DropdownMenuLabel defaults to the same size and weight as its items, which
// makes a heading read as another choice. This matches SelectLabel, the
// treatment used by the worktree picker.
@@ -524,6 +532,25 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
</DropdownMenu>
<div className="ml-auto flex min-w-0 items-center gap-1">
<Tooltip>
<TooltipTrigger asChild>
<Button
type="button"
variant="ghost"
size="sm"
aria-label={t('walkthrough.help.guide')}
onClick={() => {
void openExternalUrl(WALKTHROUGH_GUIDE_URL);
}}
>
<Icon name="question" className="size-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p className="typography-micro leading-tight">{t('walkthrough.help.guide')}</p>
</TooltipContent>
</Tooltip>
{/* A walkthrough nobody can read is worth nothing, so the prose
language is a per-review choice like the model — defaulting to the
interface language, which is the best evidence of what the reader
+6 -3
View File
@@ -2853,17 +2853,20 @@ export const dict = {
'walkthrough.empty.title': 'Noch nichts vorhanden',
'walkthrough.empty.description': 'Wählen Sie Inhalte aus, um einen Walkthrough zu erstellen.',
'walkthrough.stale.banner': 'Der Code hat sich nach diesem Review geändert. Veraltete Schritte: {count}',
'walkthrough.stop.staleAll': 'Alle veralteten Inhalte stoppen',
'walkthrough.stop.staleAll': 'Der gesamte Code, den dieser Schritt beschrieben hat, hat sich geändert.',
'walkthrough.stop.stalePartial': 'Ein Teil des vom Schritt beschriebenen Codes hat sich geändert. Fehlende Teile: {count}',
'walkthrough.stop.staleShort': 'Veraltete stoppen',
'walkthrough.stop.staleShort': 'Veraltet',
'walkthrough.stop.noCode': 'Kein Code vorhanden',
'walkthrough.uncovered.title': 'Vom Review ausgelassene Änderungen: {count}',
'walkthrough.uncovered.description': 'Diese Bereiche wurden noch nicht in den Walkthrough aufgenommen.',
'walkthrough.toc.moreFiles': 'Weitere Dateien: {count}',
'walkthrough.toc.uncovered': 'Nicht abgedeckt: {count}',
'walkthrough.toc.resize': 'Größe ändern',
'walkthrough.importance.critical': 'Kritisch',
'walkthrough.importance.critical': 'Kernänderung',
'walkthrough.importance.criticalHint': 'Dieser Schritt trägt die eigentliche Änderung, lesen Sie ihn genau. Es ist kein in Ihrem Code gefundenes Problem.',
'walkthrough.importance.context': 'Kontext',
'walkthrough.importance.contextHint': 'Eine unterstützende Änderung, damit der Rest verständlich bleibt.',
'walkthrough.help.guide': 'So funktionieren Walkthroughs',
'walkthrough.blocked.noModel.title': 'Kein Modell ausgewählt',
'walkthrough.blocked.noModel.description': 'Wählen Sie zuerst ein Modell aus.',
'walkthrough.blocked.emptyDiff.title': 'Kein Diff vorhanden',
+4 -1
View File
@@ -1143,8 +1143,11 @@ export const dict = {
'walkthrough.toc.moreFiles': 'More files: {count}',
'walkthrough.toc.uncovered': 'Not covered: {count}',
'walkthrough.toc.resize': 'Resize the contents column',
'walkthrough.importance.critical': 'Critical',
'walkthrough.importance.critical': 'Key change',
'walkthrough.importance.criticalHint': 'This step drives the rest of the change, so read it closely. It is not a problem found in your code.',
'walkthrough.importance.context': 'Context',
'walkthrough.importance.contextHint': 'A supporting change, included so the rest makes sense.',
'walkthrough.help.guide': 'How walkthroughs work',
'walkthrough.blocked.noModel.title': 'No small model available',
'walkthrough.blocked.noModel.description': 'Sign in to a model provider to generate a review.',
'walkthrough.blocked.emptyDiff.title': 'Nothing to review',
+4 -1
View File
@@ -1144,8 +1144,11 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.toc.moreFiles": "Más archivos: {count}",
"walkthrough.toc.uncovered": "Sin cubrir: {count}",
"walkthrough.toc.resize": "Cambiar el ancho de la columna de contenidos",
"walkthrough.importance.critical": "Crítico",
"walkthrough.importance.critical": "Cambio clave",
"walkthrough.importance.criticalHint": "Este paso impulsa el resto del cambio, así que léelo con atención. No es un problema detectado en tu código.",
"walkthrough.importance.context": "Contexto",
"walkthrough.importance.contextHint": "Un cambio de apoyo, incluido para que el resto tenga sentido.",
"walkthrough.help.guide": "Cómo funcionan los walkthroughs",
"walkthrough.blocked.noModel.title": "No hay ningún modelo pequeño disponible",
"walkthrough.blocked.noModel.description": "Inicia sesión en un proveedor de modelos para generar una revisión.",
"walkthrough.blocked.emptyDiff.title": "Nada que revisar",
+4 -1
View File
@@ -968,8 +968,11 @@ export const dict = {
'walkthrough.toc.moreFiles': 'Autres fichiers : {count}',
'walkthrough.toc.uncovered': 'Non traité : {count}',
'walkthrough.toc.resize': 'Redimensionner la colonne du sommaire',
'walkthrough.importance.critical': 'Critique',
'walkthrough.importance.critical': 'Changement clé',
'walkthrough.importance.criticalHint': "Cette étape porte l'essentiel du changement, lisez-la attentivement. Ce n'est pas un problème détecté dans votre code.",
'walkthrough.importance.context': 'Contexte',
'walkthrough.importance.contextHint': 'Un changement de soutien, présent pour que le reste ait du sens.',
'walkthrough.help.guide': 'Comment fonctionnent les walkthroughs',
'walkthrough.blocked.noModel.title': 'Aucun petit modèle disponible',
'walkthrough.blocked.noModel.description': 'Connectez-vous à un fournisseur de modèles pour générer une revue.',
'walkthrough.blocked.emptyDiff.title': 'Rien à examiner',
+4 -1
View File
@@ -1140,8 +1140,11 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.toc.moreFiles': 'その他のファイル: {count}',
'walkthrough.toc.uncovered': '未対応: {count}',
'walkthrough.toc.resize': '目次の列幅を変更',
'walkthrough.importance.critical': '重要',
'walkthrough.importance.critical': '主要な変更',
'walkthrough.importance.criticalHint': 'このステップが変更全体を動かしているため、じっくり読んでください。コードで見つかった問題ではありません。',
'walkthrough.importance.context': '補足',
'walkthrough.importance.contextHint': '全体を理解するために添えられた補助的な変更です。',
'walkthrough.help.guide': 'ウォークスルーの仕組み',
'walkthrough.blocked.noModel.title': '利用できるスモールモデルがありません',
'walkthrough.blocked.noModel.description': 'レビューを生成するにはモデルプロバイダーにサインインしてください。',
'walkthrough.blocked.emptyDiff.title': 'レビュー対象がありません',
+4 -1
View File
@@ -1144,8 +1144,11 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.toc.moreFiles': '다른 파일: {count}',
'walkthrough.toc.uncovered': '미포함: {count}',
'walkthrough.toc.resize': '목차 열 너비 조절',
'walkthrough.importance.critical': '중요',
'walkthrough.importance.critical': '핵심 변경',
'walkthrough.importance.criticalHint': '이 단계가 변경 전체를 이끌고 있으니 꼼꼼히 읽어 보세요. 코드에서 발견된 문제가 아닙니다.',
'walkthrough.importance.context': '참고',
'walkthrough.importance.contextHint': '나머지를 이해하는 데 도움이 되도록 함께 실은 보조 변경입니다.',
'walkthrough.help.guide': '워크스루 작동 방식',
'walkthrough.blocked.noModel.title': '사용할 수 있는 스몰 모델이 없습니다',
'walkthrough.blocked.noModel.description': '리뷰를 생성하려면 모델 제공자에 로그인하세요.',
'walkthrough.blocked.emptyDiff.title': '리뷰할 내용이 없습니다',
+4 -1
View File
@@ -1456,8 +1456,11 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.toc.moreFiles': 'Więcej plików: {count}',
'walkthrough.toc.uncovered': 'Nieuwzględnione: {count}',
'walkthrough.toc.resize': 'Zmień szerokość kolumny spisu treści',
'walkthrough.importance.critical': 'Krytyczne',
'walkthrough.importance.critical': 'Kluczowa zmiana',
'walkthrough.importance.criticalHint': 'Ten krok napędza resztę zmiany, więc przeczytaj go uważnie. To nie jest problem znaleziony w Twoim kodzie.',
'walkthrough.importance.context': 'Kontekst',
'walkthrough.importance.contextHint': 'Zmiana pomocnicza, dołączona po to, by reszta miała sens.',
'walkthrough.help.guide': 'Jak działają walkthroughy',
'walkthrough.blocked.noModel.title': 'Brak dostępnego małego modelu',
'walkthrough.blocked.noModel.description': 'Zaloguj się u dostawcy modeli, aby wygenerować przegląd.',
'walkthrough.blocked.emptyDiff.title': 'Nie ma czego przeglądać',
+4 -1
View File
@@ -1144,8 +1144,11 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.toc.moreFiles": "Mais arquivos: {count}",
"walkthrough.toc.uncovered": "Sem cobertura: {count}",
"walkthrough.toc.resize": "Redimensionar a coluna de conteúdo",
"walkthrough.importance.critical": "Crítico",
"walkthrough.importance.critical": "Mudança principal",
"walkthrough.importance.criticalHint": "Este passo conduz o restante da mudança, então leia com atenção. Não é um problema encontrado no seu código.",
"walkthrough.importance.context": "Contexto",
"walkthrough.importance.contextHint": "Uma mudança de apoio, incluída para que o restante faça sentido.",
"walkthrough.help.guide": "Como funcionam os walkthroughs",
"walkthrough.blocked.noModel.title": "Nenhum modelo pequeno disponível",
"walkthrough.blocked.noModel.description": "Entre em um provedor de modelos para gerar uma revisão.",
"walkthrough.blocked.emptyDiff.title": "Nada para revisar",
+4 -1
View File
@@ -1144,8 +1144,11 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.toc.moreFiles": "Ще файлів: {count}",
"walkthrough.toc.uncovered": "Не описано: {count}",
"walkthrough.toc.resize": "Змінити ширину колонки змісту",
"walkthrough.importance.critical": "Критично",
"walkthrough.importance.critical": "Ключова зміна",
"walkthrough.importance.criticalHint": "Цей крок веде за собою решту зміни, тож прочитайте його уважно. Це не знайдена у вашому коді проблема.",
"walkthrough.importance.context": "Контекст",
"walkthrough.importance.contextHint": "Допоміжна зміна, додана, щоб решта мала сенс.",
"walkthrough.help.guide": "Як працюють walkthrough",
"walkthrough.blocked.noModel.title": "Немає доступної small model",
"walkthrough.blocked.noModel.description": "Увійдіть до провайдера моделей, щоб створити розбір.",
"walkthrough.blocked.emptyDiff.title": "Немає що оглядати",
+4 -1
View File
@@ -1144,8 +1144,11 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.toc.moreFiles': '其他文件:{count}',
'walkthrough.toc.uncovered': '未涵盖:{count}',
'walkthrough.toc.resize': '调整目录栏宽度',
'walkthrough.importance.critical': '关键',
'walkthrough.importance.critical': '关键改动',
'walkthrough.importance.criticalHint': '这一步带动了其余改动,值得仔细阅读。它不是在你的代码中发现的问题。',
'walkthrough.importance.context': '背景',
'walkthrough.importance.contextHint': '辅助性的改动,列在这里是为了让其余部分说得通。',
'walkthrough.help.guide': 'Walkthrough 的工作方式',
'walkthrough.blocked.noModel.title': '没有可用的小模型',
'walkthrough.blocked.noModel.description': '请登录模型提供方后再生成评审。',
'walkthrough.blocked.emptyDiff.title': '没有可评审的内容',
+4 -1
View File
@@ -1156,8 +1156,11 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.toc.moreFiles': '其他檔案:{count}',
'walkthrough.toc.uncovered': '未涵蓋:{count}',
'walkthrough.toc.resize': '調整目錄欄寬度',
'walkthrough.importance.critical': '關鍵',
'walkthrough.importance.critical': '關鍵變更',
'walkthrough.importance.criticalHint': '這一步帶動了其餘變更,值得仔細閱讀。它不是在你的程式碼中發現的問題。',
'walkthrough.importance.context': '背景',
'walkthrough.importance.contextHint': '輔助性的變更,列在這裡是為了讓其餘部分說得通。',
'walkthrough.help.guide': 'Walkthrough 的運作方式',
'walkthrough.blocked.noModel.title': '沒有可用的小模型',
'walkthrough.blocked.noModel.description': '請先登入模型供應商再產生審閱。',
'walkthrough.blocked.emptyDiff.title': '沒有可審閱的內容',