Skip to content

Upkeep: T4 now builds on upstream v0.1.9 - #154

Merged
LukasDoubleU merged 203 commits into
t4from
upkeep/v0.1.9
Nov 11, 2026
Merged

LukasDoubleU merged 203 commits into
t4from
upkeep/v0.1.9

Conversation

@LukasDoubleU

Copy link
Copy Markdown
Owner

Part of #13

T4 Code now builds on upstream v0.1.9 (24e77473ec). The branch merges the tag with --no-ff, so its history keeps t4 and v0.1.9 as parents, then adds the ultracode fix, a stale generated file, the upkeep bookkeeping and the fixes for code that merged cleanly but no longer compiled.

Upstream range

  • v0.1.8..v0.1.9: 198 upstream commits.
  • Migrations: upstream adds 081_ProjectionMessageSearchText. The merged list is exactly upstream's, plus the fork's in-place change to 069_ThreadMessageSearch. The fork has no migration ids of its own, so nothing collides.
  • Workflows: upstream adds .github/workflows/mobile-dev-client.yml (new) and changes ci.yml, mobile-eas-preview-fork.yml, mobile-eas-preview.yml, mobile-eas-production.yml and mobile-showcase-screenshots.yml. None are touched here. The new workflow has a pull_request trigger for its own path, so this PR may start a run; both its jobs require github.repository == 'pingdotgg/t3code' and skip on the fork. It still needs disabling after the push.

Commits

  • Merge upstream v0.1.9: 32 conflicted files, resolved below.
  • fix(mobile): the Catppuccin theme gets the guest accent color: regenerating the mobile theme variables (as the upkeep regenerates generated files) adds the fuchsia accent to the fork's Catppuccin theme. It was already missing on t4; guest messages, guest names in the queue and the Request status use it. routeTree.gen.ts regenerates identically; highlights.generated.ts is upstream's.
  • fix(server): busy accounts recognize the ultracode toggle: see below.
  • chore(t4): build on v0.1.9 and version 0.1.10-t4.N: upstream.json (base: "v0.1.9"), the t4-release.yml example and the README. First release: t4-v0.1.10-t4.1. The release order test gains a two-digit patch.
  • fix: the fork's catch up, palette and minimap build on v0.1.9: code that merged without conflicts but failed to typecheck; listed under Semantic conflicts.

Conflicts and how they were resolved

Default: upstream's code, with the fork's behavior re-applied in the smallest form.

Thread search and migration 081 (#22553)

  • messageSearchIndex.ts: upstream's search_text column, readable-text triggers and recreateMessageSearchTriggers are taken. The fork's indexedMessageCondition (every finished user and assistant message, including user-role ones agents, schedules or the system wrote) stays, so the update trigger keeps the fork's form without the createdBy comparison, now on upstream's readable text.
  • ThreadSearch.ts: the fork's sentBy column next to upstream's messageSearchText.
  • How 081 meets the fork's index: 081 adds search_text, recreates the triggers from the current code (so with the fork's condition) and backfills search_text only for messages holding a citation link. It doesn't rebuild the index: rows already indexed stay, and backfilled rows are re-indexed by the update trigger under the fork's condition. On a fresh database, 069 and 074 create the triggers with the fork's condition and 081 recreates them the same way. t3 doctor's rebuild uses the same condition.
  • Test: the 081 migration test now also inserts an agent-written plain message and an agent-written quote at migration 80; after 81 both are found, the quote by its readable text.

