Skip to content

chore: merge upstream pingdotgg/t3code through 7ac952c630 - #204

Merged
andrewcai8 merged 105 commits into
mainfrom
sync/upstream-2026-10-14
Oct 14, 2026
Merged

andrewcai8 merged 105 commits into
mainfrom
sync/upstream-2026-10-14

Conversation

@andrewcai8

@andrewcai8 andrewcai8 commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Main was 102 upstream commits behind after #203. Today's scheduled sync failed on four conflicts. This merges upstream 8ac4b97dae..7ac952c630 as a real merge commit. Merge with Create a merge commit, never squash.

Notable upstream changes

Conflicts

  • ServerUpdateAction.tsx. Upstream's useServerUpdate now takes { quiet } and returns a ServerUpdateOutcome. The fork's manager upgrade path for cloud guests now does both too, and a refused upgrade counts as failed. Update everything still skips cloud guests, as it did before. Upstream's new skip list now shows them as "needs a manual update", though their own Update button upgrades them through the manager. That is a follow-up.
  • registry.ts. Keeps the fork's requested registration and takes upstream's boolean register result.
  • ProviderSessionManager.test.ts and ThreadLaunchService.test.ts. Both sides' tests and imports.

Semantic overlap

The fork (#193) and upstream (pingdotgg#19291, pingdotgg#19355) each added "clear the background roster when a session is released". Git merged both without a conflict. The fork's copy cleared every task on every runtime, read at write time. That would wipe tasks a replacement session had just reported, and OpenCode subagents that outlive the session. Upstream's copy reads the roster before a replacement can open. It writes with a compare-and-set, covers detach, and skips OpenCode. The fork's copy is removed. The fork's open-lock handling of release records stays, and its slow-release replacement test passes on upstream's mechanism.

Fork code adapted to upstream

  • crypto.randomUUIDv4 is a function now (9 call sites in Home, Fleet, cloud host, worker forks and managed folders).
  • Fork test fakes of the Claude query session gain applyFlagSettings.
  • The fork's Claude host probe runs in stateDir, like upstream's other instance-level probes.
  • ForkMigrations.test.ts expects upstream migration 62.
  • ProvisionOperationStore.test.ts reads only the contenders' protocol lines. Upstream's checkpoint worker now logs a warning when it falls back (fix(shared): SQLite checkpoints no longer fall back to the main thread silently pingdotgg/t3code#19417), and that warning shared stdout, so the test failed on 2 of 3 runs. It passed 6 of 6 after the change.
  • useHandleNewThread.cloud.test.ts mocks readProject, which upstream's new-thread flow now calls.

Verification

  • Typecheck reports 0 errors in apps/server, apps/web, apps/mobile, apps/desktop, packages/client-runtime, contracts, shared, provider-core, provider-opencode and provider-muse.
  • Server. Orchestration, session manager, thread launch, Claude adapter, MCP, Home, environment control, persistence, scheduled tasks and drivers: 122 files, 2051 tests. Three fail on the cloud machine used for this run and pass with a clean environment. Those three read its real AWS keys, its injected prompt note, and its installed earlyoom. They are fork tests that upstream did not touch.
  • Web. Cloud, update, sidebar, settings, hooks, chat and state: 220 files, 2478 tests pass.
  • client-runtime. Connection and state: 82 files, 1147 tests pass.
  • Mobile. Threads, connection and state: 84 files, 765 tests pass.
  • vp i leaves pnpm-lock.yaml unchanged.

Claude Opus 5.5 (1M context), Claude Code

🤖 Generated with Claude Code

StiensWout and others added 30 commits October 13, 2026 14:02
…dotgg#18369)

Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
pingdotgg#12474)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…pingdotgg#12469)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
…nger drop clients (pingdotgg#19205)

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

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

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

Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
…otgg#19160)

Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
…gdotgg#15864)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mits (pingdotgg#11368)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…hey made unnecessary (pingdotgg#19213)

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

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…se the child (pingdotgg#14416)

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>
t3dotgg and others added 20 commits October 14, 2026 04:22
…sh-only (pingdotgg#19389)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…se a resize drag (pingdotgg#19395)

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

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…offers a relink (pingdotgg#19379)

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s at the same time (pingdotgg#19411)

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

Co-authored-by: Aaron Queen <bompus@users.noreply.github.com>
Co-authored-by: Daniyal <115576848+daniyal-sh@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…d silently (pingdotgg#19417)

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

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

Co-authored-by: puccez <emanuele.puccetti@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: luke2x <97411838+luke2x@users.noreply.github.com>
…keep their own history (pingdotgg#19425)

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

Co-authored-by: Eldar Politkin <32969822+EldarPolitkin@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gdotgg#19418)

Co-authored-by: Tanner Sharon <tannermsharon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts:
- ServerUpdateAction.tsx: upstream's quiet updates and ServerUpdateOutcome now
  also cover a guest upgraded through its manager. A refused manager upgrade
  counts as failed, so Update everything reports it.
- registry.ts: keeps the fork's requested registration and upstream's boolean
  register result.
- ProviderSessionManager.test.ts, ThreadLaunchService.test.ts: both sides' tests
  and imports.

Upstream's release roster clearing (pingdotgg#19291, pingdotgg#19355) replaces the fork's copy in
writeReleasedSessionEvents. It reads the roster before a replacement can open,
keeps tasks a replacement reports, covers detach, and leaves OpenCode's alone.
The fork's open-lock handling of release records stays.

Fork code adapted to upstream changes:
- crypto.randomUUIDv4 is a function now.
- Claude query session fakes gain applyFlagSettings.
- The Claude host probe runs in the state dir like upstream's other
  instance-level probes (pingdotgg#19320).
- The fork migration test expects upstream migration 62.
- The provision contender test reads only its own stdout lines, since the
  SQLite checkpoint worker now logs when it falls back (pingdotgg#19417).
- The cloud new-thread test mocks readProject.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Oct 14, 2026
….0.4

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@andrewcai8

Copy link
Copy Markdown
Owner Author

Independent verification: PASS+NOTES

Head verified: 66e476f403 (merge b44d5c4e10, parents fork f2a2e4a6 and upstream 7ac952c630).

What I checked

Conflict resolutions.

  • ServerUpdateAction.tsx and cloud/guestServerUpdate.ts. The merged hook is upstream's useServerUpdate plus the fork's manager-upgrade path, with no other drift from either parent. useGuestServerUpgrade returns a ServerUpdateOutcome. It returns skipped on interrupt and failed on refused, and it suppresses its toast under quiet. Thrown manager failures reach useServerUpdate's catch. I checked every caller. ServerUpdateAction and ServerUpdatesAction update without quiet, so guests still get toasts. useUpdateEverything updates quietly. useAutoBalanceUpdateBanner and ConnectionsSettings only call isRemoteServerUpdate. The type-only import cycle is erased at build time.
  • registry.ts register. It keeps the fork's requested and keepBoxIdentity handling. It also returns upstream's false for platform environments and true after install. Upstream's new setCompatibility(null) plus setEnabled(true) after pairing works with boxes, because setEnabled still goes through boxes.wantsConnection.
  • Conflicted tests. ProviderSessionManager.test.ts has 57 base tests, 2 from the fork and 6 from upstream, 65 in total. ThreadLaunchService.test.ts has 46 base, 2 fork and 1 upstream, 49 in total. No test was dropped.

Roster clearing overlap. Dropping the fork's #193 block does not lose behavior #193 needed. The fork's account switch releases with manual_shutdown (provider/ProviderAccountSwitch.ts:247), and Claude sets backgroundTasksEndWithProcess: true (ClaudeAdapterV2.ts:9107), so its roster is still cleared. Server shutdown is still excluded, as #193 had it. The runtimes that no longer get cleared are Codex, which keeps no roster, Pi, which always writes [], and OpenCode, which upstream excludes on purpose. The fork's holdsOpenLock and writeReleaseRecordsUnlessReplaced compose with the new releasedBackgroundTasks. The roster is read before the lock, and the write is a compare-and-set that removes only the old task ids, so retries are idempotent. Only the open-failure path at ProviderSessionManager.ts:2342 releases while it holds the open lock, and it passes holdsOpenLock: true. That means no deadlock.

Files changed on both sides. I ran a 3-way git merge-file on all 65. Only 8 differ from the automatic merge result, and they are the 4 conflicts plus the author's adaptations. I skimmed the auto-merged server orchestration, MCP, Claude adapter and client-runtime files for semantic clashes and found none. Upstream's delegate_task worktree isolation does not bypass the fork's cloud-only refusal, because no local agent exists on such a host to call it. Upstream's Claude process-group spawn leaves Bash-tool background jobs in their own groups, so #193's usage-limit shells survive.

Adaptations. makeClaudeHostProbe now receives stateDir, which is right. Its usage turn runs with persistSession: false and settingSources: [] and is not tied to a project. This matches upstream pingdotgg#19320. No randomUUIDv4 site is left uncalled. The test edits keep real assertions. ProvisionOperationStore still asserts one winner and one observer for both effects. ForkMigrations adds migration 62. The readProject mock returns the real fixture project.

Notes (none block landing)

  1. apps/web/src/components/sidebar/updateEverything.logic.ts:115. Update everything never reaches the guest manager-upgrade path. A manager upgrade needs selfUpdate === null (cloud/guestServerUpdate.ts:36), and collectServerUpdateTargets skips those servers. So the PR's statement that a refused guest upgrade is reported by Update everything never happens in practice. Scenario: a leased cloud guest is behind the client version. Update everything lists it as skipped with "needs a manual update", while its own row button upgrades it through the manager. The base also excluded these servers, but silently. Upstream's new skip reason makes the label visible and wrong for fork guests. The new refused -> failed and quiet branches in guestServerUpdate.ts:134 also have no test.
  2. Upstream fix(server): enforce one database owner and guard update rollback pingdotgg/t3code#16102 adds a one-server-per-T3-home lock (serverOwnership.ts, exit code 78). From reading environmentControl/remotePreparation.ts:1135-1148, the fork's guest restart waits on its own server.lock before starting the new build, and it runs project add only after the server is ready, so the CLI takes the live path. That looks compatible, but no cloud guest run here exercised it.
  3. .repos/effect-smol/packages/effect/src/Crypto.ts:150 still shows randomUUIDv4 as an Effect value, while the installed effect@4.0.4 has a function. The vendored reference was not re-synced. This came from upstream and is cosmetic.

Tests run here (repo-local vp, one command at a time)

  • Server: ProviderSessionManager, ThreadLaunchService, ProviderAccountSwitch and ClaudeBackgroundWorkAfterLimit. 4 files, 150/150 passed.
  • Server: ForkMigrations, ProvisionOperationStore, ClaudeAdapterV2, OrchestratorMcpService, ManagedProjectFolders and Drivers/claudeUsage. 6 files, 307/307 passed. ProvisionOperationStore also passed 3 more runs in a row.
  • Web (--project unit): guestServerUpdate, ServerUpdateAction, updateEverything.logic, useHandleNewThread and useHandleNewThread.cloud. 5 files, 61/61 passed.
  • client-runtime: the connection/ registry, onboarding and supervisor tests, 120/120 passed. The registry.cloud, onboarding.cloud, boxPairing, hostBoxSync and provisioned tests, 5 files, 80/80 passed.
  • tsc-rs --noEmit reported 0 errors in apps/server, apps/web, apps/mobile and packages/client-runtime.

Verified by Claude Opus (poteto-agent), not the author.

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.9 KiB 20.9 KiB 0 B (0.0%) 29.3 KiB ✅
Codex Live turn messages 2 2 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB +24 B (+0.5%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB +24 B (+2.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.2 KiB 21.2 KiB +41 B (+0.2%) 29.3 KiB ✅
Claude Live turn messages 1 2 +1 (+100.0%) 8 ✅

Baseline: 4e27301 · PR result: ac7db3b · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

… sampled per-key estimate

The fork's extra tables shift the sampled rows-per-key figure from 100 to 95.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@andrewcai8

Copy link
Copy Markdown
Owner Author

Independent verification of ac7db3b: PASS+NOTES

Scope: only git diff 66e476f403 ac7db3b160, a one-assertion change in apps/server/src/persistence/Sqlite.test.ts:92-97. Node 24.21.0, bundled SQLite 3.53.4.

1. Root cause: confirmed, with one refinement.

  • With the original assertion temporarily restored, vp test run src/persistence/Sqlite.test.ts fails deterministically with expected [ { stat: '1000 95' } ] to deeply equal [ { stat: '1000 100' } ]. As committed, all 6 tests pass. The file was restored afterwards and git status is clean.
  • I saved the test's database file between its two opens and replayed the second open in plain node:sqlite. PRAGMA optimize = 0x10012 (apps/server/src/persistence/Sqlite.ts:39) gives 1000 95. 0x10002, the same pass without the temporary analysis_limit (bit 0x10), gives the exact 1000 100. So the 95 comes from the analysis_limit sampling.
  • Running ANALYZE over a range of analysis_limit values on that file gives: 100 -> 1000 51, 500 -> 1000 84, 1000 or more -> 1000 100. On this file, optimize's effective limit falls below the table's 1000 rows, so it samples.
  • Refinement: the stat rows the fork adds don't cause this. Deleting fork_sql_migrations from sqlite_stat1 (or emptying it) still gives 95. What matters is the file layout and size the fork's tables produce (withForkMigrations at apps/server/src/persistence/Migrations.ts:274). In a synthetic database with N empty table+index pairs ahead of the probe, N=100 gives 1000 100, N=120 gives 1000 92, and N=200 gives 1000 100 again. The effect doesn't grow steadily with N; it is sampling noise, and upstream's schema happens to land on 100. The test comment ("the fork's extra tables shift it") is accurate enough.

2. Production impact: none fork-specific.

  • The fork's tables don't stop stats being collected. Every table that needs them still gets a sqlite_stat1 row; the fork only adds a harmless fork_sql_migrations: 6 row.
  • Rows-per-key is approximate whenever an index is bigger than optimize's temporary limit. That is upstream's design and applies to upstream databases too: with no extra tables, a 5000-row probe gives 5000 401 (true 500) and a 20000-row probe gives 20000 1001 (true 2000). Real tables are usually far bigger than 1000 rows, so production stats are estimates either way. A 5% error on rows-per-key does not change index choice.

3. The relaxed assertion still guards the behavior.

  • Mutation check: with PRAGMA optimize removed from Sqlite.ts:39, the test fails with no such table: sqlite_stat1. Restored, tree clean.
  • The saved database has no stats for stats_probe before the second open. The first open's optimize runs before the table exists, and nothing analyzes on close. So a 1000 row in the second connection must come from the optimize on open, which is the behavior under test.
  • The first field is stable: across every analysis_limit I tried (100 to 5000), it is exactly 1000. The new assertion is deterministic and doesn't hide any regression.
  • It also still checks there is exactly one row for that index. [] or a duplicate would fail.

Notes (non-blocking)

  • The test would not catch a mask change that drops bit 0x10000: 0x12 still analyzes stats_probe on this file (1000 97). That gap was already there before this commit and is not something the test claims to check.
  • This is a fork-only edit to an upstream test file, so it will conflict if upstream touches that assertion. Making the test independent of layout (e.g. 100+ rows per key with a fixed analysis_limit) would be a better change to send upstream than to carry here.

Verified by Claude Opus (poteto-agent), not the author.

@andrewcai8
andrewcai8 merged commit 39db120 into main Oct 14, 2026
25 checks passed
@andrewcai8
andrewcai8 deleted the sync/upstream-2026-10-14 branch October 14, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.