diff --git a/AGENTS.md b/AGENTS.md
index fca448ce9..bb4b51aed 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -83,6 +83,7 @@ This section applies to any agent (Claude, Codex, Cursor, opencode, ...) working
- Keep UI and analysis engine decoupled through shared contracts.
- Prefer minimal, test-first changes for production code.
- Prefer practical, friendly, rehearsal-first wording over academic or authority-heavy language.
+- After a part is selected, the transcribe control must open tonight's first notes or range on the groove map. Do not leave `Transcribe` as a no-op or "coming soon", and do not invent a new MIR extractor.
- Do not reduce the product to a chord analyzer when form, timing, player coordination, simplification, and setup cues are the real rehearsal blockers.
- Do not frame usability as a reason to accept weak analysis quality; BandScope should aim for both easy use and high accuracy.
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 3302a6fc3..d45ecdd65 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -68,6 +68,7 @@ Last updated: 2026-03-11
- BandScope is not only a shell around chord labels, stems, and ranges.
- The technical scope includes rehearsal-facing outputs for harmony, section roadmap, groove cues, role entry and dropout cues, simplification guidance, transposition or setup guidance, confidence flags, and rehearsal priority.
- These outputs must stay aligned with `docs/brand-story.md` rather than drifting back to a song-summary-only analyzer.
+- Ready-workspace transcribe control focuses existing role notes or range on the Groove Map. It does not invent isolation playback or a new MIR product.
## Analysis target model
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eea696893..40d7bc975 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
### Added
+- The ready workspace can open tonight's first notes or range on the groove map from the selected part, honors the user's reduced-motion preference for that navigation, and no longer leaves `Transcribe` as a dead end.
- Display the analyzed song tempo (BPM) as a badge in the rehearsal workspace.
- 각 합주 역할(Role)별 개인 연습 진행도를 0~100% 범위로 기록 및 시각화할 수 있는 연습 진척도(`practiceProgress`) 트래커 기능 추가. UI 컨트롤(슬라이더 및 +/- 버튼)과 한/영 다국어 지원 포함.
diff --git a/CLAUDE.md b/CLAUDE.md
index 82c2c704a..e37ed5f49 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -6,6 +6,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
`AGENTS.md` is the canonical agent operating guide — read and follow it before making changes. It defines the security workflow (`Security Notes`), supply-chain workflow, cross-platform build rules, GitHub bootstrap rules, code style, and safety guardrails. This file complements it with commands and architecture; when in doubt, `AGENTS.md` and the docs it references win.
+After a part is selected, the transcribe control must open tonight's first notes or range on the groove map. Do not leave that button as a no-op.
+
Agent execution and delegation rules live in `docs/agents/README.md`. PR canonicalization rules live in `docs/workflow/pr-continuity.md`.
## Common commands
diff --git a/apps/desktop/src/features/workspace/GrooveMap.tsx b/apps/desktop/src/features/workspace/GrooveMap.tsx
index 2745d4d79..bc2f2c193 100644
--- a/apps/desktop/src/features/workspace/GrooveMap.tsx
+++ b/apps/desktop/src/features/workspace/GrooveMap.tsx
@@ -9,11 +9,16 @@ const EMPTY_NOTES: TranscriptionNote[] = [];
interface GrooveMapProps {
notes?: TranscriptionNote[];
isLoading?: boolean;
+ regionLabel?: string;
+ emptyMessage?: string;
}
/** Documented. */
-function GrooveMapComponent({ notes, isLoading }: GrooveMapProps) {
+function GrooveMapComponent({ notes, isLoading, regionLabel, emptyMessage }: GrooveMapProps) {
const renderedNotes = notes ?? EMPTY_NOTES;
+ const mapLabel = regionLabel ?? "Bass transcription groove map";
+ const emptyCopy =
+ emptyMessage ?? "No bass line transcription yet. Use it when you want to check the groove before rehearsal.";
// Find max offset to determine timeline width
const maxTime = useMemo(() => {
@@ -56,19 +61,24 @@ function GrooveMapComponent({ notes, isLoading }: GrooveMapProps) {
if (renderedNotes.length === 0) {
return (
- No bass line transcription yet. Use it when you want to check the groove before rehearsal.
+ {emptyCopy}
+ ) : null}
+
)}
@@ -490,4 +655,4 @@ export function Workspace({ song, sourceBootstrap = null, onSongUpdate }: Worksp
);
-}
+}
\ No newline at end of file
diff --git a/apps/desktop/src/locales/en/common.json b/apps/desktop/src/locales/en/common.json
index 39f716d50..c19285646 100644
--- a/apps/desktop/src/locales/en/common.json
+++ b/apps/desktop/src/locales/en/common.json
@@ -50,6 +50,20 @@
"workspaceStemsLabel": "Stems",
"workspaceRehearsalPrioritiesLabel": "Rehearsal Priorities",
"workspaceRolesHarmonyLabel": "Roles & Harmony",
+ "workspaceThisRole": "This part",
+ "workspaceOpenNotesAction": "See {role} notes · {pitch} from {start}",
+ "workspaceOpenNotesAria": "Open {role} notes starting at {pitch} from {start} on tonight's groove map",
+ "workspaceOpenNotesArmed": "Tonight's first {role} notes are {pitch} from {start}. Count in on the groove map.",
+ "workspaceOpenRangeAction": "See {role} range · {low}–{high}",
+ "workspaceOpenRangeAria": "Open {role} range {low} to {high} on tonight's groove map",
+ "workspaceOpenRangeArmed": "Tonight's {role} range is {low}–{high}. Count in on the groove map.",
+ "workspaceOpenCueArmed": "Tonight's {role} cue is {cue}. Count in on the groove map.",
+ "workspaceOpenNotesUnavailable": "No notes are ready yet. Stay on tonight's map.",
+ "workspaceGrooveMapRegion": "{role} notes on tonight's groove map",
+ "workspaceGrooveMapReady": "{count} notes mapped for rehearsal",
+ "workspaceGrooveMapRangeEmpty": "No note map yet for {role}. Tonight's range is {low}–{high}. {cue}",
+ "workspaceGrooveMapEmpty": "No notes yet for {role}. Stay on tonight's map.",
+ "workspaceGrooveMapCueFallback": "Use the range to lock the first entrance.",
"sectionRoadmapTitle": "Section Roadmap",
"sectionRoadmapScrollHint": "Scroll for more sections →",
"sectionGrooveLabel": "Groove",
diff --git a/apps/desktop/src/locales/ko/common.json b/apps/desktop/src/locales/ko/common.json
index 371884abb..3e55cba31 100644
--- a/apps/desktop/src/locales/ko/common.json
+++ b/apps/desktop/src/locales/ko/common.json
@@ -50,6 +50,20 @@
"workspaceStemsLabel": "스템",
"workspaceRehearsalPrioritiesLabel": "합주 우선순위",
"workspaceRolesHarmonyLabel": "역할과 화성",
+ "workspaceThisRole": "이 파트",
+ "workspaceOpenNotesAction": "{role} 음 보기 · {start}부터 {pitch}",
+ "workspaceOpenNotesAria": "오늘 그루브 맵에서 {role} 음을 {start}의 {pitch}부터 열기",
+ "workspaceOpenNotesArmed": "오늘 첫 {role} 음은 {start}의 {pitch}. 그루브 맵에서 카운트인하세요.",
+ "workspaceOpenRangeAction": "{role} 음역 보기 · {low}–{high}",
+ "workspaceOpenRangeAria": "오늘 그루브 맵에서 {role} 음역 {low}–{high} 열기",
+ "workspaceOpenRangeArmed": "오늘 {role} 음역은 {low}–{high}. 그루브 맵에서 카운트인하세요.",
+ "workspaceOpenCueArmed": "오늘 {role} 큐는 {cue}. 그루브 맵에서 카운트인하세요.",
+ "workspaceOpenNotesUnavailable": "아직 준비된 음이 없습니다. 오늘 지도에 머무르세요.",
+ "workspaceGrooveMapRegion": "오늘 그루브 맵의 {role} 음",
+ "workspaceGrooveMapReady": "합주용으로 정리된 음 {count}개",
+ "workspaceGrooveMapRangeEmpty": "{role} 음 지도는 아직 없습니다. 오늘 음역은 {low}–{high}. {cue}",
+ "workspaceGrooveMapEmpty": "{role} 음이 아직 없습니다. 오늘 지도에 머무르세요.",
+ "workspaceGrooveMapCueFallback": "첫 입장 음을 음역으로 먼저 잡으세요.",
"sectionRoadmapTitle": "구간 흐름",
"sectionRoadmapScrollHint": "더 많은 구간은 옆으로 스크롤하세요 →",
"sectionGrooveLabel": "그루브",
diff --git a/docs/design-system/component-contract.md b/docs/design-system/component-contract.md
index 22602c313..0f84f1f23 100644
--- a/docs/design-system/component-contract.md
+++ b/docs/design-system/component-contract.md
@@ -31,7 +31,7 @@ The authoritative Figma view is `31 Component Contract Catalog`. This file mirro
| Role Switcher | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-337 | `apps/desktop/src/features/workspace/RoleSwitcher.tsx` | Use `roles`, `activeRole`, and `onRoleChange`; `null` means all roles. |
| Section Roadmap Card | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-402 | `apps/desktop/src/features/workspace/SectionRoadmap.tsx` | Use `song`, `activeRole`, and optional `onSongUpdate`; avoid rebuilding its internal card layout. |
| Song Structure Timeline | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-457 | `apps/desktop/src/features/workspace/Workspace.tsx` | Feature-local `SongStructure({ sections, t })` memo component; not exported. |
-| Groove Map | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-526 | `apps/desktop/src/features/workspace/GrooveMap.tsx` | Use `notes?: TranscriptionNote[]` and `isLoading?: boolean`; preserve scrollable region semantics and note labels. |
+| Groove Map | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-526 | `apps/desktop/src/features/workspace/GrooveMap.tsx` | Use `notes?: TranscriptionNote[]`, `isLoading?: boolean`, `regionLabel`, and `emptyMessage`; `id="workspace-groove-map"` is the focus target for tonight's first notes. |
| Source Control Stack | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-655 | `apps/desktop/src/App.tsx` | Feature-local source controls for local audio, YouTube URL import, project actions, and Start Analysis; keep before metrics at 375px. |
| Export Action Group | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=19-731 | `apps/desktop/src/features/workspace/Workspace.tsx` | Feature-local export buttons call `handleExportCueSheet`, `handleExportChart`, and `handleExportHandoff`. |
| Workspace State Matrix | https://www.figma.com/design/zthWmqfNKUgJBECvv002Qk/Bandscope-Design-System-v1?node-id=99-560 | `apps/desktop/src/features/workspace/WorkspaceStates.tsx`, `apps/desktop/src/App.tsx` | Whole-workspace empty, loading, error, and ready state routing; use before changing `renderWorkspaceState()`. |
diff --git a/docs/doctoring/reduced-motion-first-notes-navigation.md b/docs/doctoring/reduced-motion-first-notes-navigation.md
new file mode 100644
index 000000000..a91ff515e
--- /dev/null
+++ b/docs/doctoring/reduced-motion-first-notes-navigation.md
@@ -0,0 +1,30 @@
+# Reduced-motion first-notes navigation
+
+## Scope
+
+The workspace first-notes action scrolls and focuses the existing groove map after a player selects a part. Smooth scrolling is not essential to exposing the selected role's analyzed notes or range, so BandScope honors the operating-system/user-agent reduced-motion preference for this interaction-triggered navigation.
+
+## Contract
+
+- The default first-notes path preserves the existing smooth scroll and focus behavior.
+- When `window.matchMedia("(prefers-reduced-motion: reduce)").matches` is true, the same action uses immediate (`auto`) scrolling and still focuses the same renderer-owned `workspace-groove-map` target.
+- If `matchMedia` is unavailable, BandScope preserves the existing smooth behavior rather than inventing a preference.
+- The preference changes animation behavior only; it does not change role selection, note/range evidence, action availability, or filesystem/network/model authority.
+
+## Verification
+
+`apps/desktop/src/features/workspace/Workspace.first-notes-reduced-motion.test.tsx` selects the demo Bass Guitar role, opens its real first-note action, and requires `scrollIntoView({ block: "nearest", behavior: "auto" })` when reduced motion is requested. Existing workspace tests continue to cover the default navigation, focus, note/range status, and fail-closed unavailable action.
+
+## Standards rationale
+
+WCAG 2.2 Success Criterion 2.3.3, Animation from Interactions (Level AAA), requires non-essential interaction-triggered motion animation to be disableable. W3C Technique SCR40 documents evaluating `prefers-reduced-motion` in JavaScript to prevent such motion. The groove-map scroll animation is not necessary to identify the selected part's notes or range, so respecting that preference is the narrow behavior-preserving implementation.
+
+This record is implementation rationale and test evidence, not a claim of WCAG certification or overall conformance.
+
+## References
+
+World Wide Web Consortium. (2024). *Web Content Accessibility Guidelines (WCAG) 2.2* (W3C Recommendation, December 12, 2024). https://www.w3.org/TR/WCAG22/
+
+World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *Understanding Success Criterion 2.3.3: Animation from interactions*. Retrieved August 18, 2026, from https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions/
+
+World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *SCR40: Using the CSS prefers-reduced-motion query in JavaScript to prevent motion*. Retrieved August 18, 2026, from https://www.w3.org/WAI/WCAG22/Techniques/client-side-script/SCR40