Account switching (#22755)

  • Orchestrator.ts merged cleanly apart from wakeWorkStartedAt, which now takes the projection (upstream) next to the fork's origin: dispatchedRunOrigin(...).
  • Upstream's OrchestratorProviderSelectionBusyError refuses thread.model-selection.set and provider.switch while a run is active. The fork's failover moves a thread with a message.dispatch on the next instance once its turn is over, so the refusal never applies to it; the fork's SWITCH_ENDS_BACKGROUND_WORK refusal is unchanged. Upstream's runtimeLayer.test.ts dropped two rows that changed instances mid-run; the fork's tests (AccountFailover, UsageLimitRecoveryWorker, ProviderSwitch.integration, ClaudeSessionCarry, ProviderSessionTransitionPolicy) pass unchanged.
  • ProviderTurnStartService.ts: the fork's providerMessageText (citations, reply references, reactions) with upstream's OpenCode native goals (#33758). The Claude session carry (feat(server): account moves keep the Claude session instead of a summary #151) merged cleanly.

OrchestratorMcpService.ts

  • Upstream's #33295 makes loadCaller and loadScopedThread read only the fields a tool names. The fork's pinned-thread listing passes []; send to thread passes ["runs"] and keeps the fresh-start refusal. nextAccount (ranked among the caller's allowed instances, busy instances passed in) merged cleanly.

linkRequest.ts (#34139)

  • Upstream now drops loopback addresses from every machine's list, including the Connect address, which is what the fork's own filter did. The file is now upstream's exactly; the fork's test for it stays and passes.

Sidebar, palette, shortcuts

  • Sidebar.tsx: upstream moved the drag ghost out and dropped useTerminalFocus (#33129); the fork's thread memory imports and its New thread dialog for Add project stay. Upstream's snooze detail labels are applied to the fork's menu too.
  • threadActionMenu.logic.ts: the fork's menu with More stays; its snooze presets use upstream's label plus detail (#24945).
  • chatRouteCommands.ts and its test: Ctrl+N keeps opening the fork's new thread dialog; New thread here uses upstream's last-used project (readLastUsedProjectKey).
  • CommandPalette.tsx: both sides' React imports.
  • UsageLimitsPooled.tsx: upstream's reset credit choices with the fork's UsageNextAccount.
  • Sidebar.browser.test.tsx, fakeEnvironment.ts: both sides' mocks and fields.

Notifications

  • ThreadNotificationCoordinator.logic.ts: the fork's observeThreadNotification takes upstream's request ids and Monitor wake grace (#32520, #32719): attention keys carry the request id, a Monitor's held completion is not settled, and backgroundWake is passed. Needs you still replaces the completion it arrives with, and runs the user didn't start stay quiet. The fork's tests now expect the request id in the key.

Citations, timeline, minimap

  • assistantCitationNavigation.ts: upstream's side chat routing (#33160), widened to the fork's reply references. The fork's useAssistantCitationSourceLink (used by the chip, sent quotes and reply references) now goes through assistantCitationRoute, so every source link opens a side chat's quote on its parent.
  • assistantCitations.ts (contracts, shared): upstream's 4096-character ids (#28084) apply to reply references too, and the href limit uses upstream's formula for both link kinds.
  • MessagesTimeline.tsx: the fork's mark capacity and tall-reply refresh next to upstream's restore refresh; upstream's chevrons replace MorphIcon (#33985) next to the fork's reply time.
  • TimelineMinimap.tsx: the fork's grouped marks and previews with upstream's display-only preview, at-end Next (#33038) and hit strip (#32151).
  • TimelineUserMessageRow.tsx: LinkIcon (#33985), emoticons next to upstream's ordered-list remark plugin (#33820).

Other

  • ThreadDetailScreen.tsx (mobile): upstream's column width wrapper plus the fork's lastVisitedAt.
  • DesktopApp.test.ts, DesktopWindow.test.ts: both sides' mocks and tests.
  • agentAwareness.test.ts: both sides' shell fields.
  • scripts/install.test.ts: upstream's 504 retry rows with the fork's 1.2.3-t4.1 release.
  • docs/user/keybindings.md: both sides' commands. docs/user/source-control.md: the fork's clone text plus upstream's pasted page URLs, which the fork's clone dialog gets through normalizePastedCloneUrl.

Semantic conflicts (merged cleanly, failed to typecheck)

  • TextGeneration.ts: upstream's generators pass the project to their fallback (#33741). Catch me up now passes the thread's project as well (ThreadCatchUpGenerationInput.projectId), and the OpenCode driver resolves its catch-up runtime as its other generators do.
  • CommandPalette.tsx: the fork's scroll to an initial highlight passes upstream's new first-row flag.
  • MessagesTimeline.tsx: the minimap reads the scroll node for upstream's at-end check, since the fork computes the visible range in a helper.
  • chatRouteCommands.test.ts: drops a branch no row reaches.

Ultracode fix

Since v0.1.8, ultracode is its own boolean model option (ultracode: true, effort xhigh). isUltracode in ProviderSessionManager.ts only checked effort === "ultracode", so a session using the toggle never ranked its account as busy (#150). It now reads the toggle with getModelSelectionBooleanOptionValue and falls back to the legacy effort value, as withLegacyUltracodeEffort does. The busy test runs once per form; the toggle row failed before the fix. docs/user/usage.md and the comments now say "with Ultracode on" instead of "at effort ultracode"; the reason text ("busy: ultracode session") didn't name the effort.

Re-checked fork behaviors

Usage-limit work (#148 wakes before a reset queue behind the limited run, failover retries, SWITCH_ENDS_BACKGROUND_WORK; #150 busy ranking; #151 Claude session carry), nextAccount, message search with agent-written messages, Experts with folding quiet experts, Needs you never buried in Settled, shelves at the bottom, last-message sort, machine icon, expert row title width, thread icons and menu, quiet background turns and Needs you notifications, reply to a reply, the minimap for long threads, catch up, citations and reply references, the new thread dialog, and the fork guards: version scheme (0.1.10-t4.1 sorts above every 0.1.9-t4.N in newestCliReleaseVersion; the desktop and remote updaters use the same numeric semver compare; install-t4.sh takes GitHub's latest release and prunes backups by timestamp), update track hidden and refused, startup recovery to the fork's releases, star prompt hidden and sourceControl.star refused, triage refused, t3 install pointing at T4's scripts, t3 update with t4-v tags, and the Windows afterPack hook skipping win32 (#153). Nothing new in v0.1.9 stars or reports to upstream from fork builds; see the open question on mobile:install.

Verification

Heavy steps ran one at a time under a shared lock, vitest with 2 workers. No dev server; browser tests ran headless in vitest.

  • vp i: lockfile unchanged.
  • Typecheck: contracts, shared, client-runtime, server (t3), web, desktop and mobile pass, plus provider-core and provider-opencode.
  • Usage limits: AccountFailover, runtimeLayer, UsageLimitRecoveryWorker, ProviderSessionManager, ClaudeSessionCarry, ProviderSessionTransitionPolicy, ProviderSwitch.integration, nextAccountInstances, OrchestratorMcpNextAccount, TaskCancelUsageLimit.integration (10 files, 296 tests) and shared usageNextAccount: all pass.
  • Search and migrations: 069_ThreadMessageSearch, 081_ProjectionMessageSearchText, ThreadSearch (38 tests) pass; Migrations, reconcileV2PreviewMigration, DatabaseMaintenance, initializeV2Database pass.
  • Server conflict areas: Orchestrator (control reads, migration, receipt race), ProviderTurnStartService, ThreadMessageIntake, ThreadCatchUpService, OrchestratorMcpService (+ activity, waitWake, toolkit integration), threadAccess, toolkits/core, linkOrigin, McpHttpServer, text generation: 17 files, 254 tests pass.
  • Fork guards: star sign-in, triage, t3 update, t3 install, self-update, pinned runtime, service preflight (8 files, 71 tests); scripts/install.test.ts and scripts/t4/install-t4.test.ts pass (5 PowerShell-only cases skip on Linux).
  • Packages: contracts (33 files), shared (citations, awareness, release order, model, usage), client-runtime (linkRequest, projects), provider-opencode driver: pass.
  • Web: 16 logic files (440 tests) and 18 browser files (120 tests) for the sidebar, palette, shortcuts, notifications, citations, timeline, minimap and usage: pass.
  • Mobile: 298 files (3391 tests) pass. Desktop: 112 of 113 files pass; scripts/browser-secret-native.test.mjs needs pkg-config and libsecret headers, which this machine lacks.
  • ProjectionStore.test.ts: 53 of 54 pass. Upstream's new "reads a fixed SQL turn-item window" test (#33305) calls StatementSync.stat, which needs Node 26; this machine runs Node 24.
  • Evals: no API key here, so no paid run. mcp-tool-use --dry-run builds the three WebMCP page tool cases that upstream's wording change (#26570) targets; --context: system text 8854 chars, tool descriptions 16670, schemas 52718 across 72 tools. The fork changed no model-facing text in this upkeep.
  • vp run check:changed origin/t4 (steps one at a time, VITEST_MAX_WORKERS=2, under the lock): unused patches, format, lint, knip, graphql, typecheck (41 packages), node tests and the React Compiler check pass. The test step ran 349 files: 346 passed, 3 failed, none from this branch:
    • AgentContextBudget.test.ts: fails as it does on t4. Measured 7129 / 8857 / 51638 bytes (Claude append / Codex context / MCP tool list) against upstream's committed 5597 / 7327 / 48217. The fork's overhead is unchanged from t4 (+1532 / +1530 / +3421).
    • ProjectionStore.test.ts "reads a fixed SQL turn-item window": Node 26 only, as above.
    • GitVcsDriverCore.test.ts "makes background upstream status fetches non-interactive": this machine's global core.sshCommand overrides the test's GIT_SSH; it passes with GIT_CONFIG_GLOBAL=/dev/null, as on t4.
  • fix(build): Windows payload stays within the file limit #153's scripts/lib/server-compile-cache.test.ts passes.

Open questions

  • mobile:install (new upstream dev tooling, scripts/mobile-native-client.ts) defaults T3_NATIVE_CLIENT_REPOSITORY to pingdotgg/t3code: with gh installed, it asks upstream's API whether HEAD is there and could dispatch upstream's mobile-dev-client.yml (only with permission, which the fork lacks). It neither stars nor reports and isn't part of any build, so I left it; a fork default would be a one-line change.
  • mobile-dev-client.yml needs disabling after the push (see Workflows).
  • The ProjectionStore window test and the desktop libsecret test need Node 26 and pkg-config; CI should run both.

Upkeep by Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code

t3dotgg and others added 30 commits November 9, 2026 12:36
pingdotgg#33538)

Co-authored-by: Yuruzuu <tauqmc@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
…otgg#33600)

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

Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
)

OpenCode usage scans materialized complete message bodies and queried empty
rowid ranges. Select in-window rowids first and project usage fields in
SQLite, keeping message bodies off the JS heap. Read each database in one
snapshot and record scan row and page counts.

On a read-only snapshot of a 3.32 GB real database, five fresh-process runs
measured 2.33x faster 30-day reads and 2.82x faster 90-day reads with identical
records. These are cold application-cache measurements; OS caches were not
cleared. Local check:changed and CI passed.

Adapted SQL projection from pingdotgg#27679
and window selection/snapshot handling from
pingdotgg#26613.

Model and harness: GPT 6.1 Sol through Codex in T3 Code.

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Tymoteusz Bielski <31070271+TymekTM@users.noreply.github.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gg#33632)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Normalize Cursor usage pages as they arrive, retain bounded raw page data, and preserve count-proven boundary deduplication and stable event keys. Use direct hex hashing, limit concurrent account refreshes to two, reuse unchanged cached records, and persist retention pruning.

Validation: check:changed passed with 61 focused tests; 40 differential reader cases matched the original output. CI and agentic reviews passed on the merged head.

GPT 6.1 Sol via Codex in T3 Code.
…approve" (pingdotgg#33645)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
New threads started without an active thread or draft used the first project in sidebar order, even after working in another project. This was visible when creating a draft from Settings or delivering a pending snapshot after reopening the app.

Remember the project from the current thread or draft, including its environment, and prefer it when a new draft needs a project. Removed or archived projects fall back to sidebar order. The new-thread keyboard shortcut reads the same preference when invoked. Pending snapshots wait while the remembered environment loads and retry when its project state becomes available.

Validation: regression coverage for project selection across environments, missing and archived projects, and a preference changed after shortcut registration. Verified Settings → reload → New thread in the client. `vp run check:changed` covers formatting, lint, affected typechecks, tests, and React compiler checks.

Model: GPT 6.1 Sol via the Codex harness.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s that build (pingdotgg#33617)

Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com>
…w at rest (pingdotgg#33599)

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

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
…bar changes (pingdotgg#33611)

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

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

Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com>
…tgg#26630)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
…ab (pingdotgg#23589)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
Add a Details action for pending background commands and subagents. Preserve Claude command metadata across roster updates and bind output visibility to the explicit command item. Keep internal task IDs, duplicate command labels, and empty output headings out of the dialog.

Validation: check:changed passed with 371 tests; CI and agentic reviews completed on a0326ab. Verified command details in real Codex and Claude runs.

Implemented and verified with GPT 6.1 Sol in the Codex harness.
juliusmarminge and others added 29 commits November 10, 2026 22:55
…g#22836)

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…un claude update (pingdotgg#34176)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
…tab opens again (pingdotgg#34168)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
…only the 2-minute sweep (pingdotgg#33548)

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

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ing a turn (pingdotgg#33900)

Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com>
…ents (pingdotgg#22553)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
… base's PR (pingdotgg#22861)

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…he binding changes (pingdotgg#32494)

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generated theme variables predated the fuchsia accent that guest
messages, guest names in the queue and the thread list's Request status
use, so the Catppuccin theme had no value for it. Regenerated with
scripts/generate-uniwind-themes.mts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since ultracode became its own model option (`ultracode: true` at effort
xhigh), sessions using it no longer ranked as busy: `isUltracode` only
checked the old `effort: "ultracode"` value. It now reads the toggle first
and falls back to the legacy effort, as `withLegacyUltracodeEffort` does.
The busy test runs once for each form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
upstream.json, the README and the t4-release.yml example follow the new
base. The first release on it is t4-v0.1.10-t4.1. The release order test
gains a two-digit patch, so 0.1.10-t4.1 sorts above every 0.1.9-t4.N.
The tray (pingdotgg#19176) and the last-message sort (pingdotgg#22032) are still carried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code that merged without conflicts but no longer compiled against v0.1.9:

- Catch me up passes the thread's project to text generation, as
  upstream's other generators now do (pingdotgg#33741), so its fallback model
  respects the project's provider settings. The OpenCode driver resolves
  its runtime the way its other generators do.
- The palette's scroll to an initial highlight says whether it is the
  first row, as upstream's scroll helper now asks.
- The minimap reads the scroll node itself for upstream's at-end check,
  since the fork computes the visible range in a helper.
- The new thread shortcut test drops a branch no row reaches.

The 081 migration test also covers user-role messages agents wrote: the
fork indexes them, and the backfill keeps and re-indexes them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LukasDoubleU
LukasDoubleU merged commit 505ba20 into t4 Nov 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.