Skip to content

Release: staging batch without OffSec - #246

Merged
manager merged 14 commits into
mainfrom
release/prod-no-offsec
Sep 25, 2026
Merged

manager merged 14 commits into
mainfrom
release/prod-no-offsec

Conversation

@manager

@manager manager commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Production release: everything that is on staging except the OffSec layer, which stays on DEV and staging. Not merged; waits for Wolf's go.

  • Library: more than 15 books opens the AI shelf and the magic books without the flag (supersedes Library: more than 15 books opens the AI without the flag #244).
  • Library: phone layout stays as wide as the phone, one loader per visit, avatars at their own size, the Add control pulses on an empty library, the info panel no longer widens the page in Safari.
  • Library: AI shelf and magic books default to Claude Opus 5.5; cover hotspots find their library by owner id.
  • Login: branded loader over the hand-off, no grey banding.
  • UX Core: Arc of Self nav item, single-row navbar, Our Projects modal pass.
  • Copilot: Claude Sonnet 5 through the subscription relay, paid OpenAI fallback removed, replies arrive whole; quieter Ask UX Core pill.
  • AI Atlas: a pushed guide with a field of the wrong shape is refused.

Built from main plus the non-OffSec commits of the staging branch; no OffSec file or string in the diff. Checks run: node scripts/release/library-batch-check.cjs PASS, tsc --noEmit clean.

🤖 Generated with Claude Code

manager and others added 13 commits September 25, 2026 20:37
The AI shelf and the magic books now open to an owner who holds the
library-ai flag or whose library holds more than 15 books (type book,
every shelf). One check, opensLibraryAi, decides for the page and both
routes; the count is read from the library on each check, nothing is
stored. The AI shelf keeps its own 30-book lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The idle pill drops to 34px, smaller label, 0.7 opacity, and loses the
orange pulse glow, so it stops burying the host page's bottom-corner
buttons and text. Full opacity returns on hover, while the panel is
open, and in the relevance-nudge state, whose pulse is also toned down.
Opacity stops at 0.7 because the 12px label must keep the 4.5:1
contrast floor over light pages. Mobile pill shrinks in step. Bundle
rebuilt, so the change is live on every locale.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
(cherry picked from commit d957e9b)
…ts modal pass

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 7fcd5ec)
…rey banding

The /auth, magic-link and email-change pages hold almost no markup while the
provider handshake runs. Two defects came out of that:

- The body gradient is propagated to the canvas but sized against the root
  box, so on those near-empty documents it tiled down the viewport as grey
  bands. The root now holds viewport height and the gradient no longer repeats.
- /auth rendered the shared Spinner without its visible prop, so it drew
  nothing at all and left the bare document on screen. All three pages now
  render AuthLoader: a full-viewport paper surface with the house brain loader,
  dark-theme aware, honouring prefers-reduced-motion.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
(cherry picked from commit 55af48d)
The merge took prod's side on every conflicted file, which dropped three
fixes this branch had made against the August structure. Rebuilt on the
new one:

- The info panel again sits in a host that is transparent to layout on
  desktop and a fixed clipping layer at the drawer breakpoints, so the
  panel parked off the right edge stops counting towards the page's
  scrollable width. Without it Safari measures a library page about two
  screens wide on a phone. The CSS for it had survived the merge with no
  element to apply to.
- The Add controls pulse again while the library holds no objects. Prod
  rewrote the empty-shelf area out of Shelf, so only the header control
  carries it now, and the round-control animation goes with the control
  it belonged to.
- The avatar boxes declare their own widths again (48px panel, 152px
  edit dialog) instead of paying for the home card's headroom.

