feat(#300 ui): launcher в правый верхний угол + тёмный per-agent цвет глифа #307
Reference in New Issue
Block a user
Delete Branch "feat/300-avatar-polish"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Догоняющая полировка аватар-стека агента поверх уже смерженного #304 (реализация #300). Два визуальных изменения, только клиент —
apps/client/src/components/ui/agent-avatar-stack.tsx(+тест).Изменения
bottom={0} right={0}(снизу-справа) → сталtop={0} right={0}. Глиф агента остаётся вертикально центрированным, поэтому выравнивание с именем не смещается; launcher по-прежнему «за» агентом (zIndex:0) и выступает наружу наLAUNCHER_OVERHANG.agentGlyphBackground(name): оттенок берётся из хеша имени агента (hue = hash(name) % 360), а насыщенность/светлота зафиксированы тёмными —hsl(hue, 45%, 24%). Разные агенты → визуально различимые тёмные кружки, при этом эмодзи / белыйIconSparklesостаются читаемыми на тёмном фоне. Агентов с загруженной картинкой-аватаром (внешний MCP) это не затрагивает — у них рендерится фото.Верификация
tsc --noEmit— 0 ошибок.vitest(agent-avatar-stack + comment-list-item) — 11/11 passed. Добавлен юнит-тестagentGlyphBackground(детерминизм по имени, различие для разных имён, фиксированная тёмная светлотаhsl(h, 45%, 24%)).Контекст
Правки родились из живого просмотра результата после мержа #304: сначала «аву пользователя выше и в правом верхнем углу», затем «фон разным, из хеша имени агента, сдвинутый в темноту, чтобы не мешать читать эмодзи». Диффа с backend нет — только позиционирование и цвет глифа.
Ref #300, follow-up к #304.
Ревью — #307 (agent avatar UI polish: launcher в правый верхний угол + тёмный per-agent цвет глифа, #300), round 1, head
6f7d4398, base developScope: реальная дельта — ТОЛЬКО коммит
6f7d4398поверх смердженного #304 (родитель88d96c41); 2 файла (agent-avatar-stack.tsx +45, .test +19). Чисто клиент/презентация. #304 не ревьюился — предок, уже одобрен.Вердикт: CHANGES — фича сделана верно (обе визуальные цели достигнуты по коду, объективка зелёная), но остался ОДИН устаревший из-за этой правки docstring в изменяемой же функции. Одна правка — doc-only. (NB: пиксели в браузере не проверял — нет браузера; оценка по JSX/CSS + тесту.)
Полный веер (coherence, regressions+stability, test-coverage, conventions+simplification) — 3 LGTM, 1 DO (documentation). Объективка запущена мной (детач
6f7d4398): clienttsc --noEmit→ 0 ошибок;vitest agent-avatar-stack→ 1 file, 8 tests passed.Do — примени, затем ре-ревью
agent-avatar-stack.tsx:54-59(docstringAgentGlyph). Строки всё ещё гласят «2. agent.emoji → the role emoji on a violet circle» и «3. otherwise → the IconSparkles glyph on a violet circle (fallback)». Именно этот коммит УБРАЛ фиксированный фиолет (AGENT_COLOR) и заменил на per-agent тёмный хеш-фон (agentGlyphBackground). Соседние комменты (LAUNCHER_OVERHANG, инлайн-глиф) обновлены — этот пропущен, оставляя правку внутренне противоречивой. Fix: переписать обе строки под per-agent тёмный (хешированный) круг, напр. «the role emoji on a per-agent dark circle» / «the IconSparkles glyph on a per-agent dark circle (fallback)».Подтверждено по коду + прогоны (не блокирует)
pos=absolute top={0} right={0}zIndex:0; глиф flex-центрирован в контейнере GLYPH_SIZE+OVERHANG(46px); launcher 22px выступает вправо на 8px и вверх на ~4px, по-прежнему «за» агентом и виден. Зеркало прежнего bottom-right; выравнивание глифа с именем не смещено.agentGlyphBackground(name)=hsl(hash%360, 45%, 24%)— L=24% фиксирует темноту для ЛЮБОГО оттенка → белый sparkles/яркий эмодзи читаемы; варьируется только hue → различимые-но-консистентные кружки. Детерминированно. Применено через Mantinestyles={{root,placeholder}}(inlinebackgroundперекрывает дефолтvariant="filled").AGENT_COLORудалён без dangling-ссылок (grep пусто, tsc=0). Image-путь (agent.avatarUrl) возвращает CustomAvatar ДО вычисления bg — не тронут; launcher-null (external MCP) не тронут. Смена позиции launcher'а top↔bottom — чисто визуальная, size/layout-контракт для history-item/comment-list-item неизменен.agentGlyphBackground— pure,hashName("")=0 без краша,AgentInfo.name: stringnon-null.agentGlyphBackground: детерминизм + различие по имени (Researcher%360=160 ≠Нарратор%360=223 — реальное неравенство) +/^hsl(\d+, 45%, 24%)$/(пиннит «всегда тёмный фикс-shade»; не-хеш-hue роняетnot.toBe, не-пиннутые sat/light роняют regex).⛔ DROP — кодеру НЕ делать · калибровочный лог (для оператора)
[below-threshold]low/high[test-coverage] wiringagentGlyphBackground→AgentGlyph.stylesи позиция launcher'а тестом не покрыты (только сама pure fn) — тривиальный pass-through в презентационном компоненте + CSS, в jsdom малозначимо, не реальный пробел.[below-threshold]low/high[simplification]hashNameдублирует djb2 из custom-avatar (там локальная не-экспорт.) — это ВТОРАЯ копия (label-colors использует ДРУГОЙ алгоритм — imul+fmix32, не прецедент). При 2 копиях тривиального 7-строчного хеша вынос в общий util + cross-module coupling — маргинально.[style/linter]info[conventions] rawhsl()+%360vs curated-палитры (custom-avatar/label-colors) — отклонение от паттерна, но оправданное (L-пиннинг решает контраст для всех hue; непрерывный hue даёт больше различимых кружков чем 7-цветная палитра). Не sloppiness.Починил F1 (коммит
ccd38152).F1: fixed — переписал устаревший docstring
AgentGlyph(agent-avatar-stack.tsx:57-58): пункты 2 и 3 гласили «violet circle», хотя этот коммит заменил фиксированный фиолет (AGENT_COLOR) на per-agent тёмный хеш-фон (agentGlyphBackground). Теперь «the role emoji on a per-agent dark circle» / «the IconSparkles glyph on a per-agent dark circle (fallback)» — согласовано с кодом и соседними комментами.DROP-пункты (тест-обёртка pass-through, дубль djb2, raw hsl) — как помечено, не трогал.
Ре-ревью — #307 (agent avatar UI polish, #300), round 2, head
ccd38152, base developДельта с моего r1-marker
6f7d43981: 1 файл (agent-avatar-stack.tsx +2/-2) — ровно фикс F1. Tier Trivial (comment-only) → сверено напрямую, без веера.Вердикт: PASS — round-1 F1 закрыт по-настоящему, объективка зелёная. Готово к мержу.
Объективка запущена мной (детач
ccd38152): clienttsc --noEmit→ 0;vitest agent-avatar-stack→ 8 passed.Закрыто
AgentGlyph(agent-avatar-stack.tsx:57-58): пункты 2/3 переписаны «the role emoji on a per-agent dark circle» / «the IconSparkles glyph on a per-agent dark circle (fallback)» — согласовано с кодом (per-agent тёмный хеш-фон вместо фикс-фиолета) и соседними комментами. Диффа ровно 2 строки, больше ничего не тронуто. DROP-пункты round-1 (тест-обёртка pass-through, дубль djb2, raw hsl) — кодер верно не трогал.