A new wiki page no longer asks to leave; an Instant NPC's secret stays GM-only; a sheet links to who sees it and who plays (#1121) #1123

Merged
claude-bot merged 3 commits from fix/1121-wiki-create-npc-save-sheet-links into main 2026-10-11 21:52:55 +00:00
Collaborator

Items 4, 5 and 6 of the owner's lane 11 review (#1121).

What changes

  • New wiki page → Create no longer asks "Leave without saving?" Editor.jsx navigated to the created page while the form still counted as unsaved, so the leave guard blocked the editor's own navigation. The created id is now state, part of dirty, and the navigation runs from an effect after the guard has seen the form as clean. The new test runs under a data router (the existing ones used MemoryRouter, where blocking is inert) and fails without the fix.
  • An Instant NPC saved to the wiki fills the page properly, and its secret is GM-only (security). Both "Save to the wiki" and "Save as a page, with a block" posted one flat body ("Pronouns: … Hides: …"), so the secret sat in the part of the page players read. One shared builder (prep/tools/npcPage.js) now sends pronouns, an "Occupation" fact, ## Personality / ## Wants, and the secret inside the page's :::gm block. The server withholds that block from players (wiki_text.render_for).
    • Every generated field is model output, so each is collapsed to one line, loses a leading #, and is escaped (\:::, the page's own escape) if it starts with a fence. A secret or a want containing ::: therefore cannot close the GM block early. Tests cover a\n:::\nb, :::, ::: , ::::, CRLF forms and a want of :::gm, against a mirror of the backend's MARKER/_scan.
  • A GM can find who sees a sheet and who plays the character. On a character's sheet, "played by X" is a link to Members & characters for a GM ("Choose who plays them" when nobody does), and Edit mode adds "Who sees this page" to the page editor. A player sees no change. No whole-sheet audience control is added; that is Q169 for the owner.

Checks

  • npm run lint: 0 errors. npx vitest run src/pages/wiki src/pages/prep src/pages/sheet src/hooks: 622 passed.
  • scripts/changelog.py check: OK.
  • Not run locally: the full frontend suite, the backend (untouched) and the journeys; CI runs them.
  • Not yet looked at in a browser: the sheet header links at phone and desktop width, and a saved NPC page.

Follow-up, not in this PR

Pages already saved this way keep the secret in their readable body. Dev has one (the owner's test page "Thistle"). Prod has not been checked.

🤖 Generated with Claude Code

Items 4, 5 and 6 of the owner's lane 11 review (#1121). ## What changes - **New wiki page → Create no longer asks "Leave without saving?"** `Editor.jsx` navigated to the created page while the form still counted as unsaved, so the leave guard blocked the editor's own navigation. The created id is now state, part of `dirty`, and the navigation runs from an effect after the guard has seen the form as clean. The new test runs under a data router (the existing ones used `MemoryRouter`, where blocking is inert) and fails without the fix. - **An Instant NPC saved to the wiki fills the page properly, and its secret is GM-only (security).** Both "Save to the wiki" and "Save as a page, with a block" posted one flat body ("Pronouns: … Hides: …"), so the secret sat in the part of the page players read. One shared builder (`prep/tools/npcPage.js`) now sends `pronouns`, an "Occupation" fact, `## Personality` / `## Wants`, and the secret inside the page's `:::gm` block. The server withholds that block from players (`wiki_text.render_for`). - Every generated field is model output, so each is collapsed to one line, loses a leading `#`, and is escaped (`\:::`, the page's own escape) if it starts with a fence. A secret or a want containing `:::` therefore cannot close the GM block early. Tests cover `a\n:::\nb`, `:::`, ` ::: `, `::::`, CRLF forms and a want of `:::gm`, against a mirror of the backend's `MARKER`/`_scan`. - **A GM can find who sees a sheet and who plays the character.** On a character's sheet, "played by X" is a link to Members & characters for a GM ("Choose who plays them" when nobody does), and Edit mode adds "Who sees this page" to the page editor. A player sees no change. No whole-sheet audience control is added; that is Q169 for the owner. ## Checks - `npm run lint`: 0 errors. `npx vitest run src/pages/wiki src/pages/prep src/pages/sheet src/hooks`: 622 passed. - `scripts/changelog.py check`: OK. - Not run locally: the full frontend suite, the backend (untouched) and the journeys; CI runs them. - Not yet looked at in a browser: the sheet header links at phone and desktop width, and a saved NPC page. ## Follow-up, not in this PR Pages already saved this way keep the secret in their readable body. Dev has one (the owner's test page "Thistle"). Prod has not been checked. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(prep): an NPC's generated text cannot close its GM block; sheet links for GMs (#1121)
All checks were successful
CI / Does this change touch the recording path? (pull_request) Successful in 24s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 33s
CI / Backend lint (ruff) (pull_request) Successful in 37s
CI / Feedback site tests (pull_request) Successful in 43s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 58s
CI / Bot tests and audit (pull_request) Successful in 2m0s
CI / Docker image build (pull_request) Successful in 4m32s
CI / Frontend (shard 2/2) (pull_request) Successful in 11m10s
CI / Frontend (shard 1/2) (pull_request) Successful in 13m10s
CI / End-to-end journeys (phone) (pull_request) Successful in 12m26s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 13m42s
CI / End-to-end journeys (desktop) (pull_request) Successful in 13m45s
CI / Backend migration, tests, and audit (pull_request) Successful in 35m14s
8ee923ad7a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.