The fourth, the single-request library load, is not rebuilt: prod paints
the library on the server, so the two round trips it removed no longer
happen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 45a2db7)
Thinking is disabled explicitly on every Claude call, since Sonnet 5
runs adaptive thinking when the field is omitted, and the reply caps
grow from 600 to 800 and 360 to 480 tokens for its larger tokenizer.
Authorized by Wolf on 2026-09-22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit cd740e3)
The concierge and landing routes no longer hold a paid Anthropic key.
They ask claude-sonnet-5 at low effort through the relay, which moves a
call from track t1 to t2 to t3 on a rate limit, and read the reply JSON
out of the text since the relay runs one turn without tools. A
streaming caller now gets the whole reply at once. Authorized by Wolf
on 2026-09-22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit d6c6b74)
Claude through the subscription relay is the only model the concierge
and landing routes call. When every track is spent the reply is empty
and the widget stays quiet instead of switching to a paid key.
Authorized by Wolf on 2026-09-22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit bac80e9)
The cover's buildings were bound to usernames. Two owners renamed
themselves on production (Mary13 is now Mary, alinamarg is now Alina), so
their buildings matched no library and the hover card showed only a name
with no About or object counts. Hotspots now carry the owner's account id,
which survives a rename and is the same on staging, whose database is a
copy of production's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit c1aaa5f)
Titles, texts and the detail and children lists on steps, entries and
system nodes are now checked as text before the guide is stored. Before,
an object in a title passed adaptGuide and broke the page only when a
visitor opened that dossier. Raised by the review on #245.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 20428ab)
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Claude finished @manager's task in 6m 45s —— View job


Review complete

  • Gather context (PR description, changed files, diff vs origin/main)
  • Understand the request (code review of this release PR)
  • Review correctness / React best practices
  • Review TypeScript quality
  • Review AGENTS.md convention compliance
  • Review accessibility & UX
  • Review security
  • Review styling / SCSS hygiene
  • Post inline comments for concrete issues
  • Post final summary

Summary

