Repository navigation
chore: sync with upstream t3code (2026-11-03) - #23
Draft
aabdel0181 wants to merge 1038 commits into
Draft
aabdel0181 wants to merge 1038 commits into
aabdel0181 wants to merge 1038 commits into
Conversation
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…old runtimes (pingdotgg#27651) Co-authored-by: Lukas <340913497+LukeCommits@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…he sidebar (pingdotgg#27695) Co-authored-by: Nicholas Wasmiller <derped@mnpl.fyi> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…g#27771) Co-authored-by: maria-rcks <maria@kuuro.net>
…ingdotgg#27818) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gdotgg#28288) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…dotgg#28364) Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: Exotic <118054752+extoci@users.noreply.github.com>
…ngdotgg#28419) Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ingdotgg#28428) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ut (pingdotgg#28491) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
…#23373) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gdotgg#23211) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tance (pingdotgg#23198) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…turn absorbed its wake (pingdotgg#28010) Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>
…ory scan ends (pingdotgg#29535) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tch (pingdotgg#29476) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…n starts (pingdotgg#28431) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ching origin (pingdotgg#27961) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…pingdotgg#27957) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…3804) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…g#23326) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ingdotgg#23561) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Exotic209093 <134711311+Exotic209093@users.noreply.github.com> Co-authored-by: Issue triage verification <triage@localhost> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#22661) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
… limit (pingdotgg#23192) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gdotgg#23219) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ngdotgg#29922) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…29909) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
128 upstream commits (ac8dce0..cefb544), 10 conflicts: - EnvironmentAuth.test: took upstream's reindented suite (Effect 4.1.2), kept T3 Learn's t3learn:// and t3code-dev:// origins and the t3code:// rejection. - cli/pair.test: kept T3 Learn's Serve-on-8443 assertion on upstream's String() args. - DelegatedCompletionDelivery.test, ProjectSettingsUpgrade.integration.test, runtimeLayer.test: upstream's NodeCrypto layer plus the fork's ProviderRegistry mock. - AgentAwarenessRelay(+test): upstream's hasLivePublishedState (pingdotgg#29369) with the fork's side-chat exemption; both store mocks. - ChatView.tsx: upstream's WorkspaceMutationIdContext wrapper (pingdotgg#29741) around the fork's side-chat timeline props. - ChatView.logic.test: deriveWorkspaceMutationId's test moved to client-runtime upstream; kept the fork's presentThreadShellFromProjection test. - TimelineAssistantRows: took upstream's revert of the hover timestamp (pingdotgg#29680); the fork's side-chat chip row stays. Clean-merge fixes: - provider-kiro (new, pingdotgg#14693): generateSideChatText unsupported stub. - cli/pair.test: Effect 4.1.2 types process args as Word, so map to strings. - client-runtime commands.test: the side-chat test uses upstream's renamed layerTestRandom. - GitHubStarPrompt (pingdotgg#29922): the thank-you toast names T3 Learn; its test expects T3 Learn's repository. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's new shell-burst test (pingdotgg#29101) stubs ThreadManagementService without listActiveSideChatThreadIds, which the fork's shell resume reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's relocated-systemd-config test (pingdotgg#29244) hardcodes t3code.service; T3 Learn installs t3learn.service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's sidebar a11y change (pingdotgg#26690) swapped the tree-item selectors the Map's nodes relied on for sidebar-row ones. A keyboard-focused Map node lost focus to the composer on window return, and focusing the panel landed on the first button instead of the Map's tab stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's image reload (pingdotgg#29741) keys chat images on a workspace mutation id that only ChatView provides. The side-chat timeline in the lesson's panel now provides the side chat's own, as upstream's embedded side chats do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merges upstream t3code into T3 Learn, now through
cefb544af3. This branch started as the 2026-10-31 sync and stacks on #22 (2026-10-30, still waiting on med). Againstmainit carries 1007 upstream commits: 136 from #22, 386 from 2026-10-31, 177 from 2026-11-01, 180 from 2026-11-02 and 128 added today (ac8dce0cc3..cefb544af3). #22 stays mergeable on its own; merging it first shrinks this diff.Still a draft: it needs med's side-chat decision, sign-off on #22's workflow, and the managed-policy call (see "Open"). Today adds no new product call.
Today (2026-11-03)
mainhas not moved since 2026-11-01, so there was one merge:upstream/main(acc0f25d57), 128 commits, 10 conflicts.Server
auth/EnvironmentAuth.test.ts: took upstream's reindented suite (Effect 4.1.2, chore(deps): upgrade Effect to 4.1.2 and alchemy to beta.85 pingdotgg/t3code#26833). Kept T3 Learn'st3learn://andt3code-dev://origins and itst3code://rejection.cli/pair.test.ts: kept both. That means upstream'sString()target and T3 Learn's Serve-on-8443 assertion.DelegatedCompletionDelivery.test.ts,ProjectSettingsUpgrade.integration.test.ts,runtimeLayer.test.ts: kept both. That means upstream'sNodeCryptolayer and the fork'sProviderRegistrymock.relay/AgentAwarenessRelay.ts: upstream'shasLivePublishedState(fix(server): settled threads no longer re-send relay clears on every PR update pingdotgg/t3code#29369), with the fork's side-chat exemption.relay/AgentAwarenessRelay.test.ts: kept both store-mock members.Web
ChatView.tsx: upstream'sWorkspaceMutationIdContextwrapper (fix(web,mobile): chat images reload when the agent rewrites the file pingdotgg/t3code#29741) now goes around the fork's side-chat timeline props.ChatView.logic.test.ts: upstream movedderiveWorkspaceMutationIdand its test to client-runtime. Kept the fork'spresentThreadShellFromProjectiontest.chat/TimelineAssistantRows.tsx: took upstream's revert of the hover timestamp (revert(web): undo hover timestamp change from #28610 pingdotgg/t3code#29680). The fork's side-chat chip row is back to its pre-fix(web): finished replies keep their hover timestamp while commands run pingdotgg/t3code#28610 shape.Fixes in the merge commit, outside conflict hunks:
provider-kiro(new provider, feat(provider-kiro): add Kiro as an ACP provider pingdotgg/t3code#14693): added an unsupportedgenerateSideChatTextstub. Typecheck caught it.cli/pair.test.ts: Effect 4.1.2 types process args asWord, so the fork'sserveArgsmaps them to strings. Typecheck caught it.commands.test.ts: the fork's side-chat test uses upstream's renamedlayerTestRandom. Typecheck caught it.GitHubStarPrompt.tsx(feat(web): ask for a GitHub star when idle, and star in one click pingdotgg/t3code#29922): the new thank-you toast said "It really helps T3 Code grow". It now names T3 Learn. Its test expected the fallback to openpingdotgg/t3code, but T3 Learn stars and opens its own repository.t3-learn-ci.ymlis unchanged; upstream did not touchci.yml. Workflow files added againstmain:.github/workflows/mobile-eas-preview-fork.yml(from #22). Today's range added none. Upstream editedrelease-desktop.yml(pingdotgg#29484 Rosetta step), which stays disabled on the fork.Fixes after the merge
test(server): the shell-burst test stubs the side-chat shell read(CI Test Server 7). Upstream's new perf(server): shell updates read a burst of threads once pingdotgg/t3code#29101 test stubsThreadManagementServicewithoutlistActiveSideChatThreadIds, which the fork's shell resume reads, so it failed withTypeError: … is not iterableatws.ts:1260.test(server): the XDG boot-service test expects T3 Learn's unit(CI Test Server 5). Upstream's new fix(server): honor relocated systemd user configuration pingdotgg/t3code#29244 test (7 cases) hardcodest3code.service, but T3 Learn installst3learn.service.fix(web): the side-chat Map keeps keyboard focus again.fix(web): side-chat images reload when their agent rewrites the file.Review
Four independent reviewers with fresh context, one per area: the conflict resolutions (remerge diff), server and providers, web/client-runtime/mobile, and branding/desktop/CLI. For each area, a skeptic then tried to refute the findings against the source. All four findings survived:
Boot-service and shell-burst tests. These are the two CI failures above, found independently by the branding and server reviewers. Both are fixed.
Map keyboard focus (fix(web): screen readers can browse and Tab through the threads sidebar again without going into focus mode pingdotgg/t3code#26690). Upstream's sidebar is no longer a tree, so it swapped the
[role="treeitem"]selectors for sidebar-row ones. The Map's nodes relied on those selectors without saying so.The Map's tab-stop node is now the panel's focus default, and keyboard-focused tree items keep focus again. The only other tree items, Settings nav and the file tree, are already exempt (dialog, shadow root). The new browser test fails without the fix.
Side-chat images (fix(web,mobile): chat images reload when the agent rewrites the file pingdotgg/t3code#29741). Upstream now reloads chat images when the agent rewrites the file, but only ChatView provides the key, so T3 Learn's side-chat timeline never got it. It now uses the side chat's own key, as upstream's embedded side chats do. This was a gap, not a regression: before fix(web,mobile): chat images reload when the agent rewrites the file pingdotgg/t3code#29741 neither timeline reloaded. Left as is: a file rewritten by the lesson's agent doesn't reload in the side chat, because image URLs are per thread. Upstream's side chats have the same limit, and the verifier's idea of also keying on the lesson's id is left for later.
A second fresh reviewer then checked the four fix commits and found no bugs. Dismissed: its suggestion to mention Map nodes in the comment above
shouldRefocusComposerOnWindowFocus. That would only widen the fork's diff in an upstream comment.Checked and fine:
subagentlineage, so side chats (fork) keep auto-resuming.listAppOwnedChildThreadIds) narrow by ownership, not lineage. Side chats are neither newly read nor newly skipped, and idle compaction still skips them..debpermissions (fix(desktop): Linux .deb no longer installs files any local user can overwrite pingdotgg/t3code#28351), Linux MIME helpers (perf(desktop): keep Linux MIME helpers off the startup path pingdotgg/t3code#29247), Rosetta bytecode (fix(desktop): prepare macOS x64 bytecode under Rosetta pingdotgg/t3code#29484), Tailscale SIGKILL (fix(tailscale): escalate hung serve commands to SIGKILL pingdotgg/t3code#28529) and ssh tunnel changes keep T3 Learn's names,t3learnscheme, 8443 and~/.t3-learn.effect/Crypto, and the fork's harnesses satisfy the newNodeCrypto/SecureRandomrequirements.Checks
Local, memory-capped, one at a time:
vp fmt --checkandvp linton every resolved or fixed file: pass.wsandbootService(58).AgentSessionScanner› "still reads the git identity…", 5 of 5 runs.ChatView.logicandGitHubStarPrompt(55).ChatView.logic,SideChatMapandSideChatTimeline(11), andSideChatPanel(30). The new Map row failed before its fix.commands(13).T3 Learn CI:
acc0f25d57: Test Server 2, 5 and 7 failed. Everything else passed, including Lint, Build and Typecheck, Test, Test Web 1–4, Release Smoke, Rust and Mobile Native Static Analysis.Test Server 7 (
ws.test) and 5 (bootService.test) are fixed above.Test Server 2 failed in upstream's new
AgentSessionScanner.test.ts› "still reads the git identity of repositories next to a blocked one" (fix(server): agent session scans no longer hang the server on an unreadable .git/config pingdotgg/t3code#23690):scan 2: expected … "pingdotgg/repo-0" … received remoteKey: null. This is upstream's own timing test.apps/server/src/project/.cefb544af3, and 5 of 5 times locally on the merge.Not fixed; reported. It passed on the next run.
e014371137(head): all 19 Linux jobs pass, including Lint, Build and Typecheck, Test, Test Server 1–8, Test Web 1–4, Release Smoke and Rust. Check is red only because Mobile Native Static Analysis never got a macOS runner: it was cancelled after 15 min queued with 0 steps on all four attempts (known, see NOTES). It passed on the merge's run, and the fix commits change nothing underapps/mobile.Open (needs med)
/side,/btwand + → Side chat (small).lineage.sideChat(large).mobile-eas-preview-fork.yml(pull_request_target,pull-requests: write) is still in this branch./Library/Application Support/T3Code/policy.json,/etc/t3code/policy.json,HKLM\SOFTWARE\Policies\T3Tools\T3Code, thecom.t3tools.t3codeprofile). As merged, T3 Learn obeys it (updates off, nightly rule, runtime-mode ceilings, locked settings, telemetry) but ignores its update mirror. Options:2026-11-02 part of this PR (180 commits, 16 conflicts)
mainhas not moved since yesterday, so there was one merge:upstream/main(d0cf0da2c0), 180 commits, 16 conflicts.Server
keybindings.ts: upstream now writes raw entries and reloads from disk, so a save keeps rules it can't read (fix(server): saving a shortcut no longer deletes rules it can't read pingdotgg/t3code#24494). The fork's rule that side-chat default shortcuts never go intokeybindings.jsonnow works on those raw entries (withoutMemoryOnlyDefaultsdecodes them).ThreadForkService.ts: upstream stopped forks from inheriting pin, auto-settle, snooze-wake, active order and delegation (fix(server): a fork no longer inherits the source thread's pin, auto-settle and delegation state pingdotgg/t3code#28378). Those resets go into the fork's sharedplanForkTargetThread, so side chats get them too.testkit/ProviderReplayHarness.ts: kept both. Upstream's harness now builds settings from a managed policy; the fork's side-chat options andsettingssit on top.cli/update.test.ts: kept both. That means the fork's stable/preview test and upstream's managed-policy tests.Web
CommandPalette.tsx,CommandPaletteThreadItems.tsx: took upstream'suseVisibleThreadShells(thread tags, feat: tag threads and hide tagged threads while recording pingdotgg/t3code#29053) and kept the fork's side-chat tree reads andcurrentThreadRef.ThreadRouteView.tsx: took upstream's tag-filter redirects. The fork's "a side chat's route is not a chat view" gate sits on the last branch.ThreadActivityBanners.tsx,V2LifecycleRow.tsx: imports from both sides.useThreadLifecycle.tsx: kept both imports. The fork'sonOpenChildThreadnow forwards upstream's new environment argument (fix(clients): open a delegated child's approval on the environment it runs in pingdotgg/t3code#28592), so a delegated child's approval opens on its own environment. Types would not have caught this.TimelineAssistantRows.tsx: upstream's hover timestamp on finished replies (fix(web): finished replies keep their hover timestamp while commands run pingdotgg/t3code#28610) goes inside the fork's row, next to the unresolved-side-chats chip.SettingsPanels.tsx: the desktop update-track row stays out (one update track). Upstream's managed-policy denial is kept on the version row and the "check for updates" toast. Its nightly-only copy goes with the track row.Client runtime, provider-core
threadShell.ts: navigation lists hide T3 Learn side chats and threads hidden by tag.archivedThreads.ts(+test): kept both. That means the fork'slistedArchivedThreadsand upstream's archive tag filter.textGenerationUtils.test.ts: kept both test suites.Fix in the merge commit, outside conflict hunks:
visibilityParentKeynow sends a T3 Learn side chat to its lesson, so a hidden lesson's side chats are hidden in lists, the archive, notifications and the palette. Test row added.docs/internals/side-chats.mdsays so.t3-learn-ci.ymlis unchanged; upstream did not touchci.yml. Workflow files added againstmain:.github/workflows/mobile-eas-preview-fork.yml(from #22). Today's range added none.Fixes after the merge
test(server): Stop-during-restart test awaits the interrupt, not drain()(CI Test Server 8). Upstream's "Stop during a restart interrupts the turn the restart could not stop" failed every time on the merge. It passes onac8dce0cc3and on yesterday's branch tip. The replay harness runs the effect daemon, which can claim Stop's interrupt before the test'sdrain().drain()then returns while the interrupt still runs, and the turn still readsrunning. Reverting either of two fork Orchestrator hunks made it pass, and both only add reads before dispatch (the side-chat step beforedispatchMessage, the lesson-lock lookup). So the fork's timing makes the daemon win. This is the same race NOTES records for the 2026-10-31/compacttest. The test now awaits the turn's interrupted event, as it already awaitsrunning. It passed 5 of 5 local runs.test(desktop): relaunch test drops T3 Learn's own app links(CI Test).fix(desktop): T3 Learn never updates from a T3 Code policy mirror.fix: managed-policy messages name T3 Learn.fix(web): a hidden lesson's side chat route reveals nothing.fix(shared): the policy registry error says reinstall T3 Learn(from the fix review).Review
Four independent reviewers with fresh context, one per area: the conflict resolutions (remerge diff), server and providers, web/client-runtime/mobile, and branding/desktop/settings. For each area, a skeptic then tried to refute the findings against the source. The resolution and server reviewers found nothing. Four findings survived, all caused by today's upstream code, and all are fixed:
t3code://links. T3 Learn's scheme ist3learn, so the links were kept and the test failed. This was CI's Test job failure.limits.updates.feedUrlreplace the GitHub update feed. T3 Learn reads T3 Code's policy locations, so an organization's T3 Code mirror would offer T3 Code builds as updates. On macOS, the bundle swap would install T3 Code over T3 Learn. T3 Learn now ignores the policy's feed and still obeys itsmodeand nightly rule. The new test fails without the fix.Checked and fine:
thread.tag.setcommands on a side chat take the lesson lock.generateSideChatText.t3-learnCLI are intact.A second fresh reviewer then checked the six fix commits. It found that the Windows registry-reader error still said "reinstall T3 Code", and that the managed-policy guide still described
feedUrlas honored; both are fixed (fix(shared): the policy registry error says reinstall T3 Learn). It also confirmed that the SelectionRestart wait can only see Stop's interrupt, so the test cannot pass vacuously. Dismissed: a T3 Learn client connected to a stock T3 Code server under a policy now reads "manages T3 Learn updates" for that server. Clients connecting to such servers are rare, and NOTES' branding rule says app-naming copy says T3 Learn.Checks
Local, memory-capped, one at a time:
vp fmt --checkandvp linton every resolved or fixed file: pass.threadTagFilter,archivedThreads,threadShell(27). The new tag-filter row failed before its fix.keybindings(with the fork's side-chat default cases),ThreadForkService,cli/update,ws(59);SelectionRestart.integration(8, five runs);cli/update,cloud/selfUpdate(29).textGenerationUtils(13).updates/*andDesktopLifecycle(98).ThreadRouteView(browser) andupdateEverything.logic(13).managedPolicyFile(2, plus 1 Windows-only skipped).DesktopUpdatePolicy, theThreadRouteViewhidden-lesson row and thethreadTagFilterrow.T3 Learn CI:
d0cf0da2c0failed two jobs. Test Server 8 failed on the SelectionRestart race. Test failed on theDesktopLifecyclerelaunch test. Both are fixed above. Mobile Native Static Analysis was cancelled after 15 min queued with no macOS runner (known, see NOTES). Everything else passed.bbb2f1ebf5: Test Server 1–8 and Test Web 1–4 passed, Test still failed onDesktopLifecycle, and the run was cancelled by the next push.d48c2d2ae7: Test Web 1 failed in upstream's newMessagesTimeline.browser.test.tsx› "keeps the worked-for heading in place when expanded at the bottom" (fix(web): preserve scroll position when expanding work details pingdotgg/t3code#29166):TimeoutError: locator.click: Timeout 29440ms exceeded … <div class="legend-list-content-container">…</div> intercepts pointer events. This is upstream's own flaky test. On cleanac8dce0cc3it fails 4 of 6 local runs (expected 577 to be close to 473). It passed on CI in the two runs before. Not fixed here; reported. That run was cancelled by the next push.20f258bc7b(head): all 20 jobs pass, including Check, Lint, Build and Typecheck, Test, Test Server 1–8, Test Web 1–4, Release Smoke, Rust and Mobile Native Static Analysis.2026-11-01 part of this PR (177 commits, 13 conflicts)
Two merges, then one review fix:
origin/maininto this branch (3fad03bad9). Main gained 9 fork commits since this branch forked: the side-chat composer, Done, Side chats Settings and the auto-release. This PR conflicted withmain, so GitHub ran no CI on it. 7 conflicts:ContextHandoffDelivery.ts: kept upstream'swithInlineContext, plus main'sisPendingContextHandoffandquiet.Orchestrator.ts: main's Done now cancels queued runs after Stop. It uses upstream'sisActiveRun(wasisBlockingRun).ProviderTurnStartService.ts: main's side-chat instructions and skill mentions sit on top of thelessonSideChat*locals. They are renamedlessonSideChatSettings/loadLessonSideChatSettings. The provider text goes through upstream'swithInlineContext.ProviderTurnStartService.test.ts: the harness keeps upstream'ssideChatinput and session. It also keeps main'scaptureProviderTurn,settings,providersandfailSettings. Main's tests uselessonSideChat.updateEverything.logic.ts(+test): took upstream's. Upstream removed the npm precheck (fix(updates): version checks respect your configured npm registry pingdotgg/t3code#27847), which covers main's boot-service exemption.docs/internals/side-chats.md: kept both round-trip notes.supportsLessonSideChats. They had readcapabilities.sideChats, which is upstream's capability now.SideChatSettingstypes its skill options with plain string ids, since upstream's picker ids are branded.upstream/main(52c5f7b094). 6 conflicts:DesktopEarlyElectronStartup.ts,DesktopEnvironment.ts,DesktopLinuxUrlHandler.test.ts: took upstream's removal of the unused Linux--classswitch (refactor(desktop): Drop the unused Linux --class switch pingdotgg/t3code#14482). T3 Learn'st3learnWM class goes with it; the window class comes fromsetDesktopName(the T3 Learn desktop entry).DesktopBackendConfiguration.test.ts: kept T3 Learn'sT3CODE_HOMEassertion and upstream's shell-discovery one.ReopenClosedViewShortcut.browser.test.tsx: kept both sides' tests.ZoomableImage.tsx: took upstream's SVG fit (fix(web): expanded SVG diagrams fill the image viewer pingdotgg/t3code#27519). It fixes the bug the fork fixed in PR fix(web): expanded diagrams fill the viewer #20, andExpandedImageDialognow infers the MIME type from data URLs and file names. The fork'sZoomableImage.logic.ts(+test) is deleted. Lost edge: an explicitimage/svg+xml; charset=…MIME type no longer upscales.SideChatPanelreadsrefreshfrom upstream's reshapeduseProviderWorkspaceSnapshotRefresh(fix(web): skill menus show loading while project skills arrive pingdotgg/t3code#28209).216906173a,2c694950e1). Since side chats can attach images (feat(web): side chats queue, steer, stop, pick a model and attach images #24), four paths that delete a side chat cleared only its draft text: closing an empty side chat's tab, Done from the palette, closing the tab while it starts, and a failed open. Their staged uploads stayed pending on the server and the draft entry stayed in storage. These paths now release both, like the panel's Done. This predates the sync. Two extended tests fail without the fix.t3-learn-ci.ymlis unchanged; upstream did not touchci.yml. Workflow files added againstmain:.github/workflows/mobile-eas-preview-fork.yml(from #22). Today's range added none.Review
Three independent reviewers with fresh context read the remerge diffs, split into: main's merge, upstream's server/shared/desktop/mobile, and upstream's web. An adversarial verifier then checked each area's findings against the source.
openSideChatpaths.SideChatPane→ChatView) have the same gap. The text itself is kept.main, not fixed here):clearGoneSideChatDrafts(useLessonSideChats.ts) is meant to keep an archived side chat's draft. Its guard readsreadThreadShell(ref)?.deletedAt === null, but archived threads leave the shell snapshot, so the guard never holds. Archiving a lesson whose side-chat tabs are open clears their drafts, and unarchiving brings the side chats back empty. The fix needs a source that knows a thread is archived; the review fix leaves this path clearing content only./goal, compaction or restarts.isActiveRunmatches the oldisBlockingRun. The queued-run cancel loop reads pending events.Checks
Local, memory-capped, one at a time:
vp fmt --checkandvp linton every resolved or fixed file: pass.ProviderTurnStartServiceandbootService(11 files, 215 tests).composerSend,versionSkewandupdateEverything(19 files, 227 tests).serverSettings(45 tests) and the release-version script test.ExpandedImageDialog, side-chat panel/composer,ChildThreadApprovals(5 files, 64 tests).openSideChat,useLessonSideChatsand the panel (7 files, 58 tests).T3 Learn CI:
52c5f7b094: all 20 jobs pass, including Check, Lint (with knip), Build and Typecheck, Test Server 1–8, Test Web 1–4 and Mobile Native Static Analysis.2c694950e1(with the review fixes): all 20 jobs pass, including Check. The run on216906173awas cancelled when2c694950e1superseded it.Open (needs med) at the time
/side,/btwand + → Side chat (small).lineage.sideChat(large).mobile-eas-preview-fork.yml(pull_request_target,pull-requests: write) is still in this branch.2026-10-31 part of this PR (386 commits, 42 conflicts)
Merges 386 upstream commits (
6575ce3250..79f1fadfc6) into T3 Learn. This branch stacks on #22 (yesterday's 136 commits, still waiting on med), so againstmainit carries 522 upstream commits. #22 stays mergeable on its own; merging it first shrinks this diff.Draft: needs a product decision from med. Upstream shipped its own side chats today (pingdotgg#26901): hidden forks with
lineage.sideChat, started with/side,/btwor + → Side chat, with Bring back to merge them into the thread. This PR keeps both features working side by side; it does not choose between them. See "Open" for the options.How the two side-chat features coexist
ExecutionEnvironmentCapabilities.sideChats(a duplicate key after the merge).sideChatskeeps upstream's meaning; T3 Learn's is nowlessonSideChats, and the server advertises both.supportsLessonSideChatsalso acceptssideChatsfrom released-learn.servers, andsupportsSideChatsrefuses upstream's/sideon them: they would create a listed fork and delete it when its tab closes.side-chatand a store actionopenSideChat, with different shapes. Upstream's stay as is; T3 Learn's tab is nowlesson-side-chat(openLessonSideChat). The persisted right-panel state goes 15 → 16 and closed views 2 → 3, with migrations that rename saved T3 Learn tabs.isPendingForRun.Conflicts (42 files)
Server
Orchestrator.ts: upstream'splanDeletion,onlyIfUnusedand inline side-chat cascade. The fork'sside-chat.cascadeeffect runs for every deleted thread. Upstream's fork and delete locks are wrapped in the fork's lesson lock.side_chat.openrefuses an upstream side-chat anchor.isBlockingRun→isActiveRun.ThreadForkService.ts(+test): forks still go throughplanForkTargetThread, now with upstream's resets and side-chat flag. A side-chat fork from a T3 Learn side chat is refused.ThreadManagementService.ts: agent listings exclude both kinds.IdleCompaction.ts: skips both kinds.ProviderTurnStartService.ts(+test): upstream'sisPendingForRunplus the fork's notes gate. Fork locals and the test harness input are renamedlessonSideChat*.ProjectionStore.ts: older-settled SQL keeps both filters. The shell index carries both flags.ShellStream.ts: T3 Learn side chats are quiet and never settled; upstream side chats keep upstream's rules.ThreadSearch.ts(+test): both predicates in all 4 queries. The fork's fixture islessonSideChatOf.storageCleanup.ts(+test): worktree ownership follows both kinds. The fork's test scenario islesson-side-chat.serverRuntimeStartup.ts,relay/AgentAwarenessRelay.ts: both predicates.cli/invocation.ts(+test): upstream's real-path shim check is ported tot3-learn.Contracts, shared, client-runtime, mobile
contracts/orchestrationV2.ts:isOlderSettledThreadShell=isListedThreadLineage && !isSideChatThread.shared/agentAwareness.ts: both kinds are hidden.shared/composerContextReferences.test.ts: both sides' tests.client-runtime/olderSettledThreads.ts: both kinds.client-runtime/threadShell.ts: upstream's rollups as they are; child inputs count both kinds.mobile/keyboard/CommandPalette.tsx,mobile/threads/threadListV2.ts: both kinds hidden.Web
rightPanelStore.ts(+test): the kind split, the v16 migration and a migration test.closedViewStore.test.ts,reopenClosedView.ts,ReopenClosedViewShortcut.tsx: one case per kind.RightPanelTabs.tsx: both add-menu entries (upstream's Side chat, the fork's Side-chat map). Per-kind titles and icons.RightPanelSurfaceContent.tsx:SideChatPaneforside-chat,SideChatPanelforlesson-side-chat.useRightPanelSurfaceClose.ts: upstream's delete-if-unused only for its own tabs; the fork's finish only forlesson-side-chat.useRightPanelSurfaceClose.browser.test.tsx(add/add): upstream's file at this path. The fork's test moves touseRightPanelSurfaceClose.lessonSideChat.browser.test.tsx.ChatView.tsx: upstream's embedded mode and/sideas they are. The fork's entry points are off when embedded or inside an upstream side chat. Both capability gates use the helpers.AssistantSelectionToolbar.tsx: the fork's Ask in side chat plus upstream's background-thread Tab guard.useChatShortcuts.browser.test.tsx: both sides' tests.CommandPalette.tsx(+logic test): the Welcome guide action plus upstream's project actions. The side-chat actions are gated bysupportsLessonSideChats.BackgroundThreadAnnouncer.tsx: both kinds are skipped.Sidebar.logic.ts: upstream's exportedisSidebarHiddenThreadas it is. The fork's variant is renamedisSidebarHiddenRowThread.onboarding/WelcomeWizard.tsx: upstream's hint, plusAPP_BASE_NAMEin its new copy.settings/KeybindingsSettings.logic.ts: one parameter order. The flag is renamedlessonSideChats.Fixes in the merge commit, outside conflict hunks: the capability split and helpers (with a table test),
ServerEnvironment(+test), anddocs/internals/side-chats.md(capability, lock order, coexistence). Also:APP_VERSIONimport after upstream movedAboutVersionTitle.GitHubStarPrompt: names T3 Learn and its repo.environmentin a keybindings test mock.ThreadFork.execution.test.ts› "native_fork fork's first /compact": the test harness runs the effect daemon, which can claim the turn start before the test'sdrain(). It failed 3/3 after the merge (it passes 3/3 on upstream; the fork's pre-dispatch lock lookup shifts the race). The test now awaits the session-open milestone and passes 3/3.Fixes after the merge
fix(web): upstream's relationships test loads without the fork's entities helper: upstream's newThreadRelationshipsControlbrowser test mocksstate/entitieswith a fixed export list, so the fork'sisLineageThreadimport failed to load (first CI run, Test Web 1). The pure helper moved to client-runtime'sthread-relationships.fix(web): official builds' side-chat tabs keep their kind in T3 Learnfix(web): Mod+S in a T3 Learn side chat no longer opens the save dialogfix(web): a waiting T3 Learn side chat no longer reads as a subagentci: split T3 Learn's Test Web across four runnersandci: give T3 Learn's Test Web 30s per test. Upstream's new PDF reload test (fix(web): preserve PDF scroll and zoom across autoreloads pingdotgg/t3code#25555) took 13.2 s in one run and timed out at 15.0 s twice on the same commit. With four shards it still took 14.9 s. Its file is untouched by the fork and passes locally. A local--testTimeout=300run confirmed the CLI flag overrides the browser project's 15 s limit.Review
Five independent reviewers with fresh context read the remerge diff, split by area (server orchestration, turn start and projections, contracts/shared/client-runtime/mobile, the web right panel, and web chat/settings). A skeptic then tried to refute each finding against the source. Three survived, all low severity, and all are fixed:
side-chattabs, saved at v14, to T3 Learn's. Reconcile then dropped them, leaving an empty upstream side chat as a hidden fork. Now only v15 tabs, which only T3 Learn wrote, are renamed. Closed views (v2 is ambiguous) are corrected on reopen from the shell. One test row covers each, and both fail without the fix.Checked and fine (no findings):
thread.deletecomposition.ProviderTurnStartService.test(28 = 20 + 6 + 2).t3-learnresolution.Checks
Local, memory-capped, one at a time:
vp fmt --checkandvp linton the 358 files that differ from upstream: pass.threadListV2(64): pass.Also: the 7 web test files covering the review fixes (152 tests), the previously failing
ThreadRelationshipsControlbrowser test and the relationship helpers' tests all pass.T3 Learn CI:
fc8f75ac8cfailed Test Web 1 on theThreadRelationshipsControlimport (fixed above). Everything else passed, including Lint (with knip), Build and Typecheck, Test Server 1–8 and Mobile Native Static Analysis.146677f7e6failed Test Web 2 twice in "keeps workspace PDF scroll and zoom after reloads" (Test timed out, 15.0 s). That is upstream's new test on the slower runner; see the CI fixes above.798b30f74dwas all green; the PDF test took 14.9 s.b5fd58ea40(run 41214410688): all 20 jobs pass, including Check, Lint, Build and Typecheck, Test Server 1–8, Test Web 1–4 and Mobile Native Static Analysis.Open (needs med)
/side,/btwand + → Side chat. Options:sideChatsOfferedfalse, no/side//btwitems and no + → Side chat. It is a small follow-up.lineage.sideChatmodel. That is a large port.mobile-eas-preview-fork.yml:pull_request_target,pull-requests: write) is still in this branch, so this PR also needs that sign-off.aabdel0181/t3-learn. The alternatives are upstream's repo or no prompt.@picker offers T3 Learn side chats.Workflow files added against
main:.github/workflows/mobile-eas-preview-fork.yml(from #22). This range added none.Model and harness: Claude Opus 5.5 (
claude-opus-5-5) in Claude Code, run from T3 Code.🤖 Generated with Claude Code