Skip to content

Upstream checkpoint cd8c2c593275 (452 commits, #20967..) + main 12c3dc37 - #161

Merged
Nurozen merged 460 commits into
mainfrom
upstream/batch-cd8c2c593275-6ddf37
Oct 29, 2026
Merged

Nurozen merged 460 commits into
mainfrom
upstream/batch-cd8c2c593275-6ddf37

Conversation

@Nurozen

@Nurozen Nurozen commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Upstream checkpoint cd8c2c5

True merge of pingdotgg/t3code through cd8c2c593275147d7f253ca0fd93dbe6088237b1 (452 upstream first-parent commits after accepted 16918b57d675, pingdotgg#20967 onward) into Lecturn main 7ce4e260b283 (commit b32b5409), then a merge of current main 12c3dc37 (commit 18f0d00a), then review and evidence fixes. 253 upstream conflicts and 31 main conflicts resolved into Lecturn's architecture and identity.

What changes

Regressions found during verification and fixed here

  • Mobile render loop (1d008797): under the React Compiler, any focused screen with an inspector pane (Review with a diff, tablet Files) hit "Maximum update depth exceeded". The same code is in upstream cd8c2c5; this ports upstream's later fix 325a7e2 (fix(mobile): the split-view sidebar no longer crashes in an update loop pingdotgg/t3code#21867) and keeps inspector registration in a ref. Found by the Android capture.
  • Sidebar title width (8f8501ab): upstream fix(web): pinned thread marker stays put when hovering the row pingdotgg/t3code#11122's status slot reserved the hover actions' width at rest, and Lecturn's card rows put the title on that line, so titles lost 42% of their width (121 to 70 px). Titles are back to 121 px; a hovered pinned row keeps its pin in place, as fix(web): pinned thread marker stays put when hovering the row pingdotgg/t3code#11122 intends, at the cost of showing about 14 px of title while hovered.
  • Android tablet header (b9336fdf): with the Apps tab, "Lecturn" wrapped onto two lines in the 280 dp sidebar. The wordmark is single-line, and below a 320 dp row "Show apps"/"Show pull requests" move into a "More actions" menu.
  • Smaller fixes (d34966da, 8f8501ab): the queue drag gesture is no longer rebuilt every render; OpenCode reports a failed Lecturn MCP add only while MCP is not up yet; release CLI builds stamp the telemetry channel; upstream test fixtures use Lecturn names.
  • Greptile findings (d8ec6bc9): migrated pull request links keep the unknown link date, so threads edited after their PR merged still auto-settle; the pnpm update probe checks the pnpm the update runs; an expired mobile Connect account gets the sign-in error instead of reconnecting forever; delegated-task analytics keep a bounded dedupe set. The polling note on one upstream adapter test is left: upstream deletes that test and makes the harness event-driven in the next checkpoint.
  • CI on Git 2.56 (d34966da): runners moved to Git 2.56, which rewords "not a git repository"; storage cleanup now accepts both wordings. Main has the same latent failure.

Lecturn decisions (recorded in RESOLUTION_GUIDE.md)

Checks

  • Local, final tree: typecheck (35 packages), lint, format, knip, mobile native static check (SwiftLint, ktlint, detekt).
  • Local suites on the merge: web unit 8,284 and browser 1,319; server 8,370; packages 6,673; mobile 3,928 (run the way CI runs it, after the fixes); desktop 1,700; relay 857; embed 88; embed-host 18.
  • CI green on the final head.

Review

  • Independent exact-tree reviews of the merge (web, server/packages, mobile, deps/CI/identity): pass with nits; the introduced nits are fixed in d34966da. Fresh reviews of each later commit, including a sweep of both apps for the bug classes the captures exposed (effect events as dependencies, unmemoized providers, upstream row-layout assumptions): pass with nits, none open.
  • Greptile: five findings; four fixed in d8ec6bc9, one left with the reason in its thread.
  • Grok outside review: accepted the merge and every follow-up commit; its one open note (on pinned rows, Tab reaches the hover actions before the pin) matches the visual order and is left as is.

Follow-ups (on main or upstream already, not changed here)

  • Two other Git error matchers (GitVcsDriverCore.ts:510, GitManager.ts:197) only know the pre-2.56 "not a git repository" wording.
  • The Stave memory MCP server is not re-added after OpenCode drops idle servers (the analogue of upstream fix(server): OpenCode 2 threads keep T3's tools after an idle project is evicted pingdotgg/t3code#16796).
  • In the command palette, an "open-app" request with no apps stays pending; on Android, an app thread's toolbar back arrow goes to Threads, not Apps; Codex receives connected-app instructions in developer_instructions.
  • Opening /draft/<id> directly crashes the composer on the dev server, on main too.
  • Migration 050 (on main and upstream) gave links imported from the pre-V2 model the thread's last-update time as their link time, so a few of them can miss auto-settle the same way.

Evidence heads

The final head is d8ec6bc9; its last commit changes only server, provider-core and client-runtime code, none of it in a captured scene. Web images were captured on 8f8501ab; nothing under apps/web, apps/server, apps/desktop or packages changed after it. Android images were captured on b9336fdf; 3f7510ad then changed only the header cutoff for larger app fonts in ThreadListToolbar.tsx, with identical default-font output (the showcase's font), covered by unit tests. The MCP App full-screen scene uses a real stub MCP App, not a test double.

UI evidence: isolated synthetic fixture (web dev server, stub Codex, headless Chrome 1440x900 @1x dark)

Before = Lecturn main 12c3dc3; after = PR head 8f8501a (upstream checkpoint cd8c2c5 merged with main, plus review fixes). Every after image was captured on 8f8501a.

No regressions. The sidebar title-width regression found on 18f0d00 (pingdotgg#11122 status slot: 83 px slot, 70 px titles) is fixed on 8f8501a (rows 18 and 18h). Every other difference is an expected upstream change.

Scene Before (main 12c3dc3) After (8f8501a) Verdict
Home: new-thread composer and sidebar
Penguin Lab draft, opened from the sidebar (a direct load of /draft/<id> crashes on both sides, see notes).
before: Home: new-thread composer and sidebar after: Home: new-thread composer and sidebar same (pixel-identical)
Thread timeline and composer
User message, expanded work log (reasoning, commentary, command row, file-change row), markdown answer.
before: Thread timeline and composer after: Thread timeline and composer same (only the turn clock and sidebar relative times differ)
Right panel: Diff
README.md expanded (an uncommitted edit in the fixture repo).
before: Right panel: Diff after: Right panel: Diff same (only sidebar relative times differ)
Command palette
Cmd+K over the thread.
before: Command palette after: Command palette same (pixel-identical)
Settings > Connections
Local environment card and Environments.
before: Settings > Connections after: Settings > Connections expected difference: the off Network access switch has a lighter thumb in dark mode (t3code#14984). The port in the Version row also differs.
Settings > Providers
Stub Codex selected, Claude disabled.
before: Settings > Providers after: Settings > Providers expected difference: the off Claude switch has a lighter thumb in dark mode (t3code#14984). "Checked … ago" also differs.
Usage: Cost
30 days over synthetic Codex rollouts.
before: Usage: Cost after: Usage: Cost same (only sidebar relative times differ)
Usage: Tokens
Same data, Tokens view.
before: Usage: Tokens after: Usage: Tokens same (only sidebar relative times differ)
Right panel: Linked pull requests
#12-#14 linked by URL (GitHub disabled, rows unsynced).
before: Right panel: Linked pull requests after: Right panel: Linked pull requests same (only sidebar relative times differ)
Pull requests page
GitHub disabled in the fixture, so it shows the could-not-load state.
before: Pull requests page after: Pull requests page same (only sidebar relative times differ)
Mobile thread (390x844)
Same thread at mobile width.
before: Mobile thread (390x844) after: Mobile thread (390x844) same (0.001% of pixels)
Visual reply in full screen (pingdotgg#20281)
An html_render reply opened with Open full screen. The page has a full-bleed background.
before: Visual reply in full screen (#20281) after: Visual reply in full screen (#20281) expected difference (t3code#20281): the page now sits 16 px inside the frame edge (inset 0 px before, 16 px on 8f8501a)
Visual reply full screen: frame corner
560x330 crop of the same state around the frame's top-left corner.
before: Visual reply full screen: frame corner after: Visual reply full screen: frame corner expected difference (t3code#20281): before, the page touches the rounded frame; after, a 16 px ring of background separates them
MCP App that asks for full screen on load (pingdotgg#18548)
Synthetic penguin-board MCP App, fresh page load with no tap. The app prints the host's answer.
before: MCP App that asks for full screen on load (#18548) after: MCP App that asks for full screen on load (#18548) expected difference (t3code#18548): before, the app takes the whole window on load (Load request: granted); after, it stays inline (Load request: refused)
MCP App: tap Open full screen in the app
Exit full screen if open, wait 6.5 s, then click the app's own button.
before: MCP App: tap Open full screen in the app after: MCP App: tap Open full screen in the app same outcome: a tap in the app opens full screen on both sides; only the app's Load request pill differs (granted before, refused after)
Apps mode: app thread (#159)
Synthetic connected app Colony Tracker. Sidebar in Apps mode, ChatHeader app breadcrumb.
before: Apps mode: app thread (#159) after: Apps mode: app thread (#159) same (pixel-identical): Apps mode and the Colony Tracker icon and name in the ChatHeader breadcrumb on both sides
Apps mode: subagent of the app thread open
Scout-north child of the app thread.
before: Apps mode: subagent of the app thread open after: Apps mode: subagent of the app thread open expected difference (t3code#15163, fork Apps sidebar): after highlights the parent app-thread row; before has no highlighted row
Projects mode: subagent open (pingdotgg#15163)
Scout-north child of a Penguin Lab thread.
before: Projects mode: subagent open (#15163) after: Projects mode: subagent open (#15163) expected difference (t3code#15163): after highlights the parent row; before has no highlighted row
Settings > Integrations: Browser (pingdotgg#18264)
Top of the page.
before: Settings > Integrations: Browser (#18264) after: Settings > Integrations: Browser (#18264) expected difference (t3code#18264): one Browser section instead of two
Settings > Integrations: links and search (pingdotgg#17688)
Scrolled to Search engine (after) or Open links in (before).
before: Settings > Integrations: links and search (#17688) after: Settings > Integrations: links and search (#17688) expected difference (t3code#17688): a new Search engine picker (DuckDuckGo)
Command palette: Back keeps the search (pingdotgg#15940)
Typed "new thr", chose New thread in..., then Backspace back.
before: Command palette: Back keeps the search (#15940) after: Command palette: Back keeps the search (#15940) expected difference (t3code#15940): after keeps "new thr" in the search field after Back; before clears it
Draft hero with a long project name (pingdotgg#18858)
New thread in the Antarctic Field Station ... project.
before: Draft hero with a long project name (#18858) after: Draft hero with a long project name (#18858) expected difference (t3code#18858): the long name is truncated in the middle on its own line, with ? kept beside it; before cut it at the end ("Antarctic Field St… ?")
Thread without a project
Cmd+K New thread without a project, one stub turn. Header breadcrumb.
before: Thread without a project after: Thread without a project same (No project header on both sides; only relative times and "Worked for" differ)
Sidebar thread rows (crop)
260x600 crop of the sidebar from a second run with the same steps as scene 1. Rows at rest, no hover.
before: Sidebar thread rows (crop) after: Sidebar thread rows (crop) same: rows at rest measure a 32 px status slot and a 121 px title on both sides (on 18f0d00: 83 px and 70 px, fixed in 8f8501a)
Sidebar with a pinned row, at rest (crop) (pingdotgg#11122)
"Make remote coding feel local" pinned from its context menu; pointer parked away. 260x600 crop.
before: Sidebar with a pinned row, at rest (crop) (#11122) after: Sidebar with a pinned row, at rest (crop) (#11122) same: the pinned row title is 103 px and the pin is at x=177 on both sides
Pinned row hovered (crop) (pingdotgg#11122)
Pointer on the pinned row. 260x160 crop.
before: Pinned row hovered (crop) (#11122) after: Pinned row hovered (crop) (#11122) expected difference (t3code#11122): on hover, the pin and the "8m" stay put and Snooze/Settle open to their left. Before, the pin jumped 177 to 126 px and the status was hidden. Trade-off: the hovered title shows about 14 px ("M.") instead of 52 px.
Plain row hovered (crop)
Pointer on "Put the command center in your pocket". 260x160 crop.
before: Plain row hovered (crop) after: Plain row hovered (crop) same: Snooze/Settle replace the status at the right end on both sides (title 70 px)

The same scripted steps ran on both sides (replay.sh). Each side used an isolated synthetic fixture home seeded by Lecturn main, with a stub Codex, Claude off and HOME pointed at the fixture. The github.com host was disabled and the host label is masked to "Fixture Mac". New fixture pieces for this checkpoint:

  • a synthetic MCP App served by the stub Codex. It asks for full screen right after it loads and prints the host's answer;
  • a granted synthetic connected app, Colony Tracker, with no tools;
  • an html_render page with a full-bleed background.

Every after image was captured on 8f8501a; nothing is reused from 18f0d00. Scenes 1, 18 and 18h come from a second run of each side with the same short step list. A pixel diff (channel delta >40) backs every "same" verdict: what remains is relative times, the turn clock and the server port.

Fixed since 18f0d00: on 18f0d00 every sidebar row reserved the width of its hover actions at rest (t3code#11122), so titles shrank from 121 to 70 px. 8f8501a measures 121 px again.

Pinned rows: on hover, the pin and status now stay in place, as pingdotgg#11122 intends. The trade-off is that a hovered pinned row shows only about 14 px of title (row 18h).

Pre-existing, on both sides: loading or reloading /draft/<id> directly (where / redirects) crashes the composer on the dev server with "[tiptap error]: The editor view is not available". Scene 1 therefore opens the draft from the sidebar.

Not shown:

Android showcase (phone and 10-inch tablet, dark, Lecturn theme; GitHub-hosted ubuntu-24.04 capture-only harness)

Before = Lecturn main 12c3dc3 (run 40772717467). After = this PR at b9336fd (run 40786928438). Both runs are green, with 12/12 scenes per side. Synthetic showcase fixture only.

Phone (1080×1920)

Scene Before (12c3dc3) After (b9336fd) Notes
Threads list before: Threads list after: Threads list PASS: 0.06% changed, only glass-card edge anti-aliasing on one row. The bottom bar with Chats / Apps / Pulls is pixel-identical; the Lecturn crest, gold Decisions and New thread FAB are kept
Thread before: Thread after: Thread PASS: the message feed renders (both bubbles). Only the fixture timestamps differ (0.13%)
Terminal before: Terminal after: Terminal PASS: 0 changed pixels
Review (diff) before: Review (diff) after: Review (diff) PASS: it renders with no render loop. 0.13% changed, all in the bottom gesture-bar row
Environments before: Environments after: Environments Expected difference: the switches sit further left because the chevron is now its own touch target (upstream pingdotgg#17677). The environment order and routing ports vary between fixture runs
Agent activity before: Agent activity after: Agent activity PASS: 0 changed pixels

10-inch tablet, split view (1440×2560, about 800 dp)

Scene Before (12c3dc3) After (b9336fd) Notes
Threads before: Threads after: Threads Expected difference (upstream pingdotgg#21071 plus the #159 Apps port): the Chats/Apps/PRs navigation rail is gone. The sidebar header shows "Lecturn" on one line with Search, Settings and More actions; Show apps and Show pull requests sit in the More menu, because the 280 dp sidebar is under the inline-button width
Thread before: Thread after: Thread Expected difference: the rail is gone and the content is wider. The feed renders. The header matches the Threads scene
Terminal before: Terminal after: Terminal Expected difference: the rail is gone. The header matches the Threads scene
Review (diff) before: Review (diff) after: Review (diff) Expected difference: the rail is gone. It renders with no render loop
Environments before: Environments after: Environments Expected difference: the rail is gone, and the switch and chevron changes from pingdotgg#17677 apply
Agent activity before: Agent activity after: Agent activity PASS: 0 changed pixels

Sidebar header crop, top to bottom: main 12c3dc3 (rail layout), the intermediate 1d00879 (wordmark wrapped, fixed since), and this PR's b9336fd: tablet sidebar header: main, intermediate, final

🤖 Generated with Claude Code

fixfon and others added 30 commits October 18, 2026 12:50
…y compatible (pingdotgg#18563)

Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Co-authored-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
…ice (pingdotgg#18664)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… thread already got (pingdotgg#21155)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#21200)

Co-authored-by: Mnigos <56691628+Mnigos@users.noreply.github.com>
…20024)

Co-authored-by: Sinan <sinan@Mac-mini-von-Sinan.local>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ile (pingdotgg#21062)

Co-authored-by: yaacovcorcos <190350601+yaacovcorcos@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…g#21042)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…extension (pingdotgg#18857)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ge list (pingdotgg#21269)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tgg#18393)

Co-authored-by: SAPHID <saphid@users.noreply.github.com>
Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
shivamhwp and others added 26 commits October 19, 2026 12:27
…ngdotgg#19431)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ing upstream (pingdotgg#15393)

Co-authored-by: abderbj <115119179+abderbj@users.noreply.github.com>
Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: SAPHID <saphid@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…gg#21893)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ex shells (pingdotgg#18301)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…dotgg#15710)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
… is on (pingdotgg#16015)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: SAPHID <saphid@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Kalven Schraut <kalvens@rtvision.com>
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…overed space (pingdotgg#17910)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ches (pingdotgg#12291)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…otgg#12583)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…16662)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
…g#14954)

Co-authored-by: SAPHID <saphid@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
pingdotgg#15818)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
True merge of pingdotgg/t3code through cd8c2c5
(452 upstream first-parent commits after 16918b5, pingdotgg#20967..) into Lecturn
main 7ce4e26. Brings upstream's React Compiler adoption across the mobile
app (Metro compiler, coverage ratchet, no-manual-memo and hookless-use lint),
MCP apps that open full screen only after a tap, full-screen visual replies
that keep a gap from the frame edge, html previews that say how their browser
exited, PR sheet link/unlink/watch and badge work on mobile, Android fold and
navigation fixes, provider update and Claude probe recovery fixes, MCP tool
usage counting, Lecturn Connect link retries, sectioned orchestration
instructions, storage cleanup reaching archived worktrees, the pull-request
link input and list-line helpers moved into shared packages, and about 125
web fixes (sidebar subagent highlight, command palette focus and query
retention, keybinding recording, composer fade, narrow-window questions).
Lecturn keeps its identity (lecturn_ MCP tools, LECTURN_* env, PostHog
delivery instead of upstream's ingest endpoint), its migration numbering
(upstream 64 runs as fork 79), its sidebar drag shape, its Git sheet sections
and its iOS system font. The resolution guide records the deliberate
differences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings main's Lecturn Apps (#159), relay renewal and retired-gateway DNS
recovery (#155, #156), nightly quality shards (#157), the npm manifest fix
(#158) and AGENTS.md (#160) onto the upstream-integrated tree.

Lecturn Apps now runs on the upstream changes: MCP App cards in app threads
and the embed keep the tap-only full-screen gate (pingdotgg#18548) through the one
McpAppFrame; Apps mode highlights a subagent's parent row (pingdotgg#15163); app-thread
notifications use the hashed tag (pingdotgg#12289); the mobile Apps code follows the
React Compiler rules; Android split view reaches Apps through "Show <tab>"
toolbar buttons now that upstream dropped the rail (pingdotgg#21071). Server: upstream
migration 64 runs as fork 81 after Apps migrations 79/80; socket auth keeps
the feature.used callback through AppRpcAuthorization; OpenCode v2 re-adds
Lecturn MCP each turn and reports activation failures. The unused upstream
useNowSecond hook is dropped with the working timer the fork did not take.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- storage cleanup treats Git 2.56's "gitfile does not point to a valid
  repository" as a checkout Git no longer recognizes, like the older wording
  (CI runners moved to Git 2.56; upstream's match failed there)
- OpenCode v2 reports a failed Lecturn MCP add only while the server is not
  up yet, so a failed per-turn re-add no longer leaves a stale notice
- release CLI single-executable builds stamp LECTURN_TELEMETRY_CHANNEL
- the embed timeline's citation fold lookup passes keepLatestTurnOpen
- upstream test fixtures use lecturn- temp prefixes and /lecturn/ paths
- comments for the desktop single-instance lock and Android workspace
  navigation match the code; resolution guide entries for the above

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

Any focused screen with an inspector pane (Review with a diff, tablet Files,
Thread with an inspector open) hit "Maximum update depth exceeded". The
registration hook's useFocusEffect callback depended on a useEffectEvent
result, which React recreates every render, and the provider's pane
derivations could not be memoized, so each render deactivated and
re-registered the inspector.

Port upstream 325a7e2 (pingdotgg#21867), which memoizes the four pane derivations,
and keep the inspector registration in a ref so the focus callback is
constant. Owner-only deactivation and focus-scoped registration are
unchanged. A new test compiles the real file with the React Compiler and
fails on the old code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- web sidebar: upstream pingdotgg#11122's status slot reserved the hover actions'
  width at rest, and fork card rows put the title on that line, so every
  title lost about 42% of its width. SidebarRowStatusLine reserves only the
  visible status at rest; on pinned or Woke rows the hover actions open to
  the left of the markers, so the pin still stays put (pingdotgg#11122's intent)
- mobile queue: QueueDragHandle's gesture was rebuilt on every render because
  the compiler memoized it on useEffectEvent results; it now comes from a
  builder held in useState (upstream's SettingsDragHandle pattern) and is
  rebuilt only when `disabled` changes
- mobile ThreadFeed reads the content inset with `.get()` (upstream 80b48cc)
- the compiler-backed mobile tests share one loader that inlines babel
  helpers, so they no longer depend on pnpm's hidden NODE_PATH hoist

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the Apps tab, the Android threads sidebar header had four buttons, and
at tablet split-view width (280 dp sidebar) "Lecturn" wrapped onto two
lines. The wordmark is now single-line, and below a 320 dp row "Show apps"
and "Show pull requests" move into a "More actions" menu, the overflow
pattern upstream's AndroidScreenHeader already uses for the other sidebars.

Also port the ThreadNavigationSidebar half of upstream 325a7e2 (pingdotgg#21867):
the sidebar's lookup maps are memoized again, so rows stop re-rendering on
every sidebar render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The inline-button cutoff in the threads sidebar header was a fixed 320 dp,
but Android buttons grow with the app font, so from base font 18 "Lecturn"
was shortened with an ellipsis. resolveSidebarHeaderButtons now uses the
scaled button size and wordmark width: four inline buttons when the full
wordmark fits, otherwise Show apps/Show pull requests move into "More
actions", and at the largest fonts Settings joins them. Default-font
behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nurozen
Nurozen marked this pull request as ready for review October 28, 2026 23:54
yield* Fiber.join(notified);
// The reply is read with real file I/O after the clock moves, and its
// events reach the collector fiber after the frame counts as processed.
yield* awaitUntil(() => texts(2).at(-1) === "a2 found README.md", "a2 reply");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Reply tests depend on polling

The new reply check calls awaitUntil, which polls for at most 5,000 scheduler yields. AGENTS.md requires backend tests to await a specific event or Deferred and forbids polling. Slow file I/O can outlast those yields.

Signal a Deferred when the collector receives the expected reply and await it instead. Other new adapter tests also use this helper. This repository requirement must be satisfied before merging.

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmed: this breaks the AGENTS.md no-polling rule. We're not changing it in this PR. The awaitUntil helper is already used 178 times in this file on main, and this test came from upstream pingdotgg#21310. Upstream later deleted the test (pingdotgg#22557) and made the adapter harnesses event-driven with a polling lint rule (pingdotgg#22565). Those changes arrive with the next upstream checkpoint, and fixing this one call site would mean adding an event hook to the shared harness.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That context makes sense. awaitUntil still violates the no-polling rule in this test, but replacing this one call would require an event hook in the shared harness, and the upcoming checkpoint removes the test while making the harness event-driven. I agree this is better handled there rather than expanding this PR’s scope. I’m withdrawing the “must be fixed before merge” framing; this remains a known follow-up, not a blocker for this PR.

- migration 81 (upstream 64) writes migrated pull request links' linkedAt as
  the unknown date, as main did, so a thread renamed after its PR merged
  still auto-settles (pingdotgg#18232's filter dropped it)
- the pnpm-global update probe checks the pnpm the update actually runs
  (server environment), so a provider PATH with a newer pnpm no longer adds
  --allow-build to an older pnpm
- Connect targets with an owning account report session-pending only while
  the platform reports unsynced accounts, so an expired mobile account gets
  the sign-in failure instead of retrying forever
- delegated task analytics keep only the newest 1,000 reported task ids

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nurozen
Nurozen merged commit 85547e2 into main Oct 29, 2026
18 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.