# Sprint 3W Feb. 2026

- [x] SP1. Long Running Tool Call 지원 개선
  - 문제점: 현재 long running tool call(e.g. awaitAgent, pollProcess)는 정해진 max timeout을 기반으로 반복적으로 호출하는 즉, polling 방식임.
  - 개선 방향: 필요에 따라 특정 상태 (agent session의 상태, process의 상태)를 기다리면서 block할 수 있는 기능 지원이 필요.
  - 기대 효과: Parent Agent는 불필요하게 Polling을 하지 않고 이를 통해
    - Token을 불필요하게 소모하지 않음
    - 제한된 Context Window가 불필요하고 반복적인 polling tool call로 채워지는 것을 방지
  - 세부
    - 기존 long running process 시작 도구의 파라미터에 이러한 block을 지원할 수 있는 것을 추가
    - 기존 long running process monitoring 도구에 timeout을 무한대 (indefinite) 로 설정할 수 있는 것을 추가
  - 고려 사항
    - 미완 tool call 및 process 영구 정지의 가능성이 있으나 tombstone 도구 응답을 Session 재시작 시 삽입하여 오류로 처리하고 필요할 경우 재시도를 유도할 수 있음

- [x] SP2. Max Concurrency Control 관리
  - 문제점: 현재 Child Process 및 SubAgent 실행을 지원하지만 적절한 최대 병렬 실행 제한 조치가 없음, 이때문에 Computing Resource를 과도하게 사용하거나 Congestion이 발생
  - 개선 방향: Concurrency 관리 계층을 두고 최대 Child Process의 수, 최대 Sub Agent의 수를 관리할 수 있어야 하며, 위 SP1의 개선 사항을 통해 사용자의 Agent나 Process 요청을 자연스럽게 처리할 수 있어야 함
  - 기대 효과: AI Agent의 자율적 도구 및 SubAgent Fanout에도 안정적 실행을 보장
  - 세부
    - SubAgent 최대 기본 busy session 4으로 설정, 이후 spawnAgent 요청 시 기존 실행중이던 SubAgent session이 idle로 전환되는 시점에 요청을 처리하고 결과 리턴하며 요청이 처리될 수 없는 상태에서 무한 대기
    - Process의 경우 workspace도구의 runShell 등으로 실행되는 process의 숫자로 관리하며 최대 10을 기준으로 runShell 등을 처리, congestion에 대한 처리 방법은 앞서 기술된 SubAgent와 동일

- [ ] SP3. 도구 실행의 보안 격리 환경 제공
- [x] SP4. LLM API 오류로 인한 Session Interruption 복구
  - 문제점: LLM 응답 중 Malformed / Empty Response는 정상 응답 코드(200)으로 전달됨. 하지만 실제 Agentic Flow의 중단으로 이어지게 됨
  - 개선 방향
    - Exponential Backoff with Jitter 3회 재시도
    - 설정된 fallback model API로 재시도
  - **구현 완료 (2026-02-25)**
    - **`src/lib/retry-utils.ts`**: `RetryOptions`에 `jitter?: boolean` 옵션 추가. `withRetry`/`withRetryResult` 모두 ±50% jitter 적용 (`rawDelay * (0.5 + Math.random())`)
    - **`src/lib/services/settings-service.ts`**: `Settings`에 `fallbackModel?: ModelChoice` 최상위 필드 추가, `DEFAULT_SETTING`에 `undefined` 기본값
    - **`src/lib/services/rust-settings-service.ts`**: `SettingValue` 유니온에 `null` 추가, `getSettings()`에서 `fallbackModel` 로드, `updateSettings()`에서 `null` 저장 (명시적 Clear 지원) 처리
    - **`src/context/llm/useLLMListener.ts`**: SP4 retry 오케스트레이션 구현
      - `sleep` import 추가 (`@/lib/retry-utils`)
      - `executeCompletionRequest` 호출을 `attemptCompletion()` 내부 retry 루프로 교체
      - 3회 재시도 (Exponential Backoff + ±50% Jitter, base 500ms, max 30s)
      - Abort 에러는 즉시 throw (retry 대상 제외)
      - Primary model 3회 모두 실패 시 `settingsRef.current.fallbackModel`로 1회 최종 시도
      - 각 retry/fallback 시도 전 streaming indicator 리셋으로 UI 일관성 보장
    - **`src/features/settings/tabs/AIModelsTab.tsx`**: `localFallbackModel`, `onFallbackModelChange` props 추가, "Fallback LLM (SP4 Recovery)" `AgentModelPicker` UI 추가
    - **`src/features/settings/SettingsPage.tsx`**: `handleFallbackModelChange` 콜백 추가, `AIModelsTab`에 prop 전달 (빈 model 선택 시 `undefined`로 설정하여 fallback 비활성화)
