Skip to content

chore(upstream): adopt the 2026-08-23 T3 Code batch - #68

Merged
rynfar merged 31 commits into
pylonfrom
upstream/2026-08-23-batch
Aug 23, 2026
Merged

chore(upstream): adopt the 2026-08-23 T3 Code batch#68
rynfar merged 31 commits into
pylonfrom
upstream/2026-08-23-batch

Conversation

@rynfar

@rynfar rynfar commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Reviews be7d35aae..30be31195 from pingdotgg/t3code: twenty-seven commits, twenty-six change sets, all adopted. git cherry reported every one absent from Pylon. A read-only git merge-tree probe predicted five conflicts before this branch existed; all five landed where predicted.

Full per-change-set reasoning is in .agents/upstream-review.md. The parts worth a reviewer's attention:

#7774 landed as plumbing only

#7774 ships two separable things: origin metadata (client surface + app version stamped onto auth sessions and orchestration event metadata) and three PostHog events — client.connected, client.thread.started, client.turn.requested.

Pylon's AnalyticsService still defaults T3CODE_POSTHOG_KEY to T3's project key with telemetry enabled, so taking the events as written would have reported every Pylon user's thread and turn activity into T3's analytics project. Per developer decision, the metadata is kept and the three analytics.record calls are dropped, along with the now-unused helper, service acquisition, and import. Upstream's analytics test is replaced with one covering what Pylon retains: that clientSurface/clientAppVersion on the /ws URL reach the dispatched command's origin, and that a client announcing nothing yields undefined rather than a manufactured empty origin.

The inherited PostHog key is a pre-existing condition this batch did not create and deliberately did not widen. It deserves its own PR.

Migration renumbered 041 → 045

Upstream's 041_AuthSessionClientConnection collides with Pylon's existing 041_ProjectionProjectsDefaultThreadEnvMode. Pylon runs 41–44, so it lands at 045, matching the 037–040 precedent. File, test file, and the test's layer(...) label all renamed.

Three defects upstream's CI could not have caught

They only exist where Pylon has diverged. All three are fixed in 4626ce462, and all three were found by reading verification output rather than trusting exit codes — tsgo reported the first while still exiting 0.

  • #7821 inserts submissionIntent as onSend's second parameter. Pylon already had directAnnotation and delivery in positions 2 and 3, so Pylon's own onQueueFollowUp was passing "follow-up" into directAnnotation.
  • #7897 reads props.selectedThreadQueueCount; Pylon calls that value localOutboxCount.
  • #7774's migration test pinned upstream's ids (40 → 41), so under Pylon's renumbering it asserted against a table that never gained the columns.

#7794: upstream's version replaced a working Pylon fix

Pylon had already fixed the empty-composer hijack inline. Upstream's helper is strictly more precise — its :not([contenteditable="false"]) clause lets closest walk past a non-editable island to an editable host, where Pylon's would stop at the island and suppress the shortcut. Upstream's comment carries the same reasoning Pylon's did, so nothing was lost, and the shared helper reduces future divergence.

Worth a second opinion

  • #7823 widens AssetAccess past workspace-root containment so a project icon can come from an absolute path. Gated by a signed claim and an extension allowlist that includes .svg. Not a privilege escalation — a paired client already has command execution through any provider — but it does widen the asset surface, and the setting crosses the wire rather than only coming from the native picker.
  • #7893 narrows when a tool group reads as failed: last entry rather than any entry. A failure followed by a successful retry stops showing as failed. Defensible, but user-visible.
  • #7906 adds 82 --contrast-* variables as an indirection over the theme tokens. Merges clean, but Pylon-specific tokens do not route through the contrast layer, so the slider's coverage is partial. Follow-up, not a blocker.

Conflicts

Six files, all resolved Pylon-first and detailed in the ledger. Two test files had unrelated tests interleaved by git; both were rebuilt from their sources rather than untangled, preserving every test on both sides. ChatComposer.tsx was edited byte-wise — it holds NUL bytes that make grep treat it as binary without -a.

Validation

  • 2221 tests pass across the touched suites: 766 web, 1062 server, 393 across mobile, client-runtime, shared, contracts, ssh, tailscale. Zero failures in this worktree.
  • Every run also globs nested worktrees under .claude/, .prime/, and .superconductor/, which fail to collect for want of their own node_modules. Every reported failure was confirmed to carry a worktrees path segment before the run was accepted — a pre-existing vitest discovery quirk, not a defect here.
  • Typecheck clean across all seven touched packages, each confirmed to have actually run.
  • vp check over all 139 changed TypeScript files: 0 errors, 3 warnings, none introduced here (two are upstream-verbatim or identical in both forks; one is a Pylon-only dead import that predates this batch).

