chore(upstream): adopt the 2026-08-23 T3 Code batch - #68
Conversation
(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.
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 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.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
#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.
|
Follow-up on the review: fixed the AssetAccess symlink gap in The image allowlist ran on the path we were handed, not the file we open, and 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:
The remaining review findings are going into a separate PR rather than this one. |
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.
Reviews
be7d35aae..30be31195frompingdotgg/t3code: twenty-seven commits, twenty-six change sets, all adopted.git cherryreported every one absent from Pylon. A read-onlygit merge-treeprobe 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
#7774ships 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
AnalyticsServicestill defaultsT3CODE_POSTHOG_KEYto 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 threeanalytics.recordcalls are dropped, along with the now-unused helper, service acquisition, and import. Upstream's analytics test is replaced with one covering what Pylon retains: thatclientSurface/clientAppVersionon the/wsURL reach the dispatched command's origin, and that a client announcing nothing yieldsundefinedrather 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_AuthSessionClientConnectioncollides with Pylon's existing041_ProjectionProjectsDefaultThreadEnvMode. Pylon runs 41–44, so it lands at 045, matching the 037–040 precedent. File, test file, and the test'slayer(...)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 —tsgoreported the first while still exiting 0.#7821insertssubmissionIntentasonSend's second parameter. Pylon already haddirectAnnotationanddeliveryin positions 2 and 3, so Pylon's ownonQueueFollowUpwas passing"follow-up"intodirectAnnotation.#7897readsprops.selectedThreadQueueCount; Pylon calls that valuelocalOutboxCount.#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 letsclosestwalk 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
AssetAccesspast 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.--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.tsxwas edited byte-wise — it holds NUL bytes that makegreptreat it as binary without-a.Validation
.claude/,.prime/, and.superconductor/, which fail to collect for want of their ownnode_modules. Every reported failure was confirmed to carry aworktreespath segment before the run was accepted — a pre-existing vitest discovery quirk, not a defect here.vp checkover 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/#7940change iOS native markdown rendering and#7906restyles 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.
Need help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.