- [ ] SP5. Metering 기능 및 상세 사용 통계 기능
- [x] SP6. Session Request Cancel의 계층간 격리
  - 문제점: 현재 subagent session을 생성할 경우 parent session의 요청 취소가 차단이 되게 됨, 하지만 현재 동작은 cancel이라는 semantic이라기 보다는 pause에 가까움, 즉 일시 정지 하고 재시작 가능한 동작임, 따라서 사용자들이 불필요한 polling 및 중간에 steering을 위해 parent를 언제든 cancel 혹은 일시적 stop할 수 있어야 함
  - 개선 방향: parent session의 상태와 독립적으로 child session은 진행 가능함 (구조적으로 문제 없음), 따라서 parent session에서 stop 시 child session의 상태와 무관하게 stop 동작을 할 수 있어야 함
  - 기대 효과: 사용자의 제어 자유도 부여를 통해 사용자 경험 개선
  - **구현 완료 (2026-02-22)**
    - **`state.rs`**: `ACTIVE_SESSIONS` global (`OnceLock<Arc<TokioRwLock<HashMap<String, AgentSession>>>>`) 추가
      - `init_active_sessions()`: app setup 시 `AgentSessionManager`의 shared Arc 등록
      - `get_session_cancel_pending(session_id)`: read-lock만 잡고 `cancel_pending` Arc clone 반환 — hot loop에서 lock-free polling 가능
    - **`lifecycle/app_setup.rs`**: `init_active_sessions(agent_session_manager.active_sessions_arc())` 호출 추가
    - **`agent/workflow.rs`**: `cancel_workflow` deferred path에 `SessionBus::notify_status_change(&session_id)` 추가 — awaitAgent/pollProcess 대기 중인 waiter를 최대 30s 기다리지 않고 즉시 wake
    - **`mcp/builtin/session_api/handlers.rs`**: `wait_until_session_terminal` 시그니처에 `caller_session_id: Option<&str>` 추가
      - caller의 `SessionBus` entry (`caller_notifier`) + `cancel_pending` Arc 구독
      - `tokio::select!`에 `caller_notifier.notified()` branch 추가 — child 완료 또는 parent cancel 중 먼저 오는 것에 반응
      - loop 상단에서 `caller_cancel_pending.load(Relaxed)` 체크 → true면 즉시 `Err` 반환
      - `awaitAgent` / `pollProcess` 두 호출 경로 모두 `caller_session_id.as_deref()` 전달
    - **Regression tests**: `src-tauri/src/agent/session_bus.rs` – SP6 test block (4 cases)
      - `test_sp6_caller_notify_wakes_dual_waiter`: caller `notify_status_change` → dual-notifier `select!` waiter 즉시 wake
      - `test_sp6_child_notify_still_wakes_dual_waiter`: 기존 child 완료 path 유지 (정상 경로 regression)
      - `test_sp6_cancel_pending_flag_short_circuits_loop`: `AtomicBool=true` 상태에서 loop 즉시 `Err` 탈출
      - `test_sp6_quiet_caller_does_not_spuriously_wake`: 아무것도 안 fire → timeout branch 정상 hit (spurious wake 없음)
- [x] SP7. Session 삭제 시 하위 요소 정리 옵션 제공
  - 문제점: 현재 session을 삭제 시 자식 session이 그대로 남아 있음. 일부 이러한 것이 장점을 제공하는 경우 (가령 다양한 ticker의 주식 정보를 조사한 경우, session 자체가 정보 성격)가 있으나, parent session과 종합적으로 봐야 의미가 있는것들이 있을 수 있음.
  - 개선 방향: session 삭제 선택 시 옵션을 추가
    - Before: Session Item Card에서 `삭제 (휴지통 아이콘)`를 누르면 `Confirm Delete` Button이 활성화
    - After: `descendantCount > 0`인 경우 두 가지 옵션 제공; 없으면 기존 단일 버튼 유지
  - 고려 사항: 머글들에게 친숙하 더욱 명확한 Semantic의 UI를 검토 할것 (버튼의 아이콘 / Label 등 개선 가능)
  - **구현 완료 (2026-02-22)**
    - **Rust backend**
      - `session_repository.rs`: `orphan_and_delete_session` trait + SQLite/in-memory impls
        - `UPDATE sessions SET parent_session_id = NULL WHERE parent_session_id = ?` → direct children orphaned
        - `DELETE FROM sessions WHERE id = ?` → parent removed
      - `session_manager.rs`: `delete_session_only` — terminates workflow, removes active session, cleans workspace + search index, calls `orphan_and_delete_session`
      - `agent_commands.rs` + `lib.rs`: `agent_delete_session_only` Tauri command registered
    - **TypeScript frontend**
      - `session-crud.ts`: `deleteSessionOnly` backend wrapper
      - `AgentSessionListContext.tsx`:
        - `deleteSession` — BFS traversal to collect full descendant tree before filter (bug fix: was only removing self)
        - `deleteSessionOnly` — removes self, sets `parentSessionId: undefined` on direct children
      - `SessionCard.tsx`: conditional confirm UI — `descendantCount === 0` → single button; `> 0` → two-column layout with per-button description labels ("Delete all" + red `+N subagents` / "Delete only this" + muted "Subagents kept")
      - `SessionHistoryPanel.tsx` + `History.tsx`: wired `onDeleteOnly` prop chain
    - **Regression tests**: `src/context/__tests__/AgentSessionListContext.test.tsx` – SP7 test block (4 cases)
      - `deleteSession: BFS removes parent AND direct child from UI`
      - `deleteSession: BFS removes entire 3-level tree (grandparent → parent → child)`
      - `deleteSessionOnly: removes parent, direct child becomes top-level (parentSessionId cleared)`
      - `deleteSessionOnly: grandchild still linked to its own parent after orphan`

- [x] SP8. AgentDraftChatView에서 파일 첨부 기능 구현
- [x] SP9. Multi Modal 모델의 Image / Audio 데이터 첨부 지원 및 Autonomous Multi Modal Tool 구현
  - **Image 첨부 및 LLM 전달 구현 완료 (2026-03)**
    - **`src/lib/mime-utils.ts`**: MIME 타입 감지 유틸리티 중앙화 — image(jpeg/png/gif/webp 등), audio(mp3/wav/ogg 등), text 타입 통합
    - **`src/features/agent/AgentDraftChatView.tsx`**: 드래그앤드롭 경로의 MIME 감지 버그 수정 (이미지 타입 누락) + 이미지/오디오 파일 inline base64 인코딩 추가 (`status: 'inline'`)
    - **`src/lib/message-preprocessor.ts`**: Agent V2 경로에서 `attachments[].inlineContent` → `message.content`에 `MCPImageContent`/`MCPAudioContent` 블록으로 주입 (기존엔 무시됨)
    - **`useAgentFileAttachment.ts`**, **`AgentResourceAttachmentContext.tsx`**: 로컬 MIME 함수 제거 → `mime-utils.ts` 공유 유틸로 교체
  - Audio end-to-end 파이프라인 검증, Autonomous Multi Modal Tool: 미구현
