fix: populate story_name in event buffer via CRDT lookup

`subscribe_to_watcher` was pushing StoredEvents into the event
buffer with story_name hardcoded to String::new(), so /api/events
polled by the gateway always omitted the title. The 1035 fix
patched the other path (gateway_relay status_to_stored) but left
this one bleeding empty strings.

Lookup happens once at the subscriber boundary rather than at all
44 watcher emit sites — the story_id is already in hand and
crdt_state::read_item is the canonical name source.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Timmy
2026-05-14 20:24:27 +01:00
parent b64eb69aee
commit 667601012c
+13 -3
View File
@@ -31,9 +31,10 @@ pub fn subscribe_to_watcher(buffer: EventBuffer, mut rx: broadcast::Receiver<Wat
.. ..
}) => { }) => {
if let Some(from) = from_stage { if let Some(from) = from_stage {
let story_name = lookup_story_name(&item_id);
buffer.push(StoredEvent::StageTransition { buffer.push(StoredEvent::StageTransition {
story_id: item_id, story_id: item_id,
story_name: String::new(), story_name,
from_stage: from, from_stage: from,
to_stage: stage, to_stage: stage,
timestamp_ms: now_ms(), timestamp_ms: now_ms(),
@@ -41,17 +42,19 @@ pub fn subscribe_to_watcher(buffer: EventBuffer, mut rx: broadcast::Receiver<Wat
} }
} }
Ok(WatcherEvent::MergeFailure { story_id, reason }) => { Ok(WatcherEvent::MergeFailure { story_id, reason }) => {
let story_name = lookup_story_name(&story_id);
buffer.push(StoredEvent::MergeFailure { buffer.push(StoredEvent::MergeFailure {
story_id, story_id,
story_name: String::new(), story_name,
reason, reason,
timestamp_ms: now_ms(), timestamp_ms: now_ms(),
}); });
} }
Ok(WatcherEvent::StoryBlocked { story_id, reason }) => { Ok(WatcherEvent::StoryBlocked { story_id, reason }) => {
let story_name = lookup_story_name(&story_id);
buffer.push(StoredEvent::StoryBlocked { buffer.push(StoredEvent::StoryBlocked {
story_id, story_id,
story_name: String::new(), story_name,
reason, reason,
timestamp_ms: now_ms(), timestamp_ms: now_ms(),
}); });
@@ -68,3 +71,10 @@ pub fn subscribe_to_watcher(buffer: EventBuffer, mut rx: broadcast::Receiver<Wat
} }
}); });
} }
/// Look up the human-readable story name from the CRDT, or empty when absent.
fn lookup_story_name(story_id: &str) -> String {
crate::crdt_state::read_item(story_id)
.map(|view| view.name().to_string())
.unwrap_or_default()
}