Skip to content

feat(workspace): name tonight's first stop on the map - #1131

Closed
seonghobae wants to merge 6 commits into
developfrom
feat/workspace-first-stop
Closed

feat(workspace): name tonight's first stop on the map#1131
seonghobae wants to merge 6 commits into
developfrom
feat/workspace-first-stop

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Product outcome

The ready workspace keeps tonight's first playable range as its own decision, then names tonight's first stop so the room can cut together before the next entrance.

Brand and architecture already treat stops as rehearsal blockers (docs/brand-story.md, docs/architecture/rehearsal-domain-model.md). The analysis engine already detects stop-time, and the section contract already includes the stop form label. This PR is the buyer-visible map action: cut together here, then come back in on the next named section.

Exact current identity

  • Protected target: develop@749511c3ad4000090048718f685c6bee6b3d2c25.
  • Branch: feat/workspace-first-stop.
  • Exact current head: eac17a61823b2392940f865d95a14058ed95aa9f.

Current exact scope

  • firstStop selects the first form-labeled stop in form order.
  • Groove text and cue wording never invent a stop.
  • Missing or duplicate section identities fail closed so a later stop cannot steal another card.
  • The workspace callout names the previous and next labeled sections when they exist, otherwise it asks for an ear check.
  • The Section Roadmap next-action renders only on the destination stop card.
  • EN/KO copy tells the band what to do next.

Merge gate

Keep unmerged until this 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, and a qualifying independent non-author last-push approval under live protection.

Queued, pending, skipped-required, cancelled, failed, predecessor-head, protected-base, model-only, self/author, or administrative-bypass evidence is not success.

Do not mix with #811, #828/#770, #897, or first-X rehearsal-map PRs already open. Canonical #783 remains protected develop shipped truth; this branch does not copy or suppress inherited npm HIGH findings.

Do not self-approve.

Summary by CodeRabbit

  • 새 기능

    • 작업공간에서 곡의 첫 번째 스톱 지점을 자동으로 표시합니다.
    • 이전 구간과 다음 재진입 구간을 함께 안내하며, 관련 구간 카드에는 “함께 컷한 후 다시 진입” 안내가 표시됩니다.
    • 영어와 한국어 안내 문구를 지원하고, 구간 정보가 없는 경우에도 적절한 대체 문구를 제공합니다.
  • 문서

    • 준비된 작업공간의 첫 스톱 및 다음 진입 지점 안내 내용을 관련 문서에 반영했습니다.
  • 테스트

    • 첫 스톱 탐색, 안내 문구, 대상 구간 표시 및 다국어 동작을 검증하는 테스트를 추가했습니다.

Surface the first form-labeled stop so the room can cut together
before the next entrance, without inventing a stop from groove or cue
wording. Fail closed on missing or duplicate section identities.
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

Next included review available in 28 seconds.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 0257633a-29dc-4568-8fb9-f050ce998201

📥 Commits

Reviewing files that changed from the base of the PR and between eac17a6 and 4061634.

📒 Files selected for processing (4)
  • apps/desktop/src/features/workspace/firstStop.ts
  • services/analysis-engine/src/bandscope_analysis/roles/__init__.py
  • services/analysis-engine/src/bandscope_analysis/roles/coordinated_extractor.py
  • services/analysis-engine/tests/test_pipeline_integration.py
📝 Walkthrough

Walkthrough

곡의 첫 번째 stop 섹션을 식별하는 유틸리티를 추가했습니다. 워크스페이스와 섹션 로드맵은 해당 스톱과 다음 진입 지점을 안내합니다. 영어와 한국어 문구, 관련 테스트와 아키텍처 문서를 갱신했습니다.

Changes

첫 번째 스톱 안내

Layer / File(s) Summary
첫 번째 스톱 식별 로직
apps/desktop/src/features/workspace/firstStop.ts, apps/desktop/src/features/workspace/firstStop.test.ts
firstStop이 유효하고 고유한 섹션 ID를 확인한 뒤 첫 번째 stop 섹션과 인접 섹션 label을 반환합니다. fillStopCopy, isStopTarget, stopCopyValues와 유틸리티 테스트를 추가했습니다.
워크스페이스 스톱 안내
apps/desktop/src/features/workspace/Workspace.tsx, apps/desktop/src/features/workspace/Workspace.test.tsx, apps/desktop/src/locales/en/common.json, apps/desktop/src/locales/ko/common.json, AGENTS.md, ARCHITECTURE.md, CHANGELOG.md, CLAUDE.md, docs/architecture/overview.md, docs/architecture/rehearsal-domain-model.md
워크스페이스가 첫 번째 스톱의 위치와 다음 진입 안내를 표시합니다. 이전 또는 다음 섹션이 없을 때 사용할 문구와 영어·한국어 번역을 추가했습니다. 관련 설명과 변경 기록을 갱신했습니다.
섹션 로드맵 스톱 후속 작업
apps/desktop/src/features/workspace/SectionRoadmap.tsx, apps/desktop/src/features/workspace/SectionRoadmap.test.tsx
첫 번째 스톱 카드에만 함께 컷한 뒤 다음 섹션으로 재진입하는 안내를 표시합니다. 스톱이 없는 곡과 대상 카드 선택 동작을 테스트했습니다.

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