- [x] SP10. skill-mention-system.md
  - **`@skill:` / `@file:` reference 시스템 구현 완료**
  - **Frontend**: `src/features/agent/hooks/useInputToken.ts` — `@type:arg` 파싱 state machine, `@skill:`/`@file:`/`@tool:` 타입 드롭다운, arg 단계별 후보 목록 (`skillResults`/`fileResults`/`toolResults`)
  - **Frontend**: `src/features/agent/components/InputTokenDropdown.tsx` — popup UI; `AgentChatInput.tsx`, `AgentDraftChatView.tsx` 연결
  - **Backend**: `src-tauri/src/agent/references/` — `ReferenceRegistry`, `SkillReferenceResolver` (`@skill:name`), `FileReferenceResolver` (`@file:path`)
  - **Wired**: `src-tauri/src/agent/llm/completion.rs` — 매 LLM 요청 전 `build_default_registry().preprocess_message_text()` 호출 → resolved content를 user message 앞에 prepend
  - `@tool:` 백엔드 resolver (soft attention hint 주입): **미구현**
- [x] SP11. workspace의 agents.md / soul.md system prompt injection 구현
  - **`src-tauri/src/agent/llm/prompt.rs`**: `WORKSPACE_INSTRUCTION_FILES = ["agents.md", "soul.md", "CLAUDE.md"]` — 세션 workspace에서 탐색하여 "## Workspace Instructions" 섹션으로 시스템 프롬프트에 주입
  - Unit test: `agents.md` 내용이 프롬프트에 포함되는지 확인
- [x] SP12. session의 bookmark 지원
  - **Backend**: `session.rs` entity `is_bookmarked: bool`; `agent_toggle_session_bookmark` Tauri command
  - **Frontend**: `SessionCard.tsx` 북마크 토글 버튼; `SessionHistoryPanel.tsx` 북마크 필터 UI; `AgentSessionListContext.tsx` `toggleBookmark` 낙관적 업데이트
- [x] SP13. workspace의 skills 디렉토리 지원
  - `src-tauri/src/mcp/builtin/skills/mod.rs`: global skills dir + assistant-specific skills dir 병합 (중복 제거) 후 시스템 프롬프트에 주입 — 스프린트 전부터 구현되어 있었음

- [x] SP14. AI Service 구조 리팩토링 — switch 기반 → 다형성 기반 전환 (2026-03)
  - 초기 문제였던 중앙집중식 provider 분기 중, 실제 확장성 병목이던 **tool 변환**과 **message sanitization 실행 경로**는 다형성 기반으로 정리 완료
  - 구현 상태
    - **`src/lib/ai-service/types.ts`**: `IAIService.convertTools()` 및 `IAIService.sanitizeMessages()` 계약 제공
    - **`src/lib/ai-service/base-service.ts`**: 공통 파이프라인(`filterSystemErrors` → `validateToolCallPairing` → `this.sanitizeSingleMessage`)을 base class가 수행하고, provider별 차이는 subclass override로 위임
    - **각 provider service class**: `convertTools()` / `sanitizeSingleMessage()`를 통해 OpenAI-family, Anthropic, Gemini, Ollama 등의 차이를 각 클래스 내부에 캡슐화
    - **`tool-converters.ts`**: 제거 완료
    - **`message-normalizer.ts`**: `AIServiceProvider` switch dispatcher 제거, concrete service instance 기반 `sanitizeMessagesForService()` 경로로 전환
    - **`useLLMExecution.ts`**: provider enum 분기 대신 현재 `service` 인스턴스에 sanitization 위임
  - 함께 정리된 OCP 항목
    - **`ModelProvider.tsx`**, **`useAgentModels.ts`**: `supportsDynamic` 하드코딩 provider 목록 제거
    - **`AgentModelPicker.tsx`**: Ollama-only refresh 버튼 가드 제거 → 전체 provider에 refresh 공개
    - **`token-utils.ts`**: tool chain integrity 체크 allowlist에 OpenRouter 추가
  - 비고: `factory.ts`의 provider switch는 **service 생성 책임**에 해당하는 factory 로직이라 SP14의 “provider별 동작 분기 제거” 대상과는 별개로 유지

- [x] SP15. OpenRouter Provider 지원 추가 (2026-03)
  - **`src/lib/ai-service/openrouter.ts`**: OpenAI 호환 서비스로 구현, `listModels()` override로 공개 메타데이터 API (`openrouter.ai/api/v1/models`) 직접 사용
  - **`src/lib/ai-service/openrouter-metadata.ts`**: 24h 캐시 기반 모델 목록 fetch, reasoning 모델 감지 (`supported_parameters: ["reasoning"]`)
  - **`src/features/settings/tabs/AIModelsTab.tsx`**, **`ProviderCard.tsx`**: OpenRouter provider 설정 UI 추가
  - **`src/lib/ai-service/factory.ts`**, **`types.ts`**: `AIServiceProvider.OpenRouter` enum 등록 및 factory 연결
  - **Regression tests** (`src/lib/ai-service/__tests__/openrouter.test.ts`): 8개 테스트 (provider 등록, 메타데이터 API 사용 확인, reasoning 감지, cost 계산, fallback on error)

