fix(git): resolve PR badges for untracked prNNNN checkouts by number - #376
Open
omegent-app[bot] wants to merge 141 commits into
Open
omegent-app[bot] wants to merge 141 commits into
omegent-app[bot] wants to merge 141 commits into
Conversation
Add custom "Open with" applications Source: tim-smart#4 Source head: 8c4bdfbc5b57f6b600233244d330f9efa41dc498 Source commits: 08e1a4fb949585c3c441d6d00455fe904f72cd7b,cd43a401c6c148f1fe26cff72104ac527ea189f3,a8370e7502c552ebb064436e42e1c00f86f0946b,8c4bdfbc5b57f6b600233244d330f9efa41dc498 Imported: complete product delta from the source PR. (cherry picked from commit 9fae005)
Load direnv environments for provider sessions Source: tim-smart#5 Source head: 8f5fc87c13f4628c179cda44d4f32f7fe4d316b2 Source commits: e4f07014d39964fde2498bcb35588974cc5e6232,0d1463af61e0bd174f698b2519ebf3b207a2eaca,a66e4160d5f4b79140ec8fbcbc6aa66af750a991,8f5fc87c13f4628c179cda44d4f32f7fe4d316b2 Imported: complete product delta from the source PR. (cherry picked from commit 0da8bfe)
Add unsigned retry for commit signing failures Source: tim-smart#6 Source head: 7d65c5a224e97a6b811b0a84892f1fda065c5963 Source commits: 18ee567ecfdb11c9372153127b26b5cf57213a76,72a6fae23c86708080c4fed346d5bf0f136f0221,6614b28239ed2330a8f601357a413f2d50da195a,ec169369daa554541511aa28f551b36f3dd26485,7d65c5a224e97a6b811b0a84892f1fda065c5963 Imported: complete product delta from the source PR. (cherry picked from commit 03671a2)
Add /new command for contextual threads Source: tim-smart#7 Source head: 2051a8003041fe2806fcb4bc7a0d8940579fc543 Source commits: 2051a8003041fe2806fcb4bc7a0d8940579fc543 Imported: complete product delta from the source PR. (cherry picked from commit 4d94f31)
Add session dashboard board Source: tim-smart#8 Source head: d9f8e4d0a8dc22231ca315f3c595c3597f3b13e5 Source commits: 268fb8df9863ffbda51b975a8dbe68f11c41500c,dde20f271f674da22dd8f3a08201c2acf5e58ee5,df4a145e7b2cd2dc17a7a595267d2d8eb0a2a3f0,ce5723ddb0bf630a18d4cb8227b5344d12626e72,ad8c1a6af41161e1fc38a52f681b306517c7b918,6281887e6125317da0c7b4252d59bfd41c9bf35e,550db6316c634febdbe1cb27334d1347c23c7b2a,d9f8e4d0a8dc22231ca315f3c595c3597f3b13e5 Imported: complete product delta from the source PR. (cherry picked from commit cd0e281)
Recover interrupted provider turns after server restarts Source: tim-smart#9 Source head: b181832560177250b90bbfe07b0882c9e5b93493 Source commits: 7f69028a25be21f1882ecba14b62f387ad60cf2a,1d52bce1376766d804ef884d7d50b8b6d1b48cf7,b181832560177250b90bbfe07b0882c9e5b93493 Imported: complete product delta from the source PR. (cherry picked from commit 83de8f5)
Avoid repeated thread snapshot loads during subscription retries Source: tim-smart#10 Source head: c8c9eadb9de3026706bc3a403ca05b12d0da8dd5 Source commits: c8c9eadb9de3026706bc3a403ca05b12d0da8dd5 Imported: complete product delta from the source PR. (cherry picked from commit 9e400c3)
Add image upload button to compact chat composer Source: tim-smart#11 Source head: 1ff63f9b9c418ef56a46c6422d22c01de97581a8 Source commits: 1ff63f9b9c418ef56a46c6422d22c01de97581a8 Imported: complete product delta from the source PR. (cherry picked from commit 720ec65)
Truncate mobile branch toolbar controls Source: tim-smart#12 Source head: 1b7d44428472511bc98d8f936654359ce2536901 Source commits: 1b7d44428472511bc98d8f936654359ce2536901 Imported: complete product delta from the source PR. (cherry picked from commit dc2bbb4)
Clean up worktrees when archiving threads Source: tim-smart#13 Source head: a23f42d6ac671ea36b8db5d03934c089a31be448 Source commits: 4a194707ed134f993502ac5fdf36a8425f1769cd,1b6688aa5b641010cb2e9dad23d36d87257403ad,9ed32aa3923fb674380564b1ffcb3268290069b9,a23f42d6ac671ea36b8db5d03934c089a31be448 Imported: complete product delta from the source PR. (cherry picked from commit 7e02dc9)
Pass hosted app channel into Vercel web builds Source: tim-smart#14 Source head: de6966a6784b4703145c20b84fc482703bca4fa2 Source commits: de6966a6784b4703145c20b84fc482703bca4fa2 Imported: complete product delta from the source PR. (cherry picked from commit 6333d8d)
Allow worktrees to reuse the selected branch Source: tim-smart#15 Source head: 2d3900ba36c9397dc4fbe879c613a809f6b45384 Source commits: cd60531253fbafc470f5a5ac18d3e44832d3376d,2d3900ba36c9397dc4fbe879c613a809f6b45384 Imported: complete product delta from the source PR. (cherry picked from commit 5e7dff2)
Add optional worktree removal confirmation Source: tim-smart#16 Source head: c3f509fe8f690b704bb34692d9c132c0644db777 Source commits: 76f063e983ca3c39b20f79d8ea83783ab034251a,c3f509fe8f690b704bb34692d9c132c0644db777 Imported: complete product delta from the source PR. (cherry picked from commit 9886109)
Stop retrying unavailable thread subscriptions Source: tim-smart#17 Source head: 1359af8ba0b146e3d49f89b72c250f681e86199d Source commits: 1359af8ba0b146e3d49f89b72c250f681e86199d Imported: complete product delta from the source PR. (cherry picked from commit 7b37a7a)
…nd; green tip Bring Tim layer tip to typecheck green by joining main ref-refresh VCS client state with fork failureKind/worktree-cleanup contracts, restoring filterBrowseEntries/reuse-base-branch surfaces Tim dropped, and fixing ChatView/Board call-site type errors left by incomplete Tim joins. (cherry picked from commit 0e24917)
Bring fork/tim typecheck/test green after main pingdotgg#2679 + Tim client-runtime rewrite: rejoin EnvironmentSubscriptionRpcTag/localApi/ws scopes, wire BackgroundPolicy/ResourceTelemetry layers, force openpgp for signing tests on hosts with gpg.format=ssh, and treat TRACE2 child_exit without child_class as hook finish (git 2.55+).
"work" is no longer an empty full-catalog query once Worktree remove confirmation is searchable. Keep the word-wrap false-positive check and assert the worktree setting is the sole full-catalog hit.
Source: pingdotgg#4018 Source SHA: de8fd65 Imported: bounded server activity snapshots, cursor pagination, lazy web history loading, reconnect-safe reset/dedup, and disabled eager browser sidebar hydration. Adapted: preserved Tim thread lifecycle handling and Omega composer/minimap behavior while resolving current-stack conflicts. Excluded: none of the source PR behavior; native mobile pagination remains separate because pingdotgg#4018 intentionally excludes it.
…#3510) (#35) Source: pingdotgg#3510 Source SHA: 034f4936d7a1435887bb62ac3f2db61f08928cbf Imported: native mobile lazy loading for older thread activity, a 1,000-event subscription catch-up ceiling with snapshot fallback, and synchronized stale snapshot watermarks. Adapted: applied above the refreshed pingdotgg#4018 web/server candidate and preserved Tim lifecycle handling plus our mobile composer changes. Excluded: pingdotgg#3510 server/web pagination duplicated by pingdotgg#4018, the later shared-hook refactor, formatting-only commits, and contract comments. The shared refactor can be revisited independently after production validation.
Source: pingdotgg#4176 Source SHA: 56b6615 Imported: O(1) command read-model maps, deleted-thread eviction, VCS cache cleanup, browser surface cleanup, preview idle TTL, and per-thread UI cleanup. Adapted: preserved our thread settlement, snooze, and sequential worktree deletion actions while wiring upstream cleanup into the current hook. Excluded: none. Co-authored-by: Rusiru Sadathana <27785781+RusiruSadathana@users.noreply.github.com>
#44) Source: pingdotgg#4506 Source SHA: f7eaa00 Imported unchanged as one candidate provenance commit.
…tgg#4558) Imported from https://github.com/pingdotgg/t3code/pull/4558\n\nAdapted to retain our provider restart-recovery constants while replacing the local default-title check with the shared policy.
…gdotgg#4379) (#312) Imported from pingdotgg#4379 at a27510d060645809ae1472bba4dbb248dc624e25. Open file previews revalidate on mount and subscribe to debounced native filesystem watches so external edits (editors, git, agents) show without a manual refresh. Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Enrico Polanski <16064771+enricopolanski@users.noreply.github.com> Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
… (#328) Imported from pingdotgg#5344 at source SHA 783fd02 (commits b623dc2 + 783fd02 squashed into one provenance commit). Imported behavior: - `reduceThreadStreamItems`, a pure reducer that folds a batch of thread stream items into one state and one persistable snapshot. - `Stream.groupedWithin(64, 16ms)` on the live subscription so a burst of thread events publishes the `SubscriptionRef` once instead of per event, and web/mobile stop rebuilding large thread views per streamed event. - `eventBatchSize` on `EnvironmentThreadStateOptions`, plus the upstream regression tests for ordered single-publication bursts and for persisting a settled snapshot when a batch ends with a non-persistable turn start. Local adaptations: - Kept our `httpSnapshotLoadAttempted` guard around the HTTP snapshot fallback; the call now goes through `applyItems([...])`. - Restored `setDeleted` (removed upstream) for the terminal `thread-deleted` subscription failure, which never reaches the item stream and so cannot go through the batch reducer. Cache removal is shared with the reducer path via `removeCachedThread`. Excluded: - `tasks/todo.md`, the author's scratch checklist. Follow-up (fork/changes, not this layer): our `reload-required` branch and `reloadFromServer` are built on the deleted `setThread`, so rebasing fork/changes onto this layer must re-express them against the reducer (split the batch at the reload point, then re-enter `applyItems` with the remainder). Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
Eight commits, headlined by pingdotgg#5493 "paginate thread loading with user-anchored turn windows" -- 2093 insertions plus a keyset index migration. Candidate #29 ("perf: import bounded web thread history", upstream pingdotgg#4018) is confirmed superseded: upstream never merged pingdotgg#4018 and ships loadOlderTurns instead. The candidate is removed from web, mobile and client-runtime -- olderThreadActivities.ts deleted, ChatView and the mobile composer/feed/screens rewired to upstream's loadEarlier model. The SERVER half stays: deployed mobile builds still call orchestration.getThreadActivities, so the RPC, its schemas and the activity window constant are retained as a compatibility surface and marked as such. All 24 textual conflicts resolved to upstream. The expensive work was what git auto-merged wrong or left dangling, found by typecheck and tests, not markers: - threads.ts: upstream's applyItemLocked header welded onto the fork's batch reducer body, referencing an out-of-scope identifier and silently dropping upstream's synchronized branch. The fork's batching layer (groupedWithin, reduceThreadStreamItems, eventBatchSize) is removed with its two tests; the fork's load-once HTTP fallback guard is reimplemented on upstream's model and its regression test passes again. - ws.ts: the fork's reuseBaseBranch worktree flow and upstream's pingdotgg#5556 no-origin fallback are combined; neither side alone compiled. - ProjectionSnapshotQuery: upstream's new windowed message query lacked the fork's source_json column, failing decode on every windowed read; the bounded detail query destructured nine results from seven queries -- the fork's queued-messages and pending-turn-start members are restored. - BranchToolbar/SidebarV2/MessagesTimeline/ChatView: prop and rename skews reconciled; fork surface-existence assertion updated for the new feed call. - Migration ledger fixtures extended for upstream migration 037, which lands in the upstream namespace and does not collide with the fork's renumbered 037. - Upstream's new tests adapted to fork-required fields (queuedMessages, pendingTurnStart) and the fork's projection-wait in bootstrap. Verified: full recursive typecheck clean across 17 packages; 2264 tests pass including upstream's 11 pagination and 7 windowed-detail tests. The single failure (CodexTextGeneration structured output) predates this merge. fork/tim touches threads.ts, ProjectionSnapshotQuery and contracts; no tim commit is merged upstream, so review those diffs with tim provenance in mind. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 6b73b3d into fork/dev
Adopts the ten upstream commits after #368: timeline live-follow (pingdotgg#5566), reconnect-loop handling during server stalls (pingdotgg#5561), plans folded into chat (pingdotgg#5558/pingdotgg#5551), plus server settle/reconnect fixes and the transfer-budget CI test (pingdotgg#5350). The fork's "keep the open WebSocket lease when a foreground liveness probe fails" is replaced by upstream's probe model. Both target reconnect churn during server stalls; upstream splits the wake reasons (probe vs reconnect), adds tolerance windows and a first-attempt ladder skip. Keeping both was incoherent: the auto-merge left the fork's swallow in front of upstream's wakeProbeFailed path, making it dead code. The fork's diagnostics log, labelled ping-timeout errors and followNetworkStatus resume handling are kept around it. Welds found by typecheck and tests, not by conflict markers: - ChatView and ThreadFeed each ended up with two follow-state variables, the fork's superseded one still being written; converged on upstream's. - findSidebarProposedPlan was dropped from session-logic while ChatView still called it; restored. - Two timeline row-union members merged into one malformed member. - The fork's pre-latch ThreadFeed handlers survived as duplicates alongside upstream's; removed, with the fork's unread-activity dot rebuilt on the latch. - resolveOlderHistoryAutoLoad, left over from the superseded pagination candidate, was referenced only by its own tests; removed with them. - Upstream's transfer-budget test opened a socket without the fork's omegent-t3 product handshake, so the environment rejected it. Plan sidebar wiring is removed with the surface upstream deleted; the fork's settle-independent follow-up composer gate is kept. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 48aa875 into fork/dev
…373) PR badges stopped appearing in sidebar v2 for **active** threads, while settled rows kept theirs. Root-caused on the running server, fix verified against the exact failing invocation. ## What was happening The server's VCS shell-outs resolve `gh` through each repo's `.tools/bin` — the agent policy shim installed by `scripts/install-git-hooks.mjs`. Caught live off the server process: ``` CMD=node /var/lib/t3/deploy/t3code/scripts/agent-gh.mjs pr list --head release-cut-mako-easylife \ --state all --limit 20 --json number,title,url,... ``` That shim resolves the binary to delegate to via `findRealGh`, which preferred `$T3_GITHUB_REAL_GH` above everything else. **That variable names the unauthenticated `gh`** — the binary the GitHub App wrapper execs *after* minting an installation token. The host exports it (see the server start script: _"still export REAL_GH / token paths so children that reorder PATH cannot lose minting config"_) as configuration for the wrapper, not as an authenticated entry point. So the shim skipped minting entirely and ran raw `gh`: ``` $ env -i $(server env) .tools/bin/gh pr list --head release-cut-mako-easylife --state all ... To get started with GitHub CLI, please run: gh auth login exit=4 ``` Exit 4 → `SourceControlProviderError` → the warning that has been filling the journal every 45s: ``` WARN: PR lookup failed; keeping last known PR state. operation: lookupStatusPr errorTag: SourceControlProviderError branch: release-cut-mako-easylife ``` ## Why settled rows still showed badges That asymmetry is the tell. Settled worktrees take the durable settle freeze added in #362, which returns `resolveLastKnownPr(...)` **without calling the provider at all**. A frozen row can't fail a lookup it never makes. Every active row goes down the live path, hits the auth failure, and falls back to a last-known value that is empty — so the card renders with no badge. Introduced by `2ef070919` (2026-08-02, "enforce repository-owned agent ship gates"), which added the `T3_GITHUB_REAL_GH` branch to `findRealGh`. ## The fix Resolution order becomes: 1. `AGENT_GH_REAL` — this shim's own re-entry override, unchanged. 2. **PATH** — where the App-aware `gh` lives. 3. `T3_GITHUB_REAL_GH` — last resort only, so hosts without a wrapper still work. ## Verification The same command that returned exit 4, under the server's exact environment, after the change: ``` $ .tools/bin/gh pr list --head sync/upstream-48aa875c0 --state all --limit 5 --json number,state [{"number":372,"state":"MERGED"}] ``` Regression test added to `scripts/agent-pre-push.test.mjs` pinning all three tiers of the order; it fails on the pre-fix implementation and passes after. Full file: 26 tests pass. The deploy checkout was patched only to prove the fix live and has been restored to its released state, so the fleet stays consistent with its deployed SHA until this lands. Co-authored by [@patroza](https://github.com/patroza) opened by [Patrick Roza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1534783738322485399/1534783738322485399) · [T3](https://t3vm/?thread=584a9ad3-243e-4308-8a13-49acdd758b17) Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
Adopts the six upstream commits after #372: per-device provider settings (pingdotgg#4479), the modular theme library and theme editor (pingdotgg#5226), Done/Woke sidebar semantics (pingdotgg#5579), the non-pulsing Working label (pingdotgg#5580), mobile T3 Connect device cleanup (pingdotgg#5563), and a download-page copy fix (pingdotgg#4511). Upstream's new filePicker/projectSearch/themeEditor shortcuts arrive with an overlay-mode host for the command palette. The fork rewrote that component, so the host was ported rather than taken: the palette reducer gains `mode` and `ToggleMode`, and the two overlays bring their own popup instead of the popup being lifted out of OpenCommandPaletteDialog. Without that the new default keybindings would have been dead. Welds found by typecheck and tests, not by conflict markers: - SidebarV2 ended up with two per-row VCS status queries: upstream's full-mode `vcsEnvironment.status` auto-merged in above the fork's budgeted `listStatus`. Upstream's new isWoke reads prState, so the fork's query and its pr/prState derivation are hoisted above it and the duplicate dropped. Keeping the fork's list mode matters: full mode is one poller per worktree. - ElectronDialog: the fork's pickApplication and upstream's pickFiles are independent additions that collided at every declaration site. - The keybindings test fixture kept the fork's list, silently dropping upstream's two new bindings while its new assertions expected them. The v1 sidebar body is a fork rewrite; upstream restructured the same region for its own layout, so both sides were whole-body alternatives and the fork's is kept. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 23f0a1a into fork/dev
Adopts the three upstream commits after #374: mobile keyboard avoiding (pingdotgg#5451), dev-runner cold-start speedup (pingdotgg#5584), and rewritten --share instructions (pingdotgg#5586). Resolutions: dev-runner.ts unions the fork's METRO_PORT passthrough with upstream's launcher-env scrubbing (T3_SERVICE_LAUNCHER_CONTEXT / T3_BOOT_SERVICE_UNIT deletion). AGENTS.md's auto-union dropped upstream's rewritten "Dev servers" bullets into the fork's ship-gate section; the share/pairing guidance is folded into the fork's own Dev Servers section instead, replacing its older --share bullet. Lockfile regenerated. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 8100062 into fork/dev
Adopts the four upstream commits after #375: thread actions from the chat header title (pingdotgg#5592), per-turn runtime-mode recording (pingdotgg#5593), chat timeline positioning stabilization (pingdotgg#5449), and the background-work banner no longer hiding behind the update notice (pingdotgg#5595). The chat header gains upstream's inline rename and title-menu (shared threadActionMenu.logic) woven around the fork's remote-VS-Code open and usage-dot/host-resource chrome. SidebarV2 adopts the shared menu builder in place of the fork's buildSidebarV2ThreadContextMenuItems; the fork's copy-thread-id entry moves into the shared menu (and gains a handler in useThreadActionMenu) so both surfaces offer it. ChatView takes upstream's folded reconnect/version banner logic (pingdotgg#5595, a superset of the fork's resuming-update suppression) and the anchor-clearing rAF scroll (pingdotgg#5449), keeping the fork's unread-flag clearing and its unread-activity observer. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main b2ee17d into fork/dev
Adopts the seven upstream commits after #377: iOS terminal clear no longer resets the session (pingdotgg#5440), Android scroll padding above the nav bar (pingdotgg#5415), Android composer opacity (pingdotgg#5582), Clerk auth navigation headers (pingdotgg#5140), the mobile app version bump to 1.0.2 (pingdotgg#5588), click-to-unpin (pingdotgg#5578), and the correct new-thread shortcut in the sidebar tooltip (pingdotgg#5594). Three resolutions: - ThreadComposer: pingdotgg#5582 moves the backdrop gradient off Animated.View, where Reanimated silently drops experimental_backgroundImage on Android — the very bug it fixes. The fork's gradient was on that Animated.View, so it is removed there and the fork's stronger lower-band stops (0.82/0.96 dark, 0.88/0.98 light) ride on upstream's plain-View backdrop instead. - app.config: upstream's 1.0.2 version bump with the fork's MOBILE_RUNTIME_VERSION_OVERRIDE escape hatch kept; its default policy is the same fingerprint upstream documents. - SidebarV2: upstream's pingdotgg#5594 label ordering (chat.new before chat.newLocal) adopted — the fork's button has exactly the semantics upstream describes, routing multi-project setups through the palette picker and creating immediately otherwise. The fork's board and command-palette labels stay. Upstream's two new react-mocking harness tests (pingdotgg#4479) are added to the fork's isolatedUnitTestFiles. The fork's unit project runs isolate: false to reuse each worker's module graph; upstream has no such config, so those tests assume full isolation. Under a shared registry the component graph can already be bound to the real react/compiler-runtime by an earlier file, the vi.mock("react") never applies, and the compiled component reports a memo-cache hit and skips the hooks the test asserts on. That is what made AddProviderInstanceDialog.environment fail this PR's CI while passing in isolation. Two other react-mocking tests were already in that list. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 239ef1c into fork/dev
Adopts the two upstream commits after #378: reconnects no longer shift the mobile thread list (pingdotgg#5372) and the v0.0.32 release prep. pingdotgg#5372 moves connection status out of the lists into the header title slot (WorkspaceConnectionTitle / getConnectionAwareBrandHeaderOptions) and deletes WorkspaceConnectionStatus. The fork rendered that status in four places across HomeScreen and ThreadNavigationSidebar — exactly the row-shifting this fixes — so those in-list surfaces are removed and the header slots adopted. The auto-merge left one dangling {connectionStatus} in HomeScreen whose definition upstream had deleted; typecheck caught it. Fork surfaces kept around the new title: - multi-environment selection: HomeScreen keeps its selectedEnvironmentIds label derivation and environmentLabelById (BoardScreen consumes it) instead of upstream's single selectedEnvironmentId. - board mode: ThreadNavigationSidebar keeps its board branch, board-specific solid header, and board-gated search bar, with upstream's connection-aware brand slot merged into the same header options. - HomeRouteScreen keeps the fork's in-flow HomeHeader as title owner rather than also restoring upstream's native-stack title, which would surface the connection status twice. Adversarial review caught two holes in the first pass, both fixed here: getConnectionAwareBrandHeaderOptions hardcodes the brand lockup and "Threads", so spreading it over the fork's list-mode titles silently replaced "Board" / "Projects"; and iOS Home has its own IosHomeHeader owning the native title, so dropping upstream's route-level options left that path with no status surface at all. The helper now takes an optional title/brand, and both the sidebar and IosHomeHeader pass their mode title through it. A second review pass caught one more surface — the custom (Android split) sidebar large title still hardcoded "Threads" — plus the status offset being applied to caller-supplied titles that lack the brand lockup's inset. Both fixed, and mobileSurfaceExistence now asserts every adopting surface passes its own list-mode title (that assertion fails on the pre-fix tree). Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
Adopts pingdotgg#5581 (drag pinned threads into your own order) on top of the pingdotgg#5372 merge already on this branch. Pinned rows now sort by the user's arranged pinOrderKey on every platform, which is deliberately independent of the fork's thread-grouping preference: that preference still orders the active rows, but a pin is an explicit arrangement and upstream documents the sort as identical everywhere so mixed-version fleets cannot disagree. Server capability gates dragging only, never the sort. SidebarV2 keeps the fork's environment/ownership filters around the new pinned block and gains upstream's reorderablePinnedKeys. Welds the auto-merge produced, all caught by typecheck or tests: - useThreadActions.ts: upstream's ThreadPinReorderUnsupportedError landed inside the fork's clearPerThreadClientState, leaving it unclosed. - threadListV2.ts: two `for (const thread of ...)` headers stacked on one loop body; the pinned block takes upstream's order-key sort. - useThreadListActions.ts: duplicate threadEnvironment import plus local copies of helpers this fork imports from threadActionMessages. - HomeRouteScreen: upstream's single-environment onEnvironmentChange handler does not exist in this fork's multi-select screen. - projector.pinned.test.ts indexed state.threads[0]; this fork's read model keys threads by id in a HashMap. - Six migration-ledger fixtures pinned the tail at 37; upstream's 038 ProjectionThreadsPinOrderKey extends it. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
## Summary - iOS crashed on the composer **+** attachment button because `pickComposerImages` called `requestMediaLibraryPermissionsAsync()` while the app ships with `photosPermission: false` (no `NSPhotoLibraryUsageDescription`). - Open the system image picker directly (no media-library permission preflight), wrap launch failures in a structured error, and add unit coverage that the permission API is never called. ## Test plan - [x] `vp test run apps/mobile/src/lib/composerImages.test.ts` (8 passed) - [ ] On iOS: expand thread composer → tap **+** → system photo picker opens (no crash) - [ ] Cancel picker → no attachment, no error toast - [ ] Pick an image → attachment strip shows preview Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
sync(upstream): merge upstream/main 5661c61 into fork/dev
Adopts the thirteen upstream commits after #379. The headline is pingdotgg#5672 making sidebar v2 the default, which is a file-level restructure: upstream renamed the classic sidebar to LegacySidebar.tsx and moved v2's content into Sidebar.tsx, deleting SidebarV2.tsx. Git could not follow either rename because both sides had changed both files, so each was merged three-way by hand: - Sidebar.tsx = the fork's SidebarV2.tsx (multi-env and ownership filters, identity marks, budgeted listStatus, pin ordering, copy-thread-id, unread and regenerating-title chrome) with upstream's pingdotgg#5672 delta applied. That delta is a rename sweep — SidebarV2* → Sidebar*, group/v2-row → group/sidebar-row, sidebar-v2-* test ids — plus aria-busy on the rows. - LegacySidebar.tsx = the fork's old Sidebar.tsx with upstream's rename and settings-nav hoist applied. AppSidebarLayout now renders SettingsSidebarNav for both sidebars, so the legacy one no longer renders it itself. forkSurfaceExistence, the fork's anti-stack-drop net, was retargeted at the renamed files and ids rather than relaxed: all 17 assertions still run, and they are what caught LegacySidebar initially being upstream's v1 rather than the fork's. Other resolutions: - GitManager: upstream's per-branch exponential backoff for rate-limited PR lookups (pingdotgg#5673) with the fork's terminal-state freeze helper kept. - Composer: pingdotgg#5554 shows Stop while input is pending, which is exactly what the fork's shouldShowComposerInterruptAction suppressed; the predicate and its tests are retired rather than merged. - PreviewView: the fork's resolveNavigableUrl (asks the environment about tailnet routing) keeps resolving, with upstream's browser-history recording (pingdotgg#5270) layered on the successful-navigation path. - Settings: sidebarV2Enabled / sidebarV2ConfiguredByUser and enableAssistantStreaming are retired in favour of upstream's fresh keys (legacySidebarEnabled, enableLegacyTokenStreaming), which deliberately reset prior opt-ins; the mobile list toggle inverts the same way, so HomeScreen now reads through resolveThreadListV2Enabled. - .github/VOUCHED.td stays deleted: it is upstream's contributor-vouching file. Adversarial review caught one surface the key migration missed: the mobile ThreadNavigationSidebar still gated v2 on the retired threadListV2Enabled, so the iPad/split list would have stayed on the legacy layout with no setting able to change it, disagreeing with Home. It now reads through resolveThreadListV2Enabled like HomeScreen. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main 0640410 into fork/dev
Adopts the three upstream commits after #381: a cross-environment usage page reading provider transcripts (pingdotgg#5684), its chart fix (pingdotgg#5697), and one mobile sheet for model and thread settings (pingdotgg#5625). Resolutions: - server.ts / ws.ts / client-runtime state: upstream's UsageService and its usageSummary atom family are additive next to the fork's diagnostics services (HostResourceProbe, ProcessResourceMonitor, TraceDiagnostics, BackgroundPolicy) and hostResourceSnapshot family — unioned. - ThreadComposer: pingdotgg#5625 folds the model picker and provider options into a single settings sheet, replacing the fork's ControlPillMenu. The sheet is adopted, and the fork's usage signal rides on it: the trigger keeps ProviderUsageIcon with the live marker rather than upstream's plain ProviderIcon, so quota state stays visible at a glance. The fork-only collapsed-composer pill (upstream has none) now opens the same sheet instead of the retired menu. Adversarial review caught that retiring the model menu also orphaned the fork's numeric usage note: the marker survived on the trigger icon but the quota percentage the menu rows carried had no home. It now hangs off the trigger label, so both halves of the fork's usage signal survive the consolidation. The plain ProviderIcon import went with upstream's replaced icon. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
sync(upstream): merge upstream/main a20923c into fork/dev
The review-a-PR habit fetches a PR head into a renamed local branch — `git fetch origin <head-branch>:pr2182` — leaving no upstream tracking. Every head selector the PR lookup can derive then names a branch that no PR has for its head, so the thread stays badge-less for the PR it exists to review. When the selector search finds nothing, the branch has no tracking-derived head, and its name matches ^pr[-_]?\d+$, resolve the PR by that number via the provider's getChangeRequest. Gated on headBranch === localBranch so a tracked branch that merely resembles the pattern keeps the precise selector path; a lookup failure falls back to "no PR" as before. Verified against the live case: the "Adversarial Review of PR 2182" thread's worktree, whose badge only appeared after hand-setting branch tracking — this makes that repair unnecessary for every past and future such checkout. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
omegent-app
Bot
force-pushed
the
fix/pr-badge-numeric-branch-fallback
branch
from
August 8, 2026 14:10
a4b5377 to
740b1ed
Compare
Owner
|
@omegent I would first question why agents setup branches like these without tracking, and see if we can address that |
Author
|
I’ve patched the status fallback to try to reattach the branch to the real PR head branch once the PR number is known. Next I’m adding a regression test that proves the branch stops being “untracked by design” after the first successful lookup.
|
patroza
force-pushed
the
fork/dev
branch
4 times, most recently
from
October 3, 2026 10:00
80434dc to
fc6701e
Compare
This branch has not been deployed
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.
Closes the last gap in the PR-badge chain: threads whose agents check out a PR with
git fetch origin <head-branch>:prNNNN— a renamed local branch, no upstream tracking.The problem
The badge lookup finds a thread's PR by head selector: the local branch name, or the head branch
its tracking points to. A
pr2182-style checkout has neither — the local name matches no PR's head,and there is no tracking to derive the real one from. The thread reviewing PR pingdotgg#2182 was the live
case:
gh pr list --head pr2182correctly returns nothing, so the row showed no badge for the veryPR it existed to review. It only lit up after hand-setting
branch.pr2182.mergeon the worktree.The fix
In
findLatestPrForHeadContext, when the selector search finds nothing and the branch has notracking-derived head (
headBranch === localBranch) and the name matches^pr[-_]?\d+$, resolvethe PR by that number via the provider's existing
getChangeRequest(gh pr view N/glab mr show N— provider-neutral). A failed by-number lookup degrades to "no PR", exactly asbefore.
The tracking gate matters: a tracked branch that happens to be named
pr123keeps the preciseselector path, so the number can never override a real head selector — covered by the negative test.
Tests
status resolves the PR by number for an untracked prNNNN checkout— fails on the pre-fiximplementation (verified by stashing the fix), passes after; also asserts the
pr view 2182callactually happened.
status does not resolve by number once a prNNNN branch gains tracking— assertspr viewisnever called and the row stays badge-less when the tracked head genuinely has no PR.
GitManager.test.ts: 84 pass. Typecheck clean.Retroactive by design: existing worktrees need no touch-up — the fallback keys off state the server
reads on every sweep.
Co-authored by @patroza
opened by Patrick Roza in chat thread Discord · Discord · T3