Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@
## 2026-07-13 - Array.from mapping optimization
**Learning:** Using `Array.from({ length: N }).map(...)` creates an intermediate array of `undefined` values which requires memory allocation and garbage collection, adding O(N) unnecessary overhead in frequently re-rendered UI components.
**Action:** Use `Array.from({ length: N }, (_, index) => ...)` to map elements directly during array creation, avoiding intermediate allocations.
## 2024-05-18 - Dictionary deduplication maintains list order

**Learning:** When optimizing O(N^2) list appends (`if x not in lst: lst.append(x)`) with dictionaries (`dict_obj[x] = None`) for deduplication, Python 3.7+ ensures insertion order is maintained.

**Action:** Confidently use this optimization for arrays/lists without fear of changing return order or causing regressions.
6 changes: 3 additions & 3 deletions services/analysis-engine/src/bandscope_analysis/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def _build_from_pipeline(

# 4. Build final payload sections
payload_sections: list[RehearsalSectionPayload] = []
focus_sections: list[str] = []
focus_sections_dict: dict[str, None] = {}

for i, section in enumerate(detected_sections):
# Compute time range from boundaries
Expand Down Expand Up @@ -436,9 +436,9 @@ def _build_from_pipeline(

# Track high-priority sections for export summary
if section["form_label"] in ("chorus", "verse"):
if section["form_label"] not in focus_sections:
focus_sections.append(section["form_label"])
focus_sections_dict[section["form_label"]] = None

focus_sections = list(focus_sections_dict.keys())
if not focus_sections and payload_sections:
focus_sections = [payload_sections[0]["label"]]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,42 +140,34 @@ def _recognize_from_stems(self, stems: dict[str, np.ndarray], sr: int) -> list[T

def _extract_user_chords(self, section_roles: list[dict[str, Any]]) -> list[ChordLabel]:
"""Extract only user-sourced chords from role harmony data."""
chords: list[ChordLabel] = []
seen: set[str] = set()
chords: dict[str, ChordLabel] = {}
for role in section_roles:
harmony = role.get("harmony")
if isinstance(harmony, dict) and "chord" in harmony:
if harmony.get("source") == "user":
chord_name = str(harmony["chord"])
if chord_name not in seen:
seen.add(chord_name)
chords.append(
{
"chord": chord_name,
"functionLabel": str(harmony.get("functionLabel", "")),
"source": "user",
}
)
return chords
if chord_name not in chords:
chords[chord_name] = {
"chord": chord_name,
"functionLabel": str(harmony.get("functionLabel", "")),
"source": "user",
}
return list(chords.values())
Comment on lines +143 to +155

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: Deduplication semantics remain unchanged

Data-bearing chord maps keep the first duplicate's metadata. Reassigning existing ordered-set keys neither changes their position nor their exported value.

Devin Review

Was this helpful? React with ๐Ÿ‘ or ๐Ÿ‘Ž to provide feedback.


def _extract_role_chords(self, section_roles: list[dict[str, Any]]) -> list[ChordLabel]:
"""Extract model-sourced chords from role harmony data (legacy path)."""
chords: list[ChordLabel] = []
seen: set[str] = set()
chords: dict[str, ChordLabel] = {}
for role in section_roles:
harmony = role.get("harmony")
if isinstance(harmony, dict) and "chord" in harmony:
chord_name = str(harmony["chord"])
if chord_name not in seen:
seen.add(chord_name)
chords.append(
{
"chord": chord_name,
"functionLabel": str(harmony.get("functionLabel", "")),
"source": "model",
}
)
return chords
if chord_name not in chords:
chords[chord_name] = {
"chord": chord_name,
"functionLabel": str(harmony.get("functionLabel", "")),
"source": "model",
}
return list(chords.values())

def _filter_recognized_for_section(
self,
Expand Down Expand Up @@ -213,21 +205,17 @@ def _chords_for_section(
]

# Deduplicate while preserving order
seen: set[str] = set()
chords: list[ChordLabel] = []
chords: dict[str, ChordLabel] = {}
for chord_seg in valid_chords:
chord_name = chord_seg["chord"]
if chord_name not in seen:
seen.add(chord_name)
chords.append(
{
"chord": chord_name,
"functionLabel": "",
"source": "model",
}
)
if chord_name not in chords:
chords[chord_name] = {
"chord": chord_name,
"functionLabel": "",
"source": "model",
}

return chords
return list(chords.values())

def _compute_section_confidence(
self,
Expand Down
31 changes: 15 additions & 16 deletions services/analysis-engine/src/bandscope_analysis/exports/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ def _active_role_ids(section: Mapping[str, object]) -> list[str] | None:
part_graph = section.get("partGraph")
if not isinstance(part_graph, list):
return None
active: list[str] = []
active: dict[str, None] = {}
for node in part_graph:
if not isinstance(node, Mapping) or node.get("is_active") is not True:
continue
role_id = node.get("role_id")
if isinstance(role_id, str) and role_id and role_id not in active:
active.append(role_id)
return active
if isinstance(role_id, str) and role_id:
active[role_id] = None
return list(active.keys())


def _active_roles(section: Mapping[str, object]) -> list[Mapping[str, object]]:
Expand Down Expand Up @@ -121,25 +121,25 @@ def _role_display_name(role: Mapping[str, object]) -> str | None:

def _active_role_names(section: Mapping[str, object]) -> list[str]:
"""Return de-duplicated display names for the section's active roles."""
names: list[str] = []
names: dict[str, None] = {}
for role in _active_roles(section):
name = _role_display_name(role)
if name is not None and name not in names:
names.append(name)
return names
if name is not None:
names[name] = None
return list(names.keys())


def _section_cue(section: Mapping[str, object]) -> str:
"""Join the active roles' cue values into a single cue string."""
cues: list[str] = []
cues: dict[str, None] = {}
for role in _active_roles(section):
cue = role.get("cue")
if not isinstance(cue, Mapping):
continue
value = cue.get("value")
if isinstance(value, str) and value and value not in cues:
cues.append(value)
return "; ".join(cues)
if isinstance(value, str) and value:
cues[value] = None
return "; ".join(cues.keys())


def _confidence_level(section: Mapping[str, object]) -> str | None:
Expand Down Expand Up @@ -188,19 +188,18 @@ def _section_lines(sections: list[Mapping[str, object]]) -> list[str]:
def _footer_lines(song: Mapping[str, object], sections: list[Mapping[str, object]]) -> list[str]:
"""Build the footer: per-role rehearsal priorities and the export focus."""
lines: list[str] = []
priorities: list[str] = []
priorities: dict[str, None] = {}
for section in sections:
for role in _section_roles(section):
name = _role_display_name(role)
priority = role.get("rehearsalPriority")
if name is None or not isinstance(priority, str) or not priority:
continue
entry = f" - {name}: {priority}"
if entry not in priorities:
priorities.append(entry)
priorities[entry] = None
if priorities:
lines.append("Priorities:")
lines.extend(priorities)
lines.extend(priorities.keys())
summary = song.get("exportSummary")
if isinstance(summary, Mapping):
headline = summary.get("headline")
Expand Down
Loading