chore: sync upstream v0.0.32 line (47 commits) - #44
Conversation
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…hy (pingdotgg#4988) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…tgg#4855) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
actions/checkout implements sparse-checkout with --filter=blob:none, so the runner repo is a partial clone missing the .repos/ blobs. eas-cli archives the project via `git clone --depth 1 file://<workspace>`, which upload-pack cannot serve from a partial clone and exits 128 (pingdotgg#4802 broke both EAS build workflows this way). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/ scheme on Linux (pingdotgg#5015) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…elpers (pingdotgg#5027) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ingdotgg#5025) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ngdotgg#4771) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…dotgg#5055) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… to new tasks (pingdotgg#5064) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ngdotgg#4955) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…dotgg#5095) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…pingdotgg#5094) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oot (pingdotgg#5102) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: T3 Code Test <t3code-test@example.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ydration (pingdotgg#5147) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…o their thread (pingdotgg#5159) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
…debug (pingdotgg#5076) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erver running (pingdotgg#5217) Co-authored-by: Claude <noreply@anthropic.com>
Absorbs 47 upstream commits, including the libghostty-vt terminal renderer, sidebar thread search (not adopted in fork chrome — see PR body), Clerk bridge single-instance lock, and the ⌘P file picker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Thermo-nuclear code quality — DO NOT APPROVE
This is largely an upstream sync into custom, and the fork conflict resolutions (DesktopClerk, SidebarV2, ThreadTerminalDrawer geist port, terminalFont cleanup) look correct. The structural bar still applies to what lands.
Blockers
ghostty/surface.ts(1393, NEW) —GhosttyTerminalSurfaceis a god-class (~50 private fields; key/IME/pointer/scrollbar/blink co-located). Split into fonts/input/pointer/scrollbar + a thin facade. Upstream origin does not waive the 1k rule for a new module.ghostty/core.ts(1189, NEW) — ABI types, lifecycle, encode*, selection, andreadRowin one class; paste/selection re-copy the probe→alloc pattern thatencodeOutputalready owns. Decompose and dedupe.CommandPalette.tsx— proved the extraction pattern (ProjectFilePicker/ProjectContentSearchDialog) then leftOpenCommandPaletteDialogas an ~1800-line god function. Finish the judo: extract add-project/clone (and ideally browse/actions) the same way.
High
FilePreviewPanel.tsx973→1065 — moveuseFileLineRevealout; extracting the centered-scroll helper was not enough.ThreadTerminalDrawer.tsx— ghostty swap kept a giant mount effect inside a 1525-line file; extract mount/selection setup.
Watch
CheckpointReactor.ts866→946 —followWorktreeBranchDriftis coherent, but the file is near 1k; land further drift helpers elsewhere.
Acknowledge
serviceLauncher slim of selfUpdate, well-sized ProjectFilePicker/ProjectContentSearchDialog, clean renderer/runtime/serviceProtocol seams, and the fork terminalFont shim deletion. ClaudeProvider 995→1005 is threshold noise.
Restructure the blockers and re-request review.
Sent by Cursor Automation: Thermo-nuclear PR review
| readonly onLinkActivate: (text: string, event: MouseEvent) => void; | ||
| } | ||
|
|
||
| export class GhosttyTerminalSurface { |
There was a problem hiding this comment.
blocker: this lands at 1393 lines with ~50 private fields (selection/IME/pointer/scrollbar/blink/paste). Natural split is surfaceFonts / surfaceInput / surfacePointer / surfaceScrollbar + a thin facade. Upstream sync does not waive the 1k rule for a new god-class — decompose before merge.
| return left.r === right.r && left.g === right.g && left.b === right.b; | ||
| } | ||
|
|
||
| export class GhosttyTerminalCore { |
There was a problem hiding this comment.
blocker: GhosttyTerminalCore is 1189 lines mixing ABI layouts, lifecycle, encode*, selection, and snapshot. readRow alone is ~124 lines; encodePaste / selectionText re-implement the probe-size→alloc dance that encodeOutput already centralizes. Extract coreTypes / encode / rows and route paste+selection through the shared helper.
| props.setOpen(false); | ||
| }} | ||
| > | ||
| {props.mode === "files" ? ( |
There was a problem hiding this comment.
missed code-judo: this correctly extracts ProjectFilePicker + ProjectContentSearchDialog, then OpenCommandPaletteDialog (L524+) stays an ~1800-line god function still owning add-project/clone/browse/actions with repeated addProjectCloneFlow?.step branching. The PR proved the pattern — finish it. Extract at least the clone flow into its own dialog module so this file stops being the dumping ground.
| }; | ||
|
|
||
| pendingFramesByPath.set(relativePath, requestAnimationFrame(reveal)); | ||
| const guardScrollTarget = (line: number) => { |
There was a problem hiding this comment.
this pushes FilePreviewPanel past 1k (973→1065). resolveCenteredFileLineScrollTop was extracted but useFileLineReveal (~165 lines of Map state + rAF + guard cancellation) is still in-panel. Move the hook into fileLineReveal.ts (or a dedicated module) so the panel stays under the threshold.
| let setupCleanups: Array<() => void> = []; | ||
|
|
||
| const setup = async (): Promise<(() => void) | null> => { | ||
| const terminalOptions: GhosttyTerminalSurfaceOptions = { |
There was a problem hiding this comment.
ghostty migration replaced xterm but left TerminalViewport's mount as one giant async effect (setup through ~L731) inside a 1525-line file. Extract useGhosttyTerminalMount / selection+clipboard setup so the viewport is render + small sync effects. Same structural debt, new backend.
| // orphans the thread's PR. Follow the drift here: adopt the checked-out | ||
| // branch as the thread's branch, but only when the worktree belongs to | ||
| // exactly this thread — for shared cwds the strict matching is the point. | ||
| const followWorktreeBranchDrift = Effect.fn("followWorktreeBranchDrift")(function* (input: { |
There was a problem hiding this comment.
followWorktreeBranchDrift is coherent, but this file is 866→946 and approaching 1k. Prefer landing further drift/worktree helpers in a dedicated module now so the next sync does not tip CheckpointReactor over the line.
ReviewReviewed at I could not run the suite (no 1. The typography customization now depends on an upstream file it doesn't watchThis is the one I'd hold the merge for. The PR deletes The problem is what replaced the tripwire: nothing. Net trade in this PR: five tests the fork owned, exchanged for an unguarded dependency on upstream internals, with the detector for that dependency left switched off. The intent prose at Fix is two lines plus a guard: watch:
- apps/web/src/index.css
- apps/web/src/components/ThreadTerminalDrawer.tsx
+ # The fork deleted its own refit shim because the surface does this. If
+ # upstream stops, the terminal silently measures against fallback metrics.
+ - apps/web/src/terminal/ghostty/surface.tsit("keeps upstream's cold-load re-measure, which the fork's shim was deleted for", () => {
const surface = readSibling("../terminal/ghostty/surface.ts");
expect(surface).toContain("document.fonts.load(");
expect(surface).toContain('"loadingdone"');
});Failure mode without it is the exact one the deleted suite existed to catch, and it's silent: a Geist Mono grid measured at fallback advances, with the PTY wrapping to a column count nobody re-derived. 2. The replacement guard is pinned to prettier's output
expect(drawer).toContain("font: { family: resolveTerminalFontFamily(mount) }");That asserts an object literal stayed on one line. Add a expect(drawer).toMatch(/font:\s*\{\s*family:\s*resolveTerminalFontFamily\(mount\)/u);3. The fork's mono stack puts a generic family mid-list, ahead of the Nerd Font fallbacks
Upstream's own Either trim a trailing generic in 4.
|
There was a problem hiding this comment.
Review result: one actionable fork-specific finding; no other blocking issues found.
[P2] Exercise the keyless single-instance path
DesktopClerkForkSkip.test.ts:83-86 says the single-instance lock “must keep working,” but it only checks that service.configure exists. This sync changes that branch from the injected ElectronApp.requestSingleInstanceLock service to the fork-only Electron.app?.requestSingleInstanceLock() ?? true path in DesktopClerk.ts:185-195. As written, the suite would still pass if the Electron namespace did not expose app and every keyless launch silently took the ?? true fallback, allowing a second instance to continue.
Please execute service.configure with a mocked Electron app and cover both outcomes: primary registers the second-instance handler; secondary calls quit, interrupts startup, and does not register the handler. That also makes the manifest claim that singleton locking is preserved on both keyed and keyless paths an actual behavioral guard, as required by .fork/AGENTS.md.
Everything else I checked in the merge integration looks sound: the PR targets custom; the CI runner fence is preserved; the Ghostty font adaptation matches the surface’s load/remeasure behavior; the sidebar keeps the fork chrome while adapting the snooze API; the new Phosphor icon mappings resolve; 34 focused test files / 334 tests pass locally; and all GitHub CI jobs are green. The intentionally omitted inline sidebar search is reasonable as an explicit follow-up because adopting it here would replace the fork-owned chrome rather than resolve a sync conflict.
…ck tests - geist-typography now watches ghostty/surface.ts and a guard pins the cold-load re-measure the deleted refit shim relied on - call-site guard is whitespace-tolerant (regex, not a one-line literal) - terminalFontFamilyFrom strips the trailing monospace generic so the surface's Nerd Font glyph fallbacks stay ahead of any generic - searchSidebarThreadsByTitle orphan documented in fork-sidebar-chrome - DesktopClerkForkSkip now executes configure on both lock outcomes: primary registers second-instance, secondary quits and interrupts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Review feedback addressed in 1. Surface tripwire (blocking) — done, both halves. 2. Prettier-pinned guard — replaced with 3. Generic mid-list — took the trim rather than the manual verification: 4. Orphaned search helper — documented in the 5. Snooze labels don't tick on web — agreed follow-up sized; it now exists as #45 with the mobile-parity fix shape sketched. 6. Description overstated — corrected in the PR body: labels unchanged, files changed (sparse-checkout, narrowed 7. #13 conflict — correct, this PR rewrites P2 (keyless single-instance path) — done. On the Cursor automation blockers — 🤖 Generated with Claude Code |


Problem
customwas 47 commits behind the upstream mirror (origin/main=pingdotgg/t3code@e60821f0e). Notable upstream changes: the libghostty-vt terminal renderer replacing xterm.js (pingdotgg#4860), sidebar thread search (pingdotgg#4769), the Clerk bridge now owning Electron's single-instance lock, thread snoozing on mobile with the snooze API moved into client-runtime, and the ⌘P project file picker (pingdotgg#4855).How it was resolved
Four conflicted files:
.github/workflows/ci.yml— kept the fork'sci-runnersfence (macos-latest, 30 min) over upstream's new Blacksmith label. No new Blacksmith labels leaked into ci.yml, and the other workflows' runner label set is byte-identical to the fork's pre-merge state — but their files did change (sparse-checkout blocks excluding/.repos/, narrowedrun-installfilters,release.ymldroppingfetch-depth: 0from two jobs). Those workflows are release/relay/EAS paths the fork gates separately. ci.yml'smobile_native_static_analysisandrelease_smokejobs moved fromrun-install: trueto a--filter=@t3tools/scripts...install scope; CI on this branch is the proof thatrelease-smoke.tsstill resolves under it.apps/desktop/src/app/DesktopClerk.ts— took upstream's userData-before-lock setup unconditionally, kept the fork's keyless bridge skip. Upstream'sconfigurenow readsbridge.isPrimaryInstance; the keyless path (no bridge) takes the lock directly viaElectron.app.requestSingleInstanceLock()(the ElectronApp service method was removed upstream).DesktopClerkForkSkip.test.tsupdated for the layer's new providers.apps/web/src/components/SidebarV2.tsx— fork side kept wholesale (the card-rows redraw and PR feat(web): restyle sidebar chrome and monochrome accents #43 chrome own this file), then upstream's two applicable changes ported in: the tooltip inset normalization (follow-up normalization after #4700. pingdotgg/t3code#4498) and the newsnoozeWakeLabel({ now })signature (feat(mobile): add thread snoozing pingdotgg/t3code#5053). Upstream's settle-overlap fix (fix(web): stop settle controls overlapping the status label pingdotgg/t3code#4574) targets markup the fork's card redraw already replaced.apps/web/src/components/ThreadTerminalDrawer.tsx— took upstream's ghostty setup and re-portedgeist-typography: the surface takesfont: { family: resolveTerminalFontFamily(mount) }and handles the webfont re-measure itself, so the fork's xterm refit shim (refitTerminalWhenFontsReady) is deleted fromcustom/terminalFont.tsalong with its guard suite. Manifest intent text updated to match.Follow-ups in the same commit: two new phosphor shim mappings (
FileSearchIcon→ FileMagnifyingGlass,TextSearchIcon→ ListMagnifyingGlass) for the new file-picker icons.Upstream's inline search input + results listbox lives in the sidebar chrome the fork replaced in PR #43 (palette-trigger Search row, per Figma 149:6235). Adopting it would rewrite the day-old fork chrome, and the
fork-sidebar-chromemanifest explicitly forbids restoring upstream's chrome imports during a sync. The pure helper (searchSidebarThreadsByTitleinSidebar.logic.ts) and its tests are kept, so porting the feature intoSidebarV2ChromeRowslater is straightforward — but that's a design decision, not a sync resolution. Flagging for an explicit call on whether/how the fork wants inline thread search.Verification
Sidebar.logic/Sidebar.snooze/ThreadTerminalDrawer/SidebarStageBackdroptests: all passingfork-lint: 60 fork-owned files, no warnings; drift detection exit 0;vp fmt --checkclean on all hand-touched filesMerged and verified by Claude Fable 5 (claude-fable-5) via Claude Code.
🤖 Generated with Claude Code