Went through the full diff against origin/main (52 files, matches the PR's stated stats). This is a batch of independent, well-scoped changes — Library AI-by-books, avatar sizing/sizes fixes, cover hotspots by owner id, the Safari sidebar-width fix, the auth loader, UX Core nav/podcast-modal work, and the Copilot relay-only refactor. Two concrete issues, left as inline comments:

  1. CLAUDE.md now links to docs/voice-guide.md, which doesn't exist anywhere in the tree and isn't added by this PR — a dead link in the instructions every agent reads (docs/ is also gitignored for new files per this same file's Commit Hygiene section).
  2. ToolHeader.tsx / ToolHeader.module.scss — the new "Arc of Self" nav item loses its accessible name entirely below the 1160px breakpoint (label text is display: none, icon has no title/aria-label, and the explanatory tooltip is aria-hidden and hover-only with no focus-visible fallback).

Everything else checked out:

  • No OffSec strings/files anywhere in the diff — matches the PR's claim.
  • library-batch-check.cjs additions correctly cover countBooks/opensLibraryAi including the >15 boundary, and both ai-shelf.ts/magic-book.ts route to libraryAi: true consistently with ownerOfLibrary's new requires.libraryAi check (population query already includes singleShelves/objects, so the book count has data to work with).
  • concierge.ts / concierge-landing.ts / llmClient.ts refactor to the subscription relay is clean — no dangling references to the removed ANTHROPIC_KEY/OPENAI_* exports, and the raw.text narrowing in concierge.ts type-checks correctly through the JsonValue union.
  • Sidebar's drawerHost wrapper is a mechanical re-indent plus the new fixed/paint-contained clipping layer (with pointer-events: none/auto split correctly) — matches the stated Safari overflow-width fix.
  • All new/changed pulse and tooltip animations have prefers-reduced-motion: reduce handling (Library.module.scss, Shelf.module.scss, Sidebar.module.scss, AuthLoader.module.scss).
  • Font sizes touched in widget/src/styles.css and elsewhere stay within the font passport's allowed list (12/13/14/15/16px); the widget's new .ks-aux-pill opacity dip to 0.7 checks out at ≥4.5:1 contrast against white/black/gray host backgrounds by my estimate, though contrast against an arbitrary embedding page's background can't be fully guaranteed by CSS alone — worth a manual spot-check if time allows, not blocking.
  • stripGuide.ts's new fieldsError uses any consistently with the rest of that file's existing boundary-validation style for untrusted Terminal-pushed JSON — not a new convention violation.
  • Hardcoded owner ids in coverHotspots.ts (7/10/538) replace hardcoded usernames for the same three libraries; reasoning is documented inline and isn't a new class of exposure vs. what was already there.

No test suite exists to run (Playwright E2E only per AGENTS.md, not wired into this review), and I did not execute tsc --noEmit or the batch-check script myself — the PR description states both pass; nothing in the diff contradicts that.

Comment thread CLAUDE.md Outdated
- No AI-isms: no "let me know if…", no "happy to help", no preamble before the answer.
- Reference piece: **"The Rise of the Choice Architect"** (article on keepsimple.io). Match its register.

Worked examples: [docs/voice-guide.md](docs/voice-guide.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a link to docs/voice-guide.md, but that file doesn't exist anywhere in the tree (not tracked, not added by this PR) — docs/ is gitignored for new files per the Commit Hygiene section further down this same file. Right now this is a dead link in the project instructions every agent reads. Either add and commit the file in this PR, or drop the line until it exists.

Fix this →

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d60cbcb: the line is dropped from CLAUDE.md.

/>
)}
{isArc && (
<span className={styles.ArcTooltip} aria-hidden>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility: below 1160px, .ArcLabel (the only visible text for this link) is set to display: none in ToolHeader.module.scss (@media (max-width: 1160px) { .ArcLabel { display: none; } }, line ~512), and ArcOfSelfIcon is a bare <svg> with no <title>/aria-label. At that breakpoint the <a> has no accessible name at all for screen reader / accessibility-tree purposes — display: none removes the text node from the tree too.

The tooltip that would explain the icon (arcOfSelfTooltip) is marked aria-hidden here and only shown via @media (hover: hover) { .ArcMenuItem:hover .ArcTooltip { ... } } — CSS :hover only, no :focus/:focus-visible variant — so keyboard users get neither a label nor the tooltip.

Suggest adding aria-label={itemLabel} (or similar) to the anchor for the Arc of Self item so it always has an accessible name regardless of breakpoint, and adding a :focus-visible trigger alongside :hover for the tooltip.

Fix this →

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d60cbcb: the Arc of Self anchor carries aria-label with its label, so it keeps an accessible name below 1160px, and the tooltip also shows on :focus-visible.

…c link

The Arc of Self link carries aria-label, so it keeps an accessible name
when its label is hidden on narrow screens, and its tooltip also shows on
keyboard focus. CLAUDE.md no longer links a voice guide that is not in the
tree. Raised by the review on #246.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Claude finished @manager's task in 1m 11s —— View job


Re-review complete

  • Diff PR vs origin/main for what changed since last review
  • Verify the docs/voice-guide.md dead-link fix
  • Verify the Arc of Self accessibility fix (accessible name below 1160px, focus-visible tooltip)
  • Re-scan rest of diff for anything new
  • Post updated summary

Summary

The only change since the last pass is d60cbcb ("Arc of Self keeps its name below 1160px, drop a dead doc link"), which resolves both issues raised in the previous review. Confirmed:

  1. Dead doc link — the Worked examples: [docs/voice-guide.md](docs/voice-guide.md) line is removed from CLAUDE.md. No dangling reference left.
  2. Arc of Self accessibility — src/uxcore/components/ToolHeader/ToolHeader.tsx:357 now sets aria-label={isArc ? itemLabel : undefined} directly on the <a className={styles.MenuItem}> element. Since aria-label takes precedence in accessible-name computation regardless of what's visually hidden, the link keeps a real accessible name below the 1160px breakpoint even though .ArcLabel is still display: none there. ToolHeader.module.scss also adds .ArcMenuItem:focus-visible .ArcTooltip { opacity: 1; visibility: visible; ... } alongside the existing @media (hover: hover) :hover rule — since .ArcMenuItem is the anchor itself (not a wrapper), the descendant selector correctly reaches the nested .ArcTooltip span on keyboard focus. Both keyboard and screen-reader users now get equivalent information to mouse/hover users.

No new issues introduced by this commit, and the rest of the diff (Library AI-by-books, avatar/shelf/sidebar fixes, auth loader, Copilot relay refactor, AI Atlas guide validation) is unchanged from the prior review — see that pass for the full breakdown. Diff stat still matches the PR description (51 files, +1125/-774), and no OffSec strings/files are present.

Nothing further to flag. Both inline comments from the previous review can be considered resolved.

@manager
manager merged commit d08d202 into main Sep 25, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant