Repository navigation
fix(discord-bot): ignore unmentioned Discord replies - #419
Draft
omegent-app[bot] wants to merge 205 commits into
Draft
omegent-app[bot] wants to merge 205 commits into
omegent-app[bot] wants to merge 205 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>
23 upstream commits. Sixteen conflicts — this batch is mostly **mobile**, which is exactly where the fork carries the most product divergence. **Not for merging yet.** Opened for review while I investigate the mobile slowness report; some of what's in here is a candidate explanation. ## Resolutions **Android sidebar header.** Upstream deleted the native header-button module ([pingdotgg#6520](pingdotgg#6520)) so Android falls back to the shared component. The fork's list-mode buttons already live in that shared component, so the deletions were taken and nothing was lost. **ThreadComposer.** Upstream renamed `ComposerToolbarTrigger.tsx` → `ComposerToolbar.tsx`, and the trigger to `ComposerInlineControl` ([pingdotgg#6224](pingdotgg#6224)). The fork's usage-marked provider icon and quota note were ported onto the renamed component; upstream's queue-count line taken (the fork had none). **HomeScreen / ThreadNavigationSidebar.** Upstream extracted the v2-list preference into `useThreadListV2Enabled`. Both surfaces now read that hook with the fork's list-mode gate on top, so they still agree with each other. Also picked up upstream's `autoSettleOnMerge`. **Sidebar.tsx.** The fork hoists `isUnread`/`status` above this point, so upstream's re-declaration would not have compiled. Kept the fork's, carried upstream's explanatory note. **Markdown tables.** Upstream's cell runs pass `props.skills`; the fork's local `tableCellRuns` helper dropped them, so skills never highlighted inside a table cell. Took upstream's and removed the now-dead helper. **build-desktop-artifact.** Kept the fork's extracted `promoteDesktopBuildArtifacts` (it also copies directories, and has its own test) and took upstream's new Windows self-containment check. **AGENTS.md.** Took upstream's *How it works* / *Where code lives* / *Taste* / *Additional tips*. Deliberately **not** its verification and pull-request sections — upstream's "do not run repo-wide checks, CI owns the full suite" contradicts this fork's automated ship gate, and two contradictory policies in one agent file is worse than either alone. ## Two welds the auto-merge produced Both compiled clean in one place and broke in another, which is worth noting given how often this class recurs: - `build-desktop-artifact.test.ts` got **duplicate `FileSystem`/`Path` imports** — both sides added them. `vpr typecheck` did not flag it; only running the test did. - My own union in `mobile-preferences.ts` left `sanitizePreferences` **unclosed**, taking down two unrelated mobile suites. Again typecheck stayed silent — the transform error only surfaced under test. ## Verification `pnpm typecheck` (0 errors) · `pnpm test` — **272 files, 0 failures** · `vp build` in `apps/web` · `vp check --fix`. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) via [T3 Chat](https://t3.chat) on Discord --------- Co-authored-by: Nick Anisimov <n.anisimov.23@gmail.com> Co-authored-by: Exotic <118054752+extoci@users.noreply.github.com> Co-authored-by: Bilal Bakr <62337003+Bil0000@users.noreply.github.com> Co-authored-by: maria <maria@kuuro.net> Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Chris Deeming <chris@xenforo.com> Co-authored-by: Simone <lucenz@proton.me> Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com> Co-authored-by: t3-code[bot] <236186684+t3-code[bot]@users.noreply.github.com> Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Co-authored-by: Adamulek123 <adam.bogucki@piekna.edu.pl> Co-authored-by: Paul van Dyk <paul@vandyk.fr> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com> Co-authored-by: Taylor Bombay <taylor@warheadent.com> Co-authored-by: Rakshith Bhat <88523594+RakshithBhat03@users.noreply.github.com> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: David Hu <davidhu314@gmail.com> Co-authored-by: Tyler <tyler@southboundsoftware.com> Co-authored-by: tsouth89 <tsouth89@users.noreply.github.com> Co-authored-by: t3-code[bot] <t3-code[bot]@users.noreply.github.com> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> 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>
…nt (#402) `refreshThreadShellSummary` runs on **every event in a thread** and loaded every activity row that thread has ever produced — payloads included — to compute one integer, `pendingUserInputCount`. Those payloads are the tool timeline, and they are enormous. On this deployment: | | | |---|---| | Busiest thread | **10,652 activity rows / 467 MB** | | Rows that thread's count actually derives from | **0** | | Whole database: activity payloads | 5.01 GB | | …rows carrying a user-input request id | **13 rows / 10 KB** (0.0002%) | `derivePendingUserInputCountFromActivities` only reacts to three kinds — `user-input.requested`, `user-input.resolved`, `provider.user-input.respond.failed` — and skips everything else, so the read now filters on exactly those. Measured against the live database: ``` before: 10,652 rows 467.4 MB 348.8 ms after : 0 rows 0.000 MB 6.9 ms ``` …and that is before the Effect Schema decode, array copy and sort that followed it. ## Why this is the memory problem systemd's per-run accounting for `t3code-server` shows every long-lived run climbing to the 32 GB `--max-old-space-size`: | CPU | wall | memory peak | disk read | |---|---|---|---| | 8h37m | 16h11m | **34.1 G** | 58.6 G | | 2h11m | 4h02m | **32.4 G** | 23.7 G | | 10h28m | 1d 1h | **31.8 G** | 28.8 G | At the cap the process sits in back-to-back full GCs. That is why **every** client — desktop and mobile alike — saw slow thread opens, slow actions, stalled sync and dropped connections, and why restarting the server fixed it for a while. The `stop` that preceded the last restart had to be SIGKILLed after the 2-minute timeout. It is also cumulative rather than sudden: the cost is per-thread and grows with that thread's accumulated activity, which is why it felt fine last week and bad this week. ## Not a merge casualty Worth stating, since the suspicion was that a sync dropped something: this hot path is **byte-identical to upstream's**. Of the ten upstream perf/reconnect commits in range, eight are 100% present and the two partials are files this fork deliberately rewrote. `fork/tim` has zero perf-related commits among its 18 unmerged ones. Upstream has the same code; our thread sizes are what make it pathological — so this is a clean upstream candidate too. ## Changes - `ProjectionThreadActivityRepository.listByThreadIdAndKinds` — same ordering and row decoding as `listByThreadId`, short-circuits an empty kind list without touching SQL. - `refreshThreadShellSummary` passes the three kinds the deriver reads, named next to the deriver so they stay in step. ## Verification `pnpm typecheck` (0 errors) · `pnpm test` — 273 files, 0 failures · `vp check --fix`. Five new repository tests cover the filtering, ordering parity with the unfiltered list, payload decoding parity, thread isolation, and the empty-kinds short circuit. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) via [T3 Chat](https://t3.chat) on Discord 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>
Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
8 upstream commits, nine conflicts, all mobile — concentrated in the composer and outbox files this fork rewrote for its queue feature. The notable one is pingdotgg#6543 "steer active turns by default": it removes upstream's freshThreadBusy guard from the outbox drain, converging on what this fork has been doing all along — hand ownership to the server, which queues follow-ups during an active turn. The fork's comment predicted exactly that, so its version is kept: it is now the same behaviour, plus a "deferred" drain outcome that upstream lacks. Reporting an editor hold as success used to clear retry state and spin beginDispatch → finish → effect forever, and upstream's boolean would not typecheck against the DrainOutcome the rest of that function returns. Other resolutions: - composerImages: the fork's iOS guard (requestMediaLibraryPermissionsAsync hard-crashes without a usage string) and upstream's Android foreground handoff (pingdotgg#6324) are independent, so both are kept — including catch *and* finally, so a picker failure is still reported to the caller and the handoff still ends. - T3ComposerEditor: took upstream's wrapped native view and Android selection-change fix (pingdotgg#6323); the fork's older block referenced a setter that upstream renamed, so it would not have compiled. - SettingsRouteScreen: took upstream's runAppUpdateCheck and its new "ready" state, but kept the fork's bundleLabel fallback — upstream has no bundle label and falls through to null, which would blank that row here. Upstream replaced its local runUpdateCheck with the shared helper, so the fork's now-unreachable copy is removed rather than left to rot. - ThreadComposer: dropped upstream's re-added queueCount prop; the fork already declares it from the previous sync and it would have been a duplicate. - ThreadDetailScreen / ThreadRouteScreen / use-thread-composer-state: fork-only queue props and state upstream has no equivalent for; kept. - thread-outbox-model: kept the fork's comment, which still documents the decision now that upstream's logic matches it. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
…changes Two adversarial reviews found the merge left mobile with eight typecheck errors, and the workspace typecheck I trusted had not actually run — the `vpr` shim was not on PATH, so grepping its output for "error TS" counted an empty stream and reported clean. `pnpm typecheck` reports them; vitest never typechecks, so the suite stayed green throughout. - T3ComposerEditor: the merge took upstream's wrapped native view (pingdotgg#6323) but none of what it calls — the `expo-paste-input` wrapper import, the `useNativePaste` import, and the `handlePaste` binding. - SettingsRouteScreen: upstream's `runAppUpdateCheck` reports an "Update ready" state the fork's local `UpdateCheckState` union does not have, so the setter did not match the callback and the new `=== "ready"` branch compared non-overlapping types. It now uses the `AppUpdateCheckState` already imported. `reportUpdateFailure` went with the local helper it served. - thread-outbox-model: upstream keeps `threadBusy` in the contract even though pingdotgg#6543 stopped gating on it, and its new tests still pass it. Accepted again as an explicitly unused field, rather than editing upstream's tests — their assertions then keep compiling across future syncs. - activeThreadBusy: pingdotgg#6543 removed it upstream; the fork's copy was required by ThreadComposer, never read there or in ThreadDetailScreen, and superseded by `sendEntersQueue`. Removed end to end instead of passing a value nothing uses. The drain comment predicted upstream would keep waiting on threadBusy; pingdotgg#6543 matched us, so it now says so. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
Merge upstream/main into fork/dev (8 commits)
…405) Token stats were missing from Discord/GitHub turn footers. Grok was the obvious case, but the hole was per-adapter: if a provider never emitted `thread.token-usage.updated` (or only emitted a used-total), the footer had model and duration and nothing else. - **Grok / Cursor / Kimi (ACP):** parse `_meta.totalTokens` on ordinary session updates (they often skip `usage_update` / `PromptResponse.usage`) - **OpenCode:** map assistant/session/step token rollups to last in/out - **Claude:** copy input/output onto `last*` so the footer can show ↑/↓ - **Codex:** already emitted last in/out; unchanged - **Footer:** if in/out are missing, show `usedTokens` (`grok-4.6 · 31m 31s · 140k`) ## Test plan - [x] `vp test run` OpenCodeAdapter, ClaudeAdapter, AcpRuntimeModel, AcpCoreRuntimeEvents, turnResponseStats, GrokAdapter, CursorAdapter - [x] lint on the changed files opened by [patroza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1538080379636945017/1538080379636945017) · [T3](https://t3vm.tail86038f.ts.net/?thread=96f87e18-60db-4e7c-8b8e-d20f9bf54371) Made with grok-4.6 in T3 Code. --------- 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>
## What Changed `resolveProjectJumpTarget` now ranks matches instead of treating every name a project answers to as equal: - `primaryProjectNames()` — title, workspace folder basename, and the project's *own* repository identity (`canonicalKey` / `displayName` / `name` / `owner/name`). - `remoteProjectNames()` — names derived from `repositoryIdentity.remotes[]`. A primary match always beats a remote-only match; thread recency only breaks ties *within* a tier. Remote matches still resolve when nothing else answers to the name, so a fork addressed by its upstream name keeps working. ## Why `t3code://open/project?project=<name>` folded all of those names into one flat set and then picked whichever match had the most recent thread activity. Remotes are deliberately part of the identity (see `packages/contracts/src/environment.ts:122-124`: a fork answers to more than one repository) — but so does any clone that happens to carry an unrelated remote. Concretely: a `macs-holding/scanner` checkout had an extra remote for a subtree workflow: ``` effect-app-libs https://github.com/effect-app/libs.git origin https://github.com/macs-holding/scanner.git ``` That made the scanner project answer to `libs`. Scanner is far busier than libs, so the recency tie-break won and a `Hyper+i` shortcut bound to `project=libs&action=latest` reliably opened a **scanner** thread instead. Because matching spans every connected environment, the busiest clone anywhere won — the jump landed in a different environment's scanner from any machine. Tiering keeps recency useful (it still picks between several real `libs` projects across environments) while making a stray remote unable to hijack the name. ## Downstream Fork Relationship Base branch `fork/dev`. Touches `apps/web` only; no dependency on another open PR. ## Verification - `pnpm vp test run --project unit src/projectJump.test.ts` in `apps/web` — 5 passed, including two new cases: - a project matched *only* via a secondary remote still resolves (fork fallback preserved); - a busier scanner clone carrying an `effect-app/libs` remote no longer outranks the real `libs` project, and the returned `latestThread` is libs'. - `pnpm exec tsgo --noEmit` in `apps/web` — clean. - Reproduced the original bug end to end before the fix (deep link landed on `scanner / Cut Empasa Release Rehearsal`) and confirmed unaffected names (`project=.config`) always resolved correctly. ## Checklist - [x] This PR is small and focused - [x] I explained what changed and why - [ ] I included before/after screenshots for any UI changes (n/a — no UI change) - [ ] I included a video for animation/interaction changes (n/a) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
15 upstream commits, fourteen conflicts. The bulk come from pingdotgg#6572 (open remote environments in your local editor over SSH), which lands squarely on surfaces this fork has rewritten. The one that mattered: OpenInPicker. The fork replaced that component wholesale with its own "open with" system (449 lines against upstream's 74), so neither side could win outright. Upstream's remote path is ported into the fork's dispatch instead: for a remote environment, openInEditorMutation launches the editor on the *server*, which is the wrong machine — the viewing machine now gets a Remote-SSH deep link. That matters more here than upstream, since this fork routinely drives several environments at once. Other resolutions: - ElectronShell: upstream moved editor schemes into SAFE_EXTERNAL_PROTOCOLS, which returns any URL carrying one. The fork validates hostname and path first, and that check already permits upstream's `<scheme>://vscode-remote/ssh-remote+…` links, so the fork's two-tier check stays — with the scheme list now derived from upstream's constant rather than hardcoded, so a new remote-capable editor is covered automatically. - LegacySidebar: the shared context after the conflict was the fork's, so upstream's block could not be spliced in; kept the fork's conditional structure and ported upstream's Button migration onto it by hand. - ChatView: took upstream's glass Button styling for scroll-to-end, kept the fork's unread-activity dot and label. - build-desktop-artifact: upstream's pingdotgg#5877 removed WINDOWS_ASAR_UNPACK, so the fork's assertion had no symbol left to assert against; took upstream's. Its linux assertion then exposed a real gap — the fork registered t3code-dev on mac but not linux, while declaring an explicit MimeType. Both now cover the dev scheme. - PortExposure test: pingdotgg#6572 added hasListenerOnHost to NetServiceShape; the fork's stub predated it. - IPC, ws, contracts, ChatHeader, toast, index.css: unions of independent additions, minus the duplicate imports the union produced. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
Merge upstream/main into fork/dev (15 commits)
## Summary The PR panel mapped every unclassified `gh` exit to **GitHub CLI command failed.**, so the real guest-wrapper reason never reached the UI. That is what `pingdotgg#6613` (`pingdotgg/t3code`) showed this time. The live t3vm image already has ops #80 (host-qualified `--repo`). The product `#373` shim fix is still on `fork/dev`. App-only mint dies with: ``` t3-github-app-token: app is not installed on pingdotgg/t3code (or repo does not exist) ``` The App is installed on `patroza` / `macs-holding` / `effect-app` / `aaaomega` — not `pingdotgg`. This change passes through guest wrapper lines (`t3-github-app-token:` / `gh-app-wrapper:`) as the command-failed detail, and keeps raw provider stderr off the VCS error message (tokens stay out of logs). Installing the App on `pingdotgg` (or using a user/SSH token for those reads) is still required for the panel to actually load that PR. ## Test plan - [x] `vp test run apps/server/src/vcs/VcsProcess.test.ts apps/server/src/sourceControl/GitHubCli.test.ts` - [ ] After deploy: open a PR the App is not installed on and confirm the panel shows `app is not installed on …` instead of the generic CLI line - [ ] Confirm a `patroza/t3code` PR still loads on t3vm Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
Merges 86 upstream commits into fork/dev. Notable weld points: - CommandPalette: ports upstream's pinned clone destination (pingdotgg#5989) onto the fork's synchronous browse path, which has no browseNavigation coordinator. - ChatMarkdown/ChatComposer/ChatView: keeps the fork's richer renderers and send path while adopting upstream's oversized-prompt preflight (pingdotgg#6602) and markdown title stripping (pingdotgg#4133). - ProjectionSnapshotQuery: trims the fork's lazy-load window before upstream's pinned-activity union (pingdotgg#6153) so hasMoreActivities still means what it says. - ProviderRuntimeIngestion: upstream's canReplaceThreadTitle guard with the fork's title sanitisation and provider-initiated interaction-mode sync. - usageProviders: upstream's PROVIDER_PRESENTATION record, extended to the fork's four providers. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
merge: sync upstream through 20a7042 (86 commits)
## Summary The thread PR panel used the project's primary repository identity. On a fork that prefers **upstream**, so `#410` was loaded as `pingdotgg#410`. That number exists only on the fork: | Repo | #410 | | --- | --- | | `patroza/t3code` | open — docs(agents): drop obsolete fork stack workflow | | `pingdotgg/t3code` | GraphQL: could not resolve | The agent on the left found the fork PR (`gh pr view 410` with `GH_REPO` / origin). The panel asked GitHub for the upstream number and showed **Pull request not found**. This is not the earlier App-install / wrapper issue. Ops #81 and product #408 already landed; t3vm is minting public-read fallback tokens. **Fix:** open the panel from the change-request URL (`patroza/t3code`), and accept any of the checkout's remotes on the server so origin is still this project. ## Test plan - [x] `vp test run apps/server/src/pullRequest/PullRequestService.test.ts apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts` - [ ] After deploy: open the `#410` thread panel and confirm it loads `#410` - [ ] Confirm an upstream PR on the same checkout still opens against `pingdotgg/t3code` Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
AGENTS.md is the single current fork workflow: - change PRs target `fork/dev` and squash-merge - update `main` from `upstream/main`, then classic-merge into `fork/dev` - catching a change PR up is rebase or merge — pick one Removed the historical stack/handover docs (`docs/fork-stack.md`, `docs/fork-base.md`, `docs/stable-dev-release-branch-handover.md`) so they cannot describe a past or future model. Grok 4.6 / T3 Discord opened by [patroza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1538189075251601469/1538189075251601469) · [T3](https://t3vm/?thread=866be431-d52a-48b6-bb4b-cfcd2399d79c) --------- 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>
#401 was squash-merged. That kept the code and threw the lineage away: the 23 upstream commits stopped being ancestors, so `fork/dev` read as **29 commits behind upstream when only 6 were genuinely outstanding**, and the next sync would have re-merged and re-resolved all 23 — on the same mobile files that took sixteen conflicts to land the first time. Nobody noticed for two merges. It surfaced in a deploy alert that said **"Commits (2)"** for a range that had carried 23. ## What this adds A `push`-triggered check on `fork/dev` that fails when a commit which carried a sync has fewer than two parents, and prints the `-s ours` repair in the log. Sync commits are identified by **the head branch of the PR they came from**, not by their subject, because subjects vary by merge method: ``` Merge pull request #400 from patroza/sync/upstream-2026-08-12b Merge upstream/main into fork/dev (23 commits) (#401) merge: sync upstream through b73232b ``` A merge-button commit names the branch inline, so no API call is needed; squash and rebase commits are resolved through the API, with the subject line as a fallback when that is unavailable. **Ordinary fork PRs are untouched** — they are expected to squash, and are never checked. ## Verified against the real commits | commit | what it is | result | |---|---|---| | `5e63531b1` | #401, squash-merged sync | **fails**, exit 1 | | `0bf7835cc` | #400, sync merged properly | recognised as a sync, passes (2 parents) | | `a76069bd9` | #402, an ordinary squashed PR | not flagged | The third row is the one that matters most: the guard has to stay silent on your normal workflow. ## This detects, it does not prevent Worth being explicit, since it was the first question asked: **clicking merge does not fail.** The check runs after the merge lands, because GitHub has no per-PR merge-method control, and a repository-wide setting cannot allow squash for ordinary fork PRs while requiring a merge commit for syncs. Squash merges do fire `push` — `5e63531b1` triggered Fork CI at 08:08 — so this turns a silent, weeks-later discovery into a red check within a minute. Actual prevention is `gh pr merge <n> --merge`, which is how #398, #399 and #400 all landed correctly. That is now written into the sync runbook in `AGENTS.md`. If you would rather it be enforced at the button, the next step is a `sync:upstream` label workflow that merges the PR through the API once checks pass — say the word and I will add it. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) via [T3 Chat](https://t3.chat) on Discord --------- 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>
…PRs (#413) Manual `/omegent today-recap` (alias `/agent today-recap`) starts a recap thread for the repo bound to the calling Discord channel (`t3-<shortName>` topic). No schedule — someone has to run it. ## Why Daily recaps of PR opens/merges/closes (with Discord thread links) are useful and cheap. Doing it as a slash command now lets us iterate on format without a cron. ## What - `/omegent today-recap` in a project channel (e.g. scanner) opens a new thread and asks the agent for that repo's UTC-day recap - Same from a child thread: recap still lands on the parent project channel - `@Omegent today-recap` / `today recap` as a mention fallback - Prompt encodes the format we settled: what/why from PR descriptions, `[PR #N](url)`, bare Discord thread URLs, `## 🟢 MERGED` / `## 🔴 CLOSED` / `## 🟠 OPEN`, `### fix` / `### feat` outline - Recap turns run `--local` (no worktree) ## Test plan - [x] `vp test run` todayRecap, slashCommands, channelInfoPin, mentions, MentionRouter - [x] `apps/discord-bot` typecheck - [x] targeted lint - [ ] After deploy: `/omegent today-recap` in the scanner channel opened by [joshuadima](https://discord.com/users/593167616273809448) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1539325452873769041/1539325452873769041) · [T3](https://t3vm.tail86038f.ts.net/?thread=1c8e37cb-722d-405e-8071-5c8c3cd159fe) --------- Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Joshua Dimaunahan <170177550+MindfulLearner@users.noreply.github.com>
Merges 66 upstream commits into fork/dev. Notable weld points: - ChatComposer: upstream pingdotgg#7150 relocated the prompt editor, length validation and footer, leaving the fork's copies as a second live layout. Ported the fork-only pieces into upstream's copies first — the environment-unavailable placeholder, the model picker's usage snapshot, and the attach-images button that drives the hidden iOS file input — then dropped the stale layout. - MessagesTimeline: upstream's new active-turn block indexes whatever it iterates; the fork walks its collapsed/interleaved list, so the block was rebased onto that list to keep the indices referring to one array. - DesktopUpdates: upstream's action reservation and widened installable check, kept compatible with the fork's Linux dir-install mode. - CommandPalette: dropped the `open` prop upstream removed while keeping the fork's file-picker / content-search overlays, and took upstream's newer reduceCommandPaletteUiState over the fork's relocated copy of the old one. - mobile-showcase-screenshots: GitHub-hosted runners (this fork has no Blacksmith) with upstream's palette-driven timeout. - ProviderRegistry.test: kept the fork's coverage for mergeProviderSnapshots / selectProvidersByKind, which upstream deleted while leaving both exported. Upstream's new t3code/no-native-title-tooltip rule flagged seven fork-only components; four had a title duplicating an existing aria-label, three needed the label moved off the native tooltip. rerere was disabled for this merge: it had replayed earlier resolutions onto new upstream content, which is exactly how a weld goes silently wrong. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
merge: sync upstream through f708f63 (66 commits)
…one (#417) Thread search restricted assistant matches to the single row a turn names as its terminal message: ```sql messages.message_id IN ( SELECT turns.assistant_message_id FROM projection_turns AS turns WHERE turns.assistant_message_id IS NOT NULL ) ``` Providers stream an answer as many assistant items — roughly ten per turn now, and climbing as chunking gets finer — and only the last is linked as `turns.assistant_message_id`. Everything said before it was invisible to search. That is why full-text search appeared to "stop working" without anything visibly changing: the query never changed, the shape of the data under it did. ## Measured on a live `state.sqlite` | | searchable | |---|---| | before | 7,118 / 20,094 settled messages (35%) | | after | 20,094 (100%) | | assistant messages before | 3,430 / 16,406 (21%) | A real query for `worktree` goes from **138 to 187 threads**. All 425 threads with assistant text had *some* searchable row, so the symptom was a search quietly missing most of what was said, not one missing whole threads — which is exactly why it was hard to pin down. ## Scope - **Tool calls were never involved.** They are activities in `projection_thread_activities`, not rows in `projection_thread_messages`, so they stay out by construction. - **`system` notices** are now excluded explicitly rather than incidentally. - **Per-thread dedupe is unchanged**: `thread_match_rank = 1` still collapses a thread to one best row, preferring a user match, then the most recent. - **Streaming rows stay excluded** via the existing `is_streaming = 0`. ## Known limit A phrase that straddles a split boundary still will not match — each message row is matched independently, so "the quick brown" in one item and "fox" in the next is two rows, not one string. Fixing that means matching against a per-turn concatenation, which is a bigger change with its own cost; happy to do it as a follow-up if it matters in practice. ## Tests The existing test asserted the old behaviour outright — its fixture literally read `'Interim needle must not be searchable.'` — so that expectation is inverted here, and a split-answer case is added whose matching half is not the turn's `assistant_message_id`. Mutation-checked: restoring the old restriction fails both new assertions. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com> --------- Signed-off-by: aoright <102943475+aoright@users.noreply.github.com> Co-authored-by: Rodrigo Brechard <rodrigobrechard@gmail.com> Co-authored-by: Rodrigo Brechard <rodrigo@clubtidy.fr> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Bilal Bakr <62337003+Bil0000@users.noreply.github.com> Co-authored-by: Eddy Naboulet <93473191+eddy-naboulet@users.noreply.github.com> Co-authored-by: maria <maria@kuuro.net> Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Co-authored-by: Pavlo Trinko <paul.trinko95@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: Chris Deeming <chris@xenforo.com> Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Co-authored-by: Francisco Arredondo <95440147+frarredondo@users.noreply.github.com> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Nitay Rabinovich <nitayr@wix.com> Co-authored-by: Lars Nieuwenhuis <35393046+lnieuwenhuis@users.noreply.github.com> Co-authored-by: Tristan Knight <admin@snappeh.com> Co-authored-by: Nick Anisimov <n.anisimov.23@gmail.com> Co-authored-by: Maslin Edwin <maslinje@gmail.com> Co-authored-by: aoright <102943475+aoright@users.noreply.github.com> Co-authored-by: Guilherme Barros <gbarros1095@gmail.com> Co-authored-by: Rishet11 <154429365+Rishet11@users.noreply.github.com> Co-authored-by: Augie <augie@luebbers.email> Co-authored-by: Taras <Taras.Fomin@gmail.com> Co-authored-by: Gianmarco <gianmarcosimone89@gmail.com> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: Inaya Yousfi <zied.essaber@gmail.com> Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com> Co-authored-by: Rakshith Bhat <88523594+RakshithBhat03@users.noreply.github.com> Co-authored-by: GPT-5.6 <noreply@openai.com> Co-authored-by: David Balderston <dbalders@gmail.com> Co-authored-by: Dara Adedeji <76637177+SunkenInTime@users.noreply.github.com> Co-authored-by: Luis Gustavo Couto Wacker <luis.wacker@pagar.me> Co-authored-by: Jake Leventhal <jakeleventhal@me.com> 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>
## Why Sentry short ids (`SCANNER-313`) have the same shape as Jira keys (`PROJ-123`). The Discord bot extracted those tokens from sentry.io URLs and Sentry alert embeds, pinned them under **Jira**, and injected `jira: SCANNER-313` into agent turns — so the agent treated an obvious Sentry issue as a Jira ticket. ## What - Do not treat sentry.io URLs, Sentry-bot authors, or Sentry Discord embeds as Jira. Atlassian browse / `selectedIssue` URLs are still extracted. - Drop already-stored false positives on pin refresh and backfill (and skip mining our own Omegent Info pin, which echoed the misclassified key). - Persist sentry.io issue URLs and render them as **Sentry** on the thread-info pin (above Jira). ## Test plan - [x] `vp test run` jiraLinks, sentryLinks, threadInfoPin, ThreadLinkStore, threadContext, MentionRouter - [x] `apps/discord-bot` typecheck - [ ] After deploy: Sentry alert / pasted `https://*.sentry.io/issues/SCANNER-313` should pin **Sentry**, not **Jira** opened by [Patrick Roza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [what happened here?](https://discord.com/channels/1083767712431480922) --------- Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
…#414) ## Summary Omegent on t3vm failed with `T3 did not become ready after a server restart` because the Discord bot re-exchanges `local-bootstrap-credential` on every process start, and that grant was seeded with the **desktop 24h TTL**. After `t3code-server` had been up more than a day, a bot-only restart (or a deploy that restarted only the bot) looped `invalid_credential` forever. - Keep the desktop IPC bootstrap seed at 24h. - Seed the file-backed local grant with a long-lived TTL (colocated trusted clients). - Persist the 30-day bearer under the bot data dir and reuse it on the next start; clear and re-bootstrap if T3 rejects it. - Also include basename asar unpack globs (`*.node` as well as `**/*.node`) so `packWindowsServerAsar` still creates `server.asar.unpacked` on hosts where `@electron/asar` 3.4 does not treat `**` as nested. ## Test plan - [x] `PairingGrantStore` local-file grant still consumes after 25h and 400d - [x] Desktop IPC grant still expires after 24h - [x] Persisted bearer reuse / host mismatch / remaining-time floor / disk round-trip - [x] T3Session existence contract for persist + invalid_credential fallback - [x] `build-desktop-artifact` Windows asar unpack tests - t3vm: rebuilt dist, restarted server then bot; new Discord bot session issued 2026-08-20 06:49 UTC and HTTPS `/` is 200 again --------- Co-authored-by: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
…ap (#418) `/omegent today-recap` posted the ack twice (channel starter + slash reply) and opened a thread with no recap in it until/unless the agent finished — so the thread looked empty. ## What - Open one public thread with no starter message - Slash ack is ephemeral (jump only) - Recap is the only public bot message, inside that thread - Mention-in-channel still threads off the mention; mention-in-thread only posts a jump, not a second ack opened by [joshuadima](https://discord.com/users/593167616273809448) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1539325452873769041/1539325452873769041) · [T3](https://t3vm.tail86038f.ts.net/?thread=1c8e37cb-722d-405e-8071-5c8c3cd159fe) Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Joshua Dimaunahan <170177550+MindfulLearner@users.noreply.github.com>
Discord reply pings put the parent author in `mentions` without an in-content <@id>. People use replies as quotes, so Omegent was starting turns from those. Require an explicit @mention (or role mention) on replies. Thread-talk also skips replies. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
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.
Discord reply pings put the parent author in
mentionswithout an in-content<@id>. People use replies as quotes, so Omegent was starting turns from those.Require an explicit
@mention(or bot-role mention) on replies. Thread-talk also skips replies.Test plan
vp test runThreadTalkPolicy, MentionRouter, slashCommandsvp check+vpr typecheckon push@Omegentshould stay silent;@Omegenton a reply still starts a turnopened by patroza in chat thread Discord · Discord