From the #139 audit (Part C, bug cluster 2). Design conversation first.
One recurring bug cluster — #55, #56, #60, #64, #71, #120, #122, #132, #136 — is the same failure: speaker identity is stringly typed. "Local Speaker N" prefixes, "index:label" namespace keys (TranscriptionRunner.swift:173, 646), per-chunk vs global namespaces that must agree by string convention across SpeakerAssignment → SpeakerReconciler → TranscriptMerger. Every bug in the cluster is a namespace/label-agreement failure a type would have caught.
Proposal: a small SpeakerLabel type (source + scope + index) so the agreement is compiler-enforced instead of convention. An addition that meets the "right structure, not bloat" bar.
Why now: propose the type design before #26 (cross-session recognition) and #68 (persistent renames) deepen the investment in strings. Related: #139.
From the #139 audit (Part C, bug cluster 2). Design conversation first.
One recurring bug cluster — #55, #56, #60, #64, #71, #120, #122, #132, #136 — is the same failure: speaker identity is stringly typed.
"Local Speaker N"prefixes,"index:label"namespace keys (TranscriptionRunner.swift:173, 646), per-chunk vs global namespaces that must agree by string convention acrossSpeakerAssignment→SpeakerReconciler→TranscriptMerger. Every bug in the cluster is a namespace/label-agreement failure a type would have caught.Proposal: a small
SpeakerLabeltype (source + scope + index) so the agreement is compiler-enforced instead of convention. An addition that meets the "right structure, not bloat" bar.Why now: propose the type design before #26 (cross-session recognition) and #68 (persistent renames) deepen the investment in strings. Related: #139.