Skip to content

chore(upstream): sync marcode through 053affbe - #61

Draft
maarco wants to merge 95 commits into
mainfrom
claude/gracious-bohr-23l2b6
Draft

chore(upstream): sync marcode through 053affbe#61
maarco wants to merge 95 commits into
mainfrom
claude/gracious-bohr-23l2b6

Conversation

@maarco

@maarco maarco commented Aug 29, 2026

Copy link
Copy Markdown
Owner

What Changed

Merges pingdotgg/t3code@053affbe into main — 93 upstream commits on top of merge base 133f3f73. Two-parent merge commit ddfa0c60; no rebase, no force push, no ours/theirs file takes. One follow-up commit 03bbdba7 repairs two fixtures the merge left stale (see "Follow-up commit" below).

CI is green on 03bbdba7 — all four required checks plus all three server shards.

30 paths conflicted. Every one was resolved by combining upstream's intent with Marcode's.

Conflict decisions

Server / persistence

Path Decision
apps/server/src/cloud/bootService.ts Took upstream's new launchd PATH key (launch agents don't inherit a shell PATH) and kept Marcode's MARCODE_HOME export. The launcher reads MARCODE_HOME and exits without it, so upstream's T3CODE_HOME key would ship a service that never boots. Upstream did not add PATH to the systemd unit, so there is no gap there.
apps/server/src/cloud/bootService.test.ts Kept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.ts Upstream's two new migrations renumbered to the next free Marcode ids. Marcode's ProjectWorkspaceLayout holds 033, so every shared migration sits one id higher: 042_ProjectionThreadLinkedPullRequest043, 043_ProjectionThreadsUnsettledAt044, with the renamed test's toMigrationInclusive bounds shifted to match. Renumbering an applied id would re-run or skip it on existing installs.
ServerEnvironment.ts / contracts/environment.ts (+ tests) Kept both capabilities: upstream's threadPullRequestLinking and Marcode's workspaceLayoutMutations.
apps/server/src/server.test.ts Kept both imports.

Web

Path Decision
connection/clientMetadata.ts (+ platform.ts) Adopted upstream's shared presentation helper — better OS, device-type, browser-family and hosted-vs-server detection — but sourced the label from APP_BASE_NAME. Upstream hardcodes "T3 Code Desktop"/"T3 Code Web", which is user-visible in Settings → Connections. Added a test pinning the Marcode labels.
settings/KeybindingsSettings.tsx Took upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsx Kept Marcode's bare Electron drag strip. Upstream's only change in the conflicted region was adding /projects/:id to the footer Back allowlist; Marcode's FloatingPillNav shows "Back to Workspace" on every off-thread route, which already covers that page.
ChatView.tsx Kept Marcode's title-only ChatHeader (thread actions are portaled into FloatingPillNav, onOpenPullRequest included, via openThreadPullRequest); took upstream's new useThreadActions hook. Dropped upstream's openProjectPullRequest, which had no caller left.
ChatMarkdown.tsx Took upstream's editorPreferences / editorLabels / remoteOpen / readThreadShell imports; kept openFileInFloatingEditor; dropped useRightPanelStore (Marcode retired the right-panel file surface) and useActiveEnvironmentId (upstream's explicitEnvironmentId prop replaced its last caller).
ThreadTerminalDrawer.tsx Kept Marcode's xterm link provider. Upstream's clickable-link fix (883e1a3c) lands in the shared terminal-links.ts, which merged clean, so extractTerminalLinks already carries it — no port needed.
composerDraftStore.ts Kept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsx Kept FolderOpenFilled (the pill is filled-icon only); dropped the inline label now that editorLabelForPlatform supplies one for every option.
useHandleNewThread.ts, Sidebar.tsx, threadSidebarWidth.test.ts, docs/README.md Additive combinations of both sides.

Mobile

