Skip to content

chore(upstream): isolate remote session cookies and settle pre-cursor gap sources - #481

Merged
rynfar merged 10 commits into
pylonfrom
upstream/2026-09-11-precursor-gaps
Sep 11, 2026
Merged

chore(upstream): isolate remote session cookies and settle pre-cursor gap sources#481
rynfar merged 10 commits into
pylonfrom
upstream/2026-09-11-precursor-gaps

Conversation

@rynfar

@rynfar rynfar commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Eighteen upstream commits before the ledger's reviewed-through cursor (beae2147a9) had no port and no recorded decision in Pylon. They were not patch-equivalent, their subjects were not in Pylon history, and neither .agents/upstream-review.md nor its archive named their SHAs or PR numbers. This PR gives every one of them a disposition so the cursor is honest. It also ports the ones Pylon was still missing, including the remote web session cookie fix.

Tracking: #414. Frozen upstream head: 6c583620ff7ad3235b135af7107c0543467eecfa. Base: origin/pylon at b66eca91de.

How it was ported

Before porting, each source was checked for the same behavior already in Pylon under a different subject: key identifiers and strings from the upstream diff, later upstream rewrites of the same lines, and the archived decisions. Where a later upstream commit Pylon already carries replaced a source, it is recorded as superseded. The rest were cherry-picked with -x or spliced into Pylon's current files, following upstream's final shape at the frozen head.

Sources

Source Upstream PR Outcome Note
8dcb96314c976899e4df6951fb9af03131c2a46f #8733 Superseded Reverted #8693. #8734 (30175a8af0) re-landed the unified composer banners the next day, and Pylon adopted it as #221 (b455a4912a). Pylon has ComposerBanner/ComposerSurface and no ThreadSyncStatusPill, which matches the frozen head.
8b817cbcaad71a53e2ef73f3881067f8aa8094bc #8840 Superseded #9606 (c3b8825bf4, Pylon d49bc768c7) rewrote the failure icons: severe failures use circle-alert, and ordinary failures keep the tool icon with a trailing X.
7963ac7404ff2196c3e8e4198ecc02a5e742b0a1 — (release v0.0.37) Skipped Pylon versions independently.
ad38700ac678b8c8a0310d434a44d94a7ee6a47f #8917 Already covered / skipped The diagnostic-override rule in .macroscope/check-run-agents/effect-service-conventions.md is already present through the #9321 rewrite (cb10c155ef). .macroscope/approvability.md is absent in Pylon and was skipped, following the earlier CS-5/V20 skips.
4e8e64fc065a4a72535eee5fe60b689f5b48d35c #8933 Skipped Pylon has no .coderabbit.yaml, and CodeRabbit posts no checks or reviews on Pylon PRs.
5ce92c2f192040bf77c0211fa33bf03c74c031ef #8932 Partially adopted Adopted the shimmer clipping: the row clips overflow and MaskedView uses StyleSheet.absoluteFill. Excluded the shimmer: live derivation, which #10173 and #10273 later rewrote and Pylon already carries.
f47e74004af232f0e3df8dc10093601d1c2c3ea3 #8851 Adopted with adaptation Header breadcrumb clipping, a truncating locked-workspace label, a minimum width for workspace controls and pre-paint label measurement. Pylon keeps the branch selector in the left run, so upstream's branch flex-basis hunk has no equivalent.
0df043fd4eaa190eb491a3060836156eb0ae915e Skipped CodeRabbit auto_review config; not used here.
85b656ff300f71060ad6305c7e1e29a72b442ce9 Skipped CodeRabbit config formatting; not used here.
c78ae50a5a5fdf8f42d0aaa0103b26ee836f0cfc #8085 Adopted Clean pick; see below.
ce71c04f0aa9d2e5cd340e2a04cb1b0d5e24419d #8936 Partially already covered; remainder adopted resolveViewedImageAsset, workEntryViewedImagePath, ChatMarkdownAssetImage and mobile feed rendering landed with the #9023 port (8e98cef906). Adopted the remaining part: web's duplicate tool-group helpers are removed in favor of client-runtime's.
0947c30e6946b2ad6d6cd518fd44292e75e834e8 #9010 Already covered work-log/presentation.ts already imports @t3tools/client-runtime/markdown-images.
b883fc066ea5c9bebbe1c3e9b4bc2471aab3685f #8367 Adopted Final shape at the frozen head; see below.
9dbdcece5f488c66f6b9ac516b610f45bbbb676a #9033 Superseded #8890 (e9db39ce05) replaced this banner layout with an inline description and details popover. Pylon carries it from the #402 composer batch (3f1594c9a3).
9d1879b142a2f5d01383357646a4679d1a2bd202 #9076 Adopted See below.
cb007469161ff0db2bc2dc8123c4b30e186aae50 #8925 Adopted Web only, as upstream.
692eb1a5792b9930959b19805acf2bf2611318c9 #9092 Superseded #9332 (854541a04e, Pylon 87d7448d35) replaced the panel-triggered refresh with per-PR state shared by the panel and both sidebars.
60cef47ec983637ddc68faed7b1488b6f3c3a175 — (release v0.0.38) Skipped Pylon versions independently.

