Skip to content

fix(desktop): AppImage updates keep their filename - #36306

Merged
juliusmarminge merged 1 commit into
mainfrom
factory/pr-25756-a1794597635
Nov 13, 2026
Merged

juliusmarminge merged 1 commit into
mainfrom
factory/pr-25756-a1794597635

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

No code changed in this pass: the brief listed nothing to change, and the watch on #36306 ended with all 35 checks passed on a275e56, Macroscope's approvability review APPROVED with no findings, CodeRabbit reporting 'No actionable comments were generated' (merge risk Minimal), and no line comments from either bot. mergeable_state is clean. CodeRabbit's only remarks were on the pull request description (it found no linked bug issue in the Scope section), which is not a code finding and not rated high.

The change itself is unchanged from the previous step: builds that publish an update feed name the Linux AppImage T3-Code-.AppImage (stable) or T3-Code-Nightly-.AppImage (nightly), so electron-updater 6.8.9 replaces the installed file in place instead of deleting it and writing a new versioned name; the AUR release script resolves whichever name a release published; and on the launch the old updater starts after the first versioned-to-version-free update, the new build leaves a relative symlink at the removed versioned path so existing launchers keep working without a bridge release.

Supersedes #25756. The change is @juliusmarminge's; their commits are kept.

Reproduction on main

On Linux, download a versioned T3 Code AppImage into ~/Applications, make it executable, create a stable-name symlink targeting it, and create a desktop entry launching that symlink. Launch through the desktop entry, accept an in-app update and restart, then quit and launch through the desktop entry again: main leaves its target missing. For the changed behavior, install a version-free AppImage produced by this PR, point the same launcher at it, and repeat an update to a later release: the path should remain usable. Also test an existing versioned install updating to the first version-free release; this PR alone still breaks that launcher once. These steps were derived from the issue and diff, not executed.

Evidence

Linux x86_64 packaged desktop app, 1920x1080, light theme, isolated synthetic data. Install an AppImage in ~/Applications, create a stable symlink and desktop entry, launch it, accept an update and restart, quit, then launch the same desktop entry again. Updates used real electron-updater with locally built synthetic releases.

Before After
9efd960925 a275e564ec
Before: launcher fails after update After: launcher reopens updated app
Versioned 0.1.9 → 0.1.10: original path missing, symlink broken, launcher exit 1. Version-free 0.1.10 → 0.1.11: original path preserved, launcher exit 0, app reopened.
Before recording After recording

Existing versioned-install migration also passed: base-built 0.1.9 → head-built version-free 0.1.11 restored the previous path as a relative symlink and reopened through the unchanged launcher. This supersedes the triage note predicting one remaining break. Migration recording, migration capture.

Driver, CDP helper, reproduction instructions.

Runtime transcripts: base, head, migration.

Not shown:

  • Nightly and ARM64 AppImages, AUR release automation, and dock-specific integration were not exercised; verification covered Linux x86_64 stable AppImages through a desktop entry and symlink.

Tests

No commands run locally in this pass, since nothing changed. Read from the forge: all 35 check runs on a275e56 concluded success or skipped (including the 8 required checks, Lint, Test Server 1-8, Test Web, CodeRabbit); Macroscope review state APPROVED; CodeRabbit: no actionable comments.

Not in this change

Who did the work

  • Written by Claude Fable 5.2, in Claude Code
  • Reviewed by GPT-6.1 Sol, in Codex, and by Claude Opus 5.5, each on its own
  • Proof captured by GPT-6.1 Sol and checked by Claude Opus 5.5

Run by the t3code factory in T3 Code.

Release AppImages were named T3-Code-<version>-<arch>.AppImage.
electron-updater replaces an installed AppImage in place only when its
name has no x.y.z version; otherwise it deletes the file and writes the
update under the new name, so symlinks, desktop entries and dock pins
pointed at nothing after every update.

Builds that publish an update feed now name the AppImage
T3-Code-<arch>.AppImage (stable) or T3-Code-Nightly-<arch>.AppImage
(nightly). The AUR release script looks up whichever name a release
published.

An install that still has a versioned name is updated by its old
updater, which deletes that path once more. The new build repairs it on
the launch the updater starts: the previous launch's URL handler entry
still names the removed path, and a relative symlink to the new file is
left there. Later updates replace the version-free file in place.

Fixes #8944

Co-Authored-By: Claude Fable 5.2 <[email protected]>
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Nov 13, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at a275e56

Macroscope's review found this PR approvable — Linux AppImage releases use stable filenames so updates preserve launcher paths, with a guarded compatibility alias for existing versioned installs. AUR lookup retains legacy-name fallback and checksum validation; existing files are never overwritten by the alias repair.

You can add or adjust custom eligibility rules. Learn more.

@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 21.5 KiB 21.5 KiB 0 B (0.0%) 24.4 KiB ✅
Codex Live turn messages 1 1 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.9 KiB 21.9 KiB 0 B (0.0%) 24.4 KiB ✅
Claude Live turn messages 1 1 0 (0.0%) 8 ✅

Other scenarios

All 64 scenario measurements match main.