Not done

No real-client pass in web or mobile. #6433/#7940 change iOS native markdown rendering and #7906 restyles the token layer; both warrant a look in a running client before release. No UI screenshots for the same reason.


Claude Opus 5 in Pylon.


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

Bil0000 and others added 29 commits August 22, 2026 22:30
(cherry picked from commit 0a46daaf63e78cdd188f6eb944ce5ee463e63216)
(cherry picked from commit 837f6b871a88db0986c98a5a5ebc6bd80b4f2546)
Co-authored-by: GPT-5.6 <noreply@openai.com>
(cherry picked from commit 292c6dd8c242d2b5e2b727295dd17951e55c2d3d)
(cherry picked from commit 9b5d416872591d215c4a16d6f87798c8486522d8)
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
(cherry picked from commit c3e37094e04de71accf497c6110c5305223e0090)
(cherry picked from commit e0b4f4639037ce539e6feac7eaf11995cf5490f8)
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
(cherry picked from commit b381fdb12cb7cb241e2b8aca84941375f3fb43f4)
(cherry picked from commit 44e4a7071d84c95f4d273cc3c6c9682166502745)
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
(cherry picked from commit 592c5983c14d248aa3cfddb8e6c7372f12cd1ab6)
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
(cherry picked from commit 421088c27367da227d922ce999c1637416a6d0f4)
… environment (#7086)

(cherry picked from commit 035058a23e651ea5f407c9ab73cf5329cc40c102)
… (#7774)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 11f051373e79b38fa16f3ec1af825f5164907c1b)
(cherry picked from commit ce91284f832fc71bf46ff2a8ffc290e20db4e83d)
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
(cherry picked from commit f34b9d31b3ddbd53a553141fd769721fca4b8eb5)
(cherry picked from commit 2274444e92275fda2033de6636e3143ac3599ffb)
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
(cherry picked from commit 0ede2ed0de8214c0e9168dcf1936e68e5c730e10)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 2c4158f87a1b6a586d0aa5e0338f122cb7887c4f)
(cherry picked from commit 49c2b4471c59b21759eb2e254e9c4fa2579888a3)
…ndpoints (#7116)

(cherry picked from commit d9c1732b2791f762bce06e4898cdb6679ce24961)
(cherry picked from commit dedcd99a9d16240327ce763b885b326aff607bdb)
(cherry picked from commit 77c9d1eb5b6a48d38f6f0a2bb4a8cff8e4752ade)
(cherry picked from commit 6c693baecf75454cac96d1ae3f78afc73f2cbe53)
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
(cherry picked from commit 6e9c57f7ba9eab9e987da7a660664a1df683e9cf)
…ng (#7937)

(cherry picked from commit 4e00471d1ab340b46742565bb6ce6462160b4d0c)
(cherry picked from commit 5a7a7cf2925c88388a023f0d4eb6b9096884e817)
(cherry picked from commit 4e169df1dd12e0ed960dcb310e9460897759a55e)
…ng main (#7078)

(cherry picked from commit 30be31195883635aba96031a8d79c255fb28b438)
… signatures

Three adopted commits assumed upstream shapes that Pylon has diverged from, so
each compiled or passed upstream and failed here.

#7821 inserts `submissionIntent` as onSend's second parameter. Pylon's onSend
already carried `directAnnotation` and `delivery` in positions 2 and 3, so its
own `onQueueFollowUp` caller was passing "follow-up" into `directAnnotation`.

#7897 reads `props.selectedThreadQueueCount` on ThreadDetailScreen. Pylon calls
that same value `localOutboxCount`; both are fed from
`composer.selectedThreadQueueCount` at the route, so only the prop name differs.

#7774's migration test pinned upstream's ids, running migrations to 40 and then
41. Pylon renumbered that migration to 045, so the before/after pair is 44 and
45; against upstream's ids the new columns were never created.
Twenty-six change sets from twenty-seven upstream commits, all adopted, with
the cursor advanced to 30be3119. Records the migration renumber, the
plumbing-only shape of #7774, the three Pylon-divergence defects the adoption
surfaced, and the retirement of U-4326's dead revisit condition.
@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Aug 23, 2026
@github-actions

github-actions Bot commented Aug 23, 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.4 KiB +3 B (+0.0%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB +8 B (+0.1%) 7.3 KiB
Codex Live turn WebSocket wire 6.5 KiB 6.5 KiB −5 B (−0.1%) 7.8 KiB
Codex Live turn WebSocket decoded 55.0 KiB 55.0 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 16 16 0 (0.0%) 21
Claude Total thread wire 13.4 KiB 13.5 KiB +9 B (+0.1%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB −6 B (−0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.6 KiB 6.6 KiB +15 B (+0.2%) 7.8 KiB
Claude Live turn WebSocket decoded 55.8 KiB 55.8 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 16 16 0 (0.0%) 21

Baseline: 35217db · PR result: b9728d7 · 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.0 KiB

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

rynfar added 2 commits August 22, 2026 23:12
#7821's user doc arrived saying "T3 Code opens another new thread", three lines
below a paragraph that already said Pylon. docs/user/ is shipped-product voice,
and an inherited compatibility name is not permission to restore visible T3
branding — this was the only new T3 mention the batch introduced there.
#7823 let a project favicon come from outside the workspace, but the image
allowlist still ran on the path we were handed rather than the file we open.
Since `assetResponseHeaders` derives Content-Type from the resolved path, an
`icon.png` symlinked to `notes.html` was served as `text/html` on the app's own
origin, and only `.svg` carries a CSP.

The workspace branch had the same hole, just bounded: `resolveCanonicalWorkspaceFile`
re-checks containment after `realPath` but never re-checks the extension, so a
symlink with both ends inside the workspace cleared every check.

Enforced at the canonical path instead, at all three points a favicon is
resolved: minting, serving a workspace claim, and serving an external claim. The
serve-time guards matter for claims minted before this change and for a file
swapped for a symlink after its URL was issued.

Each of the three tests fails with only its own guard removed.
@rynfar

rynfar commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up on the review: fixed the AssetAccess symlink gap in b9728d767.

The image allowlist ran on the path we were handed, not the file we open, and assetResponseHeaders derives Content-Type from the resolved path — so icon.png symlinked to notes.html was served as text/html on the app's own origin. The workspace branch had the same hole bounded to inside the workspace: containment is re-checked after realPath, the extension never was.

Now enforced against the canonical path at all three resolution points (mint, serve-workspace, serve-external). Three tests, each verified to fail with only its own guard removed.

Two corrections to this PR's description:

  • I wrote that upstream's #7794 helper is "strictly more precise" than the fix Pylon already had. That's overstated. In the nested case they behave identically; the real divergence is a standalone contenteditable="false" island with no editable ancestor, where Pylon suppressed the shortcut and upstream fires it. Defensible, but a behavior change rather than a pure improvement. The test's closest stub also matches by substring, so the :not(...) clause is not actually exercised.
  • #7893 is half-applied — but it's upstream's own inconsistency, not a merge error here. Their head has at(-1)! at one work-toggle producer and .some(...) at the other, and our copy matches byte-for-byte.

The remaining review findings are going into a separate PR rather than this one.

@rynfar
rynfar merged commit 188a409 into pylon Aug 23, 2026
14 checks passed
@rynfar
rynfar deleted the upstream/2026-08-23-batch branch August 23, 2026 16:36
rynfar added a commit that referenced this pull request Aug 24, 2026
The appearance contrast boost mixes every foreground role toward one shared
target, so at a full 100% they all resolve to exactly that target. Measured in a
browser against the real tokens: at the slider's own maximum of 200,
`--contrast-foreground`, `--contrast-muted-foreground`, `--contrast-placeholder`
and `--contrast-icon-muted` all come back `oklab(0 0 0)`. Body text, muted
timestamps and placeholder text become the same colour, so an empty composer
reads as a filled one.

It degrades before the maximum too — lightness separation between normal and
muted text runs 0.278 at the default, 0.111 at 160, 0.055 at 180, then 0.

Scaling the foreground mix to 0.6 keeps the top of the range clearly darker than
the default while holding the roles apart, and leaves the slider's range and
direction untouched. Borders keep the full curve: they carry a single role, so
converging costs no hierarchy, and their quarter-weight already bounds them.

Arrived with #7906 (upstream) in #68; not a Pylon-authored defect.
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.