Richer session events, and three checks that stop dropping real ones (#1189) #1192

Merged
claude-bot merged 6 commits from fix/1189-v4-prompt into main 2026-10-14 15:33:22 +00:00
Collaborator

Closes #1189. This is the owner's choice after the private Session 14 comparison: the v4 prompt with the looser checks.

Prompt

EXTRACT_SYSTEM_PROMPT now asks for one or two sentences: who did what, to whom or with what, and how it turned out. Every name and detail must come from the cited lines, the example has a single actor, people the action was done to stay out of actors, and the outcome line is cited as well. The reasons for each clause are in the code comment.

Validation (beat_service.validate_beats)

  • (a) Stamps inside a range line. A cited stamp inside a [start-end] line, or at its end, resolves to that line and is recorded as a repair. Before, it was rejected as "not in the transcript".
  • Credit from inside the cited exchange (CREDIT_ACTOR_INSIDE_CITED_SPAN, now on). An actor is credited from their own line when it sits inside a two-ended cited exchange of at most 120 s with nobody but the GM and the beat's own actors in it.
  • (b) The GM's neighbouring line (GM_NEIGHBOUR_SECONDS = 5, on). An event crediting the GM that cites only someone else's line is kept when the GM's line is within 5 s before or after that line, with nobody in between. This applies to the GM only, never a player.

Measured

On the synthetic fixtures, compared with the current prompt: beat validation 0.840 → 0.928 and coverage 0.751 → 0.895 with v4 and the looser check, and attribution 0.515 → 0.798.

On the real Session 14 (read-only), v4 had about 60 story events against 36. (a) and (b) recovered 3 GM events and gave none to the wrong person. The look-forward adds two more of the remaining shapes. The eval history rows are in evals/results/history.jsonl.

The eval harness also gains --detail, which reports how specific the events are and where their names come from.

Tests

On docker-test, from a git archive:

  • 921 passed across the summarisation modules (test_beat_service, test_summarise_*, test_evals_*, and others).
  • ruff format and check are clean.
  • changelog.py check and the version sync are OK.
  • The CI stub eval is above every threshold (0.967 / 0.967 / 1.000 / 0.967).

New tests cover the look-forward in both directions: credited, someone in between, outside the window, and never for a player. They also cover the GM line that starts inside a cited player range.

No migration and no bot contract change.

🤖 Generated with Claude Code

Closes #1189. This is the owner's choice after the private Session 14 comparison: the v4 prompt with the looser checks. ## Prompt `EXTRACT_SYSTEM_PROMPT` now asks for one or two sentences: who did what, to whom or with what, and how it turned out. Every name and detail must come from the cited lines, the example has a single actor, people the action was done to stay out of `actors`, and the outcome line is cited as well. The reasons for each clause are in the code comment. ## Validation (`beat_service.validate_beats`) - **(a) Stamps inside a range line.** A cited stamp inside a `[start-end]` line, or at its end, resolves to that line and is recorded as a repair. Before, it was rejected as "not in the transcript". - **Credit from inside the cited exchange** (`CREDIT_ACTOR_INSIDE_CITED_SPAN`, now **on**). An actor is credited from their own line when it sits inside a two-ended cited exchange of at most 120 s with nobody but the GM and the beat's own actors in it. - **(b) The GM's neighbouring line** (`GM_NEIGHBOUR_SECONDS = 5`, **on**). An event crediting the GM that cites only someone else's line is kept when the GM's line is within 5 s before *or after* that line, with nobody in between. This applies to the GM only, never a player. ## Measured On the synthetic fixtures, compared with the current prompt: beat validation 0.840 → 0.928 and coverage 0.751 → 0.895 with v4 and the looser check, and attribution 0.515 → 0.798. On the real Session 14 (read-only), v4 had about 60 story events against 36. (a) and (b) recovered 3 GM events and gave none to the wrong person. The look-forward adds two more of the remaining shapes. The eval history rows are in `evals/results/history.jsonl`. The eval harness also gains `--detail`, which reports how specific the events are and where their names come from. ## Tests On docker-test, from a git archive: - 921 passed across the summarisation modules (`test_beat_service`, `test_summarise_*`, `test_evals_*`, and others). - ruff format and check are clean. - `changelog.py check` and the version sync are OK. - The CI stub eval is above every threshold (0.967 / 0.967 / 1.000 / 0.967). New tests cover the look-forward in both directions: credited, someone in between, outside the window, and never for a player. They also cover the GM line that starts inside a cited player range. No migration and no bot contract change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Adds `python -m evals --detail` (evals/detail.py): words per verified story
beat, and capitalised names in beat summaries sorted into cited lines /
elsewhere in transcript or legend / invented. Report only, no threshold. Also
written to --record lines as detail_* fields.

The extraction prompt is unchanged. Four wordings were measured live against
Gemma 4 26B (alias qwen3.5, llama.cpp at 10.3.0.28:8090), on the six synthetic
fixtures plus the synthetic session; history.jsonl carries every run
(git_sha 9b10a86 = current prompt, 9b10a86+1189-vN = the variants):

  v1  shape "<one or two sentences, plain past tense: who did what, to whom
      or with what, and how it turned out>" + a specifics rule with a
      two-actor placeholder example and "Keep one event per beat"
  v2  single-actor example; separate "one beat is one event" rule
  v3  v2 without that rule, plus "someone the action was done to or for is
      named in the summary, not added to 'actors'"
  v4  v3 plus "cite the outcome line as well as the actor's own line"

Every variant raised words per beat (10.8 -> 15-16) with no invented names
and precision unchanged, but every one also lowered beat validation (0.840,
flat across 4 baseline runs, -> 0.73-0.81) and coverage (0.724-0.771 ->
0.70-0.71), outside the baseline's spread. The model folds a GM's set-up and
outcome lines into the player's action and then cites the GM lines, so the
actor no longer spoke any cited line. Shipping that would trade lost events
for longer sentences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v5 = v4 without any request for the outcome: shape line "<one or two
sentences, plain past tense: who did what, and to whom or with what>", the
names-from-cited-lines rule, the one-actor example, and "someone the action
was done to or for is named in the summary, not added to 'actors'". v4's
"cite the outcome line as well" sentence dropped, since it only patched the
outcome merging.

Three live runs on Gemma 4 26B: beat validation 0.845 (current 0.840, flat),
no invented names, words per beat 10.9 -> 14.2, but coverage 0.717
[0.707-0.736] against the current prompt's [0.724-0.771]. Outside the
spread, so the extraction prompt stays as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The richer-beat prompt v4 cites the GM's set-up and outcome lines and not
the player's own line between them ("Astrid split the ooze" citing the GM's
00:01:05 and 00:01:58, Astrid's swing at 00:01:22 uncited), so the beat is
rejected for "did not speak any cited line" although actor and exchange are
right.

beat_service.CREDIT_ACTOR_INSIDE_CITED_SPAN (default False, so nothing
changes in production) credits such an actor when the beat cites at least
two real lines no more than CITED_SPAN_MAX_SECONDS (120) apart, the actor
spoke between them, and nobody but the GM and the beat's own actors spoke
between them. The actor's lines are added to the evidence and the credit is
recorded as a repair. No window around the citations: the line after a cited
GM outcome is where a bystander's reaction sits (Fenwick's "Nice work!").

Live, Gemma 4 26B (alias qwen3.5), 6 synthetic fixtures + Halloway Reach,
v4 prompt applied for the runs only (not committed), switch on, three runs,
recorded as 9b10a86+1189-v4-loose; current prompt re-run once as 9b10a86:

  v4-loose: coverage 0.895 [0.857-0.914], attribution 0.798 [0.774-0.838],
  chronology 0.849 [0.786-0.881], beat validation 0.928 [0.923-0.940],
  precision 1.000, words/beat 15.9, invented names 0, verified 59.7 [56-67]
  current recheck: 0.736 / 0.476 / 0.810 / 0.840 / 1.000, 11.1 words, 74

Rescued 8 beats a run (the ooze kill and the silver split, on the five
clean_run-transcript fixtures), every one attributed correctly; still
rejected 8.3 a run, all citing a single line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The v4 extraction prompt the owner chose after the Session 14 comparison
asks for who did what, to whom or with what, and how it turned out, taking
every detail from the cited lines.

Validation:
- a cited stamp inside a [start-end] line, or at its end, resolves to that
  line (a repair, not "not in the transcript");
- CREDIT_ACTOR_INSIDE_CITED_SPAN is on: an actor alone with the GM inside a
  cited two-ended exchange is credited from their own line;
- GM_NEIGHBOUR_SECONDS = 5: an event crediting the GM that cites only
  someone else's line is kept when the GM's line is within five seconds
  before or after it, with nobody in between. GM only.

The eval history records the runs behind the choice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests: the range test pins (a) alone; the GM neighbour credits the line inside the range (#1189)
All checks were successful
CI / Backend lint (ruff) (pull_request) Successful in 27s
CI / Does this change touch the recording path? (pull_request) Successful in 31s
CI / Which journeys does this change need? (pull_request) Successful in 31s
CI / Docker image build (pull_request) Successful in 35s
CI / Feedback site tests (pull_request) Successful in 46s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 55s
CI / Bot/backend version sync (pull_request) Successful in 58s
CI / Bot tests and audit (pull_request) Successful in 2m5s
CI / Frontend (shard 2/2) (pull_request) Successful in 7m14s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 8m23s
CI / Frontend (shard 1/2) (pull_request) Successful in 16m2s
CI / End-to-end journeys (desktop) (desktop) (pull_request) Successful in 16m56s
CI / Backend migration, tests, and audit (pull_request) Successful in 29m6s
bab22928a0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude-bot deleted branch fix/1189-v4-prompt 2026-10-14 15:33:23 +00:00
Sign in to join this conversation.
No description provided.