Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ naia-shell은 **Naia Visual Agent를 위한 데스크톱 셸(앱)**이다. 사
| **텍스트 대화** | 셸이 agent 를 spawn → gRPC `Chat` 스트림으로 대화. new core 경로 | ✅ |
| **provider/모델 설정** | 설정 UI → agent `SetWorkspace`/reload 로 앱 재시작 없이 모델 교체 | ✅ |
| **환경 사이드카** | 뇌와 분리된 독립 서비스(예: BGM `bgm-sidecar`). 뇌가 죽어도 생존 | ✅ |
| **선제 발화 profile** | “개인 라디오 시작해” 또는 “행사 소개 시작”으로 opt-in. 장기 activity stream을 기존 텍스트·TTS·BGM 표현에 연결 | ✅ 기술 slice / 제품 검증은 부분 |
| **음성 I/O · 아바타 · TTS** | 음성 입출력·아바타 표현 | 🔜 옛 경로 존재, 새 코어 이식은 UC2 후속 |
| **다중 모달 표현** | 하나의 표현 의도를 음성/아바타/로봇 몸체가 함께 소비 | 🔜 egress 분화 자리 예약 |

> ✅ = 새 코어에 구현+테스트(Playwright e2e 포함). 🔜 = 설계/옛 경로 존재, 이식 진행.
> 정확한 추적은 `docs/user-scenarios.md`(UC SoT)와 `docs/requirements.md` 참조.
> 실제 Tauri 검증은 profile 저장·복원, DJ 실제 YouTube BGM·첫 결과·stop, 전시 greeting·stop까지다.
> audible TTS·live 질문 끼어들기·모든 제어·장시간/현장 품질은 아직 native 검증으로 주장하지 않는다.

---

Expand Down
14 changes: 14 additions & 0 deletions docs/acceptance-criteria.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
이 문서는 자율 작업에서 **"완료선언 ≠ 완료"** 를 구조적으로 막는 방법론이다.
2026-05-30 alpha-n-naia-144 실험(placeholder glyph 가 "17/17 통과"로 넘어간 드리프트)에서 도출.

## UC15 선제 발화 증거 경계

| 흐름 | 계약/통합 | 실제 Tauri | 제품/현장 |
|---|:---:|:---:|:---:|
| profile 저장·복원 | ✅ | ✅ | 미검증 |
| DJ 실제 YouTube BGM·첫 결과·stop | ✅ | ✅ | 미검증 |
| 전시 greeting·stop | ✅ | ✅ | 미검증 |
| DJ 멘트2·모든 제어·live 끼어들기 | ✅ | 미검증 | 미검증 |
| 전시 질문 중단→답변→resume·stale audio 폐기 | ✅ | 미검증 | 미검증 |
| audible proactive TTS·장시간 품질 | seam 계약 | 미검증 | 미검증 |

`71-proactive-speech-profiles.spec.ts`는 TTS를 끄고 실행한다. 따라서 이 표의 실제 Tauri 열보다 넓은
완료 주장을 하지 않는다. 남은 제품 acceptance는 `nextain/naia-agent#84`에서 추적한다.

## 1. 동기 (실측된 드리프트)

