Skip to content

chore(upstream): sync marcode through 761d4bac - #73

Merged
maarco merged 709 commits into
mainfrom
claude/gracious-bohr-ltd2ws
Sep 6, 2026
Merged

chore(upstream): sync marcode through 761d4bac#73
maarco merged 709 commits into
mainfrom
claude/gracious-bohr-ltd2ws

Conversation

@maarco

@maarco maarco commented Sep 5, 2026

Copy link
Copy Markdown
Owner

What Changed

Merges pingdotgg/t3code@761d4bac (705 upstream commits since f035a0f4) into main as one two-parent merge commit. 116 paths conflicted and were resolved by hand.

Retired surfaces — Marcode product contracts kept

  • The right-panel file/files surfaces stay deleted: FileBrowserPanel, FilePreviewPanel and their exclusive dependencies. Upstream's new openFile/openAttachment store actions, file-surface tabs, copy-path menu item and the FilePreviewPanel branch in ChatView go with them. filePreviewMode.ts is restored — ChatMarkdown's retained task-checkbox tests need setMarkdownTaskChecked.
  • ChatHeader keeps Marcode's title-only header plus the pill-nav ThreadActionsCluster. Upstream's entire delta there is the title action menu, project favicon/icon and new-thread-in-project machinery this fork deliberately does not mount.
  • SidebarChrome stays the bare Electron drag strip. The pinning test in threadSidebarWidth.test.ts caught the merge reintroducing SidebarBrand — exactly what it exists for.

Upstream refactors adopted, Marcode behaviour re-applied on top

  • terminalOutput.ts — took upstream's chunked output model and ported Marcode's ANSI escape-boundary trimming onto both cut points (reset and append), so a trim still never lands inside a CSI/OSC/bare-ESC sequence.
  • fileSaveCoordinator — took upstream's confirmedRevision tracking. Combining it with Marcode's cancel() exposed a real bug: upstream's new entry guard compares latestRevision with confirmedRevision, so a write in flight when the buffer was discarded confirmed a stale revision and let the discarded buffer persist a second time. cancel() now zeroes both counters and a cancel token stops the in-flight write from confirming.
  • PullRequestCandidatePicker, SidebarUpdateReleaseNotes, PullRequestListFilters, ComposerSurface, updatesTestHarness, writeFakeCli — upstream's extractions taken, with Marcode's tooltip, type-scale and glass-transparency intents re-applied at the new shared producer rather than kept as a divergent copy.
  • rightPanelStore drops the dead updatePullRequestTabStatus; RightPanelTabs gains upstream's browser-profile submenu, tab scroll buttons and PR status seeds while keeping Marcode's surface-overflow menu and shelf geometry.

Migrations

Upstream's 042047 renumbered to Marcode's 043048. ProjectWorkspaceLayout keeps 033 and every shared migration stays one id higher, as the registry comment requires — renumbering an applied id would re-run or skip it on existing installs. Migration tests renumbered with them.

Fork-boundary breaks that merged cleanly and produced no conflict

These are the dangerous ones; each was found by grepping the merged tree and by typecheck:

Break Fix
vite.config.ts lint overrides addressed the plugin as t3code/; seven oxlint-disable directives and two rule tests did the same renamed to marcode/; the per-file effect-runtime debt map moved from the rule source into the config, merging both baselines
t3 theme and t3 app read T3CODE_HOME MARCODE_HOME, the base-dir variable everywhere else in this CLI
updatesTestHarness exported T3CODE_HOME/T3CODE_DESKTOP_MOCK_*; DesktopRemoteUpdates and AnalyticsService tests set T3CODE_* names their sources no longer read renamed to MARCODE_*
bootService's service-stopped message and six test assertions named t3code.service marcode.service, via the BOOT_SERVICE_UNIT_FILE constant
AgentSessionScanner matched /.t3/worktrees/ /.marcode/worktrees/
~100 user-visible strings said "T3 Code"/"T3 Connect" across server CLI, desktop activation, onboarding, settings, clientMetadata, mobile authClientMetadata and user docs rebranded to Marcode
ExpandedImagePreview and theme tests used t3code: / t3code:theme marcode: / marcode:theme
scripts/package.json lost the yaml dependency the upstream-sync tooling parses the manifest with restored
ci.yml folded ripgrep into an upstream step, silently breaking the pin in upstream-sync-workflow.test.ts kept as its own Install workspace search dependency step

