Skip to content
Draft
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 src/wazzup/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ def generate_structured_summary(self, request: SummaryRequest) -> SummaryRespons
"Every bullet must include citations containing source item IDs from the input. "
"Merge input items into one bullet when they describe the same story, campaign, incident, vendor, "
"product, or affected organization; cite every source item ID that supports the merged bullet. "
"Do not infer winners, outcomes, timelines, or cause-and-effect details that are not explicitly stated "
"in the cited input items. "
"Otherwise preserve the input order so newly published hourly articles stay at the top. "
"Do not include Markdown fences or commentary."
)
Expand Down Expand Up @@ -628,6 +630,7 @@ def build_prompt_payload(request: SummaryRequest) -> dict[str, Any]:
"Keep bullets concise and source-grounded.",
"Preserve the input item order so newly published hourly articles stay at the top, except when merging related items into one synthesized bullet.",
"Merge closely related input items into one synthesized bullet when they describe the same story, campaign, incident, vendor, product, or affected organization; cite every source item ID that supports the merged bullet.",
"Do not infer winners, outcomes, timelines, or cause-and-effect details unless the cited item titles or summaries explicitly say so.",
"When an input item includes relatedItems, treat the item and relatedItems as one correlated story and cite every source item ID that supports the bullet.",
],
}
Expand Down
17 changes: 17 additions & 0 deletions tests/test_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,22 @@ def test_prompt_allows_synthesized_bullets_for_related_items(self) -> None:
self.assertIn("same story", style_guide)
self.assertIn("cite every source item ID", style_guide)

def test_prompt_style_guide_blocks_unsupported_merged_claims(self) -> None:
payload = build_prompt_payload(
SummaryRequest(
kind="hourly",
window_start="2026-05-06T20:00:00Z",
window_end="2026-05-06T21:00:00Z",
generated_at="2026-05-06T21:00:00Z",
timezone="Europe/Amsterdam",
summary_language="en",
items=[],
)
)
style_guide = "\n".join(payload["styleGuide"])
self.assertIn("Do not infer winners, outcomes, timelines, or cause-and-effect details", style_guide)
self.assertIn("explicitly say so", style_guide)

def test_prompt_style_guide_requires_english_translation(self) -> None:
payload = build_prompt_payload(
SummaryRequest(
Expand Down Expand Up @@ -309,6 +325,7 @@ def fake_run(command, capture_output, cwd, env, text): # type: ignore[no-untype
self.assertEqual(DEFAULT_COPILOT_AGENT, command[command.index("--agent") + 1])
prompt = command[command.index("-p") + 1]
self.assertIn("Merge input items into one bullet", prompt)
self.assertIn("Do not infer winners, outcomes, timelines, or cause-and-effect details", prompt)
self.assertNotIn("Create one bullet for each input item", prompt)
return Mock(returncode=0, stdout="", stderr="")

Expand Down