한 프로젝트가 한글 폰트를 "구현 완료, 17/17 테스트 통과"로 인도했다. 그러나:
Expand Down
1 change: 1 addition & 0 deletions docs/progress/01.requirements/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ scripts/check-traceability.mjs 가 이 표를 파싱한다. (ID 형식 = REQ-###
| REQ-009 | 도구/스킬 | 에이전트 **도구루프 + skills**(time/weather/memo/github/obsidian/mcp 등, agent-local) | In-progress | UC-005 | SPEC-006 | TEST-S-005 |
| REQ-010 | 브라우저 | 에이전트 **브라우저 조작**(navigate/click/fill/snapshot, agent-local + 외부 CLI) | Draft | UC-006 | SPEC-006 | TEST-S-006 |
| REQ-011 | 유투브/BGM | **공간 분위기 BGM**(youtube search/play/volume, agent-local + shell player) | Draft | UC-008 | SPEC-006 | TEST-S-008 |
| REQ-012 | 선제 발화 profile | 개인 라디오 DJ·전시 소개 activity를 gRPC로 구독해 기존 텍스트/TTS/BGM에 표현하고 yield/control/stop 전달. native 증적은 시작/BGM 또는 greeting/stop까지 | Partial | UC-015 | SPEC-009 | TEST-S-015 |

## 비기능 요구사항 (NFR → REQ, 횡단 — TEST-S 직결)

Expand Down
1 change: 1 addition & 0 deletions docs/progress/02.user-scenarios/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
| UC-006 | ⑦브라우저 | 에이전트가 브라우저를 조작(navigate/click/fill) (구 UC6) | REQ-010 | Draft | TEST-S-006 |
| UC-011 | 자기상태 | naia 가 자기 상태(시스템/진단/장치)를 정직 보고 (구 UC11/UC14) | REQ-002 | In-progress | TEST-S-011 |
| UC-007 | ⑨워크스페이스(제외) | 에이전트가 host-system 관측·조작(승인) (구 UC7/UC7a) — **현 스코프 제외**(DriftDetector/MutationGate=old 소비자 부재, 방향 미해결) | REQ-004, REQ-005 | Draft | TEST-S-007 |
| UC-015 | 선제·연속 발화 | 개인 라디오 DJ와 회사 전시 소개가 무입력으로 시작하고 기존 표현 경로를 사용. 계약 흐름 구현, native는 시작/BGM 또는 greeting/stop 경계 | REQ-012 | Partial | TEST-S-015 |

> **제외(루크 2026-06-15)**: ⑧메모리(구 UC3/UC4)=off-scope(naia-memory 다른 세션 소유, canon out_of_scope). ⑨워크스페이스(UC-007)=보류(신규발명 방향 결정 후).
> 상세 granular(S01~71 — provider/voice/skills/channels 60+)·테스트 커버리지 맵 = `docs/user-scenarios.md`.
1 change: 1 addition & 0 deletions docs/progress/03.uc-tests/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
| TEST-S-007 | UC-007 | workspace 관측/조작 | e2e | `packages/shell/e2e/91-workspace-panel.spec.ts`(old-path) | Planned |
| TEST-S-008 | UC-008 | youtube BGM 검색/재생 | e2e | — | Planned |
| TEST-S-011 | UC-011 | 자기상태/진단 보고(Diagnostics RPC) | e2e | — | Planned |
| TEST-S-015 | UC-015 | 계약: activity 표시/TTS·yield/control/stop·stale 폐기. 실제 Tauri: profile 저장·복원, DJ 실제 BGM·첫 결과·stop, 전시 greeting·stop | 계약+부분 native | `packages/shell/src/lib/__tests__/speech-profile-commands.test.ts`, `packages/shell/e2e-tauri/specs/71-proactive-speech-profiles.spec.ts` | Partial |
| TEST-S-101 | REQ-101 | substrate-agnostic: core 가 @tauri-apps 미의존(import 검사) | 정적 | (compile-integrity + import 검사) | Planned |
| TEST-S-103 | REQ-103 | provenance: provider 출처 추적(actor/correlation) | e2e | `packages/shell/e2e/uc-provider-provenance-live.spec.ts` | Pass |
| TEST-S-104 | REQ-104 | 계약 드리프트 0토큰 결정론 게이트 | 게이트 | `scripts/conform/` (conform-gate) | Planned |
Expand Down
1 change: 1 addition & 0 deletions docs/progress/04.features/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ area = core(헥사고날 코어 @nextain/naia-os-core) / shell(packages/shell) /
| SPEC-006 | UC-001 | **UC1 ChatService gRPC** — startTurn/cancel/deliverChunk + chat-bridge + shell-compat(makeShellChatService) + 도구/승인 페이로드 포워딩. ports/uc1·app/chat·adapters | core | Done(graft+e2e) | TEST-F-006 |
| SPEC-007 | UC-012 | **UC12 OnboardingController** — submit/assets/startNaiaAuth/onNaiaAuthCallback/complete/completeWith(§D 신규계약)/update. app/control/onboarding | core | In-progress(completeWith graft 완료, 나이아계정 OAuth 흐름 graft 미연결) | TEST-F-007 |
| SPEC-008 | UC-002 | **V2 음성** — SensoryPort/ExpressionPort/VoiceProviderPort + os-local 어댑터(AudioPlayer/MicCapture/STT/avatar). ports/v2·domain/voice | core | Done(os-local 이식, external WS=루크머신) | TEST-F-008 |
| SPEC-009 | UC-015 | **선제 발화 전달** — persisted profile 설정, session activity stream, 기존 agent_response/TTS/BGM 표현, yield/control/stop, generation 기반 stale 폐기 | shell+Rust | Partial(native acceptance 후속) | TEST-F-009 |

## 비고
- **graft 미연결(dormant)** = SPEC 은 이식+리뷰+컴파일 완료지만 실행 셸(packages/shell)이 아직 new-core 경유 안 함(old 경로 구동). graft 완료 = SPEC-006(chat)·SPEC-003(승인, chat흐름 내)·SPEC-007 일부(completeWith).
Expand Down
1 change: 1 addition & 0 deletions docs/progress/05.features-tests/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
| TEST-F-006 | SPEC-006 | UC1 chat/bridge/shell-compat/chunk-fields/child-stdio/trace 계약·통합 | `src/test/uc1-chat.contract.test.ts`, `uc1-bridge.contract.test.ts`, `uc1-shell-compat.contract.test.ts`, `uc1-chunk-fields.test.ts`, `uc1-child-stdio.contract.test.ts`, `uc1-trace.integration.test.ts` | Pass |
| TEST-F-007 | SPEC-007 | UC12 OnboardingController 계약(stale키 strip·completeWith·complete 가드) | `src/test/uc12-onboarding-controller.contract.test.ts`, `uc12-onboarding.contract.test.ts` | Pass |
| TEST-F-008 | SPEC-008 | V2 voice 도메인(startup-lazy) + live-adapter(parity) | `src/test/v2-voice-domain.test.ts`, `v2-live-adapter.test.ts` | Pass |
| TEST-F-009 | SPEC-009 | parser·session/profile generation·yield/control/stop은 계약 테스트. 실제 Tauri는 DJ BGM/첫 text와 전시 greeting, stop만; TTS·live barge-in은 미검증 | `packages/shell/src/lib/__tests__/speech-profile-commands.test.ts`, `packages/shell/e2e-tauri/specs/71-proactive-speech-profiles.spec.ts` | Partial |

## 비고
- Pass = `npx vitest run src/test` 191 cases pass(2026-06-15). `.mjs` 가드 파일 17개는 vitest `process.exit` 아티팩트로 파일레벨 RED 처럼 보이나 케이스 전부 통과(`feedback_test_exit_code_not_pass_count`).
Expand Down
3 changes: 2 additions & 1 deletion docs/progress/99.dev-comm/assembly-matrix-2026-06-10.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

---

## 수직 UC 트랙 — UC1~14 전수 (분류; UC1 상세)
## 수직 UC 트랙 — UC1~15 전수 (분류; UC1 상세)

| UC | 이식/보충 | 주 인지포트 | 권위 | slice/상태 |
|---|---|---|---|---|
Expand All @@ -66,6 +66,7 @@
| UC13 승인게이트 | 이식+보충 | ApprovalPort | mixed | **F1 계약+코드** |
| UC13a 중단/e-stop | **보충** | SafetyPort | scenario | pending(H-safety) |
| UC14 degradation | **보충** | InteroceptivePort→Express | scenario | **F1(정직 degradation 신설)** |
| UC15 자유·연속 발화 전달 | 이식+보충 | Agent gRPC→ExpressionPort·SafetyPort | naia-agent #82 contract | **기술 slice 구현, native acceptance partial** |

### UC1 상세 — 텍스트 대화 (Chat→사고→표현)
| # | 조각(S) | old | 이식/보충 | 인지 포트 | fit | 권위 | 상태 |
Expand Down
9 changes: 7 additions & 2 deletions docs/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ localStorage `naia-config` 는 파일에서 하이드레이트되는 **순수
|---|---|---|:---:|
| **FR-CONT-SHELL.1** | agent 연결 뒤 persisted proactive profile을 `ConfigureSpeechProfile`로 전달하고, 비어 있지 않은 현재 session별 `SubscribeSpeechActivities` 장기 stream을 최대 하나 구독해 self-init `AgentEvent.request_id`, `activity_id`를 보존한다. | Rust contract + live gRPC | Implemented |
| **FR-CONT-SHELL.2** | activity `AgentEvent`를 기존 `agent_event_to_ui_json`→`agent_response` 경로로 보내 텍스트·usage·finish/error의 기존 표현 소비자를 재사용한다. 별도 event union·반복 상태 기계는 만들지 않는다. | Rust transcode + 기존 chat event 회귀 | Implemented |
| **FR-CONT-SHELL.3** | 자유 발화 cancel은 관측한 requestId+activityId를 agent `Cancel`에 돌려주고, activityId 관측 전 또는 session 명시 정지는 thin `StopSpeechActivity` command/RPC로 위임한다. requestGeneration은 requested Chat에만 사용하며 ordinary Chat cancel과 self-init activity cancel을 혼합하지 않는다. | Rust unary contract + e2e-tauri | Implemented |
| **FR-CONT-SHELL.7** | unsolicited activity는 ordinary Chat의 currentRequestId 필터와 별도 activity ref로 수용한다. 새 사용자 입력은 queue보다 먼저 `interruptTts → YieldSpeechActivity → activityResume 토큰을 실은 Chat` 순서로 처리하고, 이전 activityId/profileGeneration의 늦은 text/TTS를 폐기한다. quiet/stop은 Yield 대신 Stop을 사용한다. | ChatArea contract + e2e-tauri ordering | Implemented |
| **FR-CONT-SHELL.3** | 자유 발화 cancel은 관측한 requestId+activityId를 agent `Cancel`에 돌려주고, activityId 관측 전 또는 session 명시 정지는 thin `StopSpeechActivity` command/RPC로 위임한다. requestGeneration은 requested Chat에만 사용하며 ordinary Chat cancel과 self-init activity cancel을 혼합하지 않는다. | Rust unary contract; native Tauri는 stop만 | Implemented |
| **FR-CONT-SHELL.7** | unsolicited activity는 ordinary Chat의 currentRequestId 필터와 별도 activity ref로 수용한다. 새 사용자 입력은 queue보다 먼저 `interruptTts → YieldSpeechActivity → activityResume 토큰을 실은 Chat` 순서로 처리하고, 이전 activityId/profileGeneration의 늦은 text/TTS를 폐기한다. quiet/stop은 Yield 대신 Stop을 사용한다. | ChatArea contract; native ordering은 미검증 | Implemented |
| **FR-CONT-SHELL.4** | subscriber disconnect/dispatcher 종료/agent 재시작에서 stream task와 client 자원을 정리한다. server가 해당 session active를 cancelled로 끝낼 수 있도록 stream을 실제 drop한다. | disconnect live test + watchdog | Implemented |
| **FR-CONT-SHELL.5** | 같은 session 중복 구독 0, 서로 다른 session은 독립 구독, 요청 기반 기존 Chat stream과 일반 cancel/event correlation 무회귀를 보장한다. | duplicate/session isolation + existing Chat tests | Implemented |
| **FR-CONT-SHELL.6** | transcript read/delete의 session basename은 agent writer와 동일하다. canonical `[A-Za-z0-9_-]+` 최대 128자는 그대로, 나머지는 UTF-8 SHA-256 전체 hex를 쓰고 양쪽 공통 벡터를 검증한다. | Rust `safe_session_base` + agent shared-vector contract | Pending (후속 hardening) |
Expand All @@ -272,6 +272,11 @@ NFR: agent-owned(반복·deadline·memory를 셸에 복제 금지), bounded(sess
현재 session 집합에 한정), wire-compatible(기존 AgentEvent union 재사용), observable(debug 로그에
session subscribe/start/terminal/disconnect와 requestId, 시크릿 없음).

검증 경계: PR #381의 실제 Tauri 테스트는 profile 저장·복원, DJ 실제 YouTube BGM·첫 결과·stop,
전시 greeting·stop을 검증한다. 이 테스트는 `ttsEnabled: false`이므로 audible proactive TTS,
DJ 멘트2, 질문 barge-in→답변→resume, 모든 제어, stale audio 폐기를 native로 증명하지 않는다.
그 흐름은 현재 Rust/프론트/agent 계약·통합 테스트 증거이며, 제품 live acceptance는 agent #84 후속이다.

## 비기능 요구사항 (NFR) — 횡단(전 tranche)

| ID | 요구사항 | 근거(1단계 구조) |
Expand Down
9 changes: 6 additions & 3 deletions docs/user-scenarios.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,13 @@ naia-agent가 사용자 요청의 기존 `Chat` stream에서 연속 발화를
P02 검증:

- Rust 단위/계약: `agent_grpc.rs`의 activity event 변환, subscribe/stop 요청, 같은 session 중복 구독 방지.
- 실 백엔드: `agent_grpc.rs` live test 또는 e2e-tauri에서 agent spawn → session subscribe → self-init
- 실 백엔드/계약: `agent_grpc.rs` agent spawn → session subscribe → self-init
text/usage/finish → 기존 `agent_response`, requestId cancel/stop, disconnect 정리를 검증.
- 프론트 계약: ChatArea에서 unsolicited activity 표시/TTS, `interruptTts → yield/stop → Chat` 순서,
stale audio/text 폐기를 검증한다. e2e-tauri에서 개인 DJ BGM play/stop과 전시 질문 barge-in을 검증한다.
stale audio/text 폐기를 검증한다.
- 실제 Tauri `71-proactive-speech-profiles.spec.ts`: profile 저장·복원, 개인 DJ의 실제 YouTube BGM·첫
결과 text·stop, 전시 greeting·stop만 검증한다. 이 테스트는 TTS를 꺼 두므로 audible TTS, DJ 멘트2,
전시 질문 barge-in→답변→resume, 모든 control, stale audio 폐기를 native로 증명하지 않는다.

Test Coverage Map: UC15 / FR-CONT-SHELL.1~7 → Rust `agent_grpc` contract+live tests,
`packages/shell/e2e-tauri` activity stream full-stack, 기존 `src/main/adapters/tauri/uc1`·ChatArea cancel 회귀.
`packages/shell/e2e-tauri` 시작/표현 일부 full-stack, 기존 `src/main/adapters/tauri/uc1`·ChatArea cancel 회귀.
Loading