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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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

@maarcomaarco 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

PathDecision
apps/server/src/cloud/bootService.tsTook 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.tsKept both tests. Marcode's MARCODE_HOME pin now passes macRenderOptions, since upstream's renderer requires environmentPath.
apps/server/src/persistence/Migrations.tsUpstream'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.tsKept both imports.

Web

PathDecision
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.tsxTook upstream's WarningTooltipIcon and BrowserKeybindingNotice extractions and kept Marcode copy in both — the extracted notice component hardcoded "T3 Code".
sidebar/SidebarChrome.tsxKept 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.tsxKept 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.tsxTook 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.tsxKept 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.tsKept the marcode: storage key, took upstream's version bump to 9 so an upstream-shaped payload is discarded rather than misread.
chat/OpenInPicker.tsxKept 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.mdAdditive combinations of both sides.

Mobile

PathDecision
CompactBrandTitle.tsxPorted 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.tsKept "Marcode Mobile", took upstream's phone/tablet detection.
HomeHeader.tsx, T3Wordmark.tsxKept Marcode's MarcodeMark; kept Marcode's deletion of T3Wordmark.tsx.
app.config.tsKept 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.

t3dotggand 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>
juliusmarmingeand others added 22 commits August 28, 2026 16:02
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-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 29, 2026
@github-actions

github-actionsBot commented Aug 29, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.4 KiB13.2 KiB−245 B (−1.8%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+6 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.5 KiB6.3 KiB−251 B (−3.8%)7.8 KiB
CodexLive turn WebSocket decoded55.0 KiB54.7 KiB−308 B (−0.5%)66.4 KiB
CodexLive turn messages169−7 (−43.8%)21
ClaudeTotal thread wire13.4 KiB13.3 KiB−177 B (−1.3%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB−1 B (−0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.4 KiB−176 B (−2.6%)7.8 KiB
ClaudeLive turn WebSocket decoded55.8 KiB56.4 KiB+532 B (+0.9%)66.4 KiB
ClaudeLive turn messages169−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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXLvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

20 participants

@maarco@t3dotgg@tris203@flamboh@RakshithBhat03@StiensWout@lnieuwenhuis@MohtashamMurshid@SunkenInTime@luckyPipewrench@krutftw@colonelpanic8@gsimone@juliusmarminge@ipanasenko@ikifar2012@anirudhsama@none23@extoci@shivamhwp