Merge Risk: 🟡 Moderate · up to eac17

The first-stop guidance can display "none" instead of the fallback ear-check message when a neighboring section has no name, and the associated test currently fails. Merge should wait until unnamed sections are handled correctly.

Sequence Diagram(s)

sequenceDiagram
  participant Workspace
  participant firstStop
  participant Locales
  participant SectionRoadmap
  Workspace->>firstStop: 곡의 첫 번째 stop 식별
  firstStop-->>Workspace: stop 정보와 인접 label 반환
  Workspace->>Locales: 조건별 안내 문구 조회
  Locales-->>Workspace: 현지화된 문구 반환
  SectionRoadmap->>firstStop: 섹션 카드가 stop 대상인지 확인
  firstStop-->>SectionRoadmap: 대상 여부 반환
  SectionRoadmap-->>Workspace: 해당 카드에 후속 작업 안내 표시
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (8 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 작업공간에서 오늘의 첫 번째 스톱을 식별하고 이름을 표시하는 주요 변경 사항을 정확하고 간결하게 설명합니다.
Full details: Docstring Coverage

Explanation

Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (8 skipped: 8 unsupported.)

✨ Finishing Touches 💡 1
📝 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-first-stop

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.

coderabbitai[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 new potential issues.

Devin Review


# Preserve the established package-level import while routing the analysis
# pipeline through the cross-role temporal coordination boundary.
RoleExtractor = CoordinatedRoleExtractor

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Cached songs miss stop labels

Existing analysis caches bypass CoordinatedRoleExtractor because their schema remains valid. Previously analyzed songs omit stop labels until users clear the cache.

Prompt for agents
The package-level RoleExtractor now changes persisted RehearsalSong output by adding stop labels, but services/analysis-engine/src/bandscope_analysis/api.py still accepts ANALYSIS_CACHE_SCHEMA_VERSION 1 results created before this behavior existed. Increment the analysis-result cache schema/version and its cache directory or otherwise invalidate old result caches, while preserving the reusable stem feature cache. Add a cache test proving an old result is treated as a miss and reanalysis produces stop labels.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

if section_start_time <= stop_start_time <= section_end_time:
section_candidate = section_candidates[section_index]
if isinstance(section_candidate, dict):
section_candidate["form_label"] = "stop"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Stop labels retain old identities

A detected stop changes only form_label, leaving IDs such as verse-1. The workspace then treats a stop as a mismatched section identity.

Prompt for agents
Stop-time coordination mutates form_label without reconciling the SectionCandidate id and sequence_index fields. The section model defines id as a slug derived from form_label and sequence_index, while downstream first-stop logic relies on section identities to target the correct card. Preserve the original structural label separately if needed, then emit a contract-consistent stop section identity and sequence numbering, with tests for multiple stops and collisions with existing section IDs.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +15 to +17
# Preserve the established package-level import while routing the analysis
# pipeline through the cross-role temporal coordination boundary.
RoleExtractor = CoordinatedRoleExtractor

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Import paths now differ semantically

Package-level RoleExtractor mutates section labels, while roles.extractor.RoleExtractor does not. Equivalent-looking imports now expose different behavioral contracts.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

if not isinstance(section_boundaries, list) or len(section_boundaries) != len(section_candidates):
return

stop_time_moments = temporal_hits.detect_stop_time(audio_stems, sample_rate)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Role extraction adds another stem scan

Every package-level extract call runs detect_stop_time across all stems. Repeated callers cannot reuse the temporal result.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +56 to +60
if section_start_time <= stop_start_time <= section_end_time:
section_candidate = section_candidates[section_index]
if isinstance(section_candidate, dict):
section_candidate["form_label"] = "stop"
break

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Shared endpoints select the prior section

Inclusive ranges overlap at exact boundaries. Forward scanning deliberately assigns that stop to the preceding section, preserving the next section as re-entry.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Collaborator Author

Supersession evidence is now complete on canonical owner #934 rather than by title/number deduplication.

No #1131 review, check, approval, or predecessor-head evidence is transferred. #934 must earn fresh exact-head gates and independent approval on its own current head.

@seonghobae seonghobae closed this Sep 2, 2026
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.

1 participant