fix(workflow): 面板 label 截断保留 #数字 后缀(同 dim 多 finding 可区分)

audit workflow 用 verify:\${dim}#\${findingIdx} 命名 verify agent。
旧逻辑 slice(0, 18) 从右切把 #idx 全吃了——同 dimension 多 finding
肉眼无法区分。新逻辑:含 #数字 后缀时保留后缀,前缀截断 + … 省略号。

例:verify:correctness#0 → verify:correctn…#0
   verify:architecture#15 → verify:archite…#15

Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
claude-code-best
2026-06-14 11:11:39 +08:00
parent bd470b5ad4
commit 0f1403bd87
2 changed files with 35 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import { SentryErrorBoundary } from '../../components/SentryErrorBoundary.js';
import type { RunProgress } from '../progress/store.js';
import { call as panelCall } from '../panel/panelCall.js';
import { clampSelected, WorkflowsPanel } from '../panel/WorkflowsPanel.js';
import { truncateLabel } from '../panel/AgentList.js';
import { STATUS_DOT } from '../panel/status.js';
import { __resetWorkflowServiceForTests, getWorkflowService } from '../service.js';
@@ -20,6 +21,23 @@ test('clampSelected空列表→0越界→末位负/NaN→0正常→
expect(clampSelected(Number.NaN, 3)).toBe(0);
});
// truncateLabel短 label 原样;含 `#数字` 后缀时保留后缀,前缀截断 + 省略号;
// 无后缀则从右切。让 audit workflow 的 verify:${dim}#${idx} 多 finding 仍可区分。
test('truncateLabel短 label 原样;含 #数字 后缀保留后缀前缀截断;无后缀从右切', () => {
// 短 label 原样
expect(truncateLabel('agent-1', 18)).toBe('agent-1');
expect(truncateLabel('review:bugs', 18)).toBe('review:bugs');
// 刚好 max 长度(边界)
expect(truncateLabel('review:correctness', 18)).toBe('review:correctness');
// 超 max + 含 #数字 后缀:保留后缀,前缀截断 + 省略号
expect(truncateLabel('verify:correctness#0', 18)).toBe('verify:correctn…#0');
expect(truncateLabel('verify:architecture#15', 18)).toBe('verify:archite…#15');
// 多位 #idx 也能区分
expect(truncateLabel('verify:correctness#2', 18)).toBe('verify:correctn…#2');
// 无 #数字 后缀:从右切(旧行为)
expect(truncateLabel('a-very-long-label-no-suffix', 18)).toBe('a-very-long-label-');
});
// STATUS_DOT 覆盖四种状态,且均为可见圆点字符。
test('STATUS_DOT 覆盖 running/completed/failed/killed 且为非空字符', () => {
const statuses = ['running', 'completed', 'failed', 'killed'] as const;

View File

@@ -8,6 +8,22 @@ const SPINNER_FRAMES = ['·', '✢', '✱', '✶', '✻', '✽'];
const FRAME_MS = 120;
const LABEL_MAX = 18;
/**
* 截断 label 到 max 字符。保留尾部 `#数字` 后缀audit workflow 的
* `verify:${dim}#${findingIdx}` 格式)——同 dimension 多 finding 的 verify
* agent label 仍可区分(前缀用 `…` 省略)。无后缀则从右切(旧行为)。
* 已导出便于单测覆盖。
*/
export function truncateLabel(raw: string, max: number): string {
if (raw.length <= max) return raw;
const m = raw.match(/#\d+$/);
if (!m) return raw.slice(0, max);
const suffix = m[0]; // 含 # 号
const prefix = raw.slice(0, raw.length - suffix.length);
const available = max - suffix.length - 1; // -1 留给 …
return `${prefix.slice(0, available)}${suffix}`;
}
/**
* 右 agent 列表(已按选中 phase 过滤)。
* 选中行仅在本列聚焦focused=true时铺 selectionBg 底(保留 fg非反色
@@ -39,7 +55,7 @@ export function AgentList({
const highlighted = selected && focused;
const running = a.status === 'running';
const mark = running ? frame : v.mark;
const label = (a.label ?? `agent-${a.id}`).slice(0, LABEL_MAX);
const label = truncateLabel(a.label ?? `agent-${a.id}`, LABEL_MAX);
return (
<Box key={a.id} backgroundColor={highlighted ? 'selectionBg' : undefined} justifyContent="space-between">
<Box>