Background
While executing #93's fix, a second context-starvation bug surfaced: generate_topic_summaries in SummarizeMeetingJob uses Topics::SummaryContextBuilder to feed analyze_topic_summary, and that builder only passes agenda structure (AgendaItem.title + the usually-empty AgendaItem.summary field + packet attachments) — not the MeetingSummary.generation_data["item_details"] content.
This is the same root cause as #93 RC1, but a different job and different prompt. #93 fixed it for analyze_topic_briefing by adding recent_item_details via Topics::RecentItemDetailsBuilder. That fix does NOT touch analyze_topic_summary.
Observable symptom
On topic 513 after the #93 fix deployed:
MeetingSummary.generation_data["item_details"] for m94 (2025-08-04 PUC) correctly contains the fake-stickers story: "Staff said fake garbage stickers are still being found, and the hauler is notifying public works and police. They also noted social media chatter about switching away from the sticker system to an automated option…"
- But ts514 (TopicSummary for topic 513 × meeting 94) says only: "A meeting agenda includes an item titled 'SOLID WASTE UTILITY: UPDATES AND ACTION, AS NEEDED.'"
- That stale ts514.generation_data flows into
GenerateTopicBriefingJob#build_briefing_context as prior_meeting_analyses, polluting the briefing's factual_record with generic entries even though the underlying meeting has specific content.
Root cause
app/services/topics/summary_context_builder.rb:34-88 — agenda_items_data builds each item as:
{
id: item.id,
number: item.number,
title: item.title,
summary: item.summary, # AgendaItem.summary — almost always nil
recommended_action: item.recommended_action,
citation: item_citation,
attachments: doc_attachments # item-level packet attachments
}
No call to MeetingSummary.generation_data["item_details"]. The per-item minutes content exists but never reaches the per-meeting topic summary prompt.
Proposed fix
Mirror #93's pattern:
- Add a helper on
Topics::SummaryContextBuilder (or a new service) that, for the meeting bound to the builder, fetches the latest MeetingSummary.generation_data["item_details"] and matches entries to the linked agenda items via Topics::TitleNormalizer.normalize.
- Include the matched entries in
agenda_items_data output under a new key (e.g. item_details_summary) alongside summary/recommended_action.
- Update the
analyze_topic_summary prompt template (lib/prompt_template_data.rb) to reference the new field and prefer it over raw packet previews when writing per-meeting factual_record entries.
- Re-run
SummarizeMeetingJob for affected meetings to regenerate TopicSummary rows with fresh content.
- Re-run
GenerateTopicBriefingJob for affected topics so the briefing picks up the cleaner prior_meeting_analyses.
Scope
Acceptance
After this fix plus a cascade rerun of SummarizeMeetingJob for topic 513's live meetings (m94, m8, m178):
Discovered while working on
Refs #93. Surfaced while diagnosing why topic 513's briefing still had a generic m94 entry after #93 shipped. See the diagnostic output in the #93 PR comments / plan doc for details.
References
Background
While executing #93's fix, a second context-starvation bug surfaced:
generate_topic_summariesinSummarizeMeetingJobusesTopics::SummaryContextBuilderto feedanalyze_topic_summary, and that builder only passes agenda structure (AgendaItem.title+ the usually-emptyAgendaItem.summaryfield + packet attachments) — not theMeetingSummary.generation_data["item_details"]content.This is the same root cause as #93 RC1, but a different job and different prompt. #93 fixed it for
analyze_topic_briefingby addingrecent_item_detailsviaTopics::RecentItemDetailsBuilder. That fix does NOT touchanalyze_topic_summary.Observable symptom
On topic 513 after the #93 fix deployed:
MeetingSummary.generation_data["item_details"]for m94 (2025-08-04 PUC) correctly contains the fake-stickers story: "Staff said fake garbage stickers are still being found, and the hauler is notifying public works and police. They also noted social media chatter about switching away from the sticker system to an automated option…"GenerateTopicBriefingJob#build_briefing_contextasprior_meeting_analyses, polluting the briefing'sfactual_recordwith generic entries even though the underlying meeting has specific content.Root cause
app/services/topics/summary_context_builder.rb:34-88—agenda_items_databuilds each item as:No call to
MeetingSummary.generation_data["item_details"]. The per-item minutes content exists but never reaches the per-meeting topic summary prompt.Proposed fix
Mirror #93's pattern:
Topics::SummaryContextBuilder(or a new service) that, for the meeting bound to the builder, fetches the latestMeetingSummary.generation_data["item_details"]and matches entries to the linked agenda items viaTopics::TitleNormalizer.normalize.agenda_items_dataoutput under a new key (e.g.item_details_summary) alongsidesummary/recommended_action.analyze_topic_summaryprompt template (lib/prompt_template_data.rb) to reference the new field and prefer it over raw packet previews when writing per-meetingfactual_recordentries.SummarizeMeetingJobfor affected meetings to regenerateTopicSummaryrows with fresh content.GenerateTopicBriefingJobfor affected topics so the briefing picks up the cleanerprior_meeting_analyses.Scope
Topics::SummaryContextBuilder,analyze_topic_summaryprompt, and theSummarizeMeetingJob→generate_topic_summariespath.analyze_topic_briefing(already fixed in Topic briefings starve on agenda structure: context starvation + empty KB + orphan TopicSummary rows #93) or any other consumer ofSummaryContextBuilder.Topics::TitleNormalizerandTopics::RecentItemDetailsBuilderfrom Topic briefings starve on agenda structure: context starvation + empty KB + orphan TopicSummary rows #93 are reusable — much of the fix is composing existing pieces.Acceptance
After this fix plus a cascade rerun of
SummarizeMeetingJobfor topic 513's live meetings (m94, m8, m178):factual_recordnames the fake-stickers story, not "agenda includes an item titled…"factual_recordentry for 2025-08-04 references the fake stickers incidentfactual_recordcontains no residual "agenda included" boilerplate across meetings where minutes existDiscovered while working on
Refs #93. Surfaced while diagnosing why topic 513's briefing still had a generic m94 entry after #93 shipped. See the diagnostic output in the #93 PR comments / plan doc for details.
References
app/jobs/summarize_meeting_job.rb:88-135(generate_topic_summaries— call site)app/services/topics/summary_context_builder.rb:34-88(agenda_items_data— gap)app/services/topics/recent_item_details_builder.rb(reusable pattern from Topic briefings starve on agenda structure: context starvation + empty KB + orphan TopicSummary rows #93)lib/prompt_template_data.rb"analyze_topic_summary"entry (prompt to update)