Skip to content

Release: Atlas Story and Ladder tabs, widget on Sonnet 5.5 (no OffSec) - #250

Merged
manager merged 3 commits into
mainfrom
release/atlas-tabs
Oct 13, 2026
Merged

manager merged 3 commits into
mainfrom
release/atlas-tabs

Conversation

@manager

@manager manager commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Production release authorized by Wolf on 2026-10-13. OffSec stays off main.

  • AI Atlas: the header row holds ATLAS / STORY / LADDER as an ink-framed switch with icons and falling leaves behind the unselected tabs. STORY and LADDER render the article (with its nine-step decomposition board and a legend for the red and blue marks) and the vibecoding ladder (climb plus level modal). Words come from src/lib/aiAtlas/readings.json, written by scripts/ai-atlas/strip-readings.mjs; tab and legend labels are pushable page words.
  • Widget: Copilot model moves from Claude Sonnet 5 to Sonnet 5.5 (already on staging since 2026-09-28).

Checks: git diff origin/main carries no OffSec lines; tsc --noEmit clean.

🤖 Generated with Claude Code

manager and others added 3 commits October 13, 2026 11:07
Anthropic released Claude Sonnet 5.5 (claude-sonnet-5-5) on 2026-09-28 and
Wolf ordered every Sonnet 5 default moved to it. The widget reaches Claude
through the subscription relay, which now runs Claude Code 2.1.284 and
answers claude-sonnet-5-5 (live probe 200, cli transport, track t1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header row after the brand now holds three tabs: ATLAS (the map),
ARTICLE and LADDER. They replace the welcome banner and the meta label.
The article carries its nine-step decomposition board; the ladder keeps
its climb and the level modal. Words come from readings.json, written by
scripts/ai-atlas/strip-readings.mjs from the source pages, which keeps
only what the tabs render. Tab labels are pushable page words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…legend

The header tabs become an ink-framed switch with the fill sliding to the
selected tab, a line icon per tab, and momiji leaves falling behind the
unselected ones (seeded after mount, paused on hover, gone under reduced
motion). ARTICLE is renamed STORY (hash stays #article). The story frame
carries a legend for the red and blue marks in its top padding. Legend
labels are pushable page words. Ported from the look accepted on the
Terminal's Atlas on 2026-10-13.

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

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Claude finished @manager's task in 23s —— View job


Review of PR #250: Atlas Story and Ladder tabs, widget on Sonnet 5.5

I reviewed the full diff in one pass. I didn't run tsc or the app, and I didn't read all 1390 added CSS lines or all 876 lines of readings.tsx. I sampled them for SSR safety, innerHTML use and font sizes.

Checked and fine

  • git diff origin/main | grep -ic offsec returns 0, so OffSec is not in the diff.
  • readings.tsx has no top-level window or document access. window.matchMedia is guarded by typeof window, and the other accesses sit inside functions and effects.
  • I found no innerHTML or dangerouslySetInnerHTML in readings.tsx. Marked text is rendered from {t, m} runs, so there is no XSS path.
  • The public-repo rules are respected. strip-readings.mjs reduces the source to visible words and ladder data, and logs/ is gitignored. I did not open readings.json to confirm it holds only rendered words.
  • The new tab and legend labels were added to PAGE_TEXT_DEFAULTS, and the tab labels to SHORT_LABEL_KEYS.
  • The CLAUDE_MODEL bump to claude-sonnet-5-5 matches the model ID.

Points to look at

  1. Font sizes vs the passport. Most new rules use var(--fs-*), which I could not resolve to px. The literal sizes 16px, 14px and 12px are all on the allowed list. Check that the --fs-* tokens also resolve to allowed values, and that nothing falls below 8px.
  2. Inline style in readings.tsx. Lines 723, 744 and 761 use style={{ ['--k' as any]: ... }}. This is the single-dynamic-property case that AGENTS.md allows, but the as any could be a typed CSSProperties cast.
  3. Imperative DOM in readings.tsx. The board and the level modal build DOM with createElementNS, createElement('div') and createElement('button'). This is a port of vanilla JS. It works if everything is cleaned up in effects (the resize listener is). It is fragile with React 19 strict-mode double effects, so confirm there are no duplicate nodes on remount.
  4. strip-readings.mjs (inline comment): vm.runInNewContext is not a sandbox, and the lazy regex in literal() can truncate nested literals.
  5. Tests. Only Playwright E2E applies in this repo. I saw no new test for tab switching or for the #hash sync that ai-atlas.tsx now handles for the new tabs.

No blockers found. Items 1 and 3 are worth a manual check on staging before the production release.

try {
const dir = process.argv[2];
if (!dir) throw new Error('usage: strip-readings.mjs <public folder>');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Minor: vm.runInNewContext is not a security boundary. It's fine for a local, trusted source folder, but add a one-line note in the header that the script must only be pointed at a trusted checkout. Also, literal() uses a lazy regex ending at the first ]\n or }\n, so a nested literal that closes on its own line will truncate silently. The throw on parse failure covers most cases, but a count check against the expected step count would be safer.

@manager

manager commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Review read, no change needed before merge:

  1. The --fs-* tokens resolve to 16, 20, 24 and 32px, all on the passport; nothing is below 12px.
  2. --k/--i are single dynamic custom properties, as AGENTS.md allows.
  3. The board effect clears the stage, the step bar and the tip box both before drawing and in its cleanup, so a strict-mode double run leaves one copy; the level modal is plain React.
  4. literal() cannot truncate silently: a cut literal is unbalanced and vm throws, which the script journals as a failure. The source folder is a trusted local checkout.
  5. No Playwright test added in this release.

🤖 Generated with Claude Code

@manager
manager merged commit b2db01d into main Oct 13, 2026
2 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