Path Decision
CompactBrandTitle.tsx Ported to upstream's semantic Uniwind classes — upstream deleted useThemeColor and the new lint rule bans importing it — while keeping MarcodeMark and Marcode's off-production-only stage pill.
lib/authClientMetadata.ts Kept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsx Kept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.ts Kept Marcode's per-channel adaptive-icon assets and the white production background. See "Deliberately not taken" below.

Tooling

  • vite.config.ts — enabled upstream's new rule under Marcode's plugin namespace; kept no-native-title-tooltip at warn.
  • oxlint-plugin-marcode/rules/no-mobile-uniwind-theme-escape-hatches.* — accepted into the renamed plugin directory, harness ids rebranded t3code/marcode/.
  • scripts/build-desktop-artifact.test.ts — kept both imports and both assertions; Marcode's provisionprofile fixture path retained.
  • pnpm-lock.yaml — regenerated with pnpm 11.10.0 against the merged manifests, not hand-edited.

Silent breaks caught (clean merges, no conflict marker)

These are the dangerous ones — they merged without a mark and would have shipped broken:

  1. apps/server/src/cli/theme.ts — a brand-new upstream command reading T3CODE_HOME. Marcode's CLI base-dir variable is MARCODE_HOME everywhere else (config.ts, pair.ts, triage.ts), so t3 theme would have ignored the user's configured home and written to the default install. Switched to MARCODE_HOME; its test renamed to assert the Marcode variable so a future sync fails loudly.
  2. Three oxlint-disable-next-line t3code/no-global-process-runtime comments (preload.ts, verify-preload-bundle.mjs, externalLauncher.test.ts). Marcode's plugin namespace is marcode, so these were inert and the rule would have fired in CI. Renamed.
  3. connection/clientMetadata.ts and BrowserKeybindingNotice — upstream refactors that pulled Marcode-localized copy back to "T3 Code" (see table above).
  4. apps/mobile/app.config.ts dev + nightly channels — auto-merge silently swapped Marcode's per-channel BRAND_ASSET_PATHS foregrounds for upstream's single shared ./assets/android-icon-foreground.png. Restored, with a seam comment.
  5. hooks/useEnvironmentThemeSync.test.ts — upstream's new test seeds the stored theme under t3code:theme. Marcode's STORAGE_KEY in useTheme.ts is marcode:theme, so the seed read as "no stored theme" and all four appearance assertions silently fell back to the default. Caught by CI, fixed in 03bbdba7.

Follow-up commit 03bbdba7

CI caught two fixtures the merge left stale. Both are Marcode fork-boundary fixtures, and the first is a pin doing exactly its job:

  • persistence/Migrations.test.ts — Marcode's pin on the migration-id offset. The sync renumbered upstream's two new migrations to 043/044 and the expected list still ended at 042. Updated, and re-anchored on id >= 33 instead of slice(-10): every sync appends, so a fixed tail window keeps sliding ProjectWorkspaceLayout — the fork-critical row — out of the assertion.
  • hooks/useEnvironmentThemeSync.test.ts — the storage-key break described above. Seeded with Marcode's key, hardcoded rather than imported: this file loads ./useTheme dynamically after stubbing globals, and a static import pulls React in before those stubs and breaks the hook calls. The constraint is noted at STORAGE_KEY so the next sync sees why.

Removal pins kept

Upstream deleted two test files that were the only guards on Marcode behavior. Both kept, with seam comments explaining why:

  • apps/mobile/src/lib/mobileBranding.test.ts (upstream 73f8cfc0) — pins resolveMobileStageLabel returning "" on stable, not upstream's "Alpha".
  • apps/web/src/components/threadSidebarWidth.test.ts (upstream f6f2be32) — carries the keeps the brand out of the sidebar header assertion, the only guard against a sync restoring SidebarBrand/T3Wordmark into SidebarChrome.tsx. Its default-width case now inlines 16 * 16 rather than re-widening upstream's module API, since upstream un-exported THREAD_SIDEBAR_DEFAULT_WIDTH.

New pin added: apps/web/src/connection/clientMetadata.test.ts asserts the Marcode client labels.