Adopted behavior and Pylon adaptations

#8085: remote web session cookies. Remote production web servers on one hostname all used t3_session, so they overwrote each other's browser sessions. Cookie names now derive from the persisted environment ID. A valid legacy t3_session still authenticates at the lowest precedence, after the current cookie, Bearer and DPoP, and /api/auth/session rewrites it under the new name. ServerEnvironmentIdentity is split from the descriptor, so t3 auth, t3 pair, t3 project and t3 connect load the ID without launcher checks. The ID file is published atomically and repaired through environment-id.recovery. Desktop and development cookie names are unchanged. Pylon's descriptor additions (machine kind, capabilities, agent activity publishing) survive the split. Clients only read sessionCookieName informationally. Pairing is unchanged, but a browser whose shared cookie was already overwritten must pair again, as upstream notes.

#8367: server config bootstrap. A session opens one subscribeServerConfig stream, takes its first snapshot as the initial config, and replays that snapshot plus the latest theme and usage-limit-source events to later subscribers. Deduplication needs an exact input match, so web passes { environmentThemes, usageLimitSources, usageLimitsCommand } and mobile passes { usageLimitSources, usageLimitsCommand }: the same options their createServerEnvironmentAtoms subscriptions already use. This carries Pylon's usage-limit events, matching upstream's frozen head. Probes still fall back to server.getConfig for servers without a connection probe, and every supported server sends a snapshot first. The projection moved to state/serverConfigProjection.ts. RpcSession's make stays private, as Pylon's workspace audit requires. Pylon's browser-profile preflight still works because it awaits session.initialConfig. Test fake sessions not touched upstream (serverUsage, threads-atoms, threads-failures) gained subscribeServerConfig.

#9076: quit shortcut modes. confirmQuit is now "direct" | "hold" | "double-click"; Hold is the default. Settings uses a selector, the overlay shows a hint for the selected mode, and the preload validates the new hint shape. Legacy booleans decode true to Hold and false to Direct, in both browser storage and the desktop settings file, and save back as the mode string. T3 Code's shared-storage values now decode instead of falling back through #459's lenient path. Desktop still reads the mode through readConfirmQuit, which keeps Hold when the file cannot be read. Its test also covers a missing file and Direct. The lenient-decoding tests (contracts, desktop, web) used confirmQuit: "hold" as their unreadable example, so they now use diffLayout: "unified", and the web test also checks that a stored "double-click" is read. QuitHold.ts and its tests now match the frozen head, which already includes the #9141/#9485/#9657 fixes Pylon had. docs/user/keybindings.md describes the three modes.

#8925: Project settings in thread menus. The item appears in the sidebar thread menu, the legacy sidebar's project thread menu and the chat header thread menu (useThreadActionMenu). It opens /projects/$projectKey with the logical project key, and the context-menu fallback gains the settings icon. That icon was also missing for the existing chat breadcrumb entry. User docs mention the new entry point. Mobile is unchanged, as upstream.

#8851, #8932 and #8936 (web grouping): see the table.

Removed from Pylon

  • The boolean confirmQuit and its switch, replaced by modes that keep both previous behaviors (Hold and Direct).
  • Web's copy of toolGroupAction, summarizeToolGroup, omitSupersededLifecycleMarkers and toolGroupSummaryKind. It had drifted from client-runtime: it lacked approval-activity classification, viewedImagePath reads and case-insensitive "Read file". Web now matches mobile and upstream.
  • RpcSession.layer; layerWithOptions replaces it.