- [x] SP16. swarm API 보완
  - spawnAgent
    - 문제점: idle 전환 시 마지막 메시지만 받게됨, 문제는 이럴 경우 실제 어떤 과정을 거쳐서 작업을 수행했는지에 대한 정보가 전혀 없어 sub agent가 할루시네이션으로 답변한 것을 구분할 수 없음.
    - 개선 방향: idle - busy - idle의 busy 구간동안 몇 turn의 recurring (도구 호출 및 메시지) 처리가 있었는지를 함께 응답에 포함
    - **구현 완료 (2026-03)**: `wait_until_session_terminal` 반환 값에 `count_session_turns`를 통해 측정된 턴(도구 호출 및 메시지 처리 횟수) 수를 포함하도록 `spawnAgent`와 `awaitAgent` 응답 구조 수정 (`handlers.rs`, `utils.rs`).
  - subagent 재사용
    - 문제점: 기존 session에 메시지를 보내는 방법이 있음에도 불구하고 spawnAgent를 호출. 더 심각한것은 caller agent가 이 spawnAgent가 기존 Assistant한테만 보내면 맥락이 유지되고 있는것(즉, 같은 세션에 보내는 것으로 인식)으로 착각함
    - 개선 방향: 도구 설명에 간단 명료하게 도구의 기능에 대한 설명을 보완
    - **구현 완료 (2026-03)**: `spawnAgent` 도구 설명에 기존 session 재사용 불가 및 `messageAgent` 도구 안내 추가 (`tools.rs`).
- [x] SP17. Message Context Management 개선
  - 문제점: 현재 message context 관리는 고정 sliding window를 기반으로 함. 이로 인해 아래와 같은 제약과 성능 한계가 존재
    - 고정 window size로 인한 context 유실
    - 고정 window의 내용 전체가 prompt cache 적용이 되지 않기 때문에 요청 처리 지연이 발생, 비용 증가
  - 개선 방향
    - compact 기반의 message stack 관리 방식 구현
    - message stack이 설정 context window(token count) 임계치(90%)를 초과할 경우 async compact를 트리거하고, 같은 요청은 기존 context selector로 계속 처리
    - compact 결과는 session별로 영속 저장되어야 하며, session 생성/재개/캐시 초기화 시 함께 복원되어야 함
    - compact record는 `fromId`, `toId`, `summary`를 보존하여 요약이 대체하는 범위를 명시해야 함
    - 복원시 compact summary + compact 이후 tail messages 를 조합하여 idempotent하게 input message stack을 재구성할 수 있어야 함
    - max context 설정 값은 settings의 `maxInputContext`를 기본으로 사용하되, 선택 로직은 model max fallback과 함께 동작해야 함
  - **최종 구현 상태 (React 오케스트레이션 → Rust 오케스트레이션 마이그레이션 반영)**
    - **Rust가 오케스트레이션을 소유**: `src-tauri/src/agent/llm/completion.rs`
      - pending user message drain
      - compact summary 재주입 (Step A)
      - compaction trigger / in-flight guard / tail guard (Step B)
      - context selection 후 `llm:completion-request` 이벤트 emit
    - **Prompt 조립도 Rust에서 수행**: `src-tauri/src/agent/llm/prompt.rs`
      - stable prefix: agent identity + workspace instructions + session metadata
      - volatile suffix: ContextRegistry + builtin service contexts
      - stable prefix는 session 메모리에 캐시됨
    - **Context selection 구현 위치**: `src-tauri/src/agent/llm/context_selector.rs`
      - `select_messages_within_context`
      - grounded token calibration (`calculate_grounded_total_tokens`)
      - provider별 incomplete tool chain 제거
      - `contextStrategy == "compact"` 일 때도 최종 입력 stack selection은 동일 selector를 사용
    - **Compaction persistence**: `src-tauri/src/repositories/compact_context_repository.rs`
      - session당 1개의 compact record를 upsert
      - `from_id`, `to_id`, `summary`, `created_at` 저장
    - **Session restore 경로에서 compact context 복원**:
      - `src-tauri/src/agent/lifecycle/creation.rs`
      - `src-tauri/src/agent/lifecycle/cache.rs`
      - `src-tauri/src/agent/session_manager.rs`
    - **Frontend는 execution bridge 역할만 유지**: `src/context/llm/useLLMListener.ts`
      - `llm:completion-request` 수신 후 provider SDK 호출
      - `llm:compact-request` 수신 후 `service.compact(...)` 실행
      - 결과는 `agent_handle_llm_response`, `agent_handle_compact_response` 로 Rust에 반환
    - **현재 구현상 차이점**
      - 기존 설계안의 "100% 초과 시 compact 완료까지 hard wait" 는 현재 적용되지 않음
      - 현재 `find_compaction_split_index()` 는 전체 stack compact(`messages.len()`)를 반환하며, compact 이후 tail은 "다음 턴에 새로 쌓인 메시지들" 로 취급됨
      - sliding window path는 제거되지 않았고, `contextStrategy != "compact"` 인 경우 fallback/legacy 경로로 계속 사용 가능
    - **관련 문서**: `docs/architecture/message-context-management.md`

- [x] SP18. Message Context Managment 기본 설정을 compact Mode, 48K로 변경
  - **구현 완료 (2026-03-08)**
    - **`src/lib/services/settings-service.ts`**: `DEFAULT_SETTING`의 `contextStrategy`: `'window'` → `'compact'`, `maxInputContext`: `32768` → `49152` (48K)
- [x] SP19. subagent에 YOLO Mode 상태 상속
  - parent agent가 yolo mode가 활성화된 경우 subagenth는 이 값을 그대로 상속받도록 동작
