Skip to content

feat(workspace): tap a session tempo when the song has none - #1072

Open
seonghobae wants to merge 16 commits into
developfrom
feat/workspace-tap-tempo
Open

feat(workspace): tap a session tempo when the song has none#1072
seonghobae wants to merge 16 commits into
developfrom
feat/workspace-tap-tempo

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Product outcome

When tonight's song has no stored tempo, the player can tap a steady groove at least four times. BandScope measures a session-only count-in tempo, then tells the room to count in at that BPM and check the first range. This does not write song.tempo, invent MIR tempo detection, play song audio, or change stem/model authority.

Complementary to #1070 (trusted stored-tempo click). Does not close #961 or #770.

Exact current identity

  • Protected base: develop@749511c3ad4000090048718f685c6bee6b3d2c25.
  • Branch: feat/workspace-tap-tempo.
  • Exact current head: 759d571af92ddc6b13045e4f3ddc800cc44fcedd.
  • Open, non-Draft, unmerged.

Current behavior

  • Tap-derived tempo requires at least four taps and admits only a finite 33–300 BPM result.
  • Intervals use the median of the bounded tap history; long pauses remain bounded input rather than triggering an arbitrary reset.
  • Stored RehearsalSong.tempo follows the shared contract instead: every finite positive stored BPM suppresses session tapping, including values outside the narrower tap-derived 33–300 range.
  • Tap state belongs to one loaded song instance. A different load/analysis result receives a fresh in-memory session even when id/title/section timing collide.
  • Immutable edits emitted by the mounted Workspace (currently practice progress and SectionRoadmap chord edits) explicitly inherit that loaded-song session, so an ordinary rehearsal edit does not erase taps.
  • Session identity is held in a WeakMap; it is not persisted, exported, logged, or sent over IPC/network.
  • The rendered component lives in TapTempoPanel.tsx; this avoids a case-only module collision with the lower-case tapTempo.ts logic module on case-insensitive filesystems.
  • English/Korean next-action copy remains: count in at the measured BPM, then check tonight's first range.

TDD / review repairs

  • Chord-edit reset: RED d6ad7840ed12c3b51e19229edcce2bea5c379d45; initial projection repair 10af39ee5e816ea9f477948b5b23195f508e5027; final ownership model is the loaded-instance repair below.
  • Stored-tempo surface contradiction: RED 39c1b53351f765ae6d6ffc8153a747c8c52ca573; FIX c03c87d65c7f82c80b8fa3227b63c4a26520ab8b.
  • Distinct-song projection collision: RED 7dc56fd566d955ef8e32994918bfe402ad18741a; FIX 571698b44cb2929b94b407e4abbffafcccefdda9 (per-loaded-object WeakMap identity) + f475cc95077da8816cce37b5820db0e79200d82b (inherit identity only through Workspace-owned immutable edits).
  • Case-insensitive module collision: FIX 31d854162004b76ad6749607f9ae811668d82ae1 renames the rendered module to TapTempoPanel.tsx and updates production/test imports.

Fresh inline review-thread inventory on 759d571a… has zero unresolved threads. The latest Devin review on this head contains informational confirmations rather than a new defect finding.

Exact-head verification state

Fresh current-head repository evidence on 759d571af92ddc6b13045e4f3ddc800cc44fcedd is terminal-success for deterministic CI/build/Rust, Windows/macOS, coverage, dependency-review, security-audit, SBOM, release-preflight, OSV, Scorecard, Trivy FS, Semgrep, CodeQL, secret-scan, Bandit, and supply-chain inventory. Skipped jobs are not success.

The required provider lanes remain non-passing and block merge: OpenCode has no authenticated verdict bound to this HEAD; Noema and Strix reach health/provider preflight but their shared gateway preflight returns HTTP 502, with the sidecar logs also recording request_failed status=413 code=request_too_large. The latest rerun details are recorded in the current-head PR comment.

CodeRabbit rate limiting and provider failures are not approvals or source-quality evidence. A qualifying independent approval must also bind to this exact HEAD under the active ruleset before merge.

Security / privacy boundary

  • No new file, URL, subprocess, IPC, model, dependency, or persistent storage authority.
  • Tap timestamps are session-local UI state.
  • Malformed/non-finite clocks and tap state fail closed.
  • A stored tempo is trusted only after the existing shared song contract; the tap-derived tempo retains its narrower rehearsal-usable bound.
  • Session ownership does not derive from attacker-controlled musical content, so distinct loaded songs cannot collide by matching ids/titles/timing.

Merge gate

Keep unmerged until one unchanged exact head has every applicable repository and central CI/build/release/security/SAST/SBOM/supply-chain/coverage/review gate terminal-success, zero valid unresolved findings, exact required coverage/docstring evidence, and a qualifying independent non-author last-push approval under live protection.

Queued, pending, skipped-required, cancelled, absent, neutral, failed, stale, predecessor-head, protected-base, model-only, self/author, status-only, rate-limited, or administrative-bypass evidence is not success. Never weaken protection or transfer predecessor evidence.

Do not mix with #811, #828, or #897. Do not invent a parallel MIR product.


Devin Review

Summary by CodeRabbit

  • 새로운 기능

    • 신뢰할 수 있는 BPM이 없는 곡에서 세션 탭 템포를 측정할 수 있습니다.
    • 최소 4회 탭하면 BPM을 계산하고, 해당 템포로 카운트인 및 첫 연주 구간을 안내합니다.
    • 곡 변경 시 탭 세션을 안전하게 초기화하거나 유지합니다.
  • 문서

    • 탭 템포 사용 방법과 측정 기준을 문서화했습니다.
  • 테스트

    • 탭 템포 계산, 초기화, 곡 전환 및 BPM 유무에 따른 표시 동작을 검증했습니다.