Compatibility identifiers left upstream-shaped on purpose: T3_BOOT_SERVICE_UNIT, T3_SERVICE_LAUNCHER_CONTEXT, @t3tools/*, the t3 CLI/package name, com.t3tools.t3code.service, T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR, and the t3code: storage keys Marcode never migrated.

Terminal divergence

ThreadTerminalDrawer stays on xterm — kept for its search, which upstream's Ghostty surface has no equivalent for. Upstream's migration meant re-porting by hand: the wrapped-link range helpers upstream deleted from terminal-links.ts are restored, the drawer reads the new chunked output, openTerminalLinkInPreview drops the removed args, and writeTerminalOutputUpdate moved to the Ghostty surface that owns it. The divergence is now commented where it lives, per AGENTS.md.

Why

The scheduled sync could not land this delta on its own — 116 conflicted paths means the workflow files a blocked issue and pushes nothing. This is the hand resolution that unblocks it, and after it merges the next scheduled run sees a new merge base and returns to clean-merge on its own.

UI Changes

No screenshots: this container has no display and the sync makes no new Marcode-authored UI. The user-visible deltas are upstream's own (welcome wizard, browser-profile submenu, PR list filters, panel animations) plus the Marcode surfaces this merge preserves rather than changes. Worth one test-t3-app pass on a machine with a browser before this comes out of draft — see below.

Checklist

  • This PR is small and focused — it is not, and cannot be: one upstream delta is one merge commit.
  • I explained what changed and why
  • I included before/after screenshots for any UI changes — see above
  • I included a video for animation/interaction changes — not applicable

Verification run

  • Full-workspace vp run -r typecheck: clean (15 packages).
  • vp lint over apps packages scripts oxlint-plugin-marcode infra: 0 errors (warnings are pre-existing react-compiler/tooltip categories).
  • vp fmt --check over all 1805 changed files: clean.
  • Focused tests green: contracts, shared, client-runtime state, web stores/files/sidebar/connection/theme, server boot service/CLI/migrations/environment/providers, oxlint plugin, upstream-sync tooling.

Two failures reproduce identically on origin/main in this container and are not from the merge — verified in a disposable detached worktree at origin/main:

  • packages/shared/src/Net.test.tsfindAvailablePort returns preferred when it is free: the container's port allocation. Neither Net.ts nor its test is touched by this merge.
  • apps/web/src/components/ThreadTerminalDrawer.test.tsFailed to resolve entry for package "@aliimam/icons": the published package's main/module point at files only its build produces, so an --ignore-scripts install cannot resolve it. Fails the same way on main with vite-plus 0.2.2.

A third, Manager.test.ts > preserves non-notFound cwd stat failures, fails only here: the container runs as root and a chmod 000 directory does not block uid 0. It passes in CI.

Follow-up commits: CI, and three more silent breaks

The merge commit went red on four required jobs. Every cause was a fork-boundary
break of the same class as the table above — an upstream fixture or gate that
merged without a conflict and then did not describe Marcode.

Job Cause Fix
Check upstream added a knip dead-code/dependency gate in this sync, running against Marcode's tree for the first time dropped four deps the fork genuinely no longer imports (@types/react, react, @effect/atom-react from client-runtime; @radix-ui/react-popover from web) and added a scoped apps/web ignore, marked as a seam, for Marcode-owned modules knip cannot see mounted. Also reformatted projectWorkspace.ts, untouched by the merge but reformatted by this sync's oxfmt bump
Test BrowserSession.test.ts asserted persist:t3code-preview- persist:marcode-preview-, matching PREVIEW_PARTITION_PREFIX
Test Server 1 Manager.test.ts seeded T3CODE_SECRET to prove secret stripping; Manager.ts strips on the MARCODE_ prefix, so the fixture had stopped exercising the behaviour it names MARCODE_SECRET
Test Server 2 six new upstream migrations slid Marcode's id-33 anchor out of the migration pin's slice(-10) window widened to slice(-16), keeping id 33 inside — it is the anchor the one-id offset is measured from
Test Server 1 (2nd round) apps/server/src/cli/app.test.ts, new in this sync, starts a fake desktop under <root>/.t3 and then invokes t3 app with no base directory. Marcode resolves that default to ~/.marcode, so the fake desktop listened on a socket the CLI never dialed fixtures use the Marcode home; os-jank.test.ts now pins resolveBaseDir for undefined and blank input, so a future sync that reintroduces ~/.t3 fails at the resolver instead of in a fixture

WSL node-pty marker — a break CI could not have caught

Auditing the tree for ~/.t3 after that last failure turned up a genuine
runtime bug in new upstream code. DesktopWslEnvironment writes the WSL node-pty
prebuild marker as marcode-wsl-node-pty.json, but upstream's new
node_pty_payload_present() guard scans for t3code-wsl-node-pty.json.

That guard exists to stop a runtime whose pty.node went missing from staying
cache-ready forever. Pointed at a marker nothing writes, it inverts: every cached
WSL runtime reads as missing its native payload and is reinstalled on every
launch. The test suite agreed with the guard because its fixture staged the same
pre-rename name — both sides were self-consistently wrong, and green.

The marker is now one exported constant shared by the build script, the probe,
the install guard and the fixture, with a test asserting all three scripts carry
it and none carry the old name.

This also resolves the WSL question this description previously left open:
$HOME/.t3/wsl-runtime becomes $HOME/.marcode/wsl-runtime, through the same
kind of constant. That staging path is new in this sync and has never shipped, so
no installed runtime needs migrating. The .t3code-wsl-runtime-{ready,selected}
dotfiles inside a staged runtime are left alone: internal, written and read by
the same script, and not the user-visible identity the ~/.t3 rename was about.

Left for a decision

  • Attachment preview. Upstream added "open a browser-previewable chat attachment in a right-panel file surface". Marcode retired that surface and the floating editor opens workspace paths, not attachment blobs, so attachments download for now. Porting an attachment surface into the floating editor is feature work, not merge work; the seam is commented in ChatView.
  • cursor-hygiene-webhook.yml is a new upstream workflow keyed on CURSOR_T3CODE_WEBHOOK_* repo secrets. It skips cleanly when they are absent.
  • Vendored subtrees: no sync needed. The effect catalog version did not move (4.0.0-beta.103) and infra/relay's alchemy dep is unchanged, so neither coupling in .github/upstream-sync.yml is triggered. .repos/effect-smol sits at beta.102, a skew that predates this merge.

Still worth doing before this leaves draft

CI is green on cfa4587aCheck, Test, Mobile Native Static Analysis and
Release Smoke all pass. Not yet done, and not doable from this container:

  • a test-t3-app pass on a machine with a browser, per the sync runbook's UI-hotspot rule;
  • a test-t3-mobile pass — the PR carries the 📱 Native Change label.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MXHnM9VTENCo5sjeucMArL


Generated by Claude Code

t3dotgg and others added 30 commits September 4, 2026 07:26
Defer the draft walk and JSON serialization until the storage write flushes.
Preserve hydration, migrations, attachment verification, and final flushes.

Continues the web portion of [pingdotgg#9049](pingdotgg#9049).
The mobile storage migration remains separate.

Created with GPT-6 Astra (preview) in Codex.

Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
)

Append terminal history incrementally and materialize text for snapshots and coalesced disk writes.
Clear evicted line references without changing retained output.

Continues [pingdotgg#9357](pingdotgg#9357). The original contribution and author credit are preserved.
The current line limit and wire format stay unchanged. A strict byte limit remains separate work.

Created with GPT-6 Astra (preview) in Codex.

Co-authored-by: will <will@moondiner.com>
Keep bounded, byte-counted terminal chunks and append only unread output. Use UTF-16 cursors so compaction preserves live terminal replies. Reset on lifecycle changes or a real retained-data gap.

Keep the existing wire protocol, native buffer interface, and client retention limit. Native streaming and strict server replay byte bounds remain separate.

Continue the client helpers from pingdotgg#9027 at source head 9391da2.

Created with GPT-6 Astra (preview) in Codex.

Co-Authored-By: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>
Stop post-construction terminal snapshots, canvas paint, and cursor timers while a drawer or right panel is hidden. Keep parsing output and answering VT queries, then render current state once on reveal.

Cover delayed WASM initialization, selection behavior, zero-size mounts, and reveal with real-core headless tests. Keep the existing startup background fill.

Continue the zero-size guard from source commit eb5b681 in the terminal streaming contribution.

Created with GPT-6 Astra (preview) in Codex.

Co-Authored-By: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dotgg#9713)

Accept file-backed image drafts and v4 outbox records while keeping current inline image creation and v3 outbox writes.

Retain image files during previews, uploads, and legacy inline reads. Preserve image MIME types and stop canceled sends after asynchronous reads.

The later file-backed writers remain held until new native runtime fingerprints contain these readers and the storage guards.

Continue Wout Stiens' mobile draft work with separate reader-only corrections. The original contribution remains unchanged.

Created with GPT-6 Astra (preview) in Codex.

Co-Authored-By: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Read only the selected thread's events when resuming its detail stream. Measure bounded row counts and serialized payload bytes before replay, using the existing aggregate index and a captured authoritative head.

Keep snapshot resets for oversized or invalid cursors. Reset recreated threads when a snapshot exists, and keep bounded replay for deleted threads whose snapshot is absent. Shell replay and the detail-event filter are unchanged.

Created with GPT-6 Astra (preview) in Codex.
…g#9651)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Reuse ordered timeline entries and raw rows for safe streaming text updates. Keep full derivation for structural, metadata, activity, and control changes.

Preserve immutable attachment-preview objects when their current URLs are unchanged. Cover URL renewal/removal, completion, grouping, pagination, and earlier-row immutability.

Continue extoci's ordered timeline projection work with separate integration and attachment corrections. The original contribution remains unchanged.

Created with GPT-6 Astra (preview) in Codex.

Co-Authored-By: extoci <hi@extoci.lol>
Give HTTP sends and response-body reads ten seconds each. Keep the existing typed transport errors, delivery records, and queue policy.

Abort stalled requests and let the next signed job run. JWT retrieval is outside these deadlines. Do not add retries for an uncertain response result.

Created with GPT-6 Astra (preview) in Codex.
juliusmarminge and others added 21 commits September 5, 2026 01:53
…rt (pingdotgg#5362)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
…gdotgg#9965)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
705 upstream commits, 116 conflicted paths. Conflict decisions, grouped:

Retired surfaces (Marcode product contracts kept)
- Right-panel file/files surfaces stay deleted: FileBrowserPanel, FilePreviewPanel
  and their exclusive deps (FileBreadcrumbs, filePath, useFileSaveCoordinator,
  fileTreePathReconciliation). Upstream's new openFile/openAttachment store
  actions, file-surface tabs, copy-path menu item and FilePreviewPanel branch in
  ChatView go with them. filePreviewMode.ts is restored: ChatMarkdown's retained
  task-checkbox tests need setMarkdownTaskChecked.
- ChatHeader keeps Marcode's title-only header plus the pill-nav ThreadActionsCluster.
  Upstream's whole delta there is the title action menu, project favicon/icon and
  new-thread-in-project machinery this fork deliberately does not mount.
- SidebarChrome stays the bare Electron drag strip; the pinning test in
  threadSidebarWidth.test.ts caught the merge reintroducing SidebarBrand.

Upstream refactors adopted, Marcode behaviour re-applied on top
- terminalOutput.ts: took upstream's chunked output model and ported Marcode's
  ANSI escape-boundary trimming onto both cut points (reset and append).
- fileSaveCoordinator: took upstream's confirmedRevision tracking; cancel() now
  zeroes both counters and a cancel token stops an in-flight write from
  confirming a discarded revision (upstream's guard made the old cancel leak a
  second persist).
- PullRequestCandidatePicker, SidebarUpdateReleaseNotes, PullRequestListFilters,
  ComposerSurface, updatesTestHarness, writeFakeCli: upstream extractions taken,
  with Marcode's tooltip/type-scale/transparency intents re-applied at the new
  shared producer.
- rightPanelStore drops the dead updatePullRequestTabStatus; RightPanelTabs gains
  upstream's browser-profile submenu, tab scroll buttons and PR status seeds
  while keeping Marcode's surface-overflow menu and shelf geometry.

Migrations
- Upstream's 042-047 renumbered to Marcode's 043-048; ProjectWorkspaceLayout keeps
  033 and the shared migrations stay one id higher, as the registry comment
  requires. Migration tests renumbered with them.

Fork-boundary breaks that merged cleanly and produced no conflict
- vite.config.ts lint overrides addressed the plugin as `t3code/`; Marcode's
  plugin is `marcode`. Same for seven oxlint-disable directives and two rule
  tests. The per-file effect-runtime debt map moved from the rule source into
  the config, merging both baselines.
- `t3 theme` and `t3 app` read T3CODE_HOME; this CLI's base-dir variable is
  MARCODE_HOME everywhere else.
- updatesTestHarness exported T3CODE_HOME/T3CODE_DESKTOP_MOCK_* to the desktop
  update tests; DesktopRemoteUpdates and AnalyticsService tests set T3CODE_*
  names their sources no longer read.
- bootService's service-stopped message and six test assertions named
  t3code.service; Marcode's unit is marcode.service.
- AgentSessionScanner matched `/.t3/worktrees/`; Marcode's home is `.marcode`.
- clientMetadata, mobile authClientMetadata and ~100 user-visible strings across
  server CLI, desktop activation, onboarding, settings and user docs said
  "T3 Code"/"T3 Connect".
- ExpandedImagePreview and theme tests used the `t3code:` scheme and
  `t3code:theme` key; Marcode uses `marcode:`/`marcode:theme`.
- scripts/package.json lost the `yaml` dependency the upstream-sync tooling parses
  the manifest with.
- ci.yml: ripgrep stays its own "Install workspace search dependency" step so the
  pin in upstream-sync-workflow.test.ts keeps matching.

Terminal divergence
- ThreadTerminalDrawer stays on xterm (kept for its search). Upstream's move to
  their Ghostty surface required re-porting by hand: the wrapped-link range
  helpers upstream deleted from terminal-links.ts are restored, the drawer reads
  the new chunked output, openTerminalLinkInPreview drops the removed args, and
  writeTerminalOutputUpdate moved to the Ghostty surface that owns it. The
  divergence is now commented where it lives.

Verification: full-workspace typecheck clean; vp lint reports zero errors;
vp fmt --check clean over all 1805 changed files; focused tests green across
contracts, shared, client-runtime state, web stores/files/sidebar/connection,
server boot service/CLI/migrations/environment, oxlint plugin and sync tooling.
Two failures reproduce identically on origin/main in this container and are not
from the merge: packages/shared Net.test.ts port allocation, and
ThreadTerminalDrawer.test.ts failing to resolve @aliimam/icons under an
--ignore-scripts install.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MXHnM9VTENCo5sjeucMArL
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. labels Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.4 KiB 13.6 KiB +166 B (+1.2%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 7.0 KiB +137 B (+1.9%) 7.3 KiB
Codex Live turn WebSocket wire 6.5 KiB 6.6 KiB +29 B (+0.4%) 7.8 KiB
Codex Live turn WebSocket decoded 55.0 KiB 57.1 KiB +2.0 KiB (+3.7%) 66.4 KiB
Codex Live turn messages 16 10 −6 (−37.5%) 21
Claude Total thread wire 13.4 KiB 13.5 KiB +90 B (+0.7%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 7.0 KiB +144 B (+2.0%) 7.3 KiB
Claude Live turn WebSocket wire 6.5 KiB 6.5 KiB −54 B (−0.8%) 7.8 KiB
Claude Live turn WebSocket decoded 55.8 KiB 57.8 KiB +2.0 KiB (+3.5%) 66.4 KiB
Claude Live turn messages 16 8 −8 (−50.0%) 21

Baseline: 200e149 · PR result: cfa4587 · 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: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

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

Four CI jobs failed on the merge commit. Each cause and its fix:

Check (knip) — upstream added a knip dead-code/dependency gate in this sync,
so it ran against Marcode's tree for the first time. Dropped dependencies the
fork genuinely no longer imports (`@types/react`, `react`, and
`@effect/atom-react` from `packages/client-runtime`; `@radix-ui/react-popover`
from `apps/web`) and regenerated the lockfile. Added a scoped `apps/web` ignore
block, marked as a fork seam, for the Marcode-owned modules knip reports as
unused because the fork mounts them from surfaces upstream does not have.
Also reformatted `packages/client-runtime/src/operations/projectWorkspace.ts`,
which the merge left untouched but the oxfmt bump in this sync reformats.

Test — `apps/desktop/src/preview/BrowserSession.test.ts` asserted on
`persist:t3code-preview-`. This is a silent fork-boundary break: upstream
rewrote the test, it merged without a conflict, and the production prefix in
`BrowserSession.ts` is Marcode's `persist:marcode-preview-`. Fixture updated to
match the source of truth.

Test Server 1 — same class of break in
`apps/server/src/terminal/Manager.test.ts`, which seeded `T3CODE_SECRET` to
prove secret stripping. `Manager.ts` strips on the `MARCODE_` prefix, so the
upstream fixture silently stopped exercising the behavior it names. Renamed to
`MARCODE_SECRET`.

Test Server 2 — `apps/server/src/persistence/Migrations.test.ts` pins the tail
of the migration registry, and this sync added six upstream migrations, sliding
Marcode's id-33 anchor out of the `slice(-10)` window. Widened to `slice(-16)`
so id 33 stays inside the assertion: it is the anchor the one-id offset is
measured from, and a window that no longer covers it stops pinning the offset.

`apps/server/src/terminal/Manager.test.ts` still fails locally on "preserves
non-notFound cwd stat failures" because this container runs as root and a
chmod 000 directory does not block uid 0. That assertion is unrelated to the
renamed fixture and passes in CI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MXHnM9VTENCo5sjeucMArL
…e directory

`Test Server 1` failed on four cases in the new upstream file
`apps/server/src/cli/app.test.ts`. The fixtures start a fake desktop app under
`<root>/.t3` and then invoke `t3 app` with no base directory, but Marcode
resolves that default to `~/.marcode` (`resolveBaseDir` in os-jank.ts, renamed
from upstream's `~/.t3`). The fake desktop listened on a socket the CLI never
dialed, so the failure read as a broken CLI rather than a stale fixture.

Nothing pinned that default, which is why the file merged clean. `os-jank.test.ts`
now pins `resolveBaseDir` for both the undefined and blank inputs, so a future
sync that reintroduces `~/.t3` fails at the resolver instead of in a fixture.

Auditing the rest of the merged tree for `~/.t3` turned up a second break in
new upstream code, this one invisible to CI. `DesktopWslEnvironment` writes the
WSL node-pty prebuild marker as `marcode-wsl-node-pty.json`, but upstream's new
`node_pty_payload_present()` guard scans for `t3code-wsl-node-pty.json`. The
guard exists to stop a runtime whose pty.node went missing from staying
cache-ready forever; against a marker nothing writes it inverts, reporting every
cached WSL runtime as missing its native payload and reinstalling it on every
launch. The test suite agreed with the guard because its fixture staged the same
pre-rename name, so both sides were self-consistently wrong and green.

The marker is now one exported constant used by the build script, the probe, the
install guard, and the fixture, with a test asserting all three scripts carry it
and none carry the old name. The WSL runtime parent moves from
`$HOME/.t3/wsl-runtime` to `$HOME/.marcode/wsl-runtime` through the same kind of
constant; this staging path is new in this sync and has never shipped, so no
installed runtime needs migrating.

Left as-is: the `.t3code-wsl-runtime-{ready,selected}` dotfiles inside a staged
runtime. They are internal, written and read by the same script, and not the
user-visible identity the `~/.t3` rename was about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MXHnM9VTENCo5sjeucMArL
…vice

The `Check` job typechecks with the Effect diagnostics plugin enabled, which
rejects a `node:path` import where an Effect API exists
(`effect(nodeBuiltinImport)`). That plugin does not run in a plain local
`vp run typecheck`, so the import passed here and failed in CI.

The new assertions already run inside `it.effect`, so they take `Path.Path` from
the layer they were provided instead. `node:os` stays: `homedir()` is what the
resolver itself reads and the rule flags only builtins with an Effect
equivalent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MXHnM9VTENCo5sjeucMArL
@maarco
maarco merged commit 1218ed4 into main Sep 6, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.