Summary ends with an empty "What's next?" heading on Gemma 4 #595

Closed
opened 2026-09-11 03:31:47 +00:00 by claude-bot · 2 comments
Contributor

What happens

Both summary-only reruns with Gemma 4 26B (the router's qwen3.5 alias) on the dev replay session ended like this:

…Wyatt was able to identify a mid-sized city located a few miles from an exit.

What's next?

The runs were on 2026-09-10 at 06:31 UTC (at #587) and 2026-09-11 at 03:28 UTC (at 6533fa1, which includes #591). In both, the heading is there with nothing after it. Prod is also on Gemma, because the router is shared, so a real session's summary will end the same way.

Why

Both compose prompts ask the model to "end with a short 'What's next?' hook" (beat_service.py ~828, audio_service.py ~139 and ~2879). Gemma reads the quoted phrase as a heading to print, prints it, and stops. The material for a hook was there. The last events are the party learning of a mid-sized city a few miles from an exit, and the circus rumour of a faster way between towns.

_WHATS_NEXT_RE already finds the hook for note_unsummarised_windows, so the code can tell where it is.

Fix

  1. Say what the hook is. Reword both prompts to ask for content, not a heading: e.g. "End with a final short paragraph that begins 'What's next?' and says, in one or two sentences, what the party is left facing or has decided to do."
  2. Guard the output. If the summary ends with the hook and nothing after it (only whitespace or punctuation following _WHATS_NEXT_RE), drop the empty heading rather than publish it. An empty heading reads as broken; a summary without a hook doesn't. Count it on the run record, the way truncated is, so it's visible rather than silent.
  3. Test it at the request level, per feedback_llm_test_seam: assert the reworded instruction is in the system prompt, and run the guard on a stubbed reply that ends with a bare "What's next?".

Found while comparing summaries for #591.

## What happens Both summary-only reruns with Gemma 4 26B (the router's `qwen3.5` alias) on the dev replay session ended like this: ``` …Wyatt was able to identify a mid-sized city located a few miles from an exit. What's next? ``` The runs were on 2026-09-10 at 06:31 UTC (at #587) and 2026-09-11 at 03:28 UTC (at 6533fa1, which includes #591). In both, the heading is there with nothing after it. **Prod is also on Gemma**, because the router is shared, so a real session's summary will end the same way. ## Why Both compose prompts ask the model to *"end with a short 'What's next?' hook"* (`beat_service.py` ~828, `audio_service.py` ~139 and ~2879). Gemma reads the quoted phrase as a heading to print, prints it, and stops. The material for a hook was there. The last events are the party learning of a mid-sized city a few miles from an exit, and the circus rumour of a faster way between towns. `_WHATS_NEXT_RE` already finds the hook for `note_unsummarised_windows`, so the code can tell where it is. ## Fix 1. **Say what the hook is.** Reword both prompts to ask for content, not a heading: e.g. "End with a final short paragraph that begins 'What's next?' and says, in one or two sentences, what the party is left facing or has decided to do." 2. **Guard the output.** If the summary ends with the hook and nothing after it (only whitespace or punctuation following `_WHATS_NEXT_RE`), drop the empty heading rather than publish it. An empty heading reads as broken; a summary without a hook doesn't. Count it on the run record, the way `truncated` is, so it's visible rather than silent. 3. **Test it** at the request level, per [[feedback_llm_test_seam]]: assert the reworded instruction is in the system prompt, and run the guard on a stubbed reply that ends with a bare "What's next?". Found while comparing summaries for #591.
Author
Contributor

Picking this up (2026-09-11), in one branch with #588's exact-duplicate case. Both changes are deterministic, so one dev rerun will show their effect.

The plan follows the body above:

  • Prompts: reword every prompt that asks for the hook so it asks for content, not a heading.
  • Guard: drop an empty trailing hook, on both the compose path and the prose path. The guard runs before note_unsummarised_windows places its notes.
  • Record: a hook_dropped column on summarisation_runs, so it's visible and not silent.

#596 (the table-admin kind) is being built in parallel. It changes what the model produces, so it will be measured separately, after this one.

**Picking this up** (2026-09-11), in one branch with #588's exact-duplicate case. Both changes are deterministic, so one dev rerun will show their effect. The plan follows the body above: - **Prompts:** reword every prompt that asks for the hook so it asks for content, not a heading. - **Guard:** drop an empty trailing hook, on both the compose path and the prose path. The guard runs before `note_unsummarised_windows` places its notes. - **Record:** a `hook_dropped` column on `summarisation_runs`, so it's visible and not silent. #596 (the table-admin kind) is being built in parallel. It changes what the model produces, so it will be measured separately, after this one.
Author
Contributor

Fixed and measured. Merged in PR #598 (main 0935b7a) and deployed to dev, then checked with a summary-only rerun on the replay session (Gemma 4 26B, run 6d3e6f54, 2026-09-11 05:45 UTC).

The summary now ends with a real hook:

What's next? The party now knows they are near a mid-sized city and must decide how to proceed toward it.

  • hook_dropped is false: the reworded instruction (HOOK_INSTRUCTION) was enough on its own, and the guard didn't need to fire. The guard stays for models that still print only the heading, and when it fires it's recorded on the run rather than hidden.
  • Run 3, before the fix, ended on a bare "What's next?", as did the run before that.

Closing.

**Fixed and measured.** Merged in PR #598 (main `0935b7a`) and deployed to dev, then checked with a summary-only rerun on the replay session (Gemma 4 26B, run `6d3e6f54`, 2026-09-11 05:45 UTC). The summary now ends with a real hook: > What's next? The party now knows they are near a mid-sized city and must decide how to proceed toward it. - **`hook_dropped` is false:** the reworded instruction (`HOOK_INSTRUCTION`) was enough on its own, and the guard didn't need to fire. The guard stays for models that still print only the heading, and when it fires it's recorded on the run rather than hidden. - **Run 3, before the fix**, ended on a bare "What's next?", as did the run before that. Closing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#595
No description provided.