Deliberately not taken — needs your call

Upstream's Android adaptive launcher icon fix (348367dc, pingdotgg#4332) is not in this merge. Upstream fixed the icon being cropped by Android's adaptive mask by introducing one padded, safe-zone-correct android-icon-foreground.png and pointing every channel at it. Taking that asset would put T3's artwork on Marcode's Android launcher, so this PR keeps Marcode's per-channel BRAND_ASSET_PATHS foregrounds and the crop bug with them.

Marcode's universal 1024 assets carry an 824×824 body (macOS safe area, ~80% of canvas). Android's adaptive safe zone is roughly the inner 61% — so Marcode's rounded-square corners are clipped under the mask. Fixing it properly means authoring padded Marcode-branded adaptive foregrounds through the brand pipeline and reviewing them visually, which is a design change rather than a merge resolution. Flagging rather than guessing.

Why

Scheduled daily upstream sync. .github/upstream-sync.yml policy: merge strategy, draft PR, hotspots as mandatory-review paths — not automatic keep-Marcode paths, which is why upstream's PATH, device-detection, terminal-link, model-selection, and lint-rule changes were all taken even where they landed in customized files.

Supersedes the older open sync PRs #53, #55, #56, #58 (through a3a8cbd6, f6f2be32, 018d7f27) — all of those upstream commits are ancestors of 053affbe. They can be closed once this lands. Blocked-sync issues #59 and #60 are closed against this PR.

Coupled-subtree checks are clean: upstream's pnpm-workspace.yaml change was Clerk version bumps only (no effect catalog move), and infra/relay/package.json had no upstream dependency change — so neither effect-version-subtree nor alchemy-version-subtree is triggered and no sync:repos run was needed.

UI Changes

No intentional visual change. Marcode's brand surfaces, floating nav shell, unified workspace sidebar, and floating-editor ownership are all preserved as-is; the two web hunks that touch rendering (KeybindingsSettings notice, CompactBrandTitle stage pill) adopt upstream's markup for copy Marcode already owned, so they render the same text through upstream's components.

Not verified in a live client: this ran headless on a scheduled sync, so test-t3-app and test-t3-mobile passes are still outstanding before this leaves draft.

Checklist

  • This PR is small and focused — it is not; it is a 93-commit upstream sync, reviewed per-path above
  • I explained what changed and why
  • I included before/after screenshots for any UI changes — no intentional visual change; live-client verification still outstanding
  • I included a video for animation/interaction changes — n/a

Verification

CI green on 03bbdba7 (run 33261194834): Check ✅ · Test ✅ · Mobile Native Static Analysis ✅ · Release Smoke ✅ · Test Server 1/2/3 ✅ · Rust ✅ · claude-review ✅. Thread transfer stays inside every ceiling (total wire down ~1.3–1.8%, live-turn messages down 44%).

Local, before each push: vp fmt --check clean across all 486 changed files; vp run typecheck green for all seven affected packages; vp lint warnings only; pnpm install --frozen-lockfile succeeds against the regenerated lockfile; the full apps/web suite at 3218/3218 and apps/mobile + packages/contracts at 1106/1106.

Two classes of local-only failure, both verified against a disposable worktree at the pre-merge base 133f3f73 and both reproducing there identically:

  • Root/chmod: this container runs as uid 0, so permission assertions cannot fail — confirmed directly (root reads and writes a chmod 000 file). Four pre-existing upstream cases in cli/theme.test.ts, one pre-existing in server.test.ts. All five pass in CI, as Test Server 1/3 show.
  • Six web test files fail to collect: @aliimam/icons@1.1.3 declares main: dist/index.cjs but ships dist/index.js, and .wasm?inline needs an asset plugin this local run lacks. Version and integrity hash are unchanged by the lockfile regeneration. CI collects all 298 web test files without either error.

t3dotgg and others added 30 commits August 24, 2026 12:42
Co-authored-by: mweinbach <maxweinbach5@gmail.com>
…gg#7140)

