Skip to content

chore: sync with upstream t3code (2026-11-03) - #23

Draft
aabdel0181 wants to merge 1038 commits into
mainfrom
sync/upstream-2026-10-31
Draft

aabdel0181 wants to merge 1038 commits into
mainfrom
sync/upstream-2026-10-31

Conversation

@aabdel0181

@aabdel0181 aabdel0181 commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

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). Against main it 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)

main has not moved since 2026-11-01, so there was one merge: upstream/main (acc0f25d57), 128 commits, 10 conflicts.

Server

Web

Fixes in the merge commit, outside conflict hunks:

t3-learn-ci.yml is unchanged; upstream did not touch ci.yml. Workflow files added against main: .github/workflows/mobile-eas-preview-fork.yml (from #22). Today's range added none. Upstream edited release-desktop.yml (pingdotgg#29484 Rosetta step), which stays disabled on the fork.

Fixes after the merge

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.

    • On the standalone Map tab, a node you reached by keyboard lost focus to the lesson composer when you came back to the window.
    • Focusing the panel landed on the Fit toggle instead of the Map's current node.

    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:

Checks

Local, memory-capped, one at a time:

  • Typecheck: contracts, shared, client-runtime, provider-core, provider-opencode, provider-muse, provider-fx, provider-acp-registry, provider-kiro, ssh, tailscale, server, web, desktop and mobile pass. After the review fixes, web passes.
  • vp fmt --check and vp lint on every resolved or fixed file: pass.
  • Tests, all passing:
    • Server: the six conflicted test files (209). After the fixes: ws and bootService (58).
    • Server: AgentSessionScanner › "still reads the git identity…", 5 of 5 runs.
    • Web: ChatView.logic and GitHubStarPrompt (55).
    • Web browser tests: ChatView.logic, SideChatMap and SideChatTimeline (11), and SideChatPanel (30). The new Map row failed before its fix.
    • client-runtime commands (13).

T3 Learn CI:

  • Run 41657089608 on the merge 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.

      • The fork changes nothing under apps/server/src/project/.
      • It passes on upstream's CI for cefb544af3, and 5 of 5 times locally on the merge.
      • The test advances its 2 s TestClock deadline as soon as the blocked repository's read starts, so it races a real file read of another repository, and the slower GitHub runner can lose.

      Not fixed; reported. It passed on the next run.

  • Run 41659924122 on 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 under apps/mobile.

Open (needs med)

  1. Two side-chat features (from 2026-10-31, unchanged). Options:
    • (a) Keep both, as merged.
    • (b) Keep T3 Learn's and hide upstream's /side, /btw and + → Side chat (small).
    • (c) Rebuild T3 Learn's on lineage.sideChat (large).
  2. chore: sync with upstream t3code (2026-10-30) #22's workflow file mobile-eas-preview-fork.yml (pull_request_target, pull-requests: write) is still in this branch.
  3. Should a T3 Code managed policy govern T3 Learn? (from 2026-11-02) Upstream's managed policy is read from T3 Code's locations (/Library/Application Support/T3Code/policy.json, /etc/t3code/policy.json, HKLM\SOFTWARE\Policies\T3Tools\T3Code, the com.t3tools.t3code profile). As merged, T3 Learn obeys it (updates off, nightly rule, runtime-mode ceilings, locked settings, telemetry) but ignores its update mirror. Options:
    • (a) Keep that.
    • (b) Give T3 Learn its own policy locations.
    • (c) Ignore managed policy in T3 Learn.
  4. From 2026-11-01, still open: feat(clients): surface child approvals in parent threads pingdotgg/t3code#28516 shows a side chat's approval in the lesson's composer too; the archived side-chat draft bug (pre-existing).
  5. Still open from 2026-10-31: the smaller calls in its section below.
  6. From today, low priority: a side chat's images don't reload when the lesson's agent rewrites the file (see Review). Upstream's own side chats have the same limit.
2026-11-02 part of this PR (180 commits, 16 conflicts)

main has not moved since yesterday, so there was one merge: upstream/main (d0cf0da2c0), 180 commits, 16 conflicts.

Server

Web

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's listedArchivedThreads and upstream's archive tag filter.
  • textGenerationUtils.test.ts: kept both test suites.

Fix in the merge commit, outside conflict hunks:

  • Thread tags (feat: tag threads and hide tagged threads while recording pingdotgg/t3code#29053). Upstream hides a tagged thread's children with it, but finds children by lineage, and a T3 Learn side chat's lineage reads as a listed fork. visibilityParentKey now 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.md says so.

t3-learn-ci.yml is unchanged; upstream did not touch ci.yml. Workflow files added against main: .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 on ac8dce0cc3 and on yesterday's branch tip. The replay harness runs the effect daemon, which can claim Stop's interrupt before the test's drain(). drain() then returns while the interrupt still runs, and the turn still reads running. Reverting either of two fork Orchestrator hunks made it pass, and both only add reads before dispatch (the side-chat step before dispatchMessage, 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 /compact test. The test now awaits the turn's interrupted event, as it already awaits running. It passed 5 of 5 local runs.
  • Review fixes (see Review):
    • 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:

  • Relaunch test. Upstream's new desktop relaunch test (fix(desktop): a settings relaunch no longer replays the link that launched the app pingdotgg/t3code#28464) passes t3code:// links. T3 Learn's scheme is t3learn, so the links were kept and the test failed. This was CI's Test job failure.
  • Managed policy update feed. Upstream's managed policy (feat: managed policy for organization-wide T3 Code configuration pingdotgg/t3code#27197) lets limits.updates.feedUrl replace 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 its mode and nightly rule. The new test fails without the fix.
  • Policy copy. Upstream's new policy messages said "T3 Code" in T3 Learn's Settings, sidebar, desktop updater and startup recovery. They now say T3 Learn.
  • Hidden side-chat route. A side chat whose lesson is hidden by tag still ran the fork's redirect into the lesson's panel. That added a tab to the hidden lesson, left a pending composer focus and replaced upstream's redirect home. The redirect now skips hidden side chats. The new browser test fails without the fix.

Checked and fine:

  • Upstream's Stop, send, truncation and idle-compaction fixes all reach side chats.
  • New thread.tag.set commands on a side chat take the lesson lock.
  • Every text-generation runner's fixes (Claude, OpenCode, Codex, Antigravity) also cover generateSideChatText.
  • The side-chat timeline and composer still work after upstream's perf changes.
  • The Welcome guide wiring and the t3-learn CLI 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 feedUrl as 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:

  • Typecheck: contracts, shared, client-runtime, provider-core, provider-opencode, server, web, desktop and mobile pass. After the fixes: contracts, shared, desktop and web pass.
  • vp fmt --check and vp lint on every resolved or fixed file: pass.
  • Tests, all passing:
    • client-runtime threadTagFilter, archivedThreads, threadShell (27). The new tag-filter row failed before its fix.
    • Server keybindings (with the fork's side-chat default cases), ThreadForkService, cli/update, ws (59); SelectionRestart.integration (8, five runs); cli/update, cloud/selfUpdate (29).
    • provider-core textGenerationUtils (13).
    • Desktop updates/* and DesktopLifecycle (98).
    • Web ThreadRouteView (browser) and updateEverything.logic (13).
    • shared managedPolicyFile (2, plus 1 Windows-only skipped).
    • New fix tests fail without their fix: DesktopUpdatePolicy, the ThreadRouteView hidden-lesson row and the threadTagFilter row.

T3 Learn CI:

  • Run 41465857539 on the merge d0cf0da2c0 failed two jobs. Test Server 8 failed on the SelectionRestart race. Test failed on the DesktopLifecycle relaunch 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.
  • Run 41468634434 on bbb2f1ebf5: Test Server 1–8 and Test Web 1–4 passed, Test still failed on DesktopLifecycle, and the run was cancelled by the next push.
  • Run 41470047961 on d48c2d2ae7: Test Web 1 failed in upstream's new MessagesTimeline.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 clean ac8dce0cc3 it 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.
  • Run 41471373161 on 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:

  1. origin/main into 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 with main, so GitHub ran no CI on it. 7 conflicts:
    • ContextHandoffDelivery.ts: kept upstream's withInlineContext, plus main's isPendingContextHandoff and quiet.
    • Orchestrator.ts: main's Done now cancels queued runs after Stop. It uses upstream's isActiveRun (was isBlockingRun).
    • ProviderTurnStartService.ts: main's side-chat instructions and skill mentions sit on top of the lessonSideChat* locals. They are renamed lessonSideChatSettings/loadLessonSideChatSettings. The provider text goes through upstream's withInlineContext.
    • ProviderTurnStartService.test.ts: the harness keeps upstream's sideChat input and session. It also keeps main's captureProviderTurn, settings, providers and failSettings. Main's tests use lessonSideChat.
    • 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.
    • Clean-merge fixes:
      • The Side chats settings section, its search entries and the settings route read supportsLessonSideChats. They had read capabilities.sideChats, which is upstream's capability now.
      • SideChatSettings types its skill options with plain string ids, since upstream's picker ids are branded.
  2. upstream/main (52c5f7b094). 6 conflicts:
  3. Review fixes (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.yml is unchanged; upstream did not touch ci.yml. Workflow files added against main: .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.

  • Fixed: side-chat uploads leaked on close (see 3). A second fresh reviewer checked the fix and found the two missed openSideChat paths.
  • Dismissed:
    • An image-only side-chat message puts upstream's attachment placeholder into the note writer's input. Upstream's own model-facing transcript builders pass that placeholder through too; it is only stripped from user-visible surfaces.
    • Upstream's "Your typed text was set aside" toast (fix(web): typed answer moved to the draft by an option click is announced pingdotgg/t3code#24331) is scoped to the side chat's thread, so it never shows in T3 Learn's panel. Upstream's own embedded side chats (SideChatPane → ChatView) have the same gap. The text itself is kept.
  • Left for med (pre-existing on main, not fixed here): clearGoneSideChatDrafts (useLessonSideChats.ts) is meant to keep an archived side chat's draft. Its guard reads readThreadShell(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.
  • Checked and fine:
    • Main's side-chat skills/instructions reach only T3 Learn opening turns, not upstream side chats, /goal, compaction or restarts.
    • Done's isActiveRun matches the old isBlockingRun. The queued-run cancel loop reads pending events.
    • No new upstream list, search or notification surface needs side-chat hiding.
    • The desktop entry, snapshot and build-artifact branding still agree after refactor(desktop): Drop the unused Linux --class switch pingdotgg/t3code#14482.

Checks

Local, memory-capped, one at a time:

  • Typecheck: contracts, shared, client-runtime, server, web, desktop, mobile, provider-opencode and provider-acp-registry pass.
  • vp fmt --check and vp lint on every resolved or fixed file: pass.
  • Tests, all passing:
    • Server: side-chat suites, ProviderTurnStartService and bootService (11 files, 215 tests).
    • Web: side-chat panel/composer/Settings, settings search, composerSend, versionSkew and updateEverything (19 files, 227 tests).
    • Contracts settings/environment (31 tests), shared serverSettings (45 tests) and the release-version script test.
    • Desktop: the resolved startup, environment, URL handler and backend configuration tests (4 files, 56 tests).
    • Web: reopen shortcut, ExpandedImageDialog, side-chat panel/composer, ChildThreadApprovals (5 files, 64 tests).
    • The fix's paths: the two close tests, palette, openSideChat, useLessonSideChats and the panel (7 files, 58 tests).

T3 Learn CI:

  • Run 41318336178 on 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.
  • Run 41321614578 on 2c694950e1 (with the review fixes): all 20 jobs pass, including Check. The run on 216906173a was cancelled when 2c694950e1 superseded it.

Open (needs med) at the time

  1. Two side-chat features (from 2026-10-31, unchanged). Options:
    • (a) Keep both, as merged.
    • (b) Keep T3 Learn's and hide upstream's /side, /btw and + → Side chat (small).
    • (c) Rebuild T3 Learn's on lineage.sideChat (large).
  2. chore: sync with upstream t3code (2026-10-30) #22's workflow file mobile-eas-preview-fork.yml (pull_request_target, pull-requests: write) is still in this branch.
  3. New today: upstream feat(clients): surface child approvals in parent threads pingdotgg/t3code#28516 shows child-thread approvals in the parent's composer. The fork counts T3 Learn side chats as the lesson's children, so a side chat's approval now also appears in the lesson, as upstream's own side chats do. On mobile this is the only place it shows. Nothing changed for it; say if it should be hidden.
  4. The archived side-chat draft bug above (pre-existing).
  5. Still open: the smaller calls listed below for 2026-10-31.
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 against main it 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, /btw or + → 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

  • Capability. Both features used ExecutionEnvironmentCapabilities.sideChats (a duplicate key after the merge). sideChats keeps upstream's meaning; T3 Learn's is now lessonSideChats, and the server advertises both. supportsLessonSideChats also accepts sideChats from released -learn. servers, and supportsSideChats refuses upstream's /side on them: they would create a listed fork and delete it when its tab closes.
  • Right panel. Both used the tab kind side-chat and a store action openSideChat, with different shapes. Upstream's stay as is; T3 Learn's tab is now lesson-side-chat (openLessonSideChat). The persisted right-panel state goes 15 → 16 and closed views 2 → 3, with migrations that rename saved T3 Learn tabs.
  • Hiding. Every list, search, older-settled, awareness, idle-compaction and agent-listing rule hides or exempts both kinds. The palette still finds T3 Learn side chats.
  • Locks. The order is lesson → thread → that thread's upstream side chats. Neither kind of side chat can start the other: the server refuses both directions, and the web hides T3 Learn entry points inside upstream's embedded side-chat view.
  • Turn start. Upstream's inline side-chat context and the fork's opening, late summary and notes stay separate. The fork's notes rule moves inside upstream's isPendingForRun.

Conflicts (42 files)

Server

  • Orchestrator.ts: upstream's planDeletion, onlyIfUnused and inline side-chat cascade. The fork's side-chat.cascade effect runs for every deleted thread. Upstream's fork and delete locks are wrapped in the fork's lesson lock. side_chat.open refuses an upstream side-chat anchor. isBlockingRun → isActiveRun.
  • ThreadForkService.ts (+test): forks still go through planForkTargetThread, 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's isPendingForRun plus the fork's notes gate. Fork locals and the test harness input are renamed lessonSideChat*.
  • 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 is lessonSideChatOf.
  • storageCleanup.ts (+test): worktree ownership follows both kinds. The fork's test scenario is lesson-side-chat.
  • serverRuntimeStartup.ts, relay/AgentAwarenessRelay.ts: both predicates.
  • cli/invocation.ts (+test): upstream's real-path shim check is ported to t3-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: SideChatPane for side-chat, SideChatPanel for lesson-side-chat.
  • useRightPanelSurfaceClose.ts: upstream's delete-if-unused only for its own tabs; the fork's finish only for lesson-side-chat.
  • useRightPanelSurfaceClose.browser.test.tsx (add/add): upstream's file at this path. The fork's test moves to useRightPanelSurfaceClose.lessonSideChat.browser.test.tsx.
  • ChatView.tsx: upstream's embedded mode and /side as 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 by supportsLessonSideChats.
  • BackgroundThreadAnnouncer.tsx: both kinds are skipped.
  • Sidebar.logic.ts: upstream's exported isSidebarHiddenThread as it is. The fork's variant is renamed isSidebarHiddenRowThread.
  • onboarding/WelcomeWizard.tsx: upstream's hint, plus APP_BASE_NAME in its new copy.
  • settings/KeybindingsSettings.logic.ts: one parameter order. The flag is renamed lessonSideChats.

Fixes in the merge commit, outside conflict hunks: the capability split and helpers (with a table test), ServerEnvironment (+test), and docs/internals/side-chats.md (capability, lock order, coexistence). Also:

  • The pending-question digit keys answer only the panel they were pressed in.
  • An unused APP_VERSION import after upstream moved AboutVersionTitle.
  • GitHubStarPrompt: names T3 Learn and its repo.
  • A missing environment in 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's drain(). 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 new ThreadRelationshipsControl browser test mocks state/entities with a fixed export list, so the fork's isLineageThread import failed to load (first CI run, Test Web 1). The pure helper moved to client-runtime's thread-relationships.
  • Review fixes (see Review):
    • fix(web): official builds' side-chat tabs keep their kind in T3 Learn
    • fix(web): Mod+S in a T3 Learn side chat no longer opens the save dialog
    • fix(web): a waiting T3 Learn side chat no longer reads as a subagent
  • ci: split T3 Learn's Test Web across four runners and ci: 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=300 run 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:

  • Migration. The right-panel migration renamed an official build's side-chat tabs, 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.
  • Mod+S. Upstream's stash guard now skips T3 Learn's panel too, so Mod+S there opened the browser's save dialog. The fork's handler claims the chord again.
  • Label. A T3 Learn side chat's waiting question read "Subagent waiting" in the scroll summary.

Checked and fine (no findings):

  • Deadlock analysis across Done, open, the upstream fork, delete and cascades.
  • The thread.delete composition.
  • The turn-start handoff selection.
  • SQL predicates and the shell index.
  • Both parents' tests kept in ProviderTurnStartService.test (28 = 20 + 6 + 2).
  • Welcome guide wiring.
  • The CLI t3-learn resolution.

Checks

Local, memory-capped, one at a time:

  • Typecheck: contracts, shared, client-runtime, server, web, desktop and mobile all pass.
  • vp fmt --check and vp lint on the 358 files that differ from upstream: pass.
  • Server: 31 files, 688 tests, pass. This covers the 19 files the resolvers named plus every side-chat test and the files feat: side chats beside the main thread pingdotgg/t3code#26901 touched.
  • Web: 39 files, 480 tests (unit and browser), pass. This covers the right panel, closed views, reopen, the side-chat panel/map/timeline, the palette, ChatView, shortcuts, the pending-question panel, the Welcome guide and keybindings.
  • Contracts (2), shared (59), client-runtime (46) and mobile threadListV2 (64): pass.

Also: the 7 web test files covering the review fixes (152 tests), the previously failing ThreadRelationshipsControl browser test and the relationship helpers' tests all pass.

T3 Learn CI:

  • Run 1 on fc8f75ac8c failed Test Web 1 on the ThreadRelationshipsControl import (fixed above). Everything else passed, including Lint (with knip), Build and Typecheck, Test Server 1–8 and Mobile Native Static Analysis.
  • Run 2 on 146677f7e6 failed 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.
  • Run 3 on 798b30f74d was all green; the PDF test took 14.9 s.
  • On 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)

  1. Two side-chat features. Users now see T3 Learn's "Ask in side chat" and Map next to upstream's /side, /btw and + → Side chat. Options:
    • (a) Keep both as merged here.
    • (b) Keep T3 Learn's as the only side chat and hide upstream's entry points. That means sideChatsOffered false, no /side//btw items and no + → Side chat. It is a small follow-up.
    • (c) Rebuild T3 Learn's side chats on upstream's lineage.sideChat model. That is a large port.
  2. chore: sync with upstream t3code (2026-10-30) #22's workflow file (mobile-eas-preview-fork.yml: pull_request_target, pull-requests: write) is still in this branch, so this PR also needs that sign-off.
  3. Smaller product calls:
    • Upstream side chats start in approval-required mode and skip worktree checkpoints. T3 Learn side chats use the lesson's mode and still checkpoint the shared worktree; this predates the merge.
    • The new star prompt points at aabdel0181/t3-learn. The alternatives are upstream's repo or no prompt.
    • The cross-system refusal reuses upstream's text, "A side chat cannot start another side chat."
    • Still open from before: the @ 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

@aabdel0181 aabdel0181 changed the title chore: sync with upstream t3code (2026-10-31) chore: sync with upstream t3code (2026-11-01) Nov 1, 2026
davisonio and others added 28 commits November 1, 2026 21:47
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>
)

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>
…ut (pingdotgg#28491)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
juliusmarminge and others added 29 commits November 2, 2026 18:32
…#23373)

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>
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>
)

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>
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>
…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>
@aabdel0181 aabdel0181 changed the title chore: sync with upstream t3code (2026-11-02) chore: sync with upstream t3code (2026-11-03) Nov 3, 2026
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.