None of these is a Pylon-original capability.

Verification

  • Server (t3): EnvironmentAuth, EnvironmentAuthAdmin, EnvironmentAuthPolicy, SessionStore, auth utils, ServerEnvironment, cli/pair, bin: 85 passed. server.test.ts cookie migration and precedence cases: 3 passed.
  • Client runtime: rpc/session, rpc/client, state/server, serverUsage, threads-atoms, threads-failures, connection/registry, connection/supervisor, operations/commands, pullRequests, shell-sync, sourceControl, threads-pagination, threads-sync, vcs, vcsAction: 213 passed.
  • Web: MessagesTimeline.logic + MessagesTimeline 157; clientPersistenceStorage + settingsSearch 31; threadActionMenu.logic + contextMenuFallback 21; BranchToolbar.logic + ChatHeader + Sidebar.logic 251.
  • Contracts settings.test.ts: 112 passed. Desktop QuitHold + DesktopClientSettings: 43 passed.
  • Typechecks passed for t3, @t3tools/client-runtime, @t3tools/web, @t3tools/mobile, @t3tools/contracts and @t3tools/desktop; each output shows its package ran with 0 errors.
  • vp lint on changed TS/TSX found no new findings; the two remaining warnings (isSameSidebarThreadRef and useNavigate unused imports) are already on origin/pylon. vp fmt --check passed on all 69 changed files.
  • git grep -n PRIME_AGENT_DRIVER_KIND is unaffected; no provider registries were touched.

No local client pass was run; the orchestrator does one integrated pass later. Upstream UI evidence: #9076 settings selector, #8936 before/after, #8851, #8925, #8932.