Co-authored-by: Dara Adedeji <daraaded@amazon.com>
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
t3dotgg and others added 23 commits August 28, 2026 15:50
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com>
…gdotgg#7313)

Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
PRs pingdotgg#8437 and pingdotgg#8236 crossed: one made stashShortcutLabel a required
ComposerStashMenu prop, the other added a test case without it, so
main fails web typecheck.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
93 upstream commits, merge base 133f3f7. 30 conflicted paths, each resolved by
combining both intents; no whole-file ours/theirs.

Server / persistence

- cloud/bootService.ts: took upstream's new launchd PATH key (launch agents do
  not inherit a shell PATH) and kept Marcode's MARCODE_HOME export. The service
  launcher reads MARCODE_HOME and exits without it, so the upstream T3CODE_HOME
  key would ship a service that never boots.
- cloud/bootService.test.ts: kept both tests. Marcode's MARCODE_HOME pin now
  passes macRenderOptions, since upstream's renderer requires environmentPath.
- persistence/Migrations.ts: upstream's two new migrations renumbered to the
  next free Marcode ids. Marcode's ProjectWorkspaceLayout holds 033, so every
  shared migration sits one id higher here; 042_ProjectionThreadLinkedPullRequest
  -> 043 and 043_ProjectionThreadsUnsettledAt -> 044, with the renamed test's
  toMigrationInclusive bounds shifted to match.
- environment/ServerEnvironment.ts and contracts/environment.ts: kept both
  capabilities (threadPullRequestLinking, workspaceLayoutMutations).
- cli/theme.ts: NEW upstream command that read T3CODE_HOME. Marcode's CLI
  base-dir variable is MARCODE_HOME everywhere else (config.ts, pair.ts,
  triage.ts), so `t3 theme` would have ignored the user's configured home and
  written to the default install. Switched to MARCODE_HOME and renamed the test
  so a future sync fails loudly.

Web

- connection/clientMetadata.ts: adopted upstream's shared presentation helper
  (OS, device type, browser family, hosted vs server) but sourced the label from
  APP_BASE_NAME. Upstream hardcodes "T3 Code Desktop"/"T3 Code Web", which is
  user-visible in Settings -> Connections. Added a test pinning the Marcode
  labels.
- settings/KeybindingsSettings.tsx: took upstream's WarningTooltipIcon and
  BrowserKeybindingNotice extractions, kept Marcode copy in both (the notice
  component hardcoded "T3 Code").
- sidebar/SidebarChrome.tsx: kept Marcode's bare Electron drag strip. Upstream's
  only change in the conflicted region was adding /projects/:id to the footer
  Back allowlist; Marcode's FloatingPillNav shows "Back to Workspace" on every
  off-thread route, which already covers it.
- ChatView.tsx: kept Marcode's title-only ChatHeader (thread actions are
  portaled into FloatingPillNav, including onOpenPullRequest via
  openThreadPullRequest) and took upstream's new useThreadActions hook. Dropped
  upstream's openProjectPullRequest, which had no caller left here.
