Files
web-page/docs/superpowers/specs/2026-06-11-agent-oversight-timeline-design.md
2026-06-11 08:44:44 +09:00

5.6 KiB
Raw Blame History

에이전트 횡단 오버사이트 타임라인 — 설계

작성일: 2026-06-11 대상 repo: web-ui (프론트엔드) 연관 백엔드: 완료 (GET /api/agent-office/activity 필터 지원, main 2c2828c)

배경 / 목적

3개 자율 에이전트(stock 보유종목·insta 발급·lotto 진화)가 모두 도는 상태에서 "팀이 무엇을·언제·왜 했나"를 한 화면에서 보는 에이전트 횡단 오버사이트(CEO 가시화) 기능.

현재 web-ui에는 /lotto/evolver 탭의 lotto 전용 LottoActivityTimeline만 존재. 통합 /activity(전 에이전트 대상)를 소비하는 횡단 뷰가 없다.

백엔드 응답 shape (라이브 검증 완료)

GET /api/agent-office/activity?agent_id=&type=task|log&status=&days=&limit=&offset=
→ { items: [...], total: N }
  • task item: { type:'task', agent_id, task_id, message, created_at, task_type, status, completed_at, duration_seconds }
  • log item: { type:'log', agent_id, task_id, message, created_at, level }
  • status는 task 전용(type=log에 주면 무시). injection 안전(? 바인딩 + 브랜치 선택).

검증 메모:

  • 무필터 total이 65,599건 → 기본 days=7 필터 필수(task 기준 110건으로 감소).
  • requires_approval 필드는 존재하지 않음status:'pending'을 진행/대기 강조로 처리.
  • agent_id 값이 AGENT_META 키(stock/music/insta/realestate/lotto)와 일치 → 색상/이미지 재사용.

아키텍처

AgentOffice는 단일 화면(TopBar + 3×3 AgentGrid + 우측 패널) 구조. 우측 패널은 selectedAgent 상태로 분기:

  • null → (기존) EmptyDetailPanel variant="initial"ActivityTimeline으로 교체
  • placeholder-NEmptyDetailPanel variant="placeholder" (유지)
  • active agent id → SidePanel (유지)

에이전트 미선택 시 기본 우측 패널이 횡단 타임라인이 되고, 그리드와 항상 동시 노출. 항목/그리드 클릭으로 해당 에이전트 SidePanel로 전환.

신규/변경 파일

파일 역할
src/api.js agentActivity({agent_id,type,status,days,limit,offset}) 추가 — 빈 값 제외 쿼리스트링 빌드 + GET /api/agent-office/activity
src/pages/agent-office/AgentOffice.jsx selectedAgent===null 분기를 EmptyDetailPanelActivityTimeline(props: refreshTrigger, onSelectAgent)로 교체
src/pages/agent-office/hooks/useActivityFeed.js items/offset/total/hasMore/loading/error/filters 상태 관리
src/pages/agent-office/components/ActivityTimeline.jsx 컨테이너: 헤더 + ActivityFilters + 리스트 + 무한스크롤 sentinel + 상태(loading/empty/error/end)
src/pages/agent-office/components/ActivityFilters.jsx 필터 4종(agent 색칩 / type / status / days). type==='log'일 때 status 비활성
src/pages/agent-office/components/ActivityItem.jsx 한 행: agent 색·이미지 + message + 상태/level 뱃지 + 상대시간 + duration. 클릭 → onSelectAgent(agent_id)
src/pages/agent-office/AgentOffice.css 타임라인/필터/항목 스타일 (designer 스킬로 마감)

데이터 흐름

AgentOffice (selectedAgent===null)
  └─ <ActivityTimeline refreshTrigger={refreshTrigger} onSelectAgent={handleSelectAgent} />
       └─ useActivityFeed(filters)
            • mount / 필터 변경 → offset=0 fetch → items 교체
            • loadMore (sentinel 교차) → offset += limit → items append
            • refreshTrigger 변경 → offset=0 재조회 → items 교체 (WS 실시간 연동)
       └─ ActivityItem onClick → onSelectAgent(agent_id) → SidePanel로 전환

handleSelectAgent는 기존 콜백 재사용(선택 + clearNotifications).

필터 기본값

days=7, type=all, status=all, agent=all, limit=30(페이지당).

상태 / 비주얼 매핑

  • task status: succeeded → 초록 ✓ / failed → 빨강 ✗ / pending·working → 앰버 펄스 (강조)
  • log level: error / warning⚠️ / info → ·
  • agent 색상: AGENT_META[agent_id].color, 미지정 agent → 회색 #6b7280
  • offset >= total → "더 이상 활동 없음" / 무한스크롤은 IntersectionObserver

상태 처리(엣지)

  • 첫 페이지 로딩 → 스피너/스켈레톤
  • 빈 결과 → "최근 N일 활동 없음"
  • fetch 실패 → 인라인 에러 + 재시도 버튼
  • 리스트 끝 → end-of-list 표시, sentinel 관찰 중단

테스트 (TDD, vitest + RTL — 기존 패턴 따름)

  • useActivityFeed: 필터 변경 시 offset 리셋 + items 교체 / loadMore append / refreshTrigger 재조회 / hasMore = items.length < total 계산 (api mock)
  • ActivityItem: task vs log 렌더 분기, status/level 뱃지 클래스, 클릭 시 onSelectAgent(agent_id) 호출
  • ActivityFilters: type==='log'일 때 status select 비활성, 필터 변경 시 onChange 호출

비범위 (YAGNI)

  • 별도 라우트(/agent-office/activity) 미생성 — 기본 우측 패널 통합으로 충분
  • 기존 getActivityFeed(limit, offset) 헬퍼는 lotto evolver 등에서 사용 여부 확인 후 유지(신규 agentActivity와 공존, 무리한 통합 안 함)
  • LottoActivityTimeline(kind/ts/payload shape)은 다른 엔드포인트 소비 → 건드리지 않음
  • CSV/export, 검색어 필터 등 부가기능 제외

구현 순서

  1. agentActivity api 헬퍼 추가
  2. useActivityFeed 훅 (TDD)
  3. ActivityItem / ActivityFilters (TDD)
  4. ActivityTimeline 컨테이너 조립
  5. AgentOffice.jsx 분기 교체
  6. designer 스킬로 CSS 마감
  7. lint + 테스트 + 빌드 검증