Wiki link markup reads as words wherever a recap, note or card is drawn outside the wiki (#1135) #1136

Merged
claude-bot merged 19 commits from fix/1135-wiki-markup-as-text into main 2026-10-12 20:14:22 +00:00
Collaborator

Fixes #1135. The owner saw "…under The sea wall ended at the gate the The Tidewatch Ledger calls the first…" on This week → Previously on, on dev (rc11).

Cause

A summary, a note or a page's fact can carry wiki links ([[T]], [[T|shown]], [[T#Section|shown]]). Only the wiki article rendered them; every other place drew the raw text, in the app and in what leaves it.

What changes

  • One helper per side, built on the existing parsers and held to one shared case file (backend/app/sheets/conformance/wiki_plain/cases.json): wiki_links.plain_text and wiki/plainWikiText.js. [[T|shown]] → shown; [[T]] and [[T#Section]] → T; an image embed → nothing; an escaped \[[x]] → [[x]]; a ::: marker line is dropped. Everything else is left as written. It is not a projection: it decides nothing about who may read a block.
  • Server, stripped before any cut (so a truncation never leaves half a link): the cold open (This week's and the session page's "Previously on", the table's recap for the GM and the players, Prep's "where we left"), Home's and This week's "Last time", the Sessions list's recap line, storyline timeline lines, shelf and table card summaries, session/wiki/rules search excerpts and the campaign search snippet.
  • Outbound: the session_summary_approved event (the Discord post), /recap and /history, the final reminder's recap excerpt, the recap email, and the calendar feed's description. Content only: no /api/bot/* shape changes, no BOT_CONTRACT_VERSION bump.
  • Frontend, at display: the Read tab's summary, Review's summary plate (the editor still shows the markup), the read-only notes fold, Storyline chapters, card faces (cards already on a shelf keep their stored text and are stripped when drawn), the Find preview, and the article's margin Facts.
  • A crash fixed on the way (found by a review of this branch): the inline parser used private-use characters as placeholders and dereferenced an atom that did not exist when a member had typed one of those characters, which threw while rendering, in the wiki article renderer too. Typed private-use characters are now kept as text.

Checked and left alone

  • A :::gm block inside a summary, note or fact: these texts are never block text; the server does not parse blocks in them and nothing projects them, so there is no GM-only content to leak through them. A card's face comes from wiki_text.table_view, never a block. The Find preview draws the GM's own view to the GM only.
  • Not affected: the summary Versions list, the event log, highlights, the bell, the wiki feed and "Mentioned in" (titles only), editors.
  • Not audited: exports and print views.

Checks

  • Backend on the dev server: 1,069 tests passed across the new tests and every file matching summary, shelf, discord, notifications, wiki links, search, home, calendar, recap, bot, sessions, email, timeline, reminder and prep. Ruff: clean.
  • Frontend: eslint 0 errors; full vitest run 3,982 passed.
  • scripts/changelog.py check, scripts/check_version_sync.py: OK.
  • Not run locally: the journeys. e2e/identities.json's past recap now carries a link and j6-what-happened.spec.js asserts that This week and the Read tab contain no [[; CI is its first run.

Whether a recap's links should become real links is Q173 for the owner, not part of this.

🤖 Generated with Claude Code

Fixes #1135. The owner saw "…under [[The sea wall|the sea wall]] ended at the gate the [[The Tidewatch Ledger|ledger]] calls the first…" on This week → Previously on, on dev (rc11). ## Cause A summary, a note or a page's fact can carry wiki links (`[[T]]`, `[[T|shown]]`, `[[T#Section|shown]]`). Only the wiki article rendered them; every other place drew the raw text, in the app and in what leaves it. ## What changes - **One helper per side**, built on the existing parsers and held to one shared case file (`backend/app/sheets/conformance/wiki_plain/cases.json`): `wiki_links.plain_text` and `wiki/plainWikiText.js`. `[[T|shown]]` → `shown`; `[[T]]` and `[[T#Section]]` → `T`; an image embed → nothing; an escaped `\[[x]]` → `[[x]]`; a `:::` marker line is dropped. Everything else is left as written. It is not a projection: it decides nothing about who may read a block. - **Server, stripped before any cut** (so a truncation never leaves half a link): the cold open (This week's and the session page's "Previously on", the table's recap for the GM and the players, Prep's "where we left"), Home's and This week's "Last time", the Sessions list's recap line, storyline timeline lines, shelf and table card summaries, session/wiki/rules search excerpts and the campaign search snippet. - **Outbound:** the `session_summary_approved` event (the Discord post), `/recap` and `/history`, the final reminder's recap excerpt, the recap email, and the calendar feed's description. Content only: no `/api/bot/*` shape changes, no `BOT_CONTRACT_VERSION` bump. - **Frontend, at display:** the Read tab's summary, Review's summary plate (the editor still shows the markup), the read-only notes fold, Storyline chapters, card faces (cards already on a shelf keep their stored text and are stripped when drawn), the Find preview, and the article's margin Facts. - **A crash fixed on the way** (found by a review of this branch): the inline parser used private-use characters as placeholders and dereferenced an atom that did not exist when a member had typed one of those characters, which threw while rendering, in the wiki article renderer too. Typed private-use characters are now kept as text. ## Checked and left alone - A `:::gm` block inside a summary, note or fact: these texts are never block text; the server does not parse blocks in them and nothing projects them, so there is no GM-only content to leak through them. A card's face comes from `wiki_text.table_view`, never a block. The Find preview draws the GM's own view to the GM only. - Not affected: the summary Versions list, the event log, highlights, the bell, the wiki feed and "Mentioned in" (titles only), editors. - **Not audited: exports and print views.** ## Checks - Backend on the dev server: 1,069 tests passed across the new tests and every file matching summary, shelf, discord, notifications, wiki links, search, home, calendar, recap, bot, sessions, email, timeline, reminder and prep. Ruff: clean. - Frontend: eslint 0 errors; full `vitest run` 3,982 passed. - `scripts/changelog.py check`, `scripts/check_version_sync.py`: OK. - **Not run locally:** the journeys. `e2e/identities.json`'s past recap now carries a link and `j6-what-happened.spec.js` asserts that This week and the Read tab contain no `[[`; CI is its first run. Whether a recap's links should become real links is Q173 for the owner, not part of this. 🤖 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>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
style: ruff format (#1135)
All checks were successful
CI / Does this change touch the recording path? (pull_request) Successful in 22s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 1m8s
CI / Backend lint (ruff) (pull_request) Successful in 1m11s
CI / Feedback site tests (pull_request) Successful in 1m28s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m42s
CI / Bot tests and audit (pull_request) Successful in 2m38s
CI / Docker image build (pull_request) Successful in 3m32s
CI / Frontend (shard 2/2) (pull_request) Successful in 16m14s
CI / Frontend (shard 1/2) (pull_request) Successful in 19m53s
CI / End-to-end journeys (phone) (pull_request) Successful in 22m20s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 25m20s
CI / End-to-end journeys (desktop) (pull_request) Successful in 25m44s
CI / Backend migration, tests, and audit (pull_request) Successful in 33m44s
730ad0ff9a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also: Home's star-and-wish hint reads just "Optional." (#1122).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test: import expect in the inert helper (#1135)
Some checks failed
CI / Does this change touch the recording path? (pull_request) Successful in 23s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 32s
CI / Backend lint (ruff) (pull_request) Successful in 35s
CI / Feedback site tests (pull_request) Successful in 47s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m55s
CI / Bot tests and audit (pull_request) Successful in 2m0s
CI / Docker image build (pull_request) Successful in 4m59s
CI / End-to-end journeys (keyboard) (pull_request) Has been cancelled
CI / Frontend (shard 2/2) (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
CI / End-to-end journeys (desktop) (pull_request) Has been cancelled
CI / End-to-end journeys (phone) (pull_request) Has been cancelled
CI / Frontend (shard 1/2) (pull_request) Has been cancelled
69c8150fe5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix: wrap link rows in VisibleLink; Home hint reads just Optional.; player-surface tests (#1135)
Some checks failed
CI / Does this change touch the recording path? (pull_request) Successful in 17s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 25s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Feedback site tests (pull_request) Successful in 48s
CI / Docker image build (pull_request) Successful in 52s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m3s
CI / Bot tests and audit (pull_request) Successful in 1m57s
CI / End-to-end journeys (phone) (pull_request) Successful in 12m4s
CI / Frontend (shard 1/2) (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
CI / End-to-end journeys (keyboard) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop) (pull_request) Has been cancelled
CI / Frontend (shard 2/2) (pull_request) Has been cancelled
1aec79a777
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge main into fix/1135-wiki-markup-as-text
Some checks failed
CI / Does this change touch the recording path? (pull_request) Successful in 27s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 36s
CI / Backend lint (ruff) (pull_request) Successful in 42s
CI / Feedback site tests (pull_request) Successful in 56s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m32s
CI / Docker image build (pull_request) Successful in 2m29s
CI / Bot tests and audit (pull_request) Successful in 4m9s
CI / Frontend (shard 1/2) (pull_request) Successful in 10m25s
CI / End-to-end journeys (phone) (pull_request) Successful in 10m43s
CI / Frontend (shard 2/2) (pull_request) Successful in 16m3s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 20m47s
CI / End-to-end journeys (desktop) (pull_request) Successful in 20m52s
CI / Backend migration, tests, and audit (pull_request) Failing after 26m4s
713cccd06c
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test(wiki): the storyline's own text is not a page's (#1135)
Some checks failed
CI / Does this change touch the recording path? (pull_request) Successful in 21s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 31s
CI / Docker image build (pull_request) Successful in 49s
CI / Backend lint (ruff) (pull_request) Successful in 1m14s
CI / Feedback site tests (pull_request) Successful in 1m52s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m9s
CI / Bot tests and audit (pull_request) Successful in 3m10s
CI / End-to-end journeys (phone) (pull_request) Successful in 11m48s
CI / Frontend (shard 2/2) (pull_request) Successful in 13m40s
CI / End-to-end journeys (desktop) (pull_request) Successful in 13m3s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 13m5s
CI / Frontend (shard 1/2) (pull_request) Successful in 16m41s
CI / Backend migration, tests, and audit (pull_request) Failing after 35m51s
00d19b7679
The storyline routes now read storyline.body to resolve its wiki links for
the reader; the body-reads guard lists them as not a wiki page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test(wiki): a parsed link's target is not a page's title (#1135)
Some checks failed
CI / Bot/backend version sync (pull_request) Successful in 31s
CI / Does this change touch the recording path? (pull_request) Successful in 33s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Backend lint (ruff) (pull_request) Successful in 36s
CI / Docker image build (pull_request) Successful in 40s
CI / Feedback site tests (pull_request) Successful in 49s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m2s
CI / Bot tests and audit (pull_request) Successful in 2m2s
CI / End-to-end journeys (keyboard) (pull_request) Failing after 2m56s
CI / End-to-end journeys (phone) (pull_request) Failing after 2m56s
CI / Frontend (shard 2/2) (pull_request) Successful in 19m0s
CI / Frontend (shard 1/2) (pull_request) Successful in 23m28s
CI / End-to-end journeys (desktop) (pull_request) Successful in 27m5s
CI / Backend migration, tests, and audit (pull_request) Successful in 41m46s
ffa6aa504b
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge main into fix/1135-wiki-markup-as-text
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m11s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Does this change touch the recording path? (pull_request) Successful in 27s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot/backend version sync (pull_request) Successful in 33s
CI / Feedback site tests (pull_request) Successful in 43s
CI / Bot tests and audit (pull_request) Successful in 1m58s
CI / Docker image build (pull_request) Successful in 3m34s
CI / Frontend (shard 2/2) (pull_request) Successful in 15m26s
CI / End-to-end journeys (phone) (pull_request) Successful in 10m42s
CI / Frontend (shard 1/2) (pull_request) Successful in 19m43s
CI / End-to-end journeys (desktop) (pull_request) Successful in 24m15s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 24m22s
CI / Backend migration, tests, and audit (pull_request) Successful in 55m8s
b3960ff5fe
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.