Newer upstream commits after the frozen head touch some of the same files (RpcAuthorization.ts, ServerEnvironment.ts, settings.ts, thread-work-log.tsx) for unrelated features (#10677, #10856, #10839, #10875, #10671, #11014). None is a follow-up to these sources.

Ported by Claude Opus 5 in Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Long project names and locked workspace labels no longer push the thread
title or context strip controls over each other. The locked workspace label
now truncates and compacts like the selectable one, the workspace controls
keep a minimum width, and label overflow is measured before paint.

Pylon keeps the branch selector in the left run beside the workspace
controls, so upstream's branch flex-basis hunk has no equivalent here; the
overflow measurement loop already skipped zero-width children.

Adopted from f47e74004af232f0e3df8dc10093601d1c2c3ea3 (#8851)
The shimmer sweep on an active tool row now fills its masked layer with
StyleSheet.absoluteFill and the row clips overflow, so the highlight stays
inside the label instead of drawing past it.

Partially adopted: the shimmer derivation change (shimmer follows live) was
later rewritten by #10173 and #10273, which Pylon already carries.

Adopted from 5ce92c2f192040bf77c0211fa33bf03c74c031ef (#8932)
Remote production web servers on the same hostname all used the
`t3_session` cookie, and browsers do not scope cookies by port, so one
server could overwrite another's browser session. Remote web cookies now
take their name from the persisted environment ID, which survives
state-directory moves and stays distinct for environments that share an
internal path. A valid legacy `t3_session` cookie still authenticates, at the
lowest precedence, and the session endpoint migrates it to the new name.

Environment identity is split from the full descriptor so `t3 auth`,
`t3 pair`, `t3 project` and `t3 connect` load the saved ID without launcher
checks. Initialization publishes the ID atomically and repairs an empty ID
file through a retained recovery file.

Desktop and development cookie names are unchanged.

Adopted from c78ae50a5a5fdf8f42d0aaa0103b26ee836f0cfc (#8085)
The web timeline kept its own copy of the tool-group action, summary and
lifecycle-marker helpers, which had drifted from the shared client-runtime
versions mobile uses: approval activity, viewed-image entries and
case-varied "Read file" titles grouped differently on web. Web now imports
the shared helpers, matching upstream.

The rest of this source (viewed-image asset resolution, the web asset image
component, and mobile feed rendering) already landed with the #9023 media
preview port.

Adopted from ce71c04f0aa9d2e5cd340e2a04cb1b0d5e24419d (#8936)
Each client session requested the full server config twice while
connecting: once through `server.getConfig` for bootstrap and again through
the config subscription. The session now opens one `subscribeServerConfig`
stream, takes its first snapshot as the initial config, and replays that
snapshot plus the latest theme and usage-limit source events to the shared
config state, so later subscribers never open a duplicate stream.

Web opts into environment themes, usage-limit sources and the
`/usage-limits` command; mobile opts into usage-limit sources and the
command, matching the options each client's config state already
subscribes with. A different input still opens its own subscription. If the
owned stream fails, dies or ends, the connection supervisor recovers the
session instead of serving stale config. The config projection moves to its
own module.

Servers without a connection probe still fall back to `server.getConfig` for
probes, and every server Pylon supports sends a snapshot first.

Adopted from b883fc066ea5c9bebbe1c3e9b4bc2471aab3685f (#8367)
`confirmQuit` was a boolean whose enabled state accepted either a hold or a
second press without saying so. It is now an explicit mode: Direct quits on
the first Cmd/Ctrl+Q press, Hold (the default) quits after a completed hold
or a quick second press, and Double press quits on two presses within
500 ms and shows a "Press again" hint after the first. Settings uses a
selector, the overlay shows the hint for the selected mode, and the preload
and IPC contract carry the mode with each hint.

Stored booleans migrate on read, true to Hold and false to Direct, on both
browser storage and the desktop settings file, and save back as the mode
string. T3 Code writes the same modes to shared browser storage, so those
values now decode instead of falling back to the default. The desktop
still reads the mode through `readConfirmQuit`, which keeps Hold when the
settings file cannot be read. The lenient-decoding tests now use another
setting as their unreadable example.

Adopted from 9d1879b142a2f5d01383357646a4679d1a2bd202 (#9076)
Thread menus in the sidebar, the legacy sidebar, and the chat header now
include Project settings, which opens the thread's project at
`/projects/$projectKey` (resolving grouped projects to their logical key).
The sidebar project row keeps its own settings entry, the web context menu
fallback gains the settings icon those entries use, and mobile is unchanged,
as upstream.

Adopted from cb007469161ff0db2bc2dc8123c4b30e186aae50 (#8925)
Adopted from cb007469161ff0db2bc2dc8123c4b30e186aae50 (#8925)
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pylon-marketing Ready Ready Preview Sep 11, 2026 7:57am UTC

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Sep 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.9 KiB 14.1 KiB +170 B (+1.2%) 15.1 KiB
Codex Thread snapshot wire 7.2 KiB 7.2 KiB +4 B (+0.1%) 7.3 KiB
Codex Live turn WebSocket wire 6.7 KiB 6.9 KiB +166 B (+2.4%) 7.8 KiB
Codex Live turn WebSocket decoded 58.0 KiB 58.8 KiB +910 B (+1.5%) 66.4 KiB
Codex Live turn messages 8 10 +2 (+25.0%) 21
Claude Total thread wire 13.9 KiB 14.1 KiB +143 B (+1.0%) 15.1 KiB
Claude Thread snapshot wire 7.2 KiB 7.2 KiB −7 B (−0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.7 KiB 6.9 KiB +150 B (+2.2%) 7.8 KiB
Claude Live turn WebSocket decoded 58.8 KiB 59.7 KiB +928 B (+1.5%) 66.4 KiB
Claude Live turn messages 8 10 +2 (+25.0%) 21

Baseline: b66eca9 · PR result: 688aed5 · 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: 115.6 KiB
  • Claude decoded thread snapshot: 116.3 KiB

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

@rynfar
rynfar merged commit 51545d7 into pylon Sep 11, 2026
20 checks passed
@rynfar
rynfar deleted the upstream/2026-09-11-precursor-gaps branch September 11, 2026 08:31
rynfar added a commit that referenced this pull request Sep 11, 2026
Keep #481's quit shortcut modes, thread-menu project settings, and the
environment-ID recovery file in the rewritten pages. Document the RPC
session's shared server-config stream against the new base, restore the
staged Electron package name, sidebar order and filter rules, POSIX path
case sensitivity, and the migrate-dev-db source flag, and describe #479's
Antigravity restart, refresh, and send-block behavior. Point AGENTS.md at
Pylon's hosted origin and correct the ledger row.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant