A model is shown an unidentified item's party name, and a proposal about one finds its page (#993) #1003

Merged
claude-bot merged 2 commits from fix/993-unidentified-prompts into main 2026-10-01 20:17:08 +00:00
Collaborator

Closes #993. The two follow-ups from #877's audit.

1. Prompts a GM reviews no longer carry the true name

  • Draft tools (run_lore_entry_draft_generation: rephrase, expand, promote, stat block, convert, merge): the model is shown the table's name for an unidentified page. draft.current_title keeps the true title, so the GM's review and the approval's write-back are unchanged.
  • Relationship proposals: the page list's Title: line uses the table's name. Ids are unchanged.

The output of these waits for a GM, so this was never a leak by itself; it stops the model writing a true name into text meant for the table where a GM might miss it.

2. A proposal about an unidentified item updates its page

The model is shown "A tarnished silver ring", but proposals were matched to pages by true title and aliases only, so such a proposal arrived as a new page.

  • Matching is in two passes. True titles and aliases first, exactly as before. Only if nothing matches, the table's name of unidentified pages.
  • Two pages with the same party name ("A dusty potion") match nothing, and the proposal is offered as a new page. A wrong guess would update the wrong item. The model can still name a page by id.
  • An approval never writes the party's name over the page's title and never identifies the page: title_to_write() keeps the page's own title when the proposal is named by the party's name. A merge draft uses it too.

Guard

tests/wiki/test_title_readers.py's entries are updated with true reasons for each read that moved (_entry_name_keys, title_to_write, start_merge_draft), and the relationship prompt's raw read is gone from the list.

Checked

  • New tests/wiki/test_unidentified_prompts.py (11 tests): each prompt shows the party's name and not the true one; an identified page is unchanged; approving leaves title, player_title and identified_at alone; the ambiguous case; a true title wins over another page's party name.
  • Not exercised with an unidentified page: the stat block and convert modes, which read the same variable.
  • Full backend suite: 6602 passed, 14 skipped. After merging main: tests/export and tests/wiki, 607 passed.
  • ruff 0.4.4 format and check clean; changelog check OK (a security fragment).
  • No migration, no bot API change.

🤖 Generated with Claude Code

Closes #993. The two follow-ups from #877's audit. ## 1. Prompts a GM reviews no longer carry the true name - **Draft tools** (`run_lore_entry_draft_generation`: rephrase, expand, promote, stat block, convert, merge): the model is shown the table's name for an unidentified page. `draft.current_title` keeps the true title, so the GM's review and the approval's write-back are unchanged. - **Relationship proposals**: the page list's `Title:` line uses the table's name. Ids are unchanged. The output of these waits for a GM, so this was never a leak by itself; it stops the model writing a true name into text meant for the table where a GM might miss it. ## 2. A proposal about an unidentified item updates its page The model is shown "A tarnished silver ring", but proposals were matched to pages by true title and aliases only, so such a proposal arrived as a new page. - Matching is in two passes. True titles and aliases first, exactly as before. Only if nothing matches, the table's name of unidentified pages. - **Two pages with the same party name ("A dusty potion") match nothing**, and the proposal is offered as a new page. A wrong guess would update the wrong item. The model can still name a page by id. - An approval never writes the party's name over the page's title and never identifies the page: `title_to_write()` keeps the page's own title when the proposal is named by the party's name. A merge draft uses it too. ## Guard `tests/wiki/test_title_readers.py`'s entries are updated with true reasons for each read that moved (`_entry_name_keys`, `title_to_write`, `start_merge_draft`), and the relationship prompt's raw read is gone from the list. ## Checked - New `tests/wiki/test_unidentified_prompts.py` (11 tests): each prompt shows the party's name and not the true one; an identified page is unchanged; approving leaves `title`, `player_title` and `identified_at` alone; the ambiguous case; a true title wins over another page's party name. - Not exercised with an unidentified page: the stat block and convert modes, which read the same variable. - Full backend suite: 6602 passed, 14 skipped. After merging main: `tests/export` and `tests/wiki`, 607 passed. - ruff 0.4.4 format and check clean; changelog check OK (a `security` fragment). - No migration, no bot API change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into fix/993-unidentified-prompts
All checks were successful
CI / Backend lint (ruff) (pull_request) Successful in 1m4s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m18s
CI / Feedback site tests (pull_request) Successful in 1m0s
CI / Docker image build (pull_request) Successful in 26s
CI / Bot/backend version sync (pull_request) Successful in 1m0s
CI / Does this change touch the recording path? (pull_request) Successful in 43s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot tests and audit (pull_request) Successful in 2m29s
CI / Frontend (shard 2/2) (pull_request) Successful in 8m46s
CI / Frontend (shard 1/2) (pull_request) Successful in 11m9s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 11m6s
CI / End-to-end journeys (desktop) (pull_request) Successful in 11m12s
CI / End-to-end journeys (phone) (pull_request) Successful in 17m32s
CI / Backend migration, tests, and audit (pull_request) Successful in 50m40s
d53ed19056
Sign in to join this conversation.
No description provided.