Measure tonight's count-in BPM from at least four player taps when
song.tempo is missing or untrusted, then count in at that tempo and
check the first range. Session-only; this is not MIR and does not
write the song contract.
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

신뢰할 수 있는 BPM이 없는 곡에 세션 탭 템포 기능이 추가되었습니다. 최소 4회의 탭으로 안정적인 BPM을 계산하고, 곡 교체와 편집에 따라 세션 상태를 관리합니다. Workspace UI, 번역, 테스트와 문서도 갱신되었습니다.

Changes

세션 탭 템포 기능

Layer / File(s) Summary
탭 템포 계산 엔진
apps/desktop/src/features/workspace/tapTempo.ts, apps/desktop/src/features/workspace/tapTempo.test.ts
탭 시각을 검증하고 최대 8개까지 저장합니다. 3.5초를 초과한 간격에서는 새 탭 창을 시작합니다. 최소 4회의 안정적인 간격에서 중앙값 기반 BPM을 계산합니다.
Workspace 세션 통합
apps/desktop/src/features/workspace/Workspace.tsx, apps/desktop/src/features/workspace/TapTempoPanel.tsx, apps/desktop/src/features/workspace/*test.tsx, apps/desktop/src/locales/*/common.json
신뢰할 수 있는 BPM이 없는 곡에 탭 템포 UI를 표시합니다. 곡의 불변 편집에는 세션을 상속하고, 다른 곡으로 교체하면 세션을 분리합니다. 영어와 한국어 문자열을 추가했습니다.
문서와 검증 설정
AGENTS.md, ARCHITECTURE.md, CHANGELOG.md, CLAUDE.md, apps/desktop/vite.config.ts, docs/doctoring/workspace-tap-tempo.md
탭 템포 동작과 신뢰 경계를 문서화했습니다. 탭 템포 파일을 커버리지 대상에 추가했습니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: 🔴 Critical · up to a213f

This change adds temporary tap-based tempo guidance for songs without a trusted stored tempo, but the current revision is not merge-ready: required validation and approval conditions are incomplete, the recorded commit identity is inconsistent, and the UI still has bounded correctness issues around unstable taps and invalid tempo display.

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant Workspace
  participant TapTempo
  participant tapTempo
  Player->>TapTempo: 탭 버튼 입력
  TapTempo->>tapTempo: recordTap(nowMs)
  tapTempo-->>TapTempo: TapTempoState 반환
  TapTempo->>tapTempo: tapTempoReading(state)
  tapTempo-->>TapTempo: BPM과 탭 수 반환
  TapTempo-->>Workspace: 안내 문구와 탭 램프 갱신
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR은 연결된 이슈 #961의 카운트인 템포 입력 일부를 구현합니다. 그러나 #961의 핵심 요구사항인 오디오 재생, 정밀 루프, 재생 제어, 큐 탐색, 역할 제어, 상태 영속성 및 운송 상태 머신은 구현하지 않습니다. #961의 범위를 충족하려면 세션 템포 기능을 실제 로컬 오디오 재생, 결정적 카운트인과 루프, 재생 제어, 큐 탐색, 역할 제어, 접근성, 상태 복원 및 관련 검증과 통합하십시오. 이 PR을 부분 구현으로 승인하려면 연결된 이슈를 해당 세션 템포 하위 작업으로 조정하십시오.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 코드, 테스트, 번역, 문서 및 커버리지 설정 변경은 모두 세션 탭 템포 기능과 직접 관련됩니다. 연결된 이슈의 범위를 벗어난 변경은 확인되지 않습니다.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 8 files. (7 skipped: 7 …
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 저장된 템포가 없는 곡에 세션 탭 템포를 추가하는 주요 변경 사항을 정확하고 간결하게 설명합니다.
Full details: Docstring Coverage

Explanation

Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 8 files. (7 skipped: 7 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/workspace-tap-tempo

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

devin-ai-integration[bot]

This comment was marked as resolved.

Pin the current review finding before changing production behavior: a different tempo-less song must start with an empty tap window even when analysis reuses the same song id, while a same-song practice-progress update must preserve the active session taps.
Reset the session-only tap window when a different song or project owns the workspace, even when analysis reuses a constant song id. Preserve taps across same-song practice-progress and collaboration updates by keying only stable project and musical structure identity.
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Collaborator Author

Exact-head recheck for 759d571af92ddc6b13045e4f3ddc800cc44fcedd: deterministic CI/build, Windows/macOS, coverage, security, SBOM, supply-chain, and release-preflight checks are passing; unresolved review threads remain 0 and no qualifying independent approval exists.

The three non-passing required provider lanes are external/current-head evidence, not source findings: OpenCode fail-closed because no authenticated verdict is bound to this SHA; Noema and Strix sidecars reached health/provider preflight but both ended with gateway preflight HTTP 502 (the sidecar log also records a 413 request-too-large event). I am rerunning only those failed jobs; the PR remains unmerged until the provider gates and protected approval are terminal on this unchanged head.

@seonghobae

Copy link
Copy Markdown
Collaborator Author

Provider rerun result on unchanged head 759d571af92ddc6b13045e4f3ddc800cc44fcedd: Noema and Strix again reached health/provider preflight, then the shared gateway preflight returned HTTP 502; the sidecar logs again include request_failed status=413 code=request_too_large. OpenCode again failed closed because no authenticated current-head verdict was posted. This confirms an external central provider failure, not a BandScope source finding. No merge or bypass was performed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Product] Add an active rehearsal player with precise looping and role controls

1 participant