All 64 scenario measurements
Provider Scenario Metric Main baseline This PR Impact PR ceiling
Codex short turn resume WebSocket decoded 10.5 KiB 10.5 KiB 0 B (0.0%) 12.7 KiB ✅
Codex short turn resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex long turn running, cold open HTTP decoded 281.7 KiB 281.7 KiB 0 B (0.0%) 302.7 KiB ✅
Codex long turn running, cold open rows 75 75 0 (0.0%) 75 ✅
Codex long turn running, history page HTTP decoded 92.4 KiB 92.4 KiB 0 B (0.0%) 107.4 KiB ✅
Codex long turn running, history page rows 75 75 0 (0.0%) 75 ✅
Codex long turn finished, cold open HTTP decoded 381.5 KiB 381.5 KiB 0 B (0.0%) 410.2 KiB ✅
Codex long turn finished, cold open rows 151 151 0 (0.0%) 151 ✅
Codex long turn finished, socket cold open WebSocket decoded 381.6 KiB 381.6 KiB 0 B (0.0%) 410.2 KiB ✅
Codex long turn finished, socket cold open WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex long turn finished, socket cold open rows 151 151 0 (0.0%) 151 ✅
Codex long turn finished, work page HTTP decoded 186.2 KiB 186.2 KiB 0 B (0.0%) 200.2 KiB ✅
Codex long turn finished, work page rows 150 150 0 (0.0%) 150 ✅
Codex idle thread resume WebSocket decoded 65 B 65 B 0 B (0.0%) 200 B ✅
Codex idle thread resume WebSocket messages 1 1 0 (0.0%) 1 ✅
Codex fleet shell snapshot HTTP decoded 42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅
Codex fleet shell snapshot rows 27 27 0 (0.0%) 27 ✅
Codex fleet shell subscribe WebSocket decoded 65 B 65 B 0 B (0.0%) 200 B ✅
Codex fleet shell subscribe WebSocket messages 1 1 0 (0.0%) 1 ✅
Codex fleet shell resume check HTTP decoded 18 B 18 B 0 B (0.0%) 100 B ✅
Codex fleet shell resume check rows 0 0 0 0 ✅
Codex stale shell reload HTTP decoded 42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅
Codex stale shell reload rows 27 27 0 (0.0%) 27 ✅
Codex stale shell resume WebSocket decoded 140 B 140 B 0 B (0.0%) 400 B ✅
Codex stale shell resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex stale todo list cold open HTTP decoded 72.4 KiB 72.4 KiB 0 B (0.0%) 83.0 KiB ✅
Codex stale todo list cold open rows 75 75 0 (0.0%) 75 ✅
Codex stale todo list cold open nodes 2 2 0 (0.0%) 4 ✅
Codex stale todo list cold open subagents 2 2 0 (0.0%) 4 ✅
Codex stale todo list cold open plans 1 1 0 (0.0%) 2 ✅
Codex stale todo list cold open providerTurns 1 1 0 (0.0%) 2 ✅
Codex stale todo list cold open checkpoints 1 1 0 (0.0%) 2 ✅
Claude short turn resume WebSocket decoded 10.6 KiB 10.6 KiB 0 B (0.0%) 12.7 KiB ✅
Claude short turn resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude long turn running, cold open HTTP decoded 283.3 KiB 283.3 KiB 0 B (0.0%) 302.7 KiB ✅
Claude long turn running, cold open rows 75 75 0 (0.0%) 75 ✅
Claude long turn running, history page HTTP decoded 93.4 KiB 93.4 KiB 0 B (0.0%) 107.4 KiB ✅
Claude long turn running, history page rows 75 75 0 (0.0%) 75 ✅
Claude long turn finished, cold open HTTP decoded 384.2 KiB 384.2 KiB 0 B (0.0%) 410.2 KiB ✅
Claude long turn finished, cold open rows 151 151 0 (0.0%) 151 ✅
Claude long turn finished, socket cold open WebSocket decoded 384.3 KiB 384.3 KiB 0 B (0.0%) 410.2 KiB ✅
Claude long turn finished, socket cold open WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude long turn finished, socket cold open rows 151 151 0 (0.0%) 151 ✅
Claude long turn finished, work page HTTP decoded 188.1 KiB 188.1 KiB 0 B (0.0%) 200.2 KiB ✅
Claude long turn finished, work page rows 150 150 0 (0.0%) 150 ✅
Claude idle thread resume WebSocket decoded 66 B 66 B 0 B (0.0%) 200 B ✅
Claude idle thread resume WebSocket messages 1 1 0 (0.0%) 1 ✅
Claude fleet shell snapshot HTTP decoded 43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅
Claude fleet shell snapshot rows 27 27 0 (0.0%) 27 ✅
Claude fleet shell subscribe WebSocket decoded 66 B 66 B 0 B (0.0%) 200 B ✅
Claude fleet shell subscribe WebSocket messages 1 1 0 (0.0%) 1 ✅
Claude fleet shell resume check HTTP decoded 18 B 18 B 0 B (0.0%) 100 B ✅
Claude fleet shell resume check rows 0 0 0 0 ✅
Claude stale shell reload HTTP decoded 43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅
Claude stale shell reload rows 27 27 0 (0.0%) 27 ✅
Claude stale shell resume WebSocket decoded 140 B 140 B 0 B (0.0%) 400 B ✅
Claude stale shell resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude stale todo list cold open HTTP decoded 73.4 KiB 73.4 KiB 0 B (0.0%) 83.0 KiB ✅
Claude stale todo list cold open rows 75 75 0 (0.0%) 75 ✅
Claude stale todo list cold open nodes 2 2 0 (0.0%) 4 ✅
Claude stale todo list cold open subagents 2 2 0 (0.0%) 4 ✅
Claude stale todo list cold open plans 1 1 0 (0.0%) 2 ✅
Claude stale todo list cold open providerTurns 1 1 0 (0.0%) 2 ✅
Claude stale todo list cold open checkpoints 1 1 0 (0.0%) 2 ✅

