diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md
new file mode 100644
index 000000000..ca6dc84c8
--- /dev/null
+++ b/docs/product-technical-gap-baseline.md
@@ -0,0 +1,705 @@
+# BandScope Product-Technical Gap Baseline
+
+Last updated: 2026-08-30
+Base revision: `develop@749511c3ad4000090048718f685c6bee6b3d2c25` (feat(workspace): name tonight's first playable range on the map, #957)
+
+## 1. 목적과 범위 (Purpose & Scope)
+
+이 문서는 ADR/설계 문서(`ARCHITECTURE.md`, `docs/plans/*`), 브랜드 소스(`docs/brand-story.md`), 보안 소스(`docs/security/app-security.md`), 그리고 현재 저장소 상태(코드, 열린 PR 136건, 열린 이슈)를 대조하여 다음을 한 곳에 모은 baseline이다.
+
+- 기능 명세(functional spec)와 PRD/TRD로 승격되지 않은 요구사항의 공백
+- 구현된 코드와 문서가 선언하는 제품 범위 사이의 기술 Gap
+- 누락된 UML/다이어그램 산출물
+- 구매자가 체감하는 제품 Gap 우선순위 Backlog
+
+범위에는 현재 열려 있는 PR 세트를 명시적으로 포함한다. 특히 `feat(workspace): name tonight's first X on the map` 시리즈는 아직 merge되지 않았으므로, 이 문서에서는 해당 시리즈가 착지했을 때 남는 Gap까지 함께 기술한다.
+
+검증 원칙: 본 문서의 코드 관련 주장은 전부 실제 repo에 대해 `grep`/`glob`/파일 read로 확인했다. 확인 방법은 9장에 재실행 가능한 명령으로 남긴다.
+
+## 2. 현행 제품 명세 스냅샷 (Current Product Specification Snapshot)
+
+`ARCHITECTURE.md`와 `docs/brand-story.md` 기준, BandScope는 오늘날 다음을 지향한다.
+
+- 퇴근 후 합주 준비자를 위한 local-first 데스크톱 앱(Tauri + Vite + React)
+- 곡 보기(song view): 섹션별·연주 역할별 추정 화성, 폼(form)/그루브(groove) 큐, 스템(stems), 연주 가능 음역(playable ranges), 단순화 가이드(simplification), 전조/카포/튜닝/셋업 큐, 파트 겹침(part-overlap) 경고, 가시적 신뢰도(confidence), 리허설 우선순위
+- 분석 대상 모델은 곡 전체 코드 트랙이 아니라 `song -> section -> role` 계층이며, role은 악기/보컬 기능/손(hand) 단위까지 확장될 수 있다
+- 자동 분석 결과는 편집 가능하고, model-generated vs user-confirmed provenance를 유지해야 한다
+
+아키텍처 개요:
+
+```mermaid
+flowchart LR
+ subgraph Desktop["apps/desktop (Tauri + Vite + React)"]
+ UI["React UI
features/workspace, player,
ranges, chords, score, settings"]
+ Shell["src-tauri/src/main.rs
9개 typed Tauri command"]
+ Core["core/src/lib.rs
URL/경로/프로젝트 페이로드
검증 헬퍼 (분석 연산 없음)"]
+ end
+ subgraph Engine["services/analysis-engine (Python)"]
+ CLI["cli.py / api.py
stdin/stdout JSON IPC"]
+ Mods["chords / sections / roles /
ranges / temporal / separation /
transcription / exports"]
+ Sep["separation/audio_separator.py
Demucs htdemucs (CPU default)
configurable device passthrough
bandsplit-v1.json inventory-only manifest"]
+ end
+ Rust["services/analysis-engine/rust
bandscope_numeric (PyO3/maturin)
checkerboard_novelty + viterbi_decode"]
+ Types["packages/shared-types
song-section-role 계약
confidence/provenance/cue/export"]
+
+ UI -- "typed Tauri IPC" --> Shell
+ Shell --> Core
+ Shell -- "allowlisted subprocess
stdin/stdout JSON" --> CLI
+ CLI --> Mods
+ Mods --> Sep
+ Mods -. "Rust 커널 호출,
Python 참조 구현 폴백" .-> Rust
+ UI --- Types
+ Mods --- Types
+```
+
+핵심 구조적 사실(코드 확인 완료):
+
+- 로컬 오케스트레이션은 loopback HTTP가 아닌 typed Tauri IPC + stdin/stdout JSON 서브프로세스 방식이다 (`ARCHITECTURE.md`, `apps/desktop/src-tauri/src/main.rs`)
+- `apps/desktop/core`(Rust)는 분석 연산이 아니라 입력 검증(YouTube URL, project payload, score PDF source, 경로 가드) 담당이다 (`apps/desktop/core/src/lib.rs`)
+- 무거운 수치 커널 중 checkerboard novelty와 Viterbi 디코딩만 `bandscope_numeric`(Rust/PyO3)으로 포팅되어 있고, 나머지는 Python/NumPy 참조 구현이며 `tests/test_numeric_parity.py`로 f64 parity를 잠근다 (`_native.py`)
+- 스템 분리는 Demucs `htdemucs`를 기본 `AudioSeparationConfig.device="cpu"`로 실행한다. `_apply_model`은 구성된 `device`를 Demucs `apply_model(..., device=...)`에 전달하므로 비-CPU 장치 경로 자체는 존재하지만, BandScope가 CUDA/MPS를 독립적으로 admission·parity·performance·release gate한 증거는 아직 없다 (`separation/audio_separator.py`)
+- 주파수 컷오프만 정의한 `bandsplit-v1.json` 휴리스틱 밴드스플릿 manifest가 별도로 존재하지만, 현재 코드에서 이를 읽는 runtime consumer는 확인되지 않는다 (`separation/model_weights/bandsplit-v1.json`; supplemental inventory only)
+- 협업 타입(assignments/comments/approvals)은 `packages/shared-types`에 정의만 되어 있고 UI 참조가 전혀 없다 (grep 확인)
+
+## 3. 기능 명세 및 요구사항 도출 (Functional Spec Derivation)
+
+제품 능력 -> 구현 위치 -> 성숙도 매핑. 성숙도: 구현됨 / 부분구현 / 미구현.
+
+| 제품 능력 | 구현 위치 | 성숙도 |
+|---|---|---|
+| 로컬 오디오 임포트(Rust 검증 + app-owned 루트) | `apps/desktop/src-tauri/src/main.rs`, `apps/desktop/core/src/lib.rs` | 구현됨 |
+| YouTube 임포트(정책 제약, 실패 폴백) | `services/analysis-engine/src/bandscope_analysis/youtube.py` | 부분구현 (DRM/로그인 우회 없음, 실패 시 안내 카드는 PR 진행 중) |
+| 스템 분리 | `separation/audio_separator.py` (htdemucs; CPU default) | 부분구현 (플랫폼 게이트, x86 macOS 미지원; configurable device passthrough는 있으나 비-CPU 가속은 아직 BandScope release-qualified가 아님) |
+| 섹션 세그먼테이션(checkerboard novelty) | `sections/segmenter.py` + `bandscope_numeric::checkerboard_novelty` | 구현됨 |
+| 섹션별 화성(HMM + Viterbi) | `chords/chord_recognizer.py`, `chords/section_harmony.py` | 구현됨 (hand-tuned prior 수준, 4장 참조) |
+| 화성 기능 라벨/설명 | `chords/function_analyzer.py`, `RehearsalRole.harmonicExplanation?` | 부분구현 |
+| 역할(role) 추출 및 역할별 조율 | `roles/extractor.py`, `roles/tuning.py` | 부분구현 (주파수 컷오프 휴리스틱 기반) |
+| 음역/가압(range pressure) | `ranges/analyzer.py`, `ranges/pressure.py`, `ranges/pitch_tracker.py` | 구현됨 |
+| 파트 겹침 경고 | `roles/overlap.py`, `RehearsalRole.overlapWarnings` | 구현됨 |
+| 단순화 가이드 | `roles/priority.py` 연계, `RehearsalRole.simplification` 필드 | 구현됨 (문자열 필드 중심) |
+| 전조/카포/튜닝 큐 | `chords/transposition.py`, `chords/capo.py`, `roles/tuning.py` | 구현됨 (계산), 워크스페이스 노출은 PR 진행 중 |
+| 그루브/타이밍/히트/tempo-stability 큐 | `temporal/groove.py`, `temporal/hits.py`, `temporal/stability.py`, PR #1059 | 구현됨 (tempo-stability 노출은 #1059 open stacked PR) |
+| 진입/이탈/카운트/가사 큐 앵커 | `sections/anchors.py`, `CueAnchorKind = lyric\|count\|transition` | 부분구현 |
+| 신뢰도 표시(section/role 수준) | `ConfidenceMarker(low/medium/high)` + `features/workspace/ConfidenceBadge.tsx` | 구현됨 |
+| 리허설 우선순위 | `roles/priority.py`, `RehearsalPriority`, `PracticeProgress.tsx` | 구현됨 (규칙 기반 휴리스틱) |
+| 수동 수정 + provenance | `ManualOverride[]`, `ProvenanceSource = model\|user` | 구현됨 |
+| 내보내기(cue-sheet CSV, chart JSON) | `exports/chart.py`, `src/lib/export.ts` (filename sanitize, CSV escape) | 구현됨 |
+| 악보(score) 보기 | `features/score/ScoreView.tsx`, `ScoreViewer.tsx`, `pdfjs.ts` | 부분구현 (PDF 뷰잉; PDF 바이트 검증은 PR 진행 중, 자동 채보 없음) |
+| 루프 재생/역할별 재생 제어 | `features/workspace/RehearsalPlayer.tsx` | 부분구현 (PR #1062에서 선택 섹션의 실제 오디오 loop 재생, PR #1063에서 bounded playback-rate, PR #1066에서 선택 역할별 section picker, PR #1068에서 선택 cue의 수치 start/end 수동 보정, PR #1069에서 bounded seek, PR #1071에서 안전한 transport 단축키를 연결했으나 role-specific stem playback과 protected merge는 미완료) |
+| 협업(assignment/comment/approval) UI | `packages/shared-types` 타입만 존재 | 미구현 (UI 참조 0건; PR 시리즈가 첫 화면 진행 중) |
+| pad/solo/riff/hook/fill/voicing/articulation/dynamics/tuning/capo/vamp 등 plan 필드 | 없음 (shared-types에 미존재) | 미구현 (PR 시리즈가 추가 예정) |
+| 라이선싱/데모곡 first-run | `apps/desktop/src-tauri/resources/demo/*`, PR #1009 | 부분구현 (번들 provenance/license와 first-run 경로는 PR #1009에 있으나 아직 protected `develop`에 착지하지 않음; 오프라인 활성화와 P0 실오디오 정확도는 미완료) |
+| 자동 저장/crash-safe 프로젝트 포맷 | atomic publication과 bounded load의 일부가 PR #970에 구현됨 | 부분구현 (자동 저장, versioned migration, global recovery scan은 Issue #962) |
+| 서명/공증 배포+롤백 증적 | `.github/workflows/release.yml` 존재 | 부분구현 (Issue #960) |
+
+## 4. 현재 열린 PR 기반 Gap 분석 (Open-PR Gap Analysis)
+
+현재 open PR은 136건이다(2026-08-29 Asia/Seoul 기준 REST inventory). 아래 표는 그중 대표적인 PR을 뽑은 snapshot이며, 대부분은 동일 패턴의 시리즈다.
+
+### 4.1 2026-08-29 exact-head 운영 snapshot
+
+아래 표는 protected base `develop@749511c3ad4000090048718f685c6bee6b3d2c25`에 대해 GitHub REST API로 다시 읽은 대표 PR의 current head와 그 head의 Checks/review 상태다. Capture 시각은 `2026-08-29T08:11:32Z` (`2026-08-29 17:11:32 Asia/Seoul`)이며, 이후 재실행 결과는 이 snapshot의 증적으로 재사용하지 않는다. 아래 재실행 명령은 capture 시각의 open PR 전체에 대해 각 current head, 동일 SHA의 check-runs, reviews, protected base를 JSON으로 묶는다. 이전 SHA의 Checks는 현재 증적으로 재사용하지 않았다.
+
+| PR | current head | current 상태와 traceability |
+|---|---|---|
+| #1053 | `720c823bea91689c69c26877f20b4acd9feedf83` | Settings에서 분석 전/후의 audio next action과 Ranges 이동을 buyer-visible하게 연결; required `opencode-review` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1052 | `b737906aba0b95251109e53434dd8860ff6664fd` | Ranges/Player의 buyer-visible 노출, canonical first-range callout 단일화, active-role 연동, 첫 playable span 보존, 단수형 카피·다중 구간 selector·runtime object guard 보강; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1051 | `d3622b6a21ddf8ab58aa17bb565e803bf5c257ce` | WCAG 2.2 키보드 skip navigation과 focusable main landmark 최소 기준; required `opencode-review` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1049 | `7795ff40a308cae392ce9804e624d64695a49d12` | fermata plan의 첫 섹션 next action을 추가하는 Draft PR; required `opencode-review`·`strix` failure, `DRAFT/MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1048 | `8f8b2da7815741f4af96c70510951d01a4d302fc` | accelerando plan copy/provenance 양방향 검증과 beat-grid 경계 계약을 보강; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1047 | `f2879edf8fae3dc9058ebdbc042c4f79bc243006` | ritardando plan 누락 JSDoc·copy/provenance 양방향 검증과 `ritardando.py` mypy 타입 계약을 보강; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1046 | `c13314677adb0d1ae60a7d2786e858fa6b0f9306` | fade-plan copy/provenance 양방향 검증과 외부 song 교체 identity reset을 보강; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1045 | `0b03fb7b20473b808fce06a4c6a178de46f2e778` | swell-plan copy/provenance 양방향 검증과 feature-cache schema 분리를 보강; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1033 | `046db562497a8104fa525f56a6437eb13fbf4760` | Python 보안 lock baseline; required Checks pass; `REVIEW_REQUIRED/BLOCKED`, qualifying independent approval 없음 |
+| #1040 | `693732df2b9790c2f3292b23b15b01d2e6ca822a` | drop-plan copy/provenance 양방향 검증을 shared-types와 native parser에 보강; required `opencode-review` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1034 | `98a99e1bff4b63f5294d8c9a5cbdaf312b235403` | customer-facing copy, safe error localization, valid/invalid YouTube guidance를 정리; required checks pass, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #1025 | `70c8003b162f794ef37f9d104a210e8a92fd35e1` | 이 문서 PR의 current head; protected base는 `749511c3ad4000090048718f685c6bee6b3d2c25`, required `opencode-review` failure, `MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #970 | `abb39bf7bd4f9ee6fc88bdd8db80d9a4a8113545` | atomic project publication과 bounded load 보강, hard-link 불가 첫 저장 fail-closed; required `opencode-review`·`strix` failure, `MERGEABLE/BLOCKED`, qualifying independent approval 없음 |
+| #858 | `f1f5e877f07aa7486cd343ddfe8aa45a9d628bbd` | analysis/cache/temp/project path authority와 redacted logging test 계약 보강; required `opencode-review` failure, `DRAFT/MERGEABLE/BLOCKED`, unresolved thread 0, qualifying independent approval 없음 |
+| #985 | `33d14e44bf7f41dda51b0ee246f7caae088101b9` | canonical audio resource ceiling을 desktop local/YouTube handoff와 Python defense-in-depth에 연결; required `opencode-review`·`strix` failure, `DRAFT/MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #892 | `fa2abea4f0063db55490b6f392d28315a975cf59` | decoded WAV C-major acceptance와 silent aliased fixture fail-closed 보강; required `opencode-review`·`strix` failure, `DRAFT/MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #891 | `9220af2921438cb51a290ab4e4314e2fd321671d` | dry synthetic C→G/G→C two-section chord-recovery accuracy lock; real-master evidence가 아니며 required `opencode-review` failure, `DRAFT/MERGEABLE/BLOCKED`, `REVIEW_REQUIRED`, qualifying independent approval 없음 |
+| #866 | `505a595d481f8ba03abd8d13e7c17202918c833f` | canonical local-audio resource policy; required `opencode-review`·`strix` failure, `DRAFT/MERGEABLE/BLOCKED`, `CHANGES_REQUESTED`, qualifying independent approval 없음 |
+
+### 4.2 2026-08-30 tempo-stability current-head snapshot
+
+PR #1059 (`feat(tempo): surface tempo movement rehearsal cues`)의 현재 증거는 head `3d2aaa27804bd6113e8e9aee8aff611976698b40`, base `fix/temporal-log-privacy@b11b1e0c1756921c64524d691fb4fac440abc65b`이다. 이 PR은 #1055에 stacked되어 있으며 `OPEN`, `MERGEABLE`, `CLEAN`이지만 formal `reviewDecision`이 없고 qualifying independent approval도 없다. 동일 head의 Devin Review와 CodeRabbit status는 성공으로 보였고, CodeRabbit은 non-default base라 review를 건너뛴 상태이며, review thread unresolved count는 0이다. 따라서 이는 구현/리뷰 증거이지 보호 브랜치 병합 증거가 아니다. 다음 push 뒤에는 반드시 head, 동일 SHA Checks, reviews, threads를 다시 조회한다.
+
+구현 범위는 shared contract의 `TempoStability`/`TempoChange`, API의 validated tempo mapping과 local-only orchestration, Workspace의 en/ko rehearsal copy, chart JSON export, 그리고 final analysis cache v2와 reusable stem-feature cache v1의 독립 namespace다. PR branch에서 생성한 임시 click-track WAV를 실제 `TemporalAnalyzer`와 `analyze_tempo_stability`에 통과시킨 별도 probe는 `120.2 BPM`, `15 beats`, `steady`, `0 tempo changes`를 반환했다. 이 파일은 source tree나 CI fixture가 아니므로 P0 실오디오 정확도 acceptance를 대체하지 않는다.
+
+검증 증적은 pinned npm shim을 사용한 `./scripts/harness/quickcheck.sh` 성공이며, Python `684 passed, 24 skipped`, Python coverage `100.00%`, desktop `218` tests와 configured coverage `100%`, shared-types `21` tests, typecheck/mypy/Ruff/Bandit/security/supply-chain/GitHub bootstrap checks 및 Vite build 성공을 포함한다. 이 결과는 위 exact head에서 실행한 local evidence로만 취급한다.
+
+#### Security Notes
+
+- tempo 분석은 기존 validated local-audio 경계 안에 있으며 새 network, URL, subprocess, WebView, IPC 경계를 추가하지 않는다.
+- cache/export payload에는 raw `audio_path`와 `beat_times`를 넣지 않고, shared/API 계약은 finite·positive tempo만 허용한다.
+- final result cache는 schema v2로 pre-feature 결과를 재사용하지 않으며, 호환 가능한 stem features는 독립된 v1 namespace를 유지한다.
+
+`#1025`의 과거 SHA(`3c459fd033ccd94ad6cc8df6092d9e1ce4a86e6b` 등)는 이 표의 current head가 아니므로, 해당 SHA의 Checks/review를 현재 증적으로 재사용하지 않는다.
+
+### 4.3 2026-08-30 canonical audio-resource current-head snapshot
+
+PR #985 (`feat(analysis): enforce one canonical audio resource policy (#781)`)의 current head는 `b8a6db4fda36b5c07f5f30b4bd9195d5f4e2c431`이며, base는 `develop@749511c3ad4000090048718f685c6bee6b3d2c25`이다. canonical resource policy를 local/YouTube handoff와 temporal, separation, transcription, chord 경계에 연결하고, byte/header/decoded duration budget과 payload-free policy error를 공용 경계에 적용한다. 이 head에서 문서가 약속한 MP3/M4A 중 M4A path-backed intake가 libsndfile file-like probe와 `librosa.load(fileobj)` 조합 때문에 막히는 실제 결함을 확인했고, 후속 PR #1065로 보완했다.
+
+동일 head의 hosted 상태는 `OPEN`, `DRAFT`, `MERGEABLE`, `BLOCKED`, `REVIEW_REQUIRED`이며 review thread unresolved count는 0이다. CodeRabbit은 draft라 review를 건너뛴 성공 상태이고, 일반 CI/build/security/supply-chain gate는 통과했다. `noema-review`는 sidecar `413 request_too_large`, `opencode-review`는 current-head verdict 부재, `strix`는 잘못된 `LLM_API_BASE` 설정으로 실패했다. 이는 source finding이 아닌 외부 review/provider 증거 실패이므로 우회하지 않는다. formal qualifying independent approval은 없고, 동일 Gap의 이전 draft #866에는 #985를 canonical successor로 남겼다.
+
+후속 #1065는 이 head 위에 stacked 되었으며, #985 소유 브랜치는 덮어쓰지 않았다.
+
+#### Security Notes
+
+- 숫자 메타데이터는 caller/decoder가 공급하는 untrusted input이며, finite·정수성 검증 전에 실패할 수 있는 Python numeric conversion도 payload-free policy error로 정규화한다.
+- 수정은 파일 열기, 디코드, URL, subprocess, IPC 경계를 추가하지 않으며, 기존 encoded/decoded resource budget과 local-only 분석 경계를 유지한다.
+- `10**1000` overflow 회귀 테스트는 예외 타입과 stable reason code가 외부에 노출되는 경계를 확인한다.
+
+### 4.4 2026-08-30 real-audio loop current-head snapshot
+
+PR #1062 (`feat(player): play real audio section loops`)의 current head는 `949154375304ebef41e03d2e8bfde3ae86a40714`이며, base는 stacked branch `feat/rehearsal-player-first-section-loop@7a59047b004faa7a0b584f3d6d68c94889a452d5`이다. Tauri asset protocol은 startup scope를 비워 두고 native file-dialog 또는 validated YouTube-cache 경로의 canonical exact file만 runtime allowlist에 추가한다. `RehearsalPlayer`는 실제 `