feat(infra): naver-fetch 워커 2D 표시 — fetcher 라벨·수집 상태·Naver Fetch 타이틀

BE가 /api/agent-office/nodes에 등재한 naver-fetch(kind=fetcher) 워커 카드가
데이터 구동 2D 패널에 자동 표시되도록 statusVisual 매핑 보강.
- kindLabel('fetcher') → '수집 워커'
- workerStateLabel state:'fetching' → '수집 중'
- WORKER_TITLES 'naver-fetch' → 'Naver Fetch'
TDD: statusVisual.test.js 3케이스 추가(RED→GREEN).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHXzpsZQxKG9hQmNRfZjRS
This commit is contained in:
2026-07-10 11:02:16 +09:00
parent 9de96f5851
commit f688229c95
2 changed files with 18 additions and 1 deletions

View File

@@ -29,6 +29,8 @@ export function workerStateLabel(w) {
return '장중'; return '장중';
case 'market_closed': case 'market_closed':
return '휴장'; return '휴장';
case 'fetching':
return '수집 중';
default: default:
return '온라인'; return '온라인';
} }
@@ -54,6 +56,7 @@ export const WORKER_TITLES = {
'insta-render': 'Insta Render', 'insta-render': 'Insta Render',
'task-watcher': 'Task Watcher', 'task-watcher': 'Task Watcher',
ai_trade: 'AI Trade', ai_trade: 'AI Trade',
'naver-fetch': 'Naver Fetch',
}; };
export function workerTitle(name) { export function workerTitle(name) {
@@ -65,5 +68,6 @@ export function kindLabel(kind) {
if (kind === 'render') return '렌더 워커'; if (kind === 'render') return '렌더 워커';
if (kind === 'watcher') return '작업 감시'; if (kind === 'watcher') return '작업 감시';
if (kind === 'trader') return '트레이딩'; if (kind === 'trader') return '트레이딩';
if (kind === 'fetcher') return '수집 워커';
return kind || ''; return kind || '';
} }

View File

@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { linkColor, workerStateLabel, workerStatus, workerColor, workerTitle } from './statusVisual'; import { linkColor, workerStateLabel, workerStatus, workerColor, workerTitle, kindLabel } from './statusVisual';
describe('statusVisual', () => { describe('statusVisual', () => {
it('maps link status to theme colors', () => { it('maps link status to theme colors', () => {
@@ -22,6 +22,18 @@ describe('statusVisual', () => {
expect(workerStateLabel({ alive: true, state: 'market_open' })).toBe('장중'); expect(workerStateLabel({ alive: true, state: 'market_open' })).toBe('장중');
}); });
it('labels a fetching worker as collecting', () => {
expect(workerStateLabel({ alive: true, state: 'fetching' })).toBe('수집 중');
});
it('maps kind to a one-line role label', () => {
expect(kindLabel('render')).toBe('렌더 워커');
expect(kindLabel('watcher')).toBe('작업 감시');
expect(kindLabel('trader')).toBe('트레이딩');
expect(kindLabel('fetcher')).toBe('수집 워커');
expect(kindLabel('unknown')).toBe('unknown');
});
it('derives worker status with dead-letter and paused precedence', () => { it('derives worker status with dead-letter and paused precedence', () => {
expect(workerStatus({ alive: false })).toBe('down'); expect(workerStatus({ alive: false })).toBe('down');
expect(workerStatus({ alive: true, state: 'paused' })).toBe('paused'); expect(workerStatus({ alive: true, state: 'paused' })).toBe('paused');
@@ -37,6 +49,7 @@ describe('statusVisual', () => {
it('humanizes worker names', () => { it('humanizes worker names', () => {
expect(workerTitle('insta-render')).toBe('Insta Render'); expect(workerTitle('insta-render')).toBe('Insta Render');
expect(workerTitle('ai_trade')).toBe('AI Trade'); expect(workerTitle('ai_trade')).toBe('AI Trade');
expect(workerTitle('naver-fetch')).toBe('Naver Fetch');
expect(workerTitle('unknown-x')).toBe('unknown-x'); expect(workerTitle('unknown-x')).toBe('unknown-x');
}); });
}); });