- [x] SP20. Session 시작 시 AgentDraftChatView에서 workspace 지정 가능
  - 특정 디렉토리를 session 시작 전에 workspace로 지정할 수 없음
  - directory를 session에 drag & drop 하면 해당 directory를 workspace로 지정하여 대화를 시작
  - 다만 이렇게 지정된 directory는 workspace override 방식에 의해 적용되며 session 중 해제 하여 workspace 기본으로 자동생성된 workspace path로 원복 시킬 수 있음
  - **구현 완료 (2026-03-09)**
    - **Backend**: `DroppedFileService`가 디렉토리 허용하도록 수정, `check_dropped_path_type` 명령 추가
    - **Backend**: `register_session_override` 시 default path를 보존하여 `AgentWorkspacePanel`에서 원복(cancel) 가능하도록 개선
    - **Frontend**: `AgentDraftChatView`에서 디렉토리 드롭 감지 시 `workspaceOverride` 상태로 관리 및 UI 표시
    - **Frontend**: 세션 생성 시 `workspacePath` 파라미터 전달 로직 추가

- [x] SP21. See / Listen 도구 구현
  - seeContent(url={web, file}): convert content and put it as content with proper mime type with data url (base64)
  - listenContent(url={web, file}): convert content and put it as content with proper mime type with data url (base64)
  - ref. how the image/audio content is attached to the context
  - **구현 완료 (2026-03-11)**
    - **Backend**: `src-tauri/src/mcp/builtin/media/` — `MediaServer` builtin MCP server
    - **Backend**: `seeContent` fetches image (HTTP or local file), base64-encodes → `MCPContent::Image`
    - **Backend**: `listenContent` fetches audio (HTTP or local file), base64-encodes → `MCPContent::Audio`
    - **Backend**: MIME type resolved from `Content-Type` header (web) or file extension (local)
    - **Backend**: 20 MB size cap; workspace isolation enforced for local paths
    - **Backend**: `BuiltinServiceId::Media` added to enum, `from_alias`, `name()`, factory, and server/tools.rs

- [X] SP22. Enhance tools feature
  - [x] SP22-1. Tool 응답 Semantic 개선
    - Error Semantic의 제한적 사용
      - 현재 문제점: timeout 및 내부 구현의 exception을 모두 에러로 응답. AI Agent의 입장에서는 단순히 backend 구현에 대한 정보일뿐 AI Agent 귀책 오류는 아님
      - 개선 방향: AI Agent의 귀책 Error, 즉 도구의 잘못된 사용, Param Validation 등에서만 error를 응답
      - 완료: builtin error guidance, builtin proxy timeout, UI cancel, interactive shell 비정상 종료/timeout semantic을 정리했고 integration regression으로 고정함
  - [x] SP22-2. swarm과 assistant를 하나의 domain으로 통합
    - Semantic 일관성 개선
      - assistant vs. agent 하나의 도메인 이름으로 통일
    - interface revision
      - agent / create => 기존의 createAssistant
      - agent / list => 기존의 swarm_listType 혹은 assistant_listAssistant
      - agent / update => 기존의 assistant_updateAssistant
      - agent / startSession => 기존의 spawnAgent, awaitResponse
      - agent / messageToSession => 기존 생성된 session에 message를 보냄
      - agent / checkSession
      - agent / stopSession => 진행 중인 session을 강제 중지 시킴, UI에서 사용자가 cancel 버튼을 누르는 것과 동일 (AgentChatInput 참고)
    - 기능 개선
      - agent / create 시 리소스 공유 개선
        - 성공시 응답에는 생성된 session의 id 그리고 workspace path가 포함되도록 함
        - 그래서 하위 agent가 작업한 결과 파일을 실수 없이 가져올 수 있게 함
      - 완료: public builtin surface는 `agent` canonical로 통합했고 `assistant` / `swarm` / `session_api`는 compatibility alias로만 유지함
  - [x] SP22-3. UI 도구 간소화 및 통합
    - 제안의 핵심 이점: "컨텍스트 중심의 상호작용"
      - 현재는 정보를 **보여주는 행위(`presentContent`)**와 사용자의 **선택을 받는 행위(`promptUser`)**가 분리되어 있습니다.
      - 현재 방식: `presentContent`로 리포트를 보여준 뒤, 다음 턴에 `promptUser`로 "위 리포트 중 무엇을 택하시겠습니까?"라고 물어야 함. (2개 턴 소모, 맥락 단절 발생 가능)
    - 통합 방식: 리포트 하단에 선택 버튼이나 입력창이 포함된 UI를 한 번에 렌더링. 사용자는 리포트를 읽는 즉시 그 맥락 안에서 응답.
    - **구현 완료 (2026-03-15)**
      - **통합 도구 구현**: `src-tauri/src/mcp/builtin/ui/tools.rs`, `src-tauri/src/mcp/builtin/ui/mod.rs`
        - `presentInteractive`를 UI 기본 도구로 정리
        - display-only는 `interaction` 생략, 즉시 사용자 응답이 필요할 때만 `interaction` 포함
      - **공개 surface 간소화**:
        - `ui::all_tools()`에서 legacy split 도구 `promptUser`, `presentContent` 제거
        - `waitForUserResume`, `presentInteractive`만 LLM에 공개
        - `visualizeData`, `promptUser`, `presentContent`, `getUserAnswer`, `resumeFromWait`, `circuitBreak`, `resumeCircuitBreak`는 compatibility/internal 경로로만 유지
      - **상호작용 버그 수정**:
        - text mode `presentInteractive`에서 `optionsJson` 기본값 누락으로 iframe 스크립트가 깨지던 문제 수정
        - 이로 인해 Submit/Cancel 버튼 클릭이 무반응이던 현상 해결
      - **런타임 검증 강화**:
        - `interaction` object 여부 검증
        - `interaction.type`, `interaction.prompt` 필수화
        - 허용 타입을 `text | select | multiselect`로 제한
        - `interaction.options`는 문자열 배열만 허용
      - **회귀 테스트**:
        - `src-tauri/tests/ui_interaction_template_tests.rs`: text/select 렌더링 + validation failure 케이스 6개 검증
        - `src-tauri/tests/builtin_service_registry_tests.rs`: legacy split UI 도구가 public surface에 재노출되지 않도록 회귀 고정
      - **검증 완료**:
        - `cargo fmt && cargo test --test ui_interaction_template_tests --test builtin_service_registry_tests`
        - `pnpm -s refactor:validate`