- ChatMarkdown.tsx: took upstream's editorPreferences/editorLabels and
  remoteOpen/readThreadShell imports, kept openFileInFloatingEditor, dropped
  useRightPanelStore (Marcode retired the right-panel file surface) and
  useActiveEnvironmentId (upstream's explicitPrEnvironmentId prop replaced it).
- ThreadTerminalDrawer.tsx: kept Marcode's xterm link provider. Upstream's
  clickable-link fix lands in the shared terminal-links.ts, which merged clean,
  so extractTerminalLinks already carries it.
- composerDraftStore.ts: kept the marcode: storage key, took upstream's version
  bump to 9 so an upstream-shaped payload is discarded rather than misread.
- chat/OpenInPicker.tsx: kept FolderOpenFilled, dropped the inline label now
  that editorLabelForPlatform supplies it for every option.
- hooks/useHandleNewThread.ts, Sidebar.tsx, threadSidebarWidth.test.ts,
  docs/README.md: additive combinations of both sides.

Mobile

- app.config.ts: kept Marcode's per-channel androidAdaptiveForeground assets and
  the white production background. NOTE: this drops upstream's adaptive-icon
  crop fix (pingdotgg#4332) rather than shipping T3 artwork on Marcode's launcher; see
  the PR body.
- CompactBrandTitle.tsx: ported to upstream's semantic Uniwind classes (upstream
  deleted useThemeColor and the new lint rule bans it), kept MarcodeMark and
  Marcode's off-production-only stage pill.
- lib/authClientMetadata.ts: kept "Marcode Mobile", took upstream's phone /
  tablet detection.
- lib/mobileBranding.test.ts: kept. Upstream deleted it as low-signal, but it is
  the only guard on Marcode returning "" instead of "Alpha" on the stable
  channel.

Tooling

- vite.config.ts: enabled the new rule under Marcode's plugin namespace and kept
  no-native-title-tooltip at "warn".
- oxlint-plugin-marcode/rules/no-mobile-uniwind-theme-escape-hatches.*: accepted
  into the renamed plugin directory, harness ids rebranded to marcode/.
- Three oxlint-disable comments arrived naming t3code/no-global-process-runtime,
  which is inert here; renamed to marcode/ so they actually suppress.
- scripts/build-desktop-artifact.test.ts: kept both imports and both assertions;
  Marcode's provisionprofile fixture path retained.
- pnpm-lock.yaml regenerated with pnpm 11.10.0 against the merged manifests.

Verified: fmt --check clean, typecheck green for server / web / mobile / desktop
/ contracts / scripts / oxlint-plugin, lint reports warnings only, and focused
tests pass. Five failures are the container running as root, where chmod-based
permission assertions cannot fail: four pre-existing upstream cases in
cli/theme.test.ts and one pre-existing case in server.test.ts.
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.4 KiB 13.2 KiB −245 B (−1.8%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB +6 B (+0.1%) 7.3 KiB
Codex Live turn WebSocket wire 6.5 KiB 6.3 KiB −251 B (−3.8%) 7.8 KiB
Codex Live turn WebSocket decoded 55.0 KiB 54.7 KiB −308 B (−0.5%) 66.4 KiB
Codex Live turn messages 16 9 −7 (−43.8%) 21
Claude Total thread wire 13.4 KiB 13.3 KiB −177 B (−1.3%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB −1 B (−0.0%) 7.3 KiB
Claude Live turn WebSocket wire 6.6 KiB 6.4 KiB −176 B (−2.6%) 7.8 KiB
Claude Live turn WebSocket decoded 55.8 KiB 56.4 KiB +532 B (+0.9%) 66.4 KiB
Claude Live turn messages 16 9 −7 (−43.8%) 21

Baseline: 133f3f7 · PR result: 03bbdba · 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: 109.4 KiB
  • Claude decoded thread snapshot: 110.1 KiB

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

CI caught both on ddfa0c6; my focused test selection had missed the two
files that assert on what the merge changed.

- persistence/Migrations.test.ts: this is Marcode's pin on the migration-id
  offset and it did its job — the sync renumbered upstream's two new
  migrations to 043/044 and the expected list still ended at 042. Updated,
  and re-anchored on `id >= 33` instead of `slice(-10)`: every sync appends,
  so a fixed tail window would keep sliding ProjectWorkspaceLayout (the
  fork-critical row) out of the assertion.

- hooks/useEnvironmentThemeSync.test.ts: upstream's new test seeds the stored
  theme under "t3code:theme". Marcode's STORAGE_KEY is "marcode:theme", so the
  seed read as "no stored theme" and all four appearance assertions fell back
  to the default. Seeded with Marcode's key; hardcoded rather than imported
  because this file loads ./useTheme dynamically after stubbing globals, and a
  static import pulls React in before those stubs and breaks the hook calls.
  Noted the constraint at STORAGE_KEY so the next sync sees why.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.