Raise the compose cap from 30 to 36 now that table admin no longer competes for it #600

Closed
opened 2026-09-11 13:40:23 +00:00 by claude-bot · 1 comment
Contributor

Why

beat_service._COMPOSE_MAX_BEATS = 30 (#568) was sized to what the compose prompt's "3-6 paragraphs" can hold, when a real session produced about 26 beats. Two things have changed since:

  • Gemma 4 26B verifies far more. After #596's table_admin fold, it still leaves 43–60 story events per run on the replay session: runs ace1414f and 03b3acfa, 2026-09-11. So the cap now always binds, and the #589 time-stratified pick drops 13–30 story events from the prose.
  • What gets dropped is detail in dense stretches. The Thieves' Cant reveal (01:09:53) sits in a run of six reveals between 01:08:36 and 01:11:26. At 30 buckets over a 79-minute session, that stretch gets about two slots, so the Cant is in some runs' prose and not others (runs 3, 4 and 6 no; run 5 yes).

Nothing is lost from the event log either way. The cap only governs what's narrated.

Change

  • _COMPOSE_MAX_BEATS goes from 30 to 36, and the compose prompt's "3-6 paragraphs" becomes "3-7 paragraphs", so the two instructions still agree.
  • The comment's reasoning and numbers are updated to the Gemma measurements.
  • The owner's "short summary plus full event log" decision (#568) still stands. This is a modest widening, not a return to narrating everything.

How it's measured

One summary-only rerun of the dev replay session against run 6 (03b3acfa, 2,573 characters), looking at:

  • summary length, which should stay short (roughly 3,000 characters at most)
  • whether dense-stretch details such as the Cant appear
  • whether the opening and hook still hold

If the length grows past that or coverage doesn't move, revert and look at bucket weighting instead.

## Why `beat_service._COMPOSE_MAX_BEATS = 30` (#568) was sized to what the compose prompt's "3-6 paragraphs" can hold, when a real session produced about 26 beats. Two things have changed since: - **Gemma 4 26B verifies far more.** After #596's `table_admin` fold, it still leaves 43–60 *story* events per run on the replay session: runs `ace1414f` and `03b3acfa`, 2026-09-11. So the cap now always binds, and the #589 time-stratified pick drops 13–30 story events from the prose. - **What gets dropped is detail in dense stretches.** The Thieves' Cant reveal (01:09:53) sits in a run of six reveals between 01:08:36 and 01:11:26. At 30 buckets over a 79-minute session, that stretch gets about two slots, so the Cant is in some runs' prose and not others (runs 3, 4 and 6 no; run 5 yes). Nothing is lost from the event log either way. The cap only governs what's narrated. ## Change - `_COMPOSE_MAX_BEATS` goes from 30 to **36**, and the compose prompt's "3-6 paragraphs" becomes "3-7 paragraphs", so the two instructions still agree. - The comment's reasoning and numbers are updated to the Gemma measurements. - **The owner's "short summary plus full event log" decision (#568) still stands.** This is a modest widening, not a return to narrating everything. ## How it's measured One summary-only rerun of the dev replay session against run 6 (`03b3acfa`, 2,573 characters), looking at: - summary length, which should stay short (roughly 3,000 characters at most) - whether dense-stretch details such as the Cant appear - whether the opening and hook still hold If the length grows past that or coverage doesn't move, revert and look at bucket weighting instead.
Author
Contributor

Measured: raising the cap alone doesn't rescue the dense-stretch details, and the replay shows why. Merged in PR #601 (main c8116d7), deployed to dev; run 7 is b0613da6 (Gemma 4 26B, 2026-09-11 14:13 UTC).

Run 7 against run 6:

  • Length: 2,675 characters (run 6: 2,573), so it's still short. ✔
  • Opening and circus rumour: in. ✔
  • The #588 exact-duplicate rule fired for the first time (1 collapsed).
  • The Thieves' Cant is still missing, and the mid-sized city is lost (run 6 had it). Both events were extracted and verified this run: 01:08:55 and 01:11:26.
  • The extra room went to chatter: "the group took a moment to discuss the game Phasmophobia", "Viquilonto (Viq) made a joke about separating curds from chaff".

Replay of the deterministic selector on run 7's stored events (read-only, select_beats_for_compose at both caps):

Event Picked at 30 Picked at 36
01:08:55 Thieves' Cant (labelled other) no no
01:11:26 mid-sized city (labelled other) no no
00:17:06 Phasmophobia chatter (other) no yes
00:55:14 curds/chaff joke (social) no yes

The six extra slots bought:

  • 00:04:14 water depth
  • 00:17:06 Phasmophobia
  • 00:26:48 bridge description
  • 00:37:45 "Harrowhark requests a perception check"
  • 00:42:29 detect magic
  • 00:55:14 curds joke
  • 01:04:19 circus rumour

The cause is the fill step, not the cap. After taking one event per time slice, leftover slots are filled by rank = (kind tier, t_start, …): story kinds before other, then earliest first. So:

  1. Leftover slots are biased towards the start of the session. The ending, which is what the hook needs, loses every tie. In run 7 the hook degraded to "The party is currently at Ironroot Hold…".
  2. A late event the model labelled other comes last, whatever the cap. Both targets are real reveals that the model labelled other, and ~35–45% of this session's story events are other.

A bigger cap only extends the same earliest-first queue, which is how the chatter got in.

Proposed follow-up, not built yet:

  • Fill leftover slots across time, not earliest-first. Hand them to the slices with the most unpicked events: the densest stretches get more, and none gets fewer. Keep kind as a tiebreak within a slice only, as #589 intended.
  • Separately, label chatter instead of expecting it to be omitted. The extractor was told to leave out talk that isn't about the game. It recorded the Phasmophobia talk anyway, as other, with the summary "off-topic chatter", which is #596's lesson again. Labelling it table_admin (or a sibling kind) would keep it out of the pick.

Keeping 36 for now: the length is fine, and the fill fix is what makes the extra room count. If the fill fix doesn't move coverage either, revert to 30.

**Measured: raising the cap alone doesn't rescue the dense-stretch details, and the replay shows why.** Merged in PR #601 (main `c8116d7`), deployed to dev; run 7 is `b0613da6` (Gemma 4 26B, 2026-09-11 14:13 UTC). **Run 7 against run 6:** - **Length:** 2,675 characters (run 6: 2,573), so it's still short. ✔ - **Opening and circus rumour:** in. ✔ - **The #588 exact-duplicate rule fired for the first time** (1 collapsed). - **The Thieves' Cant is still missing, and the mid-sized city is lost** (run 6 had it). Both events were extracted and verified this run: 01:08:55 and 01:11:26. - **The extra room went to chatter:** "the group took a moment to discuss the game Phasmophobia", "Viquilonto (Viq) made a joke about separating curds from chaff". **Replay of the deterministic selector on run 7's stored events** (read-only, `select_beats_for_compose` at both caps): | Event | Picked at 30 | Picked at 36 | |---|---|---| | 01:08:55 Thieves' Cant (labelled `other`) | no | no | | 01:11:26 mid-sized city (labelled `other`) | no | no | | 00:17:06 Phasmophobia chatter (`other`) | no | **yes** | | 00:55:14 curds/chaff joke (`social`) | no | **yes** | **The six extra slots bought:** - 00:04:14 water depth - 00:17:06 Phasmophobia - 00:26:48 bridge description - 00:37:45 "Harrowhark requests a perception check" - 00:42:29 detect magic - 00:55:14 curds joke - 01:04:19 circus rumour **The cause is the fill step, not the cap.** After taking one event per time slice, leftover slots are filled by `rank = (kind tier, t_start, …)`: story kinds before `other`, then **earliest first**. So: 1. **Leftover slots are biased towards the start of the session.** The ending, which is what the hook needs, loses every tie. In run 7 the hook degraded to "The party is currently at Ironroot Hold…". 2. **A late event the model labelled `other` comes last**, whatever the cap. Both targets are real reveals that the model labelled `other`, and ~35–45% of this session's story events are `other`. A bigger cap only extends the same earliest-first queue, which is how the chatter got in. **Proposed follow-up, not built yet:** - **Fill leftover slots across time, not earliest-first.** Hand them to the slices with the most unpicked events: the densest stretches get more, and none gets fewer. Keep kind as a tiebreak *within* a slice only, as #589 intended. - **Separately, label chatter instead of expecting it to be omitted.** The extractor was told to leave out talk that isn't about the game. It recorded the Phasmophobia talk anyway, as `other`, with the summary "off-topic chatter", which is #596's lesson again. Labelling it `table_admin` (or a sibling kind) would keep it out of the pick. Keeping 36 for now: the length is fine, and the fill fix is what makes the extra room count. If the fill fix doesn't move coverage either, revert to 30.
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#600
No description provided.