Baseline: c83e78f · PR result: a275e56 · Source CI: success

Scenario and decoded snapshot size

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

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

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

@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Published Linux AppImages now use channel-specific, version-free names. AUR release handling selects matching assets, and Linux desktop setup can recover a prior versioned AppImage path and create a symlink during updater relaunch.

Changes: Linux AppImage Naming and Update Handling

Layer / File(s) Summary
Published AppImage artifact names
scripts/build-desktop-artifact.ts, scripts/build-desktop-artifact.test.ts
Published stable and nightly Linux AppImages use distinct names without the version placeholder. The test checks both conditions.
AUR release asset selection
packaging/aur/scripts/release.sh, packaging/aur/t3code-bin/PKGBUILD, packaging/aur/t3code-nightly-bin/PKGBUILD
The release script checks the channel-specific asset before the legacy versioned name and validates its SHA-256 digest. The selected asset name is passed to the PKGBUILD.
Linux desktop update path recovery
apps/desktop/src/app/DesktopLinuxUrlHandler.ts, apps/desktop/src/app/DesktopLinuxUrlHandler.test.ts, apps/desktop/src/app/DesktopPreReadyPlatform.ts, apps/desktop/src/app/DesktopPreReadyPlatform.test.ts
The desktop setup parses the existing desktop entry. During updater relaunch, it can create a relative symlink from a prior versioned AppImage path to the current filename. Tests cover path matching and updater-flag behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant DesktopPreReadyPlatform
  participant readFileSync
  participant replacedVersionedAppImagePath
  participant symlinkSync
  DesktopPreReadyPlatform->>readFileSync: Read existing desktop entry
  readFileSync-->>DesktopPreReadyPlatform: Return entry contents
  DesktopPreReadyPlatform->>replacedVersionedAppImagePath: Resolve prior AppImage path
  replacedVersionedAppImagePath-->>DesktopPreReadyPlatform: Return path or null
  DesktopPreReadyPlatform->>symlinkSync: Link prior path to current AppImage filename
Loading

Suggested reviewers: mwolson

Merge Risk: Minimal · up to a275e

This change gives Linux AppImages version-free names so the updater can update them in place, and it keeps the AUR release flow working. No merge-blocking risk was found. A real packaged update under a desktop session was not tested.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title states the main change: AppImage update flows now keep the installed filename, which matches the version-free artifact naming, the AUR lookup changes, and the symlink repair in the diff. It …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description is detailed on the problem context, change, reproduction, and verification evidence, and it follows the template's sections loosely. Two gaps remain. The Problem section is not labeled…
Full details: Title check

Explanation

The title states the main change: AppImage update flows now keep the installed filename, which matches the version-free artifact naming, the AUR lookup changes, and the symlink repair in the diff. It uses the conventional commit form and is specific enough for a teammate scanning history.

Full details: Description check

Explanation

The description is detailed on the problem context, change, reproduction, and verification evidence, and it follows the template's sections loosely. Two gaps remain. The Problem section is not labeled as such and the Change section is embedded in prose. The Scope section does not link a bug issue in its body. The commit message names #8944, but the author says the description is the pipeline's to edit. Verification is thorough, with local-test caveats noted. The description also has an extensive run-metadata section that the template does not ask for. Overall the description is mostly complete, so it passes.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between c83e78f and a275e56.

Files selected for processing: 9

  • apps/desktop/src/app/DesktopLinuxUrlHandler.test.ts
  • apps/desktop/src/app/DesktopLinuxUrlHandler.ts
  • apps/desktop/src/app/DesktopPreReadyPlatform.test.ts
  • apps/desktop/src/app/DesktopPreReadyPlatform.ts
  • packaging/aur/scripts/release.sh
  • packaging/aur/t3code-bin/PKGBUILD
  • packaging/aur/t3code-nightly-bin/PKGBUILD
  • scripts/build-desktop-artifact.test.ts
  • scripts/build-desktop-artifact.ts

Limit details: You’ve used all 10 included reviews currently available.

@juliusmarminge
juliusmarminge merged commit e07585e into main Nov 13, 2026
36 checks passed
@juliusmarminge
juliusmarminge deleted the factory/pr-25756-a1794597635 branch November 13, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Versioned AppImage filename breaks desktop entries and symlinks on every update

1 participant