feat(webapp): the party, items, reputation and downtime (lane 8 PR 3) — stacked on #874 #878

Merged
claude-bot merged 18 commits from build/lane8-3-parties into main 2026-09-28 00:19:34 +00:00
Collaborator

Lane 8 (#734), PR 3. Stacked on #874 (lane 8 PR 2a). It covers D168 (W4), D198 (W12), D234 (W16), D233, D165 and D166.

What's built

  • The party audience (D168). "The party" always names one party, and existing party audiences become the main party. The audience test that checks Python, members and SQL agree now covers two parties. With one party, behaviour is exactly as before. :::party <name> blocks now resolve.
  • Parties and membership (/api/campaigns/{cid}/parties): membership is recorded as spans, joined and left at a session, with a reason for each. Swapping characters is recorded in the same way. Every campaign gets a main party.
  • Items:
    • holders: the pool, a character, an NPC or a place;
    • custody, where "found" and "given" are recorded automatically;
    • per-reader responses: a hidden holder reads as "held by someone".
    • Unidentified items (IS-122): players see the player title everywhere the wiki shows the item, including the AI and transcriber feeds. The remaining non-wiki title reads are tracked in #877.
  • XP and gold by character (D198): old rows move to the character played at that session. Old requests still work, and each total gains a per-character breakdown. XP, gold and loot can be removed and restored.
  • Reputation: changes against a session, shown to everyone, a party or GMs only.
  • Downtime: a player logs it for their own character, and the GM approves it.
  • W16 (D234): anyone who may edit a page directly can upload or remove its picture. Under "suggest" they get none, and pictures from a web address stay GM-only.

Migration 8d4e5f6a7b8c (on 8b2c)

The data step:

  • creates each campaign's main party;
  • places every character in it, with join and leave sessions;
  • moves loot, XP and gold to characters;
  • adds a "found" custody row for every item.

It's idempotent. On the demo seed, "the party" reaches the same readers before and after, and down then up gives the same result.

Tests

  • New: test_parties_api (18), test_parties_migration, test_wiki_pictures (5), and 4 two-party audience tests.
  • Extended: the crawl now covers a second party, an unidentified item's true name, a GM-only holder, reputation and downtime.
  • Full backend suite: 5,579 passed, 1 failed (test_discussions_no_ai). It's fixed, and the affected tests pass (37).
  • ruff is clean; the version and changelog checks pass.

For the owner

There are eight small choices, on the questions page:

  • where an item goes when its holder has no character;
  • the main-party fallback;
  • who can see reputation;
  • that everyone reads downtime;
  • the downtime budget waits for #126;
  • deleting a party;
  • export coverage;
  • what a swap does.

🤖 Generated with Claude Code

Lane 8 (#734), PR 3. **Stacked on #874** (lane 8 PR 2a). It covers D168 (W4), D198 (W12), D234 (W16), D233, D165 and D166. ## What's built - **The party audience (D168).** "The party" always names one party, and existing party audiences become the main party. The audience test that checks Python, members and SQL agree now covers **two parties**. With one party, behaviour is exactly as before. `:::party <name>` blocks now resolve. - **Parties and membership** (`/api/campaigns/{cid}/parties`): membership is recorded as spans, joined and left at a session, with a reason for each. Swapping characters is recorded in the same way. Every campaign gets a main party. - **Items:** - holders: the pool, a character, an NPC or a place; - custody, where "found" and "given" are recorded automatically; - per-reader responses: a hidden holder reads as "held by someone". - **Unidentified items (IS-122):** players see the player title everywhere the wiki shows the item, including the AI and transcriber feeds. The remaining non-wiki title reads are tracked in #877. - **XP and gold by character (D198):** old rows move to the character played at that session. Old requests still work, and each total gains a per-character breakdown. XP, gold and loot can be removed and restored. - **Reputation:** changes against a session, shown to everyone, a party or GMs only. - **Downtime:** a player logs it for their own character, and the GM approves it. - **W16 (D234):** anyone who may edit a page directly can upload or remove its picture. Under "suggest" they get none, and pictures from a web address stay GM-only. ## Migration `8d4e5f6a7b8c` (on `8b2c`) The data step: - creates each campaign's main party; - places every character in it, with join and leave sessions; - moves loot, XP and gold to characters; - adds a "found" custody row for every item. It's idempotent. On the demo seed, "the party" reaches the same readers before and after, and down then up gives the same result. ## Tests - **New:** `test_parties_api` (18), `test_parties_migration`, `test_wiki_pictures` (5), and 4 two-party audience tests. - **Extended:** the crawl now covers a second party, an unidentified item's true name, a GM-only holder, reputation and downtime. - **Full backend suite:** 5,579 passed, 1 failed (`test_discussions_no_ai`). It's fixed, and the affected tests pass (37). - ruff is clean; the version and changelog checks pass. ## For the owner There are eight small choices, on the questions page: - where an item goes when its holder has no character; - the main-party fallback; - who can see reputation; - that everyone reads downtime; - the downtime budget waits for #126; - deleting a party; - export coverage; - what a swap does. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
WIP milestone: the five discussion tables (model + migration 7d15c0a1b2e3)
and app/services/audience_service.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Written before the router; they fail until it lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIP milestone: the endpoints, before the first green run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The audience service (app/services/audience_service.py) is #593's one
definition of who can see a thing: table, party, mine, chosen people and
characters, or GMs only, every GM always inside, resolved when read. It
answers for one reader, for everyone, and as a SQL predicate; a test holds
the three equal. Lanes 8 and 11 reuse it.

Discussions (migration 7d15c0a1b2e3, five tables) with the board, starting,
reading and replying, GM notes for fewer people (refused when they reach
outside the thread, IS-145; thread and post audiences intersected on every
read), answers, verdicts, audience changes with a gains/losses preview,
follows, read markers, lock, soft delete with restore, post edit/hide/delete
(T9(a)) and the Talk counts. A thread or post a reader can't see is a 404
identical to a missing one. A crawl walks every endpoint as every kind of
reader and finds nothing leaked; a test pins which modules may read the
tables (never AI context, #654).

The one-head pin moves to test_discussions_migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The migrations chain d4e6f8a0b2c3 -> 7e5afe7a1b2c -> 7d15c0a1b2e3: the
discussions migration is re-chained onto the safety one, and the one-head
pin moves to test_discussions_migration. CHANGELOG and docs/API.md keep
both sides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Written before the code; they fail until it lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIP milestone before the first run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also: talk-counts' safety_waiting in PR 1's count test, and viewers_for held
equal to Roster.viewer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
The page at /campaigns/:id/safety (CAMP-18): lines and veils for everyone;
for a GM, Edit, Remove with Undo (D12), "+ Add", and the waiting queue with
Add as a veil / Add as a line (in the GM's wording) and Dismiss. A player gets
the anonymous suggest card with the drawn words (T3(a)) and every GM named
(T10(a)), and IS-017's Sent card.

The flag dialog, "Flag something to Dana", behind four doors: This week's
card (IS-205, about no session), the foot of a live or played session's page
(T2(a), IS-210), and Table mode's players' face ("Flag something quietly").
The GM's Table-mode face gets the quiet "N waiting in Table rules & safety"
in its place, polled from GET …/safety/waiting (T4(a)).

The Contents gains the Table rules & safety entry, with the GM's count
(IS-204, IS-212); a player is never asked for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The flag's wrapper on Table mode's players' face carried .qb's paper, which
drew a strip across the old face's own background in both themes (found by
the render check). CHANGELOG bullets for Table rules & safety and its doors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The kit's "who can see this": AudiencePill, AudienceMenu and
  AudienceControl beside the chip row, with the drawn words, T10(a)'s
  naming of every GM, a Players | Characters switch and a checklist, and a
  keyboard-operable dialog that traps focus.
- The Discussions board (CAMP-19) with its filters as the address and
  T12(a)'s sentence only while empty; starting a thread (all three kinds,
  About search, a rumour's quest); a thread (CAMP-20) with answers,
  verdicts, notes for fewer people with IS-145's refusal said before
  posting, follow, moderation, widen/narrow, delete with Undo, and canon.
- Talk on every session that is not cancelled (T1(a)) and on an article,
  with the article's Read · Talk · History bar on today's page (T8(a)).
- The Contents' Discussions entry with its unread count (IS-157), Home's
  Needs you rows (IS-152), and the bell's four discussion kinds and
  safety_waiting, with a test that every server kind has an entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The reply box is the drawing's: a placeholder, not a label above it;
  a refused note stops the button without saying the refusal twice.
- A thread's title at the drawing's h2 step, so a question fits a phone.
- The article's tab bar without the band `.qb` painted on the old page;
  the Talk page and the new-thread form read the article from `entry`.
- A question's Needs you row says its day, not a table time.
- The picker is taller than a plain menu, so its people fit.
- The leave-guard list and a player's Read tabs now include lane 7's.
- CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-chains 7d15c0a1b2e3 (discussions) onto e5f7a9b1c3d4 (lane 5 PR 4b's
scene-text drop), which reached main first; 7f2d0c1a3b4e stays on top of it
and keeps the one-head pin. test_drop_scene_text_migration's pin becomes a
still-in-the-chain one, and test_notifications' history names both moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CHANGELOG: kept main's Table-mode entries (lane 5's #832 had since redrawn
the players' face and added Start/Stop to the bar) under A's new entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The players' flag door moves from SessionTable (deleted by lane 5's #832)
  onto the new players' face, PlayersTable: a block button at the foot of its
  one column, as lane4.html draws it, spaced by .tmp's own gap. The Players'
  view keeps it, being what players see. .qb-flag-table goes.
- The GM's waiting count sits at the foot of lane 5's aside, after the
  preview, "Shown to the table" and the quick note, where the drawing had
  "Flag something quietly".
- One read for the Contents count: the Table rules & safety entry takes
  talk.safety_waiting from the frame's …/talk-counts read (A's useTalkCounts),
  still gated on the viewer being a GM. useSafetyWaiting and its second
  request go; the Talk counts re-read after a write changesSafetyWaiting names.
  AppFrame.test's two safety-count tests now drive fetchTalkCounts, the
  player's with a number the server would never send.
- Notifications: the GM tasks row says "and Table rules & safety", since
  safety_waiting is filed there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Amberwake Accord talks: 15 threads and 51 posts across every kind,
state and audience — an open question with two replies the owner has not
read, an answer made canon into The Tidewatch Ledger, Dana's question to the
owner (Home's "A question for you"), rumours open, confirmed and denied,
threads about Sessions 23, 13 and 4 and two articles, a locked thread, a
deleted one, a hidden post, GM notes, and four threads the owner cannot see.
Follows, reads (the Contents says 2) and the bell's rows, written as rows.

Table rules & safety: the drawing's three lines and three veils, one line
removed, and three anonymous submissions waiting — day-only, no sender —
with Dana's one "Something is waiting" row.

The Tuesday Tide is left empty on purpose. test_demo_seed checks the counts,
the owner's view (11 of 15, 2 unread, the question in Needs you), Dana's
Needs you and waiting count, and that every seeded bell row renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
J2, at its lane 7 TODO: on the session she has just said yes to, Priya
opens Talk (T1(a)), starts a question that defaults to "Just you and Dana"
(asserted), walks the picker (a dialog; Escape hands focus back to the
pill) and asks. Dana is told in the bell, sees who can see it, replies; the
reply box names exactly that audience. Priya is told, marks the answer, and
the thread reads Answered. axe on the Talk tab, the form with the picker
open, the thread for both, and the bell with the new kind in it.

J2's safety block (#121), in a campaign of its own since the count is per
campaign: Priya suggests a veil with no name on it; Dana's Contents says
"Table rules & safety 1", the bell's generic row takes her to the queue, she
adds it as a veil in her own words, and Priya reads it.

J6's act 4: the board, the thread Priya asked about Session 2 and its Talk
tab, with a seeded GMs-only thread and GM note absent on the page and in the
API answers; and the table's line and veil. J5 and J6 expect a player's
Read and Talk tabs (IS-202) where they expected none.

The seed writes canon.talk through the product's API, and pencils Session 3
in, confirming it as its last act: J2 reads "Session 3 is on" among Priya's
twenty newest bell rows in the third project, and the question leg's reply
row per project had pushed it off (J4 met the same wall).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
J1 went straight from "Create the session" to the Contents' This week while
the session page was still arriving. In the keyboard project the Enter was
lost two runs in five once lane 7 gave that page one more request and its
Talk tab: focus ended on the session's heading, the address unchanged. It
now waits for the heading, as the rest of the suite waits for a page before
leaving it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Make it canon" on a party thread wrote the answer, unblocked, into a wiki
page the whole table reads, so members outside the party read it there
(found by the lane 8 survey). CANON_AUDIENCES is ("table",) until lane 8's
party and visibility blocks (IS-148) can carry the thread's audience into
the article; a party answer is now a 422, like a narrower one. The thread
page follows: no "Make it canon" on a party thread. Tests hold both sides;
API.md and the CHANGELOG say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge main (#833: J4 and lane 5's demo seed) into lane 7's integration (#733)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 52s
CI / Backend lint (ruff) (pull_request) Successful in 31s
CI / Feedback site tests (pull_request) Successful in 46s
CI / Bot/backend version sync (pull_request) Successful in 51s
CI / Bot tests and audit (pull_request) Successful in 2m4s
CI / Does this change touch the recording path? (pull_request) Successful in 37s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Docker image build (pull_request) Successful in 2m28s
CI / Backend migration, tests, and audit (pull_request) Successful in 15m15s
CI / Frontend tests, audit, and build (pull_request) Successful in 20m33s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 22m2s
e0ec155c4e
demo/engine.py: both lanes' calls, the rules pack before Session 24's shelf
(lane 5) and lane 7's talking and table rules after it. test_demo_seed: lane
7's discussion and safety checks and lane 5's _the_table_is_seeded, both.
demo/README.md: both lanes' "What it touches" bullets. The e2e seed,
identities.json and README merged cleanly: J4's campaign and Joaquín, and
Session 3 pencilled in and confirmed last, both kept. Preview.jsx takes
#833's `article.entry` fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Applies the owner's two lane 7 decisions on top of the built T10(a)/board work:

- D174 (T10(b)): every audience sentence that named a GM now says "the GM"
  (one) or "the GMs" (more than one) instead — the picker's labels and
  foot, the board's default-audience hint, a session note's readers, the
  Table rules & safety flag dialog and its "Not even ... can see who sent
  it" promise, and who may change the lists. A reader who is themself a
  GM still reads "you". Also fixes `rosterFromMembers`'s "party" sentence,
  which could name a GM as "everyone but <GM>" when they have no active
  character — GMs are now excluded from that count entirely.
- D176 (T12(a)): the Discussions board's opening sentence shows only while
  the board is completely empty, in place of the separate empty-state line
  (which is removed) rather than alongside it. A non-empty board shows
  neither.

Updates the J2 journey spec to the new wording, the CHANGELOG's lane 7
bullets, docs/API.md's Audience shape note, and the lane6 coverage
script's description text. Coverage script still prints "unclassified:
none".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(table): the safety waiting count under a phone GM's stage too (T15, #733)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m36s
CI / Bot tests and audit (pull_request) Successful in 5m3s
CI / Backend lint (ruff) (pull_request) Successful in 1m15s
CI / Bot/backend version sync (pull_request) Successful in 1m13s
CI / Feedback site tests (pull_request) Successful in 2m12s
CI / Does this change touch the recording path? (pull_request) Successful in 41s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Docker image build (pull_request) Successful in 1m19s
CI / Backend migration, tests, and audit (pull_request) Successful in 15m57s
CI / Frontend tests, audit, and build (pull_request) Successful in 20m35s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 20m28s
293ec95271
Addendum from the owner's answers to the lane 7 questions: T13 and T14 are
already built as recommended (verified, no change needed) — the private
question's bell line already says "you", never a GM's name, and the flag
doors on This week and a session's page are already player-only. T15 had a
real gap: the desktop aside's "N waiting in Table rules & safety" quiet
count (T4(a)) had no equivalent on a phone, since GmPhone has no aside to
put it in.

Reuses the existing WaitingCount component under the phone stage, with the
same words and the same nothing-when-none-wait rule as desktop. Two new
tests in TableMode.test.jsx cover it showing and staying silent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Conflicts, both sides kept: CHANGELOG; docs/API.md (Discussions beside
  Prep Sheets and Planning, and the contents); main.py (discussions, prep
  and planning routers); demo/engine.py (the discussions and prep/Planning
  seed methods); useContents.js (a session address takes talk and prep);
  leaveGuardCallers.test.js (NewThread and the prep sheet).
- 7d15c0a1b2e3 now revises d6f8b0c2e4a7 (it was on e5f7a9b1c3d4). The one-head
  pin returns to test_discussion_notifications_migration; lane 6's
  test_drop_generation_pinned_migration becomes "still in the chain", and
  test_drop_scene_text_migration keeps a2c4e6f8b0d1 as its successor.
- ck_notifications_kind / _subject_type: 7f2d0c1a3b4e was written on
  7e5afe7a1b2c's lists, so an upgrade would have dropped lane 9 A's
  server_ownership_offer and campaign_handed_on (and the server_ownership_offer
  subject type) from the CHECKs. Its _BEFORE lists are now f1a3c5e7b9d2's, so
  the CHECK is the union and the downgrade narrows to exactly f1a3's. The
  model's enum and SUBJECT_TYPES follow chain order; CATEGORY_FOR_KIND has
  every kind. test_server_owner_migration, test_safety_migration and
  test_notifications hold their lists as history; the discussions migration
  test checks a server-owner row survives its downgrade.
- Lane 7's 20 Depends(get_db) in discussions.py are scope="function". Lane 7
  adds no direct .delay()/.apply_async(): it notifies through main's
  notification_service.notify, which already goes off-loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge train/3-858 into lane 7 (#846): the retention test's media fix
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 59s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Feedback site tests (pull_request) Successful in 45s
CI / Bot/backend version sync (pull_request) Successful in 28s
CI / Bot tests and audit (pull_request) Successful in 2m5s
CI / Docker image build (pull_request) Successful in 34s
CI / Does this change touch the recording path? (pull_request) Successful in 29s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
CI / Frontend tests, audit, and build (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
4ed619bc14
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge branch 'train/3-858' into train/4-846
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m17s
CI / Bot tests and audit (pull_request) Successful in 4m9s
CI / Backend lint (ruff) (pull_request) Successful in 1m14s
CI / Bot/backend version sync (pull_request) Successful in 28s
CI / Docker image build (pull_request) Successful in 22s
CI / Feedback site tests (pull_request) Successful in 1m50s
CI / Does this change touch the recording path? (pull_request) Successful in 28s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
CI / Frontend tests, audit, and build (pull_request) Has been cancelled
846b997e71
Merge branch 'train/3-858' into train/4-846
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 59s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Feedback site tests (pull_request) Successful in 44s
CI / Bot/backend version sync (pull_request) Successful in 30s
CI / Docker image build (pull_request) Successful in 31s
CI / Does this change touch the recording path? (pull_request) Successful in 24s
CI / Bot tests and audit (pull_request) Successful in 5m21s
CI / Backend migration, tests, and audit (pull_request) Successful in 16m36s
CI / Frontend tests, audit, and build (pull_request) Failing after 20m50s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
183b8d9cb5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backend's recording_tests table, endpoints, handoff route,
process_recording_test and sweep, with their tests; the bot's /record/test,
tests/ capture directory, test status and handoff, not yet tested. The bot's
tests and the changelog follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
app/services/wiki_text.py parses :::gm, :::for <characters, @players>
and :::party blocks, renders a text for one reader (every block they are
outside removed without a trace), and merges a writer's edit of their
view back without ever losing, moving into view, or re-scoping a block
they couldn't see. Reading fails closed; writing is strict, with a line
number on every refusal. Example tests plus a seeded fuzzer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bot's half is tested: /record/test announces "Recording a test" before
it captures (and records anyway if the post fails, D171), captures with the
same sink into audio_temp/tests/{id}/ with absolute placement intact, hands
over through POST /api/bot/recording-tests/{id}/audio, deletes the audio if
the handoff does not land (D150), and crash recovery and the startup sweep
never take tests/ for a session. The session page's SSE keys a test's
"other" by its own id. API.md documents the routes; the changelog says it.

Closes #824.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: CLAUDE.md's recording architecture names the test path (D124)
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m43s
CI / Backend lint (ruff) (pull_request) Successful in 35s
CI / Feedback site tests (pull_request) Successful in 48s
CI / Bot/backend version sync (pull_request) Successful in 30s
CI / Docker image build (pull_request) Successful in 38s
CI / Does this change touch the recording path? (pull_request) Successful in 34s
CI / Bot tests and audit (pull_request) Successful in 5m12s
CI / Backend migration, tests, and audit (pull_request) Successful in 14m32s
CI / Frontend tests, audit, and build (pull_request) Successful in 18m34s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 12m56s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
5e8d2485cc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat: notifications out — DMs, the GM's warnings, email that reaches people (#736, lane 10 PR 2)
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m26s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Bot/backend version sync (pull_request) Successful in 27s
CI / Bot tests and audit (pull_request) Successful in 2m2s
CI / Docker image build (pull_request) Successful in 28s
CI / Does this change touch the recording path? (pull_request) Successful in 36s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Feedback site tests (pull_request) Successful in 2m3s
CI / Frontend tests, audit, and build (pull_request) Successful in 18m19s
CI / Backend migration, tests, and audit (pull_request) Successful in 37m40s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
06f441e4ab
Server and bot halves together; no pages.

- Discord DMs (D152): `notification_dm` on the durable stream, claimed before
  publish, the bell's line + link + time for session news only; sent only to a
  bot whose GET /identity lists "dm" in its new `features`. The bot's
  handler is exempt from the channel check and reports refusals to the new
  POST /api/bot/users/discord/{id}/dm-status (closed | no_shared_server | ok);
  the settings carry a `warning` beside the DM column until the next DM lands.
- The GM's warnings (D151): session_at_risk and audio_deletion_pending are
  GM-only bell rows, DM'd per the GM's grid (GM tasks x DM on by default), and
  posted to the channel only when no GM is reachable by DM. The at-risk poller
  runs for campaigns without a guild.
- A group without Discord (D153, #840): session news is emailed to every
  member unless Sessions email is explicitly off; the from-address email
  backends are retired. Reminders are `session_reminder` rows per member (only
  the last in the bell), reading the reader's RSVP.
- The reader's time: users.timezone, else the campaign's, else UTC, with the
  abbreviation, in notification emails and calendar invites.
- One star, one wish (D161): `feedback_requested`, written on completion for
  the players Home asks, never in the bell.
- D159: campaigns.voice_channel_id, stored and shown to GMs.
- PUT notification-settings writes only cells that change and never refuses an
  unchanged echo, so the page's whole-grid save keeps the defaults.
- Migration 10a1b2c3d4e5 on c4e6a8b0d2f1: the kind CHECK is the union with
  lane 9 A's and lane 7's kinds; notifications.in_bell; platform_links
  dm_failed_at/dm_failed_reason; campaigns.voice_channel_id.

Bot contract unchanged (additive).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Admin becomes a place with sections in Home's Contents rather than a page
of ten tabs, reusing the same shape lane 3 gave Settings:

- adminSections.js (16 sections, the survey's addresses); ADMIN_SECTIONS'
  `built` flag follows settingsSections.js's own rollout rule — three
  sections with no legacy screen at all (Content notices, Instance health,
  Plans & entitlements) stay unmounted for their own PR (4c/4d).
- /admin/* routes; `?tab=` redirects to the new address (paths are
  contracts, R1-8); `bot` (ambiguous) goes to AI models.
- Home's Contents "This instance" group, the crumb ("Admin › <section>"),
  and IS-377's Stop for a non-administrator (AdminDoc.jsx).
- The index (GET /admin/overview, already on this branch from lane 9 A):
  grouped status lines, D142's quiet leftovers box, and D141's accept/
  decline banner for an offered server.
- ADMIN-15 About this server: the admin GET/PUT this lane's server work
  added, now with a form.
- ADMIN-1 Users: the owner's chip, "Hand the server on…" (an offer, D68),
  Make/Remove administrator (a dialog, then an undo), delete with the
  typed name and the blocked-by-campaigns state, and D56's search-scope
  radio cards (new GET endpoint — the setter existed, nothing read it back).
- ADMIN-2 Campaigns: the instance-wide list, and an immediate (never an
  offer) hand-on for a campaign whose owner is unreachable or just moved
  on — the admin's own recovery path either way.
- D141's server-scoped attention item: AttentionItem.campaign_id/
  campaign_name become optional for the one kind that isn't a campaign's
  (server_owner_offer), checked ahead of the membership scope so it
  reaches an administrator with no campaigns of their own.
- Every other built section keeps working at its new address by mounting
  pages/Admin.jsx's existing component unchanged (the tab bar is gone);
  AI models and Discord share one interim mount until page 4c splits
  BotSettings along the new addresses — a documented departure.
- J1's Admin leg walked for real: the leftovers list, Backup's own
  heading and Contents-current row, a whole-page axe scan (no longer
  scoped to [role="alert"]), the desktop project settling the step, and
  the keyboard project reaching Admin through the account menu and its
  Contents sub-list. A new IS-377 journey test (Priya, stopped, axed).

Backend: GET /api/admin/settings/member-search-scope (D56's setter has
existed since #855; nothing read it back before this).

Not in this PR (see the survey's §7 row 4a and the file's own notes):
AI models/AI usage & speed/Discord's real split, Recording & retention,
Backup, Content packs, Content notices, Audit log's names/categories, and
Plans & entitlements — pages 4b/4c/4d.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
fix(webapp): name the offering owner on D141's accept/decline banner
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m47s
CI / Bot tests and audit (pull_request) Successful in 2m8s
CI / Backend lint (ruff) (pull_request) Successful in 1m9s
CI / Feedback site tests (pull_request) Successful in 47s
CI / Docker image build (pull_request) Successful in 33s
CI / Bot/backend version sync (pull_request) Successful in 1m8s
CI / Does this change touch the recording path? (pull_request) Successful in 32s
CI / Backend migration, tests, and audit (pull_request) Successful in 16m33s
CI / Frontend tests, audit, and build (pull_request) Failing after 21m1s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 1m3s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
4fb7b928d0
The overview's still-current owner_name is who is offering — the offer
has not resolved yet — so the banner reads "Dana is offering you this
server" rather than the anonymous fallback, matching the drawing without
a second request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- lore_entries gain an audience (lane 7's model) and a people table;
  migration 8a1b2c3d4e5f moves gm_notes and player_private_notes into
  every page's and every version's text as blocks, escaping old bodies'
  ':::' lines first.
- The wiki's routes read through wiki_audience: a page outside the
  reader's audience is 403 'This page isn't shared with you' and nothing
  else (D167); lists are one query; facts and timeline rows read as
  audiences; ?as_user= / ?as_character= for GMs (IS-128).
- The old article page keeps working: its three boxes are read out of,
  and written back into, the text (wiki_text's legacy split).
- Search, /ask, the summary, a shelf card's face, the vocabulary, the
  timeline, lane 7's about chip and canon, drafts and proposals' merges
  all read the renderer's output; a test lists every raw read.
- Export schema 14: notes travel inside the body, with the audience.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(webapp): the bell knows lane 9's two ownership kinds (#846)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 53s
CI / Backend lint (ruff) (pull_request) Successful in 1m7s
CI / Bot tests and audit (pull_request) Successful in 1m59s
CI / Bot/backend version sync (pull_request) Successful in 28s
CI / Docker image build (pull_request) Successful in 32s
CI / Does this change touch the recording path? (pull_request) Successful in 47s
CI / Feedback site tests (pull_request) Successful in 1m59s
CI / Backend migration, tests, and audit (pull_request) Successful in 16m28s
CI / Frontend tests, audit, and build (pull_request) Successful in 48m33s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 14m46s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 24m23s
2c4f2ff68b
Lane 7's test asserts the bell's NOTE_KIND covers every kind the server
defines; lane 9 A (#855) added server_ownership_offer and
campaign_handed_on after lane 7 was written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The one-head pin moves to tests/wiki/test_wiki_migration.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/wiki/test_wiki_crawl.py walks every wiki-touching read as every
reader; /ask's context is one function now (ask_lore_context) so the
crawl can read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: CHANGELOG for the wiki's text and page audiences; ruff format (#734, lane 8)
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m3s
CI / Bot tests and audit (pull_request) Successful in 2m20s
CI / Backend lint (ruff) (pull_request) Successful in 31s
CI / Bot/backend version sync (pull_request) Successful in 25s
CI / Docker image build (pull_request) Successful in 20s
CI / Does this change touch the recording path? (pull_request) Successful in 32s
CI / Feedback site tests (pull_request) Successful in 2m1s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
CI / Frontend tests, audit, and build (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
cce85bb474
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
#	docs/API.md
#	webapp/backend/app/models/notification.py
#	webapp/backend/app/services/notification_service.py
#	webapp/backend/app/services/notification_settings_service.py
#	webapp/backend/tests/conftest.py
#	webapp/backend/tests/test_discord_webhook_fallback_removal_migration.py
#	webapp/backend/tests/test_notifications.py
#	webapp/backend/tests/test_safety_migration.py
#	webapp/frontend/src/shell/AppFrame.jsx
#	webapp/frontend/src/shell/AppFrame.test.jsx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-chain 10c3d4e5f6a7 onto 10a1b2c3d4e5; the one-head pin moves to
test_recording_tests_migration. The bot lists record_test in BOT_FEATURES
(additive) so page 7a can tell a bot too old for Test the bot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into train2/1-866
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 59s
CI / Backend lint (ruff) (pull_request) Successful in 27s
CI / Bot tests and audit (pull_request) Successful in 2m4s
CI / Bot/backend version sync (pull_request) Successful in 24s
CI / Feedback site tests (pull_request) Successful in 43s
CI / Does this change touch the recording path? (pull_request) Successful in 15s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Docker image build (pull_request) Successful in 34s
CI / Frontend tests, audit, and build (pull_request) Successful in 21m33s
CI / Backend migration, tests, and audit (pull_request) Successful in 16m56s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 24m50s
70f794db34
Merge branch 'train2/1-866' into train2/2-868
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m0s
CI / Backend lint (ruff) (pull_request) Successful in 31s
CI / Feedback site tests (pull_request) Successful in 46s
CI / Bot tests and audit (pull_request) Successful in 2m2s
CI / Bot/backend version sync (pull_request) Successful in 28s
CI / Docker image build (pull_request) Successful in 20s
CI / Does this change touch the recording path? (pull_request) Successful in 17s
CI / Backend migration, tests, and audit (pull_request) Successful in 17m28s
CI / Frontend tests, audit, and build (pull_request) Successful in 21m8s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 25m10s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 31m26s
80fad5de6b
Merge branch 'train2/2-868' into train2/3-865
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 59s
CI / Backend lint (ruff) (pull_request) Successful in 42s
CI / Feedback site tests (pull_request) Successful in 57s
CI / Bot tests and audit (pull_request) Successful in 2m6s
CI / Bot/backend version sync (pull_request) Successful in 43s
CI / Does this change touch the recording path? (pull_request) Successful in 18s
CI / Docker image build (pull_request) Successful in 59s
CI / Backend migration, tests, and audit (pull_request) Successful in 16m47s
CI / Frontend tests, audit, and build (pull_request) Successful in 20m57s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 13m44s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
d318ab15b4
Merge branch 'train2/3-865' into train2/4-864
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 53s
CI / Backend lint (ruff) (pull_request) Successful in 28s
CI / Bot/backend version sync (pull_request) Successful in 33s
CI / Feedback site tests (pull_request) Successful in 46s
CI / Does this change touch the recording path? (pull_request) Successful in 16s
CI / Docker image build (pull_request) Successful in 51s
CI / Bot tests and audit (pull_request) Successful in 3m25s
CI / Backend migration, tests, and audit (pull_request) Successful in 17m32s
CI / Frontend tests, audit, and build (pull_request) Successful in 37m42s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 13m13s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
aae9943ca6
- Migration 8b2c3d4e5f6a on 10c3d4e5f6a7: lore_links and lore_references
  (written on every save, each with its block, backfilled from every live
  page), lore_name_targets (D72), relationship audiences and spans
  (IS-085), lore_entries.version_id (IS-049), campaigns.wiki_edit_mode
  (#779), wiki_templates (IS-046), reputation_levels (IS-088), and
  suggestions as drafts (IS-054).
- wiki_links: parse, resolve names per reader, Mentioned in, references
  numbered per reader, by-name, the rename rewrite, and :::for lines that
  follow a renamed character.
- wiki_edit: Who may edit, enforced on create, save and relationships;
  players create where they may, and suggest where the campaign says.
- One Save: base_version_id -> 409 with the page as it is; sections;
  D72's clash and qualified names; Settings -> Wiki's API; templates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tests/wiki: rules without a database (parser, names per reader,
  sections, renames, who may edit), the API (Mentioned in, D72, by-name,
  footnotes per reader, relationship audiences and spans, the 409,
  sections, suggestions merged as their writer, Settings -> Wiki,
  templates, the export round trip), and the migration (frozen parser
  held to the app's, the backfill on real rows, up, down and up).
- The crawl walks links, footnotes, by-name, sections and relationships
  with audiences of their own.
- The one-head pin moves to 8b2c3d4e5f6a; export and import carry the
  wiki's settings, name targets and relationship audiences and spans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rename's count of rewritten pages counts only what the writer can see.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor(backend): a footnote's thread is looked up in discussion_service (#734, lane 8 PR 2a)
Some checks failed
CI / Frontend tests, audit, and build (pull_request) Has been cancelled
CI / Backend migration, tests, and audit (pull_request) Has been cancelled
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Has been cancelled
CI / Bot tests and audit (pull_request) Has been cancelled
CI / Backend lint (ruff) (pull_request) Has been cancelled
CI / Feedback site tests (pull_request) Has been cancelled
CI / Bot/backend version sync (pull_request) Has been cancelled
CI / Docker image build (pull_request) Has been cancelled
CI / Does this change touch the recording path? (pull_request) Has been cancelled
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been cancelled
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Has been cancelled
2f99bd3d58
The discussion tables are read only by the modules test_discussions_no_ai
lists; wiki_links asks discussion_service which threads and posts a reader
may open instead of reading them itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(webapp): one Admin door in the phone Contents, Backup's axe scan scoped again (#866)
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m1s
CI / Bot tests and audit (pull_request) Successful in 4m12s
CI / Backend lint (ruff) (pull_request) Successful in 1m5s
CI / Feedback site tests (pull_request) Successful in 1m40s
CI / Bot/backend version sync (pull_request) Successful in 54s
CI / Docker image build (pull_request) Successful in 1m13s
CI / Does this change touch the recording path? (pull_request) Successful in 28s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Backend migration, tests, and audit (pull_request) Successful in 18m17s
CI / Frontend tests, audit, and build (pull_request) Successful in 41m41s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 27m48s
892477cf11
Home's "This instance" group (lane 9 page 4a, d69f412a) put a second
"Admin" link in the phone's Contents sheet alongside the account rows'
own — both land in the one `nav` there (SH-4), so `accountRow(you,
"Admin")` resolved to two. The desktop identity disc's dropdown is a
separate landmark and was never affected. Fixed by dropping the account
row's Admin whenever `contents.groups` already carries "This instance",
which only the sheet ever sees both of at once.

4a also restored J1's whole-page axe scan on `/admin/backup`, which
still mounts the legacy `BackupSection` (`.bg-indigo-600` at 2.69:1,
an unlabelled `input[min="1"]`). Scoped the scan away from that
section's own markup rather than off the whole page, since 4a did
rebuild the frame around it; page 4b (#873) replaces the section and
restores the whole-page scan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge branch 'train2/1-866' into train2/2-868
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m2s
CI / Bot tests and audit (pull_request) Successful in 2m15s
CI / Backend lint (ruff) (pull_request) Successful in 32s
CI / Feedback site tests (pull_request) Successful in 48s
CI / Bot/backend version sync (pull_request) Successful in 29s
CI / Docker image build (pull_request) Successful in 33s
CI / Does this change touch the recording path? (pull_request) Successful in 19s
CI / Backend migration, tests, and audit (pull_request) Successful in 17m30s
CI / Frontend tests, audit, and build (pull_request) Successful in 43m47s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 13m37s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 22m30s
b7ee17ec0c
Merge branch 'train2/2-868' into train2/3-865
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 59s
CI / Bot tests and audit (pull_request) Successful in 2m3s
CI / Backend lint (ruff) (pull_request) Successful in 31s
CI / Bot/backend version sync (pull_request) Successful in 26s
CI / Docker image build (pull_request) Successful in 33s
CI / Does this change touch the recording path? (pull_request) Successful in 17s
CI / Feedback site tests (pull_request) Successful in 1m53s
CI / Backend migration, tests, and audit (pull_request) Successful in 19m1s
CI / Frontend tests, audit, and build (pull_request) Successful in 22m59s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 13m37s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 31m55s
1863ce33b8
Merge branch 'train2/3-865' into train2/4-864
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m28s
CI / Backend lint (ruff) (pull_request) Successful in 29s
CI / Feedback site tests (pull_request) Successful in 45s
CI / Bot/backend version sync (pull_request) Successful in 24s
CI / Docker image build (pull_request) Successful in 26s
CI / Does this change touch the recording path? (pull_request) Successful in 14s
CI / Bot tests and audit (pull_request) Successful in 4m21s
CI / Backend migration, tests, and audit (pull_request) Successful in 18m57s
CI / Frontend tests, audit, and build (pull_request) Successful in 46m40s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 35m5s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 58m33s
4fb314fa4c
Merge branch 'train2/4-864' into w3-874
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m22s
CI / Backend lint (ruff) (pull_request) Successful in 31s
CI / Feedback site tests (pull_request) Successful in 38s
CI / Bot/backend version sync (pull_request) Successful in 26s
CI / Docker image build (pull_request) Successful in 21s
CI / Bot tests and audit (pull_request) Successful in 4m54s
CI / Does this change touch the recording path? (pull_request) Successful in 18s
CI / Frontend tests, audit, and build (pull_request) Successful in 21m32s
CI / Backend migration, tests, and audit (pull_request) Successful in 45m40s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 13m33s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 29m51s
5d49fe6d2e
Server only, before the migration and its tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every campaign gets its main party; every character is placed in it at the
first session it was played in (pins first, then the active character), an
inactive one having left at its last; every "party" audience gets the main
party's id; loot, XP and gold go to the character played at the row's
session (D198); every line gets a "found" custody row. Idempotent, and
the down path narrows what the old schema can't hold to the GMs.

The one-head pin moves here from test_wiki_links_migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crawl now walks the party pages, the ledger, custody, reputation and
downtime as every reader, with a second party's page and block, an
unidentified item's true name, a GMs-only NPC holding a line, and a
GMs-only reputation change among its secrets. Lane 7's audience test holds
the party-by-id rule equal in Python, members_of, SQL and viewers_for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upload and delete follow wiki_edit's rules for the campaign's mode, so a
player under "suggest" gets none (D233); a picture from a web address
stays GM-only in every mode, since the server fetches it.

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>
The lore summary and the proposal prompt name it as the table knows it, a
shelf card's face does too, and a discussion's "on" chip and canon mark
name it per reader. The crawl gains a thread about the ring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(backend): whether a thread is for a party is discussion_service's to say, so the discussion tables stay out of party_service (#654, #734)
Some checks failed
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m1s
CI / Backend lint (ruff) (pull_request) Successful in 30s
CI / Bot/backend version sync (pull_request) Successful in 27s
CI / Bot tests and audit (pull_request) Successful in 2m8s
CI / Feedback site tests (pull_request) Successful in 1m45s
CI / Does this change touch the recording path? (pull_request) Successful in 17s
CI / Docker image build (pull_request) Successful in 5m2s
CI / Frontend tests, audit, and build (pull_request) Successful in 45m51s
CI / Backend migration, tests, and audit (pull_request) Successful in 46m24s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 57m7s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Failing after 1h23m4s
1c70d171bd
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now carries lane 10's 10d4e5f6a7b8 and 10b2c3d4e5f6 after
10c3d4e5f6a7, which 8b2c3d4e5f6a was written on. 8b2c now revises
10b2c3d4e5f6, so the chain stays linear. The one-head pin stays on
tests/wiki/test_wiki_links_migration; test_reveal_discord_message_migration's
becomes test_this_migration_is_still_in_the_chain, and
test_recording_tests_migration takes main's version (10d4 is its child now).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts were the migration-history docstrings and the 8b2c pin test:
8b2c stays test_this_migration_is_still_in_the_chain (8d4e holds the
one-head pin) and now asserts its new parent, 10b2c3d4e5f6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge main (#885, lane 10 PR 5) into t4 lane 8 PR 2a (train 4)
All checks were successful
CI / Docker image build (pull_request) Successful in 54s
CI / Backend lint (ruff) (pull_request) Successful in 1m6s
CI / Bot/backend version sync (pull_request) Successful in 1m6s
CI / Does this change touch the recording path? (pull_request) Successful in 19s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Feedback site tests (pull_request) Successful in 1m22s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m20s
CI / Bot tests and audit (pull_request) Successful in 4m11s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 22m22s
CI / Backend migration, tests, and audit (pull_request) Successful in 45m42s
CI / Frontend tests, audit, and build (pull_request) Successful in 46m53s
cbf0279c8e
Merge t4 lane 8 PR 2a (main with #885) into t4 lane 8 PR 3 (train 4)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 55s
CI / Feedback site tests (pull_request) Successful in 47s
CI / Backend lint (ruff) (pull_request) Successful in 1m2s
CI / Bot tests and audit (pull_request) Successful in 1m57s
CI / Bot/backend version sync (pull_request) Successful in 26s
CI / Does this change touch the recording path? (pull_request) Successful in 21s
CI / Docker image build (pull_request) Successful in 36s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 14m2s
CI / Backend migration, tests, and audit (pull_request) Successful in 19m24s
CI / Frontend tests, audit, and build (pull_request) Successful in 21m31s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 40m4s
0f3a2d41b0
Sign in to join this conversation.
No description provided.