Build lane 1: the shell, Home and you (SH-1 to SH-9, HOME-1 to HOME-7) #727

Closed
opened 2026-09-22 00:12:19 +00:00 by claude-bot · 18 comments
Collaborator

Build lane 1 of the v4.5.0 redesign. The brief is docs/design/v4.5.0-brief.md (§9, the lanes in order); the build plan is docs/design/v4.5.0-build-plan.md (the rollout rule, the design-system mapping, the journeys as tests). Umbrella: #366. Goes after lane 0 (#364, the design system).

Scope

Surfaces: SH-1 to SH-9 (the shell, the Contents, the account menu, the bell, search, the footer, the patterns), HOME-1 to HOME-7 (Home, New campaign, Join, put away, Profile, Notifications, Plan & billing).
The drawing: /feedback/prototype/lane1 and lane1b — 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)

  • notifications (#655, IS-163 to IS-169): the bell, the grid of kinds by channel, per-campaign mute
  • Plan & billing on the hosted build only (#642): slots, credits, the provider hand-off, the grace period (IS-362, IS-376)
  • New campaign: templates and one-shots (IS-222, IS-223); the star-and-wish prompt (IS-213)
  • Profile: time away and weekly times as their own saves (SH-139, SH-142); calendar invites as a notification row (SH-133)

Acceptance

  • Every placement coverage/lane1.py and coverage/lane1b.py classifies as drawn or replaced is built as the prototype draws it; the script is the checklist. Rows it marks behaviour are tested, not drawn.
  • J1 (a GM's first campaign) as far as the shell and Home carry it, J2 (the bell and Home's Needs you) and J6 (Home's recap line) pass on desktop, on a phone and keyboard-only in the journeys suite (#726), with the axe scan clean (WCAG 2.2 AA, #367).
  • The brief's vocabulary (§5) throughout, from vocabulary.js; no page-level error destroys rendered content; every async operation shows progress and a next action on failure; disabled controls say why.
  • Main stays deployable after every PR of the lane: the new shell carries the old pages until each is replaced (the rollout rule).
  • The surfaces' headers in 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

  • This lane lands the vocabulary rename (§5) and introduces the journeys suite with the new shell, so later lanes add specs to a harness that exists.
  • The shell wraps the existing pages from this lane on: every old page renders inside the new app bar and Contents until its own lane replaces it.

🤖 Generated with Claude Code

**Build lane 1 of the v4.5.0 redesign.** The brief is `docs/design/v4.5.0-brief.md` (§9, the lanes in order); the build plan is `docs/design/v4.5.0-build-plan.md` (the rollout rule, the design-system mapping, the journeys as tests). Umbrella: #366. Goes after lane 0 (#364, the design system). ## Scope **Surfaces:** SH-1 to SH-9 (the shell, the Contents, the account menu, the bell, search, the footer, the patterns), HOME-1 to HOME-7 (Home, New campaign, Join, put away, Profile, Notifications, Plan & billing). **The drawing:** `/feedback/prototype/lane1` and `lane1b` — 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) - notifications (#655, `IS-163` to `IS-169`): the bell, the grid of kinds by channel, per-campaign mute - Plan & billing on the hosted build only (#642): slots, credits, the provider hand-off, the grace period (`IS-362`, `IS-376`) - New campaign: templates and one-shots (`IS-222`, `IS-223`); the star-and-wish prompt (`IS-213`) - Profile: time away and weekly times as their own saves (`SH-139`, `SH-142`); calendar invites as a notification row (`SH-133`) ## Acceptance - [ ] Every placement `coverage/lane1.py` and `coverage/lane1b.py` classifies as **drawn** or **replaced** is built as the prototype draws it; the script is the checklist. Rows it marks **behaviour** are tested, not drawn. - [ ] J1 (a GM's first campaign) as far as the shell and Home carry it, J2 (the bell and Home's Needs you) and J6 (Home's recap line) pass on desktop, on a phone and keyboard-only in the journeys suite (#726), with the axe scan clean (WCAG 2.2 AA, #367). - [ ] The brief's vocabulary (§5) throughout, from `vocabulary.js`; no page-level error destroys rendered content; every async operation shows progress and a next action on failure; disabled controls say why. - [ ] Main stays deployable after every PR of the lane: the new shell carries the old pages until each is replaced (the rollout rule). - [ ] The surfaces' headers in `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 - This lane lands the **vocabulary rename** (§5) and introduces the **journeys suite** with the new shell, so later lanes add specs to a harness that exists. - The shell wraps the existing pages from this lane on: every old page renders inside the new app bar and Contents until its own lane replaces it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Collaborator

Picking this up (2026-09-22), now that lane 0 (#364) has merged its three PRs. The PR series, in order, following the plan's working agreements (the server change first, then UI-only PRs):

  1. Notifications, the server side (#655's core, without Discussions, which wait for #654): the store, recipients worked out on the server from the audience rules, text built at read time with the reader's permissions, the in-app channel, the email adapter carrying today's recap-email opt-in over unchanged, and the API the bell and the settings grid read. Plus the campaign search endpoint SH-9 needs (one box, results tagged by kind, GM material filtered on the server).
  2. The shell around every existing page: AppLayout becomes the lane 0 shell (app bar, Contents rail and sheet, account menu, bell, search, footer, live bar); NavBar.jsx goes; the vocabulary rename (§5) lands in vocabulary.js and on the old pages. Main deployable, every old page inside the new frame.
  3. The journeys harness (#726), started in parallel now: the Compose overlay, the fake OIDC issuer, the mail catcher, the fake bot, the seed, Playwright in three projects, the journeys CI job; J1 and J2 as far as the shell carries them once (2) is in.
  4. Home (HOME-1 to HOME-4): Home replaces Dashboard, New campaign as a page opening on a choice (templates and one-shots, IS-222/IS-223), Join on Home, the fold for archived and binned campaigns, the star-and-wish prompt (IS-213).
  5. You (HOME-5 to HOME-7): Profile in sections with time away and weekly times as their own saves (SH-139/SH-142), Notifications as the grid (IS-361), Plan & billing on a hosted instance only (IS-362), calendar invites as a notification row (SH-133).

Each PR names its coverage rows from lane1.py and lane1b.py.

Picking this up (2026-09-22), now that lane 0 (#364) has merged its three PRs. The PR series, in order, following the plan's working agreements (the server change first, then UI-only PRs): 1. **Notifications, the server side** (#655's core, without Discussions, which wait for #654): the store, recipients worked out on the server from the audience rules, text built at read time with the reader's permissions, the in-app channel, the email adapter carrying today's recap-email opt-in over unchanged, and the API the bell and the settings grid read. Plus the campaign search endpoint SH-9 needs (one box, results tagged by kind, GM material filtered on the server). 2. **The shell around every existing page**: `AppLayout` becomes the lane 0 shell (app bar, Contents rail and sheet, account menu, bell, search, footer, live bar); `NavBar.jsx` goes; the vocabulary rename (§5) lands in `vocabulary.js` and on the old pages. Main deployable, every old page inside the new frame. 3. **The journeys harness** (#726), started in parallel now: the Compose overlay, the fake OIDC issuer, the mail catcher, the fake bot, the seed, Playwright in three projects, the `journeys` CI job; J1 and J2 as far as the shell carries them once (2) is in. 4. **Home** (HOME-1 to HOME-4): Home replaces Dashboard, New campaign as a page opening on a choice (templates and one-shots, IS-222/IS-223), Join on Home, the fold for archived and binned campaigns, the star-and-wish prompt (IS-213). 5. **You** (HOME-5 to HOME-7): Profile in sections with time away and weekly times as their own saves (SH-139/SH-142), Notifications as the grid (IS-361), Plan & billing on a hosted instance only (IS-362), calendar invites as a notification row (SH-133). Each PR names its coverage rows from `lane1.py` and `lane1b.py`.
Author
Collaborator

PR #742 is the shell around every page (series item 2), ahead of the server PR because the two are independent: everything the frame asks the server for is optional and degrades to nothing on a 404, so it can merge in either order. It carries the vocabulary rename too. The Contents lists only the pages that exist today; each missing entry is named in a comment against its lane.

Two decisions worth a look in the PR body: the library's components draw real links and stay free of react-router (so /design can render them), and the frame routes their clicks with one listener; and the frame is exactly the viewport, so an old page saying min-h-screen can scroll by a bar's height inside it until its lane replaces it.

PR #742 is the shell around every page (series item 2), ahead of the server PR because the two are independent: everything the frame asks the server for is optional and degrades to nothing on a 404, so it can merge in either order. It carries the vocabulary rename too. The Contents lists only the pages that exist today; each missing entry is named in a comment against its lane. Two decisions worth a look in the PR body: the library's components draw real links and stay free of react-router (so `/design` can render them), and the frame routes their clicks with one listener; and the frame is exactly the viewport, so an old page saying `min-h-screen` can scroll by a bar's height inside it until its lane replaces it.
Author
Collaborator

The server PR (series item 1) is built on build/lane1-notifications, whole backend suite green in Docker (3,674 passed, 88 new), the migration f5a6b7c8d9eb verified up, down and up against Postgres and matching the models name for name. Notifications (#655's core: store, recipients on the server, text rendered at read time with the reader's permissions, "No longer available", the email adapter with today's recap opt-in carried over and the recap email itself untouched), the settings grid and campaign mutes, campaign search, the campaign's live state, pronouns on /api/me, GET /api/meta, and docs/API.md. It rebases onto #742 and opens as a PR once that merges.

Two things it found that are decisions rather than code:

  1. GET /api/campaigns/{id}/search is already taken by the old campaign page's session-memory search (a bare array over summaries and transcripts). Two shapes cannot share a path without breaking that page on main, so the new one is /search-all for now; when lane 3 rebuilds the campaign page onto it, the old handler goes and this moves to /search. The shell's client changes one string.

  2. There is no session numbering in Quest Board. No column, field or concept anywhere, yet the prototype says "Session 14" on the Contents, the crumbs, the bell and the live bar. The server did not invent an ordinal (the nth session by date changes whenever one is cancelled), so for now every place the drawing says "Session 14" the app says the session's title, and the harness's fiction titles its sessions "Session 13: …" and "Session 14: …". If numbering is wanted for real, it is a column with a backfill and a rule for cancelled sessions: its own issue, and the owner's decision.

Smaller choices, all in the PR body: rsvp_requested folds into session_confirmed (one row for one moment, linking to the page the RSVP control is on); calendar_invite is defined but not fired, since it would double the bell for the same confirm; a vote-mode session's creation fires vote_opened (it counts the options) and a tentative one session_scheduled; muting also silences the recap email, and no existing user has a mute so nobody's mail changes today.

The server PR (series item 1) is built on `build/lane1-notifications`, whole backend suite green in Docker (3,674 passed, 88 new), the migration `f5a6b7c8d9eb` verified up, down and up against Postgres and matching the models name for name. Notifications (#655's core: store, recipients on the server, text rendered at read time with the reader's permissions, "No longer available", the email adapter with today's recap opt-in carried over and the recap email itself untouched), the settings grid and campaign mutes, campaign search, the campaign's live state, `pronouns` on `/api/me`, `GET /api/meta`, and `docs/API.md`. It rebases onto #742 and opens as a PR once that merges. Two things it found that are decisions rather than code: 1. **`GET /api/campaigns/{id}/search` is already taken** by the old campaign page's session-memory search (a bare array over summaries and transcripts). Two shapes cannot share a path without breaking that page on main, so the new one is **`/search-all`** for now; when lane 3 rebuilds the campaign page onto it, the old handler goes and this moves to `/search`. The shell's client changes one string. 2. **There is no session numbering in Quest Board.** No column, field or concept anywhere, yet the prototype says "Session 14" on the Contents, the crumbs, the bell and the live bar. The server did not invent an ordinal (the nth session by date changes whenever one is cancelled), so for now every place the drawing says "Session 14" the app says the session's title, and the harness's fiction titles its sessions "Session 13: …" and "Session 14: …". If numbering is wanted for real, it is a column with a backfill and a rule for cancelled sessions: its own issue, and the owner's decision. Smaller choices, all in the PR body: `rsvp_requested` folds into `session_confirmed` (one row for one moment, linking to the page the RSVP control is on); `calendar_invite` is defined but not fired, since it would double the bell for the same confirm; a vote-mode session's creation fires `vote_opened` (it counts the options) and a tentative one `session_scheduled`; muting also silences the recap email, and no existing user has a mute so nobody's mail changes today.
Author
Collaborator

#742 (the shell around every page, and the vocabulary rename) is merged on green CI. Main now shows every old page inside the new frame. The server PR and the harness are rebasing onto it; the harness's smoke journey is being rewritten against the new account menu and Contents, and the fiction is unified on the prototype's "Dana Whitlock".

#742 (the shell around every page, and the vocabulary rename) is merged on green CI. Main now shows every old page inside the new frame. The server PR and the harness are rebasing onto it; the harness's smoke journey is being rewritten against the new account menu and Contents, and the fiction is unified on the prototype's "Dana Whitlock".
Author
Collaborator

PR #744 is the server side (series item 1), rebased onto the shell: notifications, the settings grid and mutes, campaign search at /search-all with the shell's client pointed at it, the live endpoint with a reachable stale (the backend keeps a ten-minute memo of the last active recording it saw, so a bot that died mid-recording no longer reads as "not being recorded"), pronouns, and /api/meta. 3,684 backend tests, 98 new.

Next, chained on it so the migrations line up: Home's own server change (series item 4's first half): the three templates (a weekly series, a fortnightly vote, the setup of one of your own campaigns with nothing from its story), the one-shot preset (IS-223), and the star-and-wish prompt (IS-213, IS-216).

PR #744 is the server side (series item 1), rebased onto the shell: notifications, the settings grid and mutes, campaign search at `/search-all` with the shell's client pointed at it, the live endpoint with a reachable `stale` (the backend keeps a ten-minute memo of the last active recording it saw, so a bot that died mid-recording no longer reads as "not being recorded"), `pronouns`, and `/api/meta`. 3,684 backend tests, 98 new. Next, chained on it so the migrations line up: Home's own server change (series item 4's first half): the three templates (a weekly series, a fortnightly vote, the setup of one of your own campaigns with nothing from its story), the one-shot preset (IS-223), and the star-and-wish prompt (IS-213, IS-216).
Author
Collaborator

#744 (the server side) is merged on green CI. Main now has the notifications store and API, the settings grid and mutes, campaign search, the live endpoint, pronouns and /api/meta, and the shell's bell, search box and live bar read them. Open: #746 (the harness) in CI, #745 (the account menu's ARIA and contrast) being fixed, and Home's server change being built on top of this merge.

#744 (the server side) is merged on green CI. Main now has the notifications store and API, the settings grid and mutes, campaign search, the live endpoint, `pronouns` and `/api/meta`, and the shell's bell, search box and live bar read them. Open: #746 (the harness) in CI, #745 (the account menu's ARIA and contrast) being fixed, and Home's server change being built on top of this merge.
Author
Collaborator

PR #748 is Home's server side: the three templates, the one-shot preset (one session pencilled in through the ordinary path), and one star, one wish (asked once, the day after; the GM's read carries a name only when the person signed, and no user id at all). It also fixes #743 by honouring the eight fields campaign creation already validated. 3,760 backend tests, 55 new. Once it and the harness (#746) are on main, the Home UI PR follows: Home replaces Dashboard, New campaign as a page opening on a choice, Join on Home, the fold for archived and binned campaigns, and J1 and J2 filled in as far as Home carries them.

PR #748 is Home's server side: the three templates, the one-shot preset (one session pencilled in through the ordinary path), and one star, one wish (asked once, the day after; the GM's read carries a name only when the person signed, and no user id at all). It also fixes #743 by honouring the eight fields campaign creation already validated. 3,760 backend tests, 55 new. Once it and the harness (#746) are on main, the Home UI PR follows: Home replaces Dashboard, New campaign as a page opening on a choice, Join on Home, the fold for archived and binned campaigns, and J1 and J2 filled in as far as Home carries them.
Author
Collaborator

#748 (Home's server side) is merged on green CI, and #743 is closed by it. The Home UI PR (series item 4) is now being built: Home replaces Dashboard with Needs you, the star-and-wish prompt, the campaign cards with This week / Last time and the recap line, Join in place, and the put-away fold; New campaign as its own page opening on the four choices; a GET /api/me/home aggregate so the cards are one request; and J1 and J2 filled in as far as Home carries them once the harness (#746, rebased and back in CI after a conflict with #747) is on main.

#748 (Home's server side) is merged on green CI, and #743 is closed by it. The Home UI PR (series item 4) is now being built: Home replaces Dashboard with Needs you, the star-and-wish prompt, the campaign cards with This week / Last time and the recap line, Join in place, and the put-away fold; New campaign as its own page opening on the four choices; a `GET /api/me/home` aggregate so the cards are one request; and J1 and J2 filled in as far as Home carries them once the harness (#746, rebased and back in CI after a conflict with #747) is on main.
Author
Collaborator

The harness (#746) is merged, so the Home PR can carry J1 and J2. Merged today on this lane: #742 (the shell), #744 (the server side), #747 (the account menu fix), #748 (Home's server side); open: the Home UI PR in progress, then You.

The harness (#746) is merged, so the Home PR can carry J1 and J2. Merged today on this lane: #742 (the shell), #744 (the server side), #747 (the account menu fix), #748 (Home's server side); open: the Home UI PR in progress, then You.
Author
Collaborator

PR #749 is Home (series item 4): Needs you, the star-and-wish card, the campaign cards from a new GET /api/me/home, Join in place, the put-away fold, New campaign as a page opening on the four choices, and J1 and J2 as far as Home carries them, green in all three projects with /dashboard and /campaigns/new clean under the strict axe gate. The journeys found three more defects in the shell on the way (an underline-less link in a sentence, the bell drawing eight of twelve kinds, and the bar's link colour reaching into the bell's popover), all fixed in the PR.

One thing for the owner in the PR body: Needs you says a time in the reader's zone while the card beside it says it in the campaign's, because /api/me/attention carries no zone. The You PR (series item 5) is being built in parallel and follows.

PR #749 is Home (series item 4): Needs you, the star-and-wish card, the campaign cards from a new `GET /api/me/home`, Join in place, the put-away fold, New campaign as a page opening on the four choices, and J1 and J2 as far as Home carries them, green in all three projects with `/dashboard` and `/campaigns/new` clean under the strict axe gate. The journeys found three more defects in the shell on the way (an underline-less link in a sentence, the bell drawing eight of twelve kinds, and the bar's link colour reaching into the bell's popover), all fixed in the PR. One thing for the owner in the PR body: Needs you says a time in the reader's zone while the card beside it says it in the campaign's, because `/api/me/attention` carries no zone. The You PR (series item 5) is being built in parallel and follows.
Author
Collaborator

#749 (Home) is merged on green CI, with J1 and J2 green on the runner. Five of the lane's six PRs are on main; the last, You (Profile in sections, Notifications as the grid, Plan & billing on a hosted instance), is being built and will follow.

#749 (Home) is merged on green CI, with J1 and J2 green on the runner. Five of the lane's six PRs are on main; the last, You (Profile in sections, Notifications as the grid, Plan & billing on a hosted instance), is being built and will follow.
Author
Collaborator

PR #750 is You, the lane's last (series item 5): Profile in sections with pronouns and three independent saves, Notifications as the grid (a recaps category and calendar invites on the server side; Discord DM listed as unavailable until lane 10 delivers it, so no switch is offered that does nothing), and Plan & billing behind #642's phase 1 entitlements read, which answers "not hosted" on every real instance today so the page and its menu entry stay absent. Its journey walks the You pages in all three projects, strict-clean. 1,236 frontend and 3,821 backend tests.

After it merges, the lane's remaining gaps are the three rows deliberately left with a comment: IS-195 (the ownership-offer row on Home wants a row on /api/me/attention), IS-152 (Discussions kinds, lanes 7 and 8) and IS-376 (the hosted slot line on New campaign, with #642's provider). And for the owner: Needs you's time zone versus the card's (#749), and whether sessions should carry a real number.

PR #750 is You, the lane's last (series item 5): Profile in sections with pronouns and three independent saves, Notifications as the grid (a `recaps` category and calendar invites on the server side; Discord DM listed as unavailable until lane 10 delivers it, so no switch is offered that does nothing), and Plan & billing behind #642's phase 1 entitlements read, which answers "not hosted" on every real instance today so the page and its menu entry stay absent. Its journey walks the You pages in all three projects, strict-clean. 1,236 frontend and 3,821 backend tests. After it merges, the lane's remaining gaps are the three rows deliberately left with a comment: IS-195 (the ownership-offer row on Home wants a row on `/api/me/attention`), IS-152 (Discussions kinds, lanes 7 and 8) and IS-376 (the hosted slot line on New campaign, with #642's provider). And for the owner: Needs you's time zone versus the card's (#749), and whether sessions should carry a real number.
Author
Collaborator

#750 (You) is merged on green CI. Lane 1's build is complete: six PRs on main today, in order #742 (the shell around every page, and the vocabulary rename), #744 (notifications, campaign search and the live endpoint), #747 (the account menu's ARIA and contrast, found by the gate), #748 (templates, the one-shot and one star, one wish), #749 (Home, New campaign, Join, the fold, J1 and J2) and #750 (Profile in sections, the notifications grid, Plan & billing behind the entitlements read), with the harness (#746, closed as #726) in between.

Against the acceptance list: every placement lane1.py and lane1b.py classifies as drawn or replaced is built except the three left with a comment naming their owner (IS-195 wants an offer row on /api/me/attention; IS-152 is lanes 7 and 8; IS-376 waits for #642's hosted provider) and the Contents entries whose pages later lanes add; J1, J2 and J6's recap line pass on desktop, phone and keyboard-only with the axe scan strict on every rebuilt page; the vocabulary is vocabulary.js's; main stayed deployable after every PR; the surface headers were honoured, with the departures written into the PR bodies (the crumb bolds the campaign; Join's expired-code message stays deliberately unspecific; "Read the last recap" only when there is one; Discord DM not offered until lane 10).

Left open for the owner's review on the dev server, per the rollout rule, and for two decisions raised on the way: whether sessions should carry a real number (today the prototype's "Session 14" is the session's title), and a time zone on /api/me/attention so Needs you and the card beside it agree.

#750 (You) is merged on green CI. **Lane 1's build is complete**: six PRs on main today, in order #742 (the shell around every page, and the vocabulary rename), #744 (notifications, campaign search and the live endpoint), #747 (the account menu's ARIA and contrast, found by the gate), #748 (templates, the one-shot and one star, one wish), #749 (Home, New campaign, Join, the fold, J1 and J2) and #750 (Profile in sections, the notifications grid, Plan & billing behind the entitlements read), with the harness (#746, closed as #726) in between. Against the acceptance list: every placement `lane1.py` and `lane1b.py` classifies as drawn or replaced is built except the three left with a comment naming their owner (IS-195 wants an offer row on `/api/me/attention`; IS-152 is lanes 7 and 8; IS-376 waits for #642's hosted provider) and the Contents entries whose pages later lanes add; J1, J2 and J6's recap line pass on desktop, phone and keyboard-only with the axe scan strict on every rebuilt page; the vocabulary is `vocabulary.js`'s; main stayed deployable after every PR; the surface headers were honoured, with the departures written into the PR bodies (the crumb bolds the campaign; Join's expired-code message stays deliberately unspecific; "Read the last recap" only when there is one; Discord DM not offered until lane 10). Left open for the owner's review on the dev server, per the rollout rule, and for two decisions raised on the way: whether sessions should carry a real number (today the prototype's "Session 14" is the session's title), and a time zone on `/api/me/attention` so Needs you and the card beside it agree.
Author
Collaborator

Both of this lane's open questions are answered (owner, 2026-09-22).

Sessions get a real number — D86, and #760 is the work

Given at creation, frozen, never reused. A cancelled session keeps its number, so the sequence has gaps: 12, 13, 15.

The gap is the cost and it was chosen over the alternative deliberately. The nth-session-by-date renumbers everything after a cancellation, and by then somebody has written "session 12" in the wiki, a recap or a Discord message — a number that skips is honest; a number that shifts is a lie about something already written down.

Filed as #760 with the column, the backfill rule, the concurrency point and the places it has to surface. Its natural home is lane 4 (#730), as that lane's server PR, since lane 4 rewrites every surface that names a session; doing it there means lane 4 builds against a number instead of retrofitting one. Until then the title stays, which looks right and is what this lane shipped.

/api/me/attention gains the campaign's time zone

Answered: do it. Needs you was stating a session's time in the reader's zone while the card beside it stated the same session in the campaign's — and Home.jsx's own comment on whenText had already settled which wins ("that is the night the table agreed on; a player travelling should still see the same one"). This was a defect rather than a design question; I only asked because the fix is a server change in a lane that had closed.

In progress on fix/owner-answers-code, with SH-088's missing link and D89's twelve-month count.


That leaves this issue with nothing open but your review on the dev server. The three rows deliberately left with a comment are unchanged and still belong to later lanes: IS-195 (the ownership-offer row wants a row on /api/me/attention), IS-152 (Discussions, lanes 7 and 8), IS-376 (the hosted slot line, #642's provider).

🤖 Generated with Claude Code

**Both of this lane's open questions are answered (owner, 2026-09-22).** ## Sessions get a real number — **D86**, and #760 is the work Given at creation, frozen, never reused. A cancelled session keeps its number, so the sequence has gaps: 12, 13, 15. The gap is the cost and it was chosen over the alternative deliberately. The *n*th-session-by-date renumbers everything after a cancellation, and by then somebody has written "session 12" in the wiki, a recap or a Discord message — **a number that skips is honest; a number that shifts is a lie about something already written down.** Filed as **#760** with the column, the backfill rule, the concurrency point and the places it has to surface. Its natural home is lane 4 (#730), as that lane's server PR, since lane 4 rewrites every surface that names a session; doing it there means lane 4 builds against a number instead of retrofitting one. Until then the title stays, which looks right and is what this lane shipped. ## `/api/me/attention` gains the campaign's time zone Answered: do it. Needs you was stating a session's time in the reader's zone while the card beside it stated the same session in the campaign's — and `Home.jsx`'s own comment on `whenText` had already settled which wins ("that is the night the table agreed on; a player travelling should still see the same one"). This was a defect rather than a design question; I only asked because the fix is a server change in a lane that had closed. In progress on `fix/owner-answers-code`, with `SH-088`'s missing link and D89's twelve-month count. --- **That leaves this issue with nothing open but your review on the dev server.** The three rows deliberately left with a comment are unchanged and still belong to later lanes: `IS-195` (the ownership-offer row wants a row on `/api/me/attention`), `IS-152` (Discussions, lanes 7 and 8), `IS-376` (the hosted slot line, #642's provider). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Collaborator

A correction to this lane, and to something I told you.

Lane 3 caught it: Home shows a session's time in the campaign's zone, and D17 says it should be the reader's.

D17, verbatim:

Session times were to be shown in the campaign's zone and the reader's, side by side (IS-003). Two times make the reader work out which one is theirs.
→ One time, always the reader's own, always carrying its timezone abbreviation — the abbreviation is what tells a traveller their device has moved. When the reader's day differs from the table's, a line reconciles the two ("the table calls this Monday's session"); it appears only when there is something to reconcile. Supersedes IS-003.

Home.jsx's helper carries a comment saying the opposite — "that is the night the table agreed on; a player travelling should still see the same one" — which reads like a rule and is not one. It is a rationale written during the build, and it contradicts a decision that had already been made, for a stated reason that is the direct answer to it: the point of showing the reader's own zone is that the abbreviation is what tells a traveller their device has moved.

I then propagated it. When you answered "do it" to the time-zone question a few hours ago, I moved Needs you onto the campaign's zone in #762 so it would agree with the card beside it, and told you it followed "a rule the product already made". The disagreement between those two lines was real and worth fixing; I fixed it in the direction D17 rules out, on the strength of a code comment I should have checked against the decisions table.

What is being done

Lane 3's This-week PR was built the same wrong way, because my brief told it to be — but the delegate flagged that the CAMP-1 drawing says the reader's zone, which is what surfaced this. The owner has confirmed D17 stands, so the fix lands in that PR:

  • one time, the reader's own, always with its zone abbreviation;
  • the reconciliation line flips to D17's own direction and still appears only when the day differs;
  • Home's campaign cards, Home's Needs you rows and This week all go through one helper (utils/when.js, consolidated by that PR), so they change together and cannot drift again;
  • the comment that asserted the old rationale is rewritten to cite D17, so it is not reinstated by the next reader.

/api/me/attention keeps the campaign's timezone that #762 added — it is what the reconciliation line is drawn from. Only its use changes.

Nothing else in this lane is affected, and the lane stays complete.

🤖 Generated with Claude Code

**A correction to this lane, and to something I told you.** Lane 3 caught it: **Home shows a session's time in the campaign's zone, and D17 says it should be the reader's.** D17, verbatim: > Session times were to be shown in the campaign's zone and the reader's, side by side (`IS-003`). Two times make the reader work out which one is theirs. > → **One time, always the reader's own**, always carrying its timezone abbreviation — the abbreviation is what tells a traveller their device has moved. When the reader's *day* differs from the table's, a line reconciles the two ("the table calls this Monday's session"); it appears only when there is something to reconcile. **Supersedes `IS-003`.** `Home.jsx`'s helper carries a comment saying the opposite — *"that is the night the table agreed on; a player travelling should still see the same one"* — which reads like a rule and is not one. It is a rationale written during the build, and it contradicts a decision that had already been made, for a stated reason that is the direct answer to it: the point of showing the reader's own zone is that the **abbreviation** is what tells a traveller their device has moved. **I then propagated it.** When you answered "do it" to the time-zone question a few hours ago, I moved Needs you *onto* the campaign's zone in #762 so it would agree with the card beside it, and told you it followed "a rule the product already made". The disagreement between those two lines was real and worth fixing; I fixed it in the direction D17 rules out, on the strength of a code comment I should have checked against the decisions table. ## What is being done Lane 3's This-week PR was built the same wrong way, because my brief told it to be — but the delegate flagged that the CAMP-1 drawing says the reader's zone, which is what surfaced this. The owner has confirmed **D17 stands**, so the fix lands in that PR: - one time, the **reader's own**, always with its zone abbreviation; - the reconciliation line flips to D17's own direction and still appears **only when the day differs**; - Home's campaign cards, Home's Needs you rows and This week all go through one helper (`utils/when.js`, consolidated by that PR), so they change together and cannot drift again; - the comment that asserted the old rationale is rewritten to cite D17, so it is not reinstated by the next reader. `/api/me/attention` keeps the campaign's `timezone` that #762 added — it is what the reconciliation line is drawn *from*. Only its use changes. Nothing else in this lane is affected, and the lane stays complete. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Collaborator

The owner's review of lane 1 on dev, 2026-09-25. Most items look right: the frame, search, the bell, campaign cards, joining, Notifications, and Profile.

Fixes in batch R1 (fix/review-r1):

  • R1-1: Home's Needs you count doesn't drop after voting until a full reload, even after navigating away. It's cached above the route.
  • R1-2: the calendar feed shows up in Google Calendar named by its URL. The fix adds X-WR-CALNAME/NAME.
  • R1-7 (D107): a one-shot's "when" on New campaign is free text. It becomes a date, with an optional time.

Layout: "on a 4k monitor, this feels very left-heavy. 40% of the page is completely blank." Three wide-screen options are being mocked in the real app at 2560×1440, for the owner to choose. That will revise D90.

Answered or pending:

  • The skip link and focus moving to the heading: explained; the owner will re-check.
  • Star and wish: couldn't be triggered on dev. The demo seed (#821) sets it up for the owner's account.
  • The bell: nothing was pending to test with. #821 seeds pending items.
**The owner's review of lane 1 on dev, 2026-09-25.** Most items look right: the frame, search, the bell, campaign cards, joining, Notifications, and Profile. **Fixes in batch R1 (`fix/review-r1`):** - **R1-1:** Home's Needs you count doesn't drop after voting until a full reload, even after navigating away. It's cached above the route. - **R1-2:** the calendar feed shows up in Google Calendar named by its URL. The fix adds `X-WR-CALNAME`/`NAME`. - **R1-7 (D107):** a one-shot's "when" on New campaign is free text. It becomes a date, with an optional time. **Layout:** "on a 4k monitor, this feels very left-heavy. 40% of the page is completely blank." Three wide-screen options are being mocked in the real app at 2560×1440, for the owner to choose. That will revise D90. **Answered or pending:** - The skip link and focus moving to the heading: explained; the owner will re-check. - Star and wish: couldn't be triggered on dev. The demo seed (#821) sets it up for the owner's account. - The bell: nothing was pending to test with. #821 seeds pending items.
Author
Collaborator

Signed off by the owner on the Redesign Review page, 2026-10-01 ("Looks a lot better. Nice work!"), with one request: "The one thing I would like is for clicking on Quest Board at the top to take me back out to home if I'm in a campaign."

That change is being built under #1020. This issue closes when it is on main.

**Signed off by the owner on the Redesign Review page, 2026-10-01** ("Looks a lot better. Nice work!"), with one request: "The one thing I would like is for clicking on Quest Board at the top to take me back out to home if I'm in a campaign." That change is being built under #1020. This issue closes when it is on main.
Author
Collaborator

Closing: the owner's one request is on main. PR #1024 merged (main bcf22996, CI green on 8972bead): the "Quest Board" wordmark is a link to Home on every page of the app. The lane was signed off on the Redesign Review page on 1 October.

The same PR moved the footer to the end of the page's scroll at every width (the owner's instruction of 2 October, which supersedes the fixed footer this lane was signed off with) and made a clicked notification mark itself read. Four unrelated layout faults seen while checking it are in #1023. Not on dev until the next deploy.

**Closing: the owner's one request is on main.** PR #1024 merged (main `bcf22996`, CI green on `8972bead`): the "Quest Board" wordmark is a link to Home on every page of the app. The lane was signed off on the Redesign Review page on 1 October. The same PR moved the footer to the end of the page's scroll at every width (the owner's instruction of 2 October, which supersedes the fixed footer this lane was signed off with) and made a clicked notification mark itself read. Four unrelated layout faults seen while checking it are in #1023. Not on dev until the next deploy.
Sign in to join this conversation.
No project
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#727
No description provided.