Skip to content

feat(workspace): name tonight's first breath on the map - #1096

Open
seonghobae wants to merge 6 commits into
developfrom
feat/workspace-first-breath
Open

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

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Product outcome

The ready rehearsal map names tonight's first last-line breath from existing timeRange.end evidence so the band finishes the phrase together. Sit-out parts stay off this cue. This is not a count-out, count-in, click, chart bar, Fine, or a new MIR product.

Exact current identity

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

Current exact scope

  • firstBreath admits own-property finite non-negative section ends at or after the matching start and formats them as m:ss.
  • Blank labels, inverted spans, inherited time fields, and malformed roots fail closed.
  • When a role is selected, only an own-property active partGraph node (or a named role when no graph node exists) owns the breath.
  • Ready workspace copy names the next action: breathe together before the last line, or confirm the last-line breath when it is missing.
  • AGENTS / CLAUDE / ARCHITECTURE / CHANGELOG and the component contract stay current.
  • Doctoring: docs/doctoring/first-breath.md.

Merge gate


Devin Review

The ready rehearsal map names the first named section end from existing
timeRange.end evidence so the band breathes together before the last line.
Sit-out parts stay off this cue. This is not a count-out, count-in, click,
chart bar, Fine, or a new MIR product.
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 30 minutes.

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: Pro Plus

Run ID: f94873a9-b2e6-4d41-bef3-48f54696a1ab

📥 Commits

Reviewing files that changed from the base of the PR and between 749511c and be70ca4.

📒 Files selected for processing (14)
  • AGENTS.md
  • ARCHITECTURE.md
  • CHANGELOG.md
  • CLAUDE.md
  • apps/desktop/src/features/workspace/Workspace.test.tsx
  • apps/desktop/src/features/workspace/Workspace.tsx
  • apps/desktop/src/features/workspace/firstBreath.copy.test.ts
  • apps/desktop/src/features/workspace/firstBreath.test.ts
  • apps/desktop/src/features/workspace/firstBreath.ts
  • apps/desktop/src/i18n/index.test.ts
  • apps/desktop/src/locales/en/common.json
  • apps/desktop/src/locales/ko/common.json
  • docs/design-system/component-contract.md
  • docs/doctoring/first-breath.md

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.

@seonghobae seonghobae added area: ui-ux Frontend, interaction, design, or user experience priority: medium Normal-priority or P2 work type: feature New or expanded product capability scope: product-gap Customer-visible product gap labels Aug 30, 2026 — with Grok (by xAI)

@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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 4 potential issues.

Devin Review

Comment thread apps/desktop/src/features/workspace/firstBreath.ts
Comment on lines +53 to +87
if (Array.isArray(sectionValue.partGraph)) {
let sawSelectedNode = false;
for (const nodeValue of sectionValue.partGraph) {
if (
!isRuntimeObject(nodeValue) ||
!Object.prototype.hasOwnProperty.call(nodeValue, "role_id")
) {
continue;
}
const roleId = meaningfulRangeText(nodeValue.role_id);
if (roleId !== activeRole) {
continue;
}
sawSelectedNode = true;
if (isOwnActive(nodeValue)) {
return true;
}
}
if (sawSelectedNode) {
return false;
}
}

if (!Array.isArray(sectionValue.roles)) {
return false;
}
for (const roleValue of sectionValue.roles) {
if (!isRuntimeObject(roleValue) || !Object.prototype.hasOwnProperty.call(roleValue, "id")) {
continue;
}
if (meaningfulRangeText(roleValue.id) === activeRole) {
return true;
}
}
return false;

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: Selected sit-outs remain excluded

sectionIncludesActiveRole requires explicit activity when the selected part has a graph node. Known sit-outs cannot re-enter through the role-list fallback.

Devin Review

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

Comment on lines +118 to +133
if (
!isRuntimeObject(sectionValue.timeRange) ||
!Object.prototype.hasOwnProperty.call(sectionValue.timeRange, "start") ||
!Object.prototype.hasOwnProperty.call(sectionValue.timeRange, "end")
) {
continue;
}
const start = sectionValue.timeRange.start;
const end = sectionValue.timeRange.end;
if (typeof start !== "number" || !Number.isFinite(start) || start < 0) {
continue;
}
const endTime = formatBreathTime(end);
if (!endTime || typeof end !== "number" || end < start) {
continue;
}

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: Runtime time checks stay bounded

firstBreath isolates malformed runtime values beyond the stricter shared parser. Normal loaded and analyzed songs already require integer, positive-duration ranges.

Devin Review

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

Comment thread apps/desktop/src/locales/en/common.json Outdated

@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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 new potential issue.

Devin Review

Comment thread apps/desktop/src/features/workspace/firstBreath.copy.test.ts

@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 1 new potential issue.

Devin Review

"workspaceFirstRangeClash": "{sectionLabel}의 {roleName}은 {lowestNote}–{highestNote}이고 다른 파트와 겹칩니다. {sectionLabel} 들어가기 전에 그 충돌을 악기로 들어 보세요.",
"workspaceFirstRangeMissing": "오늘 먼저 볼 음역은 아직 귀로 확인이 필요합니다. 선택한 파트의 최저·최고음을 첫 구간 전에 확인해 보세요.",
"workspaceFirstBreathTitle": "오늘 먼저 맞출 구간 끝",
"workspaceFirstBreathNamed": "{sectionLabel}은 {endTime}에 끝납니다. 구간 경계에서 함께 마무리해 보세요.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Korean cue drops breath action

The Korean named state tells players to finish at the boundary, not breathe before the last line. The workspace contract still requires that cue.

Devin Review

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

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

Labels

area: ui-ux Frontend, interaction, design, or user experience priority: medium Normal-priority or P2 work scope: product-gap Customer-visible product gap type: feature New or expanded product capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant