Build lane 3: the campaign core and Settings (CAMP-1 to CAMP-17, SH-7) #729
Closed
opened 2026-09-22 00:12:20 +00:00 by claude-bot
·
9 comments
No Branch/Tag specified
main
feat/1328-fill-it-in
feat/1328-fill-frontend
feat/1328-fill-backend
feat/9-foundry-push
fix/9-foundry-live
feat/9-foundry-push-frontend
renovate/celery-5.x
feat/5-foundry-connect
feat/9-foundry-push-backend
feat/9-foundry-push-module
feat/5-foundry-frontend
feat/5-foundry-backend
feat/5-foundry-module
release/v4.8.0-rc1
docs/d341-convert-draft
feat/958-update-to-version
feat/958-convert-sheet
feat/958-pathbuilder-import-frontend
fix/1360-heading-order
feat/958-pathbuilder-import-backend
feat/11-weekly-digest
feat/1341-auto-update
docs/d332-superseded
chore/1345-names-cleanup
feat/1342-mentioned-pages
feat/1328-recipes
fix/1346-pgdg-key
perf/1247-shared-recording-stream
chore/132-gitleaks-allowlist
release/v4.7.1
spike/foundry-module
release/v4.7.1-rc1
docs/decisions-d332-d337
fix/bot-certifi
chore/release-4.7.0
chore/release-4.7.0-rc4
chore/deps-4.7.0
chore/release-4.7.0-rc3
fix/1280-quote-must-say-it
fix/1257-names-row-squeeze
chore/release-4.7.0-rc2
fix/1245-pg-upgrade-count
chore/release-4.7.0-rc1
feat/1257-names-in-prep
feat/1257-be
feat/1257-fe
feat/1257-rating-fixes
design/1328-fill-it-in
feat/1257-name-splits
fix/1326-redis-503
feat/1280-fact-suggestions
feat/1280-be
feat/1280-fe
design/1280-fact-suggestions
feat/1279-infobox
feat/1279-be
feat/1279-fe
feat/1321-shelf-copies
design/1279-infobox
feat/1243-table-find
feat/1257-who-rated
feat/1243-prep-drawer
feat/1243-sheet-pickers
design/1243-browse-in-place
feat/1315-hotwords-default
feat/1242-system-filters
feat/1257-more-name-styles
feat/506-leg3-hotwords
design/1242-system-filters
fix/1302-packs-polish
feat/1241-rules-library
design/1241-rules-library
feat/1245-postgres-18
integ/4.6.2
fix/1263-map-ui-2
fix/1263-map-server
fix/1263-map-ui-1
fix/1261-editor-link-menu
fix/1229-axe-4.14-name-mismatch
renovate/axllent-mailpit-1.x
renovate/eslint-monorepo
renovate/authlib-1.x
chore/release-4.6.0
chore/release-4.6.0-rc2
fix/460-rc2-screens
fix/460-rc2-server
fix/release-prerelease-exit
chore/release-4.6.0-rc1
feat/125-campaign-templates
feat/126-calendar
feat/1181-pictures-and-files
feat/1190-event-people
integ/4.6.0
feat/1191-line-of-the-night
feat/1200-starter-packs
chore/bot-multidict-and-playwright-group
fix/1202-this-week-answered-count
fix/122-124-leftovers
fix/1178-get-routes-that-write
fix/1203-journeys-check-names
design/125-campaign-templates
feat/126-calendar-engine
design/126-in-world-calendar
fix/1189-cited-stamp-in-range
fix/1189-v4-looser-check
fix/1189-richer-beats
fix/1113-export-bind-lists
fix/1154-release-notes-by-file
chore/release-4.5.0
chore/release-4.5.0-rc12
fix/1135-wiki-markup-as-text
fix/demo-usage-cost-in-window
chore/release-4.5.0-rc11
fix/1121-sheet-consistency
fix/1121-sheet-5e-terms-and-card-hp
copy/1122-busiest-pages
fix/1121-relevant-choices
fix/1121-wiki-create-npc-save-sheet-links
fix/1029-menu-stays-on-screen
docs/prototype-transcript-bin-wording
fix/1023-editor-save-row-back-scroll
fix/1020-search-exact-first
fix/1020-table-prep
fix/1020-shell-wordmark-footer-bell
fix/1020-wiki-article-party
fix/872-admin-kept-until-phone-tables
feat/l13-milestone-level-waiting
fix/1000-1001-bell-older-setup-context
fix/999-pronouns-in-prompts
fix/l19-other-class-feats
fix/1010-transcript-window-ordinary-confirm
docs/d254-d269-decisions
fix/702-member-search
fix/680-transcript-bin
fix/993-unidentified-prompts
fix/841-redis-timeouts
fix/990-binned-not-exported
fix/830-export-prep-shelf
fix/deps-audit-2026-10-01
fix/877-title-reads
fix/798-audio-received-at
build/lane11-17-j7
build/lane11-16-levelup
build/lane11-14-seams
build/lane11-14-seed
build/lane11-15-start
build/lane11-13-old-block-out
fix/980-review-r3
build/lane11-12-block
build/lane11-8-packs
fix/demo-seed-canonical-names
build/lane11-11-hot-half
docs/l11-decisions
build/lane11-7-convert
build/lane11-10-editing
fix/npm-audit-brace-expansion
build/lane11-9-sheet-page
fix/bot-pyjwt
build/lane11-6-content
fix/lane11-rank-names
build/lane11-2b-language
build/lane11-4-js-evaluator
build/lane11-3-server
build/lane11-5a-pf2e
build/lane11-5b-5e
feat/design-admin
build/lane11-2-evaluator
build/lane11-1-sheet-pieces
build/lane11-0-drawing
fix/943-quest-objectives-fk
fix/prepsheet-shelf-flake
fix/945-leftovers
build/demo-gm-copy
fix/901-email-landings
build/lane10-8-journeys
build/demo-seed-lanes-8-10
fix/887-gm-own-confirmation
build/lane9-5-j1-admin
fix/918-audience-click
fix/useasync-overtaken
ci/939-critical-path
test/937-backend-suite-speed
chore/claude-orchestration
fix/924-xp-gm-only
fix/session-stale-poll
docs/decisions-d239-d242
fix/930-pypdf
build/lane8-journeys
build/925-quest-editor
fix/894-private-page-pictures
build/lane8-p4-drafts
build/lane8-p7-map
build/lane8-p6-handouts-rules
fix/wiki-fixture-names
build/lane10-d227-test-usage
fix/rsvp-horizon-test-tuesday
fix/media-volume-owner
build/lane8-p3-editor
fix/912-unidentified-rename
build/lane8-p5-party-quests
build/lane8-handout-takeback
build/lane10-pickers
build/lane8-p2-article
build/lane8-6-map
build/lane10-7b-email-pages
build/lane8-5-handouts
build/lane10-7a-test-the-bot-pages
build/lane8-p1-pages
build/lane8-4-quests
build/lane8-2b-feeds
build/lane8-3-parties
build/lane8-2a-links
build/lane10-5-commands
build/lane9-6-seed
build/lane10-4b-reactions
build/lane9-4d-pages
build/lane9-4c-pages
build/lane10-4a-posts
build/lane10-3-email
fix/891-web-fonts
build/lane9-4b-pages
build/lane10-6-test-the-bot
build/lane10-2-notify-out
build/lane8-1-wiki-text
build/lane9-4a-frame
design/lane10-drawings
fix/j6-budget
fix/j5-phone-flake
fix/869-test-leaks
fix/843-record-start-followups
build/lane7-all
build/lane6-all
build/lane9-b2-server
chore/changelog-fragments
docs/decisions-d218
build/lane9-a-owner-overview
fix/rule-card-level-label
fix/834-retention-semantics
fix/o3c-record-without-announcement
docs/decisions-d179
docs/decisions-d131-d170
fix/851-commit-before-response
build/lane6-j3-seed
build/lane9-b1-d67-identity
fix/841-blocking-loop
build/lane9-c-backups-audit
fix/vote-race-and-start-commit
fix/recording-announcement
fix/proposal-read-leak
fix/last-admin-guard
build/lane6-p4c-planning
build/lane6-p4b-margin
build/lane6-p4a-sheet
build/lane5-j4-seed
build/lane6-base
build/lane7-pages-talk
build/lane5-pages
build/lane7-pages-safety
build/lane7-p3-safety
build/lane7-p2-notify
build/lane6-p3-planning
build/lane6-p2-history
build/lane6-p1b-items
build/lane7-p1-threads
build/lane5-p6-faces
build/lane6-p1a-sheet
build/lane5-p5-find
build/lane5-p4a-board
build/lane5-p4b-scenes
build/lane5-p3-live
build/lane5-base
build/lane5-p2-cards
docs/lane5-decisions
build/review-r2-wide
fix/review-r1
build/lane5-p1-scenes
build/demo-seed
build/lane4-journeys-j5
build/lane4-page-review-b
build/lane4-page-review-a
build/lane4-page-read
build/lane4-journeys
build/lane4-page-sess2
build/lane4-page-sess1
build/lane4-notes
build/lane4-discord-on-approval
build/lane4-scheduling
build/lane4-versions
build/760-session-number
build/lane4-decisions
build/797-erase-no-regenerate
build/test-race-audit
build/lane3-completions
build/794-dark-only
build/796-titles-scroll
build/791-retention-anchor
build/a11y-sweep
build/shell-followups
build/retention-preview
build/753-backup-readback
docs/d91-d93
build/lane3-j1
build/ci-harness-paths-selftest
fix/useauth-test-race
build/ci-harness-paths
build/777-ai-settings-read
build/lane3-settings-c
build/lane3-settings-b
build/lane3-j6
build/lane3-sessionform
build/lane3-settings-a
build/lane3-members
build/lane3-thisweek
build/lane3-story
chore/87-align-python-3.12
v4.8.0-rc1
v4.7.1
v4.7.1-rc1
v4.7.0
v4.7.0-rc4
v4.7.0-rc3
v4.7.0-rc2
v4.7.0-rc1
v4.6.2
v4.6.2-rc4
v4.6.2-rc3
v4.6.2-rc2
v4.6.2-rc1
v4.6.1
v4.6.1-rc1
v4.6.0
v4.6.0-rc2
v4.6.0-rc1
v4.5.3
v4.5.3-rc1
v4.5.2
v4.5.2-rc1
v4.5.1
v4.5.1-rc2
v4.5.1-rc1
v4.5.0
v4.5.0-rc12
v4.5.0-rc11
v4.5.0-rc10
v4.5.0-rc9
v4.5.0-rc8
v4.5.0-rc7
v4.5.0-rc6
v4.5.0-rc5
v4.5.0-rc4
v4.5.0-rc3
v4.5.0-rc2
v4.5.0-rc1
v4.4.1
v4.4.0
v4.3.0
v4.2.3
v4.2.2
v4.2.1
v4.2.0
v4.1.2
v4.1.1
v4.1.0
v4.0.1
v4.0.0
v3.11.4
v3.11.3
v3.11.2
v3.11.1
v3.11.0
v3.10.0
v3.9.1
v3.9.0
v3.8.0
v3.7.0
v3.6.1
v3.6.0
v3.5.0
v3.4.1
v3.4.0
v3.3.0
v3.2.0
v3.1.0
v3.0.0
v2.1.0
v2.0.0
v1.1.0
v1.0.0
v0.12.0
v0.11.0
v0.10.0
v0.9.1
v0.3.3
v0.9.0
v0.8.0
v0.3.2
v0.3.1
v0.3.0
v0.7.0
v0.6.0
v0.5.0
v0.4.0
v0.2.1
v0.2.0
v0.1.1
v0.1.0
Labels
Clear labels
backend
Issue related to the backend
bot
Issue related to the bot
bug
Something is not working
duplicate
This issue or pull request already exists
enhancement
New feature
frontend
Issue related to the frontend
help wanted
Need some help
invalid
Something is wrong
question
More information is needed
recording
Issue related to the recording system
security
Security hardening / vulnerability work
wontfix
This won't be fixed
No labels
backend
bot
bug
duplicate
enhancement
frontend
help wanted
invalid
question
recording
security
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/Quest-Board#729
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Build lane 3 of the v4.5.0 redesign. The brief is
docs/design/v4.5.0-brief.md(§9, the lanes in order); the build plan isdocs/design/v4.5.0-build-plan.md(the rollout rule, the design-system mapping, the journeys as tests). Umbrella: #366. Goes after lane 2.Scope
Surfaces: CAMP-1 to CAMP-17 (This week, Sessions, the session form, series, Highlights, Storyline, Analytics, Members & characters, Settings in its nine sections) and SH-7 (the shared patterns).
The drawing:
/feedback/prototype/lane2,lane2bandlane2c— the page the build must match, still by still.Decisions: the brief §7, and each surface's header in
redesign-surfaces/sources/headers.md.Server changes it needs (in this lane or an earlier one)
IS-382, #702); step down as GM (IS-383); the invite management split; the retention default and cap (IS-311)IS-094) with milestones (CA-192); series management (IS-368); sessions played in the last 30 days (CA-239)Acceptance
coverage/lane2.py,coverage/lane2b.pyandcoverage/lane2c.pyclassifies as drawn or replaced is built as the prototype draws it; the script is the checklist. Rows it marks behaviour are tested, not drawn.vocabulary.js; no page-level error destroys rendered content; every async operation shows progress and a next action on failure; disabled controls say why.redesign-surfaces/sources/headers.md(Decided lines and the owner's review notes) are honoured; a departure is a decision change on #659 first.Notes
🤖 Generated with Claude Code
Picking this up. Lane 2 (#728) is merged — all twelve public pages — so lane 3 is next in the build plan's order.
Read first: the three drawings (
/feedback/prototype/lane2,lane2b,lane2c), the three checklists, and the surfaces' headers.This is much the biggest lane yet
lane2.pylane2b.pylane2c.py309 placements to build, against lane 2's 93 and lane 1's roughly 150. CAMP-8 alone is 42 and CAMP-15 is 35 — each about a third of lane 2 on its own. So this is a longer series than the last two rather than a bigger PR.
The PR series
Working agreements §7: the lane's server changes first, then UI only; every PR names its coverage rows.
1 — Server: retention's default and its cap (D24).
IS-311andIS-312. Todayget_effective_retentiontakes a campaign's override verbatim undermax(1, …), so a campaign can keep audio longer than the instance — the instance setting is a default in name and nothing in practice. D24 makes it two numbers: a default every campaign starts from, and an absolute cap no campaign may pass, with the form naming both so a GM can see the room they have.Worth saying because it closes a loop from last lane: this is what makes the privacy page's sentence true. PUB-12 currently cannot print the drawing's "A GM can keep less than this. Nobody can keep more.", because it is not true of the code;
Privacy.jsxcarries a comment saying to restore the drawn sentence when the cap lands. That happens in this PR.2 — Server: the rest. The storyline's timeline (
IS-094) and milestones (CA-192), series management (IS-368), search scope (IS-382, #702), stepping down as GM (IS-383), and the invite-management split. Two server PRs rather than one because the first is a data-governance change that deserves reviewing on its own, and the rest are additive.3 — This week, the Sessions list, and the session form. CAMP-1, CAMP-2, CAMP-3 (64 rows). Splits
CampaignDetail.jsx; its session parts stay for lane 4.4 — Members & characters. CAMP-8 (42 rows), on its own because it is the single largest surface in the lane.
5 — Settings, the first five sections. CAMP-9 General, CAMP-10 Invites & joining, CAMP-11 Ownership, CAMP-12 Discord, CAMP-13 Recording, retention & AI (73 rows). CAMP-13 is where PR 1's cap surfaces.
6 — Settings, the last four. CAMP-14 Wiki, CAMP-15 Content packs, CAMP-16 Foundry, CAMP-17 Archive, export, clone & delete (55 rows).
7 — Series, Highlights, Storyline, Analytics, and the patterns sheet. CAMP-4 to CAMP-7 and SH-7 (75 rows). SH-7 goes last on purpose: it is the sheet the whole rebuild is measured against, and by then six PRs of this lane will have applied its patterns, so it is drawn from what was actually built rather than ahead of it.
J1 (create, time zone, invite, Discord) and J6 (Highlights, Storyline) grow with the PRs that build what they walk, as in lanes 1 and 2, rather than in a PR of their own.
Departures
None decided in advance. Anything the build cannot draw as the prototype draws it gets recorded here before it is built, per §7 — the build does not redesign.
🤖 Generated with Claude Code
A correction to my own plan, and the server series refined, after mapping what actually exists.
IS-382is not what I assumedI filed it under "search scope" next to lane 1's
search-all, as if it meant content search. It does not. Checked against the ledger and D56:It is a privacy control for who a GM can enumerate, which is harmless on a private server and a way to list strangers on a hosted one. Today
campaign_service.search_non_membersILIKEs across every non-system account on the instance with no scoping at all, and both "Add someone" and "Attach to an account" call the same endpoint. There is no "played with" concept anywhere in the backend.So this is a new instance setting plus a scoped query, on CAMP-8, not a change to the search box in the app bar. Same shape as
blurblast lane: lane 3 reads the setting, lane 9 draws the admin control that writes it.IS-383is narrower than it sounds, and cuts against an earlier decisionD57: the owner can step down as GM while another member is GM, from their own row; ownership itself is unchanged. Not any GM.
The gotcha is that #644 deliberately removed exactly this kind of guard — the code says so in four places: the last GM can leave, the owner may remove the last GM, "a campaign with no GM is a legitimate state". So
IS-383adds a sole-GM check to one specific path (the owner changing their own role) without reintroducing it for leaving or for demoting somebody else. Worth stating plainly because the obvious implementation would undo #644.The invite split needs no server work at all
D23 is an IA change: today's single
InvitePanelmixes "get a link to paste into Discord" with "manage the set of links". The backend already separates cleanly by function — nine endpoints, each doing one thing. So the split is entirely PRs 4 and 5's business, and drops out of the server series.The server series, revised to three
Front-loaded, each reviewable on its own:
1 — Retention's default and its cap (D24). In progress. The crux that the plan's one-line summary hid: retention is a
(mode, quantity)pair, so a cap expressed as a number is not a cap — a campaign could keep audio for ever by changing the mode rather than the number. An absent cap means "no cap", so every existing instance behaves exactly as today until an administrator sets one; a cap that appeared retroactively would start deleting people's audio. The clamp goes inget_effective_retention's read path, which is what the nightly sweep obeys, and a stored over-cap override is read as the cap without its row being rewritten — the GM's stated preference is worth keeping for the day the cap is raised.2 — Members' server.
IS-382's scope setting and scoped query, andIS-383's step-down. Both are CAMP-8's, both are about who can do what to whom, so they review together.3 — What the reading surfaces need. The campaign timeline (
IS-094, D47) — a new endpoint merging sessions, milestones and the wiki'stimeline_events, which exist but have never been merged;sessions_last_12_monthson the authenticated analytics response (two lines, already unblocked by lane 2's service change); a This week aggregate for CAMP-1; and a read of which sessions belong to a series.On that last: CAMP-1 has no endpoint today and would otherwise be four client calls on the campaign's most-visited surface. Lane 1 gave Home the same treatment with
GET /api/me/home, so an aggregate here is consistent rather than novel.One gotcha found and worth writing down for whoever builds the timeline:
GET /{id}/milestonesdoes not only returnMilestonerows — it synthesises "reappeared" entries for NPCs' repeat appearances, withidset to a session id rather than a real primary key.MilestoneResponsetypesidasUUID | strto allow it. Anything consuming that list expecting a real key will be wrong.So the lane is eight PRs, three server and five UI, rather than the seven I first posted.
🤖 Generated with Claude Code
Lane 3 progress, and the departures the owner has settled
Merged so far: #763 (retention's cap, D24), #764 (the members' server, D56/D57), #765 (the reading surfaces' server), #766 (Highlights, Storyline, Analytics + the D14 filter), #767 (This week, the sessions list, and the D17 clock).
Open: #768, Members & characters (CAMP-8). Behind it, the Settings frame plus General, Invites & joining and Ownership (CAMP-9, CAMP-10, CAMP-11) is built and waiting on #768 to land. In flight: the new-session form and the series (CAMP-3, CAMP-4).
Departures — owner, 2026-09-23: all three fine
aria-pressed="true"in all three stills and its caption calls it "the part people miss"; leaving somebody named in approved summaries defeats the erase. The old page defaulted it off, and the consequence of this default is that an ordinary erase regenerates GM-approved text.aria-label="Add a member"on a button reading "Add someone" is a WCAG 2.5.3 label-in-name failure inherited from the old "+ Add" button; that one would have gone regardless./campaigns/:id/manage. Six of the nine sections — Discord, AI & recording, the wiki's rules, content packs, Foundry, and archive, export & delete — are still on the old campaign page, and that page has no address per section (it draws them inline;?open=takes only the first-run actions). Without the row they would leave the navigation entirely the day Settings arrived, and archiving or deleting a campaign is not something to reach only by typing an address. It goes with the last of them.Four drawn rows not built, and why
IS-272–IS-275, CAMP-8's Foundry panel. There is no server for it anywhere — the only Foundry code in the backend imports reference content for content packs; nothing fetches an actor, stores one or records a sync time. D36: a Foundry action is never a dead button, so the panel is absent rather than drawn dead.IS-276, the typed sheet link standing in for it, is built.Checking where it belongs found that it currently belongs to nobody: lane 11 (#737) names "WIKI-19 and its seams on … CAMP-8" in scope, but its own notes put Foundry-both-ways in "phase 2 … their own issues later". Recorded on #737 so those four rows land in phase 2's scope rather than surfacing later as a hole in CAMP-8.
One server change inside a UI PR
MemberResponse.pronouns(#768).IS-230asks for a person's pronouns beside their name and there was no wire for them —MemberResponsecarried the character's only, on the page built to stop #653's confusion. Eight lines and two tests; §7 wants server work first and as its own PR, so it is flagged here rather than split.Two test-infrastructure fixes this lane paid for
Home.test.jsx.vite.config.jsraisestestTimeoutto 15s, but that is not the clock these fail on: Testing Library keeps its own 1000msasyncUtilTimeout, and Home's first render measures ~570ms on a single core.configure({ asyncUtilTimeout: 5000 })in the shared setup (#767). Same hazard #755 fixed one instance of.AppFrame.test.jsxauto-merged without a conflict and was wrong twice over: once asserting Storyline was absent after #766 built it, once asserting Settings was absent after CAMP-8's split put it there. Both caught by running the suite on the merged tree before pushing, which is now worth doing on every lane-3 merge.🤖 Generated with Claude Code
Lane 3 is built: every surface, and both acceptance journeys
Acceptance
Both pass on desktop, phone and keyboard-only, with the axe scan clean at WCAG 2.2 AA on every page they reach.
a11y-baseline.jsis still{}.Merged, in order
Drawn rows deliberately not built
Each has somewhere to go, and none is drawn as a dead control (D36).
IS-272–IS-275) and all of CAMP-16 (IS-268–IS-271,IS-321). There's no Foundry server at all, and scenes aren't first-class (#689). Nine rows in all, recorded on #737 for phase 2.IS-053,IS-088). No server behind either; tracked in #779.IS-224–IS-226). Belongs to #125.IS-315's second half). No endpoint sets one.Found along the way and filed
a11y-baselinecan't key UUID paths---in the storyAlso fixed on the way: CI and tests
CI / *. On a PR that doesn't touch it, runs are about six minutes shorter.23c82b4: four timing races, all the same shape. Each test waited for the first thing on the page and asserted something that arrives later.Still open from J1's findings
These need a decision rather than a fix:
Leaving this open for the owner's review, as with #727.
🤖 Generated with Claude Code
Correction to the summary above: the nine Foundry rows aren't waiting on an unfiled "phase 2". They're already planned under v5.0.0 – FoundryVTT Phase 1: #5 (connection settings,
IS-268/IS-269), #6 (health check,IS-270/IS-271) and #8 (member-list sync, CAMP-8'sIS-272–IS-275).IS-321is #689's. Corrected on #737 too.🤖 Generated with Claude Code
Owner decisions, 2026-09-23: the open build questions B1–B13
Every question left open by lanes 0–3 was gathered and answered in one pass. The design tracker already had none open, and lanes 1–2's were settled earlier (Q1–Q9, D17).
{}in practice.Also approved, the small fixes:
---in the story/profile#notificationsalias not prompting🤖 Generated with Claude Code
Lane 3 completions merged in #802:
---between chapters.Also merged since the last update:
Filed from this work:
Lane 3 stays open for the owner's review.
🤖 Generated with Claude Code
The owner's review of lane 3 on dev, 2026-09-25. Looks right: This week, Sessions, the form, series, Members, erase, General, Discord, Archive, Highlights and Analytics.
Fix in batch R1 (
fix/review-r1):Changes:
Pending:
Signed off by the owner on the Redesign Review page, 2026-10-01. The R3 re-check for this lane (Settings → Recording) is marked OK. No changes asked for. Closing.