- [x] SP23. Session List UI 개선
  - [x] SP23-1. Session Unread Notification 기능
    - 문제점: Session list에서 사용자가 보지 않은 혹은 상호작용이 필요한 Session을 구분할 수 없음
    - 기대: Session list에서 사용자가 보지 않은 혹은 상호작용이 필요한 Session을 구분할 수 없음. 구분 할 수 있어야 함. 또한 Session이 busy => idle / budy => error 상태로 업데이트 될 때 알림 (소리, Notfication UI)를 받을 수 있어야 함.
    - **최종 결정 (2026-03-20, revised)**
      - unread / notification semantic은 **approval + recurring-stop attention** 기준으로 정리
        - **pending user interaction / approval**
          - tool approval 등 사용자의 개입이 필요한 세션
        - **recurring workflow stop**
          - 단순 message arrival나 tool progress가 아니라, recurring workflow가 특정 stop condition에서 멈춰 사용자의 확인 가치가 생긴 세션
      - 아래 항목은 unread trigger에서 제외
        - 단순 `messageAdded`
        - 일반적인 tool execution 진행중 상태
        - cancel / manual stop
        - generic busy => idle 전이 전체
    - **UI 방향 결정**
      - top bar에 **bell 버튼**을 추가하여 unread session에 접근할 수 있도록 함
      - interaction pattern은 modal보다 **dropdown / popover style view**를 우선 채택
        - 목적이 “notification center”보다는 “빠른 확인 및 세션 이동”에 가깝기 때문
      - bell view에서는 unread session 목록과 pending approval session을 함께 보여주고, 클릭 시 해당 session으로 이동
    - **구현 완료 (2026-03-20)**
      - backend
        - `sessions` table에 `last_viewed_at`, `last_message_at` 추가
        - message insert 시 session의 `last_message_at`을 함께 갱신하도록 연결
        - `agent_mark_session_viewed` command 추가
        - 후속 조정으로 `last_attention_at`, `last_attention_reason`를 추가하여 bell state를 generic message가 아닌 attention event 기준으로 계산하도록 확장
        - `WorkflowCompleted` event는 `natural / recurringStop / cancelled` reason을 가지도록 확장
      - frontend state
        - `AgentSessionListContext`에서 global attention aggregation + pending approval aggregation 수행
        - `messageAdded` 자체는 더 이상 bell unread trigger가 아니며, `workflowCompleted(reason=recurringStop)`만 attention badge를 만든다
        - active session open / active session recurring-stop 수신 시 viewed marker를 갱신하여 false unread를 줄임
        - pending approval은 `toolCallId` 기준 dedup하여 bell count가 resume 시 중복 증가하지 않도록 처리
      - UI
        - top bar에 bell dropdown 추가
        - session name + reason badge(`Recurring stop`, `N approvals`)만 노출하는 lightweight navigation UI로 구현
        - item click 시 해당 `/agent/:sessionId`로 바로 이동
    - **비고**
      - sound / OS notification은 optional 후속 단계로 유지
      - 단순 `message unread` 기반 bell은 제거하고, attention-worthy stop condition만 대상으로 유지
  - [x] SP23-2. Session List의 혼동을 유발하는 시각적 구조 (App Sidebar)
    - 문제점: 모든 세션이 flat하게 표시되어 계층 구조를 파악하기 어려움
    - 기대: sub agent session은 시각적으로 상위 session과 구분되어야 함. (left end space or something intuitive and semantic layout)
    - **구현 완료 (2026-03-20)**
      - **`src/components/layout/AppSidebar.tsx`**
        - recent sessions를 단순 flat list가 아니라 root-first 순서로 재구성
        - `buildChildrenMap()` 기반으로 최근 세션 최대 5개 안에서 parent-child 관계를 유지해 표시
        - child session에는 indentation + `↳` cue + muted text를 적용해 root와 시각적으로 구분
      - **`src/lib/session-utils.ts`**
        - sidebar/history 양쪽에서 재사용 가능한 tree helper로 `buildChildrenMap()` 추가
      - 판단
        - sidebar는 폭이 좁으므로 full tree를 그대로 복제하지 않고 “최근 세션 within shallow hierarchy”만 표현
        - 즉, SP23-2의 목적은 달성하되 sidebar를 과도하게 복잡하게 만들지는 않음
  - [x] SP23-3. Session History에서 lineage 표시 개선
    - 문제점
      - 현재 session의 상태에 따라 tab으로 구분되며 하나의 lineage내에서 따로 떨어져 독립적으료 표시되어 해당 세션이 어떤 세션들과 연관되었는지는 결국 전체 tab에서 lineage를 찾아야 확인 가능
      - 모든 하위 세션 요소가 표시되어 전체 세션을 한눈에 파악하는데 어려움
    - 기대: 세션의 표시가 복잡하지 않고, 각 세션은 계층 구조를 즉시 파악할 수 있어야 함.
    - 접근
      - 현재 tab 구조로 되어 있는 구분 기준을 상태가 아닌 all / bookmark로 변경
      - 상태 filter는 상단의 별도 UI로 제공
      - 기본적으로는 최상위 session 요소만 노출되며
        - 해당 요소에는 하위 session 의 개수와 통계 (busy:3, idle:1, error:2) 표시
        - session 요소에 expand 버튼을 클릭하여 하위 요소 list를 펼치는 방식으로 하위 세션을 선택할 수 있음
      - 필터 적용시 해당 세션이 하위 세션일 경우 lineage 최상위 session이 보이며, 해당 lineage내에 필터 적용된 상태를 가지고 있는 session만 펼쳐짐 상태로 표시됨
    - 추가 변경점
      - 이러한 UI 컨셉을 위해 leaneage의 최상위 세션을 삭제하면 하위 모든 세션이 함께 삭제되도록 삭제를 단순화함. 즉, 상위 요소없이 하위 요소가 남아 있을 수 없도록 함
    - **구현 완료 (2026-03-20)**
      - **`src/features/history/History.tsx`**
        - Session History state를 `activeTab` + `activeStatusFilter` 구조로 분리
      - **`src/features/agent/components/SessionHistoryPanel.tsx`**
        - primary segmentation을 `all / bookmarked`로 변경
        - status filter를 별도 control로 분리
        - 기본 렌더를 always-expanded nested list에서 root-first tree view로 변경
        - root card 기준 descendant count / descendant status stats를 표시할 수 있도록 row metadata 확장
        - 특정 descendant만 필터에 매칭되어도 lineage root를 유지하는 filter-aware tree shaping 구현
        - auto-expand는 필터 결과의 ancestor를 initial seed로만 반영하고, 이후 사용자가 수동 collapse 가능하도록 수정
      - **`src/features/agent/components/SessionCard.tsx`**
        - expand/collapse toggle UI 추가
        - descendant count / descendant status summary badge 추가
        - card-level status styling 강화
          - 상태 badge뿐 아니라 카드 border / background / shadow / left accent bar로 busy / idle / paused / error를 더 쉽게 구분할 수 있도록 개선
      - **`src/lib/session-utils.ts`**
        - `buildDescendantCounts()`
        - `buildDescendantStatusCounts()`
        - tree UI가 필요로 하는 계산을 공용 유틸로 이동
      - **회귀 테스트**
        - `src/features/agent/components/__tests__/SessionHistoryPanel.test.tsx`
          - root-first default visibility
          - expand toggle
          - filter/bookmark 상황에서 lineage root 유지
          - auto-expanded lineage의 수동 collapse 허용
        - `src/features/agent/components/__tests__/SessionCard.test.tsx`
          - error 상태 card-level styling 검증 추가
      - **검증**
        - `pnpm test:run src/features/agent/components/__tests__/SessionCard.test.tsx src/features/agent/components/__tests__/SessionHistoryPanel.test.tsx`
        - `pnpm lint`
        - 전체 validation pipeline도 수동 동일 명령 체인으로 통과 확인 (`sync-builtin-services`, `lint`, `format`, `test:run`, `rust:validate`, `rust:test`, `build`, `dead-code`)
  - **현재 코드 기준 분석 (2026-03-19)**
    - 현재 구현 소유 영역
      - 세션 목록 상태/이벤트 동기화: `src/context/AgentSessionListContext.tsx`
      - Session History UI: `src/features/history/History.tsx`, `src/features/agent/components/SessionHistoryPanel.tsx`
      - 개별 세션 카드 UI: `src/features/agent/components/SessionCard.tsx`
      - App Sidebar recent sessions: `src/components/layout/AppSidebar.tsx`
    - 현재 이미 존재하는 기반 데이터
      - `AgentSession`에는 `parentSessionId`, `lineageId`, `depth`, `isBookmarked`, `status`가 이미 있음
      - `AgentSessionListContext`는 `agent:event`의 `statusChanged`를 구독하여 세션 status를 in-place 갱신함
      - `SessionHistoryPanel`은 현재도 parent-child 관계를 따라 중첩 렌더링을 수행함
      - `SessionHistoryPanel`에는 descendant count 계산 로직이 이미 존재함 (`descendantCounts`)
    - proposal과 겹치는 현재 구현 상태
      - SP23-2/3의 핵심 전제인 lineage/tree 데이터는 이미 모델링되어 있음
      - bookmark 토글 및 필터는 이미 구현되어 있음
      - lineage filter도 이미 구현되어 있음
      - session 삭제는 이미 `deleteSession`(cascade) / `deleteSessionOnly`(orphan) 두 경로로 분리되어 있음
      - 반면 unread 상태, expand/collapse 상태, descendant 통계 표시, transition notification UI는 아직 없음
  - **feasibility / validity 평가**
    - SP23-1. Session Unread Notification 기능
      - **Historical note**
        - 이 평가는 구현 전(2026-03-19) 시점의 사전 검토 메모였고, 실제 구현 단계에서 semantic이 한 차례 더 정리됨
      - **최종 구현 기준 재평가 (2026-03-20)**
        - Feasibility: **High**
        - Validity: **Strong**
      - 최종 근거
        - generic message unread는 bell signal로서 noisy하므로 제외
        - 단순 tool execution 진행중 상태도 unread에서 제외
        - 대신 `toolExecutionRequiresApproval`과 `WorkflowCompleted(reason=recurringStop)`만 attention-worthy signal로 사용
        - 이를 위해 `last_attention_at`, `last_attention_reason`, `WorkflowCompleted.reason`를 추가해 semantic ambiguity를 제거함
      - 최종 판단
        - “무슨 메시지가 왔는가”보다 “사용자 attention이 필요한 stop인가” 기준이 훨씬 타당함
        - sound / OS notification은 여전히 optional 후속 단계로 유지
    - SP23-2. Session List의 혼동을 유발하는 시각적 구조 (App Sidebar)
      - Feasibility: **High**
      - Validity: **Strong**
      - 근거
        - hierarchy를 위한 데이터 (`parentSessionId`, `depth`)가 이미 존재함
        - 현재 sidebar는 recent sessions를 flat하게만 보여주고 있어 실제로 lineage를 숨기고 있음
      - 판단
        - 문제 정의가 정확함
        - 다만 sidebar는 폭이 좁으므로 full tree보다는 root 중심 + shallow indent 정도가 적절함
    - SP23-3. Session History에서 lineage 표시 개선
      - Feasibility: **High**
      - Validity: **Strong**
      - 근거
        - 현재도 history panel은 nested render를 하고 있으며 descendant count 계산도 존재함
        - 현재 UX 문제는 “데이터/구조 부재”가 아니라 “표시 방식이 flat + status tab 중심”인 것에 가까움
      - 판단
        - all / bookmark 중심 + 별도 status filter + root-first tree view 방향은 타당함
        - 특히 lineage를 상태 tab으로 찢지 않고 하나의 그룹으로 유지하려는 발상은 현재 코드와도 잘 맞음
  - **구현 시 주의점 / 함정**
    - `SessionHistoryPanel`은 현재 render-phase state update로 stale `selectedLineageId`를 정리하고 있음
      - 즉, 여기에 expand/collapse, auto-expand-on-filter 같은 stateful logic을 그대로 누적하면 React render 흐름이 더 복잡해질 수 있음
    - filter + tree 조합은 단순 flat filter가 아님
      - 자식만 매칭되어도 root lineage를 유지해서 보여줘야 하므로 2-pass tree shaping이 필요함
    - unread를 영속 상태로 다루려면 frontend-only로 끝나지 않을 수 있음
      - backend persistence / session metadata 확장이 필요해질 수 있음
    - sidebar는 session history full tree를 그대로 축소 복제하면 과도하게 복잡해질 가능성이 큼
  - **권장 breakdown / 구현 순서**
    - 1단계: Session History 구조 정리
      - status tab 중심 구조를 `all / bookmarked` 중심으로 바꾸고
      - status filter는 별도 UI control로 분리
    - 2단계: root-first tree view 도입
      - 기본적으로 root session만 노출
      - child session은 expand/collapse로 표시
      - root 카드에 descendant count 및 상태 통계 표시
    - 3단계: filter-aware tree shaping
      - 특정 child만 필터에 매칭될 때도 lineage root를 유지하고
      - 필요한 branch만 자동 확장되도록 처리
    - 4단계: App Sidebar 축약 계층 표시
      - full tree를 복제하지 말고 recent root 중심 + 얕은 계층 표시만 제공
    - 5단계: unread semantic 확정 후 notification 추가
      - unread의 정의, clear 조건, persistence 여부를 먼저 정한 뒤
      - toast / badge를 먼저 넣고 sound / OS notification은 마지막에 optional로 추가
  - **최종 판단**
    - SP23-2 / SP23-3는 현재 코드베이스 기준으로 바로 진행 가능한 수준
    - SP23-1은 실제로 semantic definition이 선행되어야 했고, 최종적으로는 `approval + recurring-stop attention` 기준으로 정리되어 구현 완료됨

- [ ] SP24. MCP / Skills / Agent / Settings에 대한 export/import 구현
- [ ] SP25. claude, vscode, gemini, github copilot 설정 가져오기 구현
- [ ] SP26. Agent Terminology / Sidebar Chat UX 정렬
  - 문제점
    - user-facing UI에서 `assistant`라는 표현이 `agent` 개념과 섞여 보여 semantic이 다소 혼란스러움
    - App Sidebar가 collapsed 상태일 때 `chat` 메뉴가 icon-only affordance에 가까워 클릭성이 약함
    - `chat` 메뉴 icon이 현재 `Bot` 계열 의미에 가까워, 실제 “conversation / chat entrypoint”와 semantic alignment가 떨어짐
  - 기대
    - 사용자 노출 텍스트는 `assistant`보다 `agent` 또는 더 문맥에 맞는 표현으로 정리되어야 함
    - collapsed sidebar에서도 `chat` 메뉴가 더 직관적이고 누르기 쉬워야 함
    - `chat` 메뉴 icon은 메시지/대화 진입점으로 즉시 이해 가능한 시각 언어를 가져야 함
  - 권장 접근
    - **SP26-1. text-only terminology alignment**
      - locale / description / button / toast 등 user-facing copy에서 `assistant`를 `agent` 계열 표현으로 정리
      - 단, `Assistant` type / folder / route / backend command 같은 structural naming은 이번 scope에서 제외
    - **SP26-2. collapsed sidebar click affordance 개선**
      - collapsed 상태에서 `chat` item의 hit area / hover affordance / tooltip discoverability를 점검하고 보강
      - sidebar 전체 일관성을 해치지 않는 범위에서 icon-only 상태의 조작성을 개선
    - **SP26-3. chat icon semantic alignment**
      - 현재 `Bot` 중심 icon 대신 `MessageSquare` / `MessageCircle` 계열처럼 chat 의미가 즉시 전달되는 icon으로 교체 검토
  - 현재 코드 기준 판단 (2026-03-20)
    - **바로 진행 가능한 항목**
      - sidebar icon 교체
      - collapsed 상태의 click affordance 보강
      - user-facing terminology 정리
    - **별도 리팩토링으로 분리할 항목**
      - `Assistant` → `Agent` 구조적 리네임
      - feature path / route / type / backend DTO rename
  - 관련 파일
    - `src/components/layout/AppSidebar.tsx`
    - `src/components/ui/sidebar.tsx`
    - `src/locales/*/common.json`
    - `src/context/AssistantContext.tsx`
- [ ] SP27. session message의 semantic index 구축과 session 정보를 탐색하는 내장 도구 기능 구현
