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
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@
## 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.
## 2026-09-02 - List deduplication performance
**Learning:** O(N^2) list membership checks (e.g., `if item not in lst: lst.append(item)`) inside loops are a significant bottleneck and should be replaced with O(1) dictionary key lookups. Note that dictionaries should not replace sets, as sets already provide O(1) lookups and are more memory efficient.
**Action:** Replace list-based deduplication with `dict[item] = None` followed by `list(dict.keys())` in critical loops to achieve O(1) lookups while maintaining insertion order.
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
Comment on lines +127 to +128

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟑 Malformed strings crash chart exports

An unhashable string subclass in a role name, cue, or active role ID makes dictionary deduplication raise TypeError. Both export builders then violate their safe-failure contract.

Prompt for agents
Restore safe failure for all three new dictionary-based deduplication paths in services/analysis-engine/src/bandscope_analysis/exports/chart.py: _active_role_ids, _active_role_names, and _section_cue. Values can pass isinstance(value, str) while remaining unhashable, such as a str subclass with __hash__ = None; the previous list membership logic accepted these values. Preserve insertion order and linear behavior for normal strings, while skipping malformed unhashable values rather than allowing TypeError to escape. Add tests covering malformed unhashable role IDs, display names, and cue values through both public export builders.
Devin Review

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

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