From 97db94c9bf6fa5d83f94c8fff85566d7fc96276e Mon Sep 17 00:00:00 2001
From: Bilal Bakr <62337003+Bil0000@users.noreply.github.com>
Date: Thu, 13 Aug 2026 15:45:33 +0300
Subject: [PATCH 01/10] fix(web): keep pull request panel within viewport
(#6451)
---
.../src/components/preview/PreviewPanelShell.test.ts | 12 +++++++++++-
.../web/src/components/preview/PreviewPanelShell.tsx | 2 +-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/components/preview/PreviewPanelShell.test.ts b/apps/web/src/components/preview/PreviewPanelShell.test.ts
index 4ac086157a2f..31258b166bdf 100644
--- a/apps/web/src/components/preview/PreviewPanelShell.test.ts
+++ b/apps/web/src/components/preview/PreviewPanelShell.test.ts
@@ -1,6 +1,8 @@
+import { jsx } from "react/jsx-runtime";
+import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vite-plus/test";
-import { getPreviewPanelMaxWidth } from "./PreviewPanelShell";
+import { getPreviewPanelMaxWidth, PreviewPanelShell } from "./PreviewPanelShell";
describe("getPreviewPanelMaxWidth", () => {
it("allows the panel to use 70% of an ultra-wide viewport without a pixel ceiling", () => {
@@ -10,4 +12,12 @@ describe("getPreviewPanelMaxWidth", () => {
it("rounds fractional CSS pixels down", () => {
expect(getPreviewPanelMaxWidth(2_001)).toBe(1_400);
});
+
+ it("keeps inline panels inside their containing workspace", () => {
+ const markup = renderToStaticMarkup(
+ jsx(PreviewPanelShell, { mode: "inline", defaultWidth: 1_000, children: "Panel" }),
+ );
+
+ expect(markup).toContain("max-w-full");
+ });
});
diff --git a/apps/web/src/components/preview/PreviewPanelShell.tsx b/apps/web/src/components/preview/PreviewPanelShell.tsx
index 30a0c9eed0ff..17ca389feab2 100644
--- a/apps/web/src/components/preview/PreviewPanelShell.tsx
+++ b/apps/web/src/components/preview/PreviewPanelShell.tsx
@@ -51,7 +51,7 @@ export function PreviewPanelShell(props: {
return (
Date: Thu, 13 Aug 2026 10:26:36 -0400
Subject: [PATCH 02/10] Add bil0000 to VOUCHED contributors list (#6462)
---
.github/VOUCHED.td | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td
index 29910f522516..71e576e5c7e4 100644
--- a/.github/VOUCHED.td
+++ b/.github/VOUCHED.td
@@ -38,3 +38,4 @@ github:jappyjan
github:justsomelegs
github:UtkarshUsername
github:SunkenInTime
+github:bil0000
From 2ab188f1c0afe99ba269739704e2e96f0bbbe78f Mon Sep 17 00:00:00 2001
From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com>
Date: Thu, 13 Aug 2026 14:51:31 +0000
Subject: [PATCH 03/10] fix: ignore pull request actions in latency tracker
(#6476)
Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com>
---
apps/web/src/rpc/requestLatencyState.test.ts | 10 ++++++++++
apps/web/src/rpc/requestLatencyState.ts | 6 +++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/apps/web/src/rpc/requestLatencyState.test.ts b/apps/web/src/rpc/requestLatencyState.test.ts
index e5b3144d2520..68433035fd18 100644
--- a/apps/web/src/rpc/requestLatencyState.test.ts
+++ b/apps/web/src/rpc/requestLatencyState.test.ts
@@ -59,6 +59,16 @@ describe("requestLatencyState", () => {
expect(getSlowRpcAckRequests()).toEqual([]);
});
+ it.each(Object.values(WS_METHODS).filter((method) => method.startsWith("pullRequests.")))(
+ "ignores pull request workspace request %s",
+ (method) => {
+ trackRpcRequestSent("1", method);
+ vi.advanceTimersByTime(SLOW_RPC_ACK_THRESHOLD_MS * 2);
+
+ expect(getSlowRpcAckRequests()).toEqual([]);
+ },
+ );
+
it("keeps ignoring untracked methods when a display tag is supplied", () => {
trackRpcRequestSent(
"1",
diff --git a/apps/web/src/rpc/requestLatencyState.ts b/apps/web/src/rpc/requestLatencyState.ts
index 4736d3783c3b..4ec5b56f9e2b 100644
--- a/apps/web/src/rpc/requestLatencyState.ts
+++ b/apps/web/src/rpc/requestLatencyState.ts
@@ -49,7 +49,11 @@ function getSlowRpcAckRequestsValue(): ReadonlyArray
{
}
function shouldTrackRpcAck(method: string): boolean {
- return !method.includes("subscribe") && !untrackedRpcAckMethods.has(method);
+ return (
+ !method.includes("subscribe") &&
+ !method.startsWith("pullRequests.") &&
+ !untrackedRpcAckMethods.has(method)
+ );
}
function rpcAckThresholdMs(method: string): number {
From 9e201941aaa9cfece3e0ffaa4cc24bbe880d1be4 Mon Sep 17 00:00:00 2001
From: Julius Marminge
Date: Thu, 13 Aug 2026 17:04:42 +0200
Subject: [PATCH 04/10] Remove rebase requirement before opening PR (#6479)
---
AGENTS.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/AGENTS.md b/AGENTS.md
index 1b41f833ce58..12f357747991 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -114,7 +114,6 @@ An empty database is a bad test. Seed your worktree's `.t3` with a copy of real
- Never make a PR unless the developer explicitly asks you to do so.
- Conventional commit titles, plain language: `fix(web): new threads no longer spike CPU`.
- Body: the problem in a sentence or two, then how you fixed it. End with the model and harness that did the work.
-- **Rebase onto latest main before opening.** Stale branches conflict and burn a review round.
- UI changes need before/after images. Motion or timing needs a short video.
- One concern per PR. If the description says "also", split it.
- When babysitting: poll checks and comments newer than the last push, verify each bot finding against the source, fix real ones, dismiss false positives with a written reason. Stay quiet when nothing is new. Stop when the bots are green on the latest commit.
From fd51561b4e2de1893cb7eb4069937256d702572c Mon Sep 17 00:00:00 2001
From: Chris Deeming
Date: Thu, 13 Aug 2026 19:00:03 +0100
Subject: [PATCH 05/10] fix(mobile): extend blockquotes across wrapped lines
(#6482)
---
.../src/NativeMarkdownBlock.ios.tsx | 31 ++++++++---
.../src/SelectableMarkdownText.ios.tsx | 1 +
.../src/nativeMarkdownText.ts | 1 +
.../mobile/src/lib/nativeMarkdownText.test.ts | 54 ++++++++++++++++++-
4 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/apps/mobile/modules/t3-markdown-text/src/NativeMarkdownBlock.ios.tsx b/apps/mobile/modules/t3-markdown-text/src/NativeMarkdownBlock.ios.tsx
index e6a045b3cd97..5fbe6d4dff44 100644
--- a/apps/mobile/modules/t3-markdown-text/src/NativeMarkdownBlock.ios.tsx
+++ b/apps/mobile/modules/t3-markdown-text/src/NativeMarkdownBlock.ios.tsx
@@ -4,16 +4,13 @@ import type { MarkdownNode } from "react-native-nitro-markdown/headless";
import { CopyTextButton } from "./CopyTextButton";
import { MarkdownTextPrimitive } from "./MarkdownTextPrimitive";
-import {
- nativeMarkdownDocumentRuns,
- nativeMarkdownListItemBlocks,
- nativeMarkdownTextRuns,
-} from "./nativeMarkdownText";
+import { nativeMarkdownDocumentRuns, nativeMarkdownListItemBlocks } from "./nativeMarkdownText";
import { NativeMarkdownSelectableText } from "./NativeMarkdownSelectableText.ios";
import type {
MarkdownCodeHighlighter,
MarkdownHighlightedToken,
NativeMarkdownTextStyle,
+ SelectableMarkdownSkill,
} from "./SelectableMarkdownText.types";
type HighlightedCode = ReadonlyArray>;
@@ -48,12 +45,13 @@ function documentFor(node: MarkdownNode): MarkdownNode {
function SelectableNode(props: {
readonly node: MarkdownNode;
+ readonly skills: ReadonlyArray;
readonly textStyle: NativeMarkdownTextStyle;
readonly onLinkPress?: (href: string) => void;
}) {
return (
@@ -322,6 +320,7 @@ function collectTableRows(node: MarkdownNode): MarkdownNode[] {
function NativeTable(props: {
readonly node: MarkdownNode;
+ readonly skills: ReadonlyArray;
readonly textStyle: NativeMarkdownTextStyle;
readonly onLinkPress?: (href: string) => void;
}) {
@@ -359,7 +358,7 @@ function NativeTable(props: {
}}
>
+ runs={nativeMarkdownDocumentRuns(documentFor(cell), props.skills).map((run) =>
rowIndex === 0 || cell.isHeader ? { ...run, bold: true } : run,
)}
textStyle={props.textStyle}
@@ -376,6 +375,7 @@ function NativeTable(props: {
function NativeMarkdownImage(props: {
readonly node: MarkdownNode;
+ readonly skills: ReadonlyArray;
readonly textStyle: NativeMarkdownTextStyle;
readonly onLinkPress?: (href: string) => void;
}) {
@@ -384,6 +384,7 @@ function NativeMarkdownImage(props: {
return (
@@ -445,6 +446,7 @@ function inlineGroups(nodes: ReadonlyArray): MarkdownNode[] {
function NativeMixedParagraph(props: {
readonly node: MarkdownNode;
+ readonly skills: ReadonlyArray;
readonly textStyle: NativeMarkdownTextStyle;
readonly onLinkPress?: (href: string) => void;
}) {
@@ -455,6 +457,7 @@ function NativeMixedParagraph(props: {
@@ -462,6 +465,7 @@ function NativeMixedParagraph(props: {
@@ -473,6 +477,7 @@ function NativeMixedParagraph(props: {
function NativeList(props: {
readonly node: MarkdownNode;
+ readonly skills: ReadonlyArray;
readonly textStyle: NativeMarkdownTextStyle;
readonly highlightCode: MarkdownCodeHighlighter;
readonly onLinkPress?: (href: string) => void;
@@ -534,6 +539,7 @@ function NativeList(props: {
;
readonly textStyle: NativeMarkdownTextStyle;
readonly highlightCode: MarkdownCodeHighlighter;
readonly onLinkPress?: (href: string) => void;
@@ -566,6 +573,7 @@ export function NativeMarkdownBlock(props: {
@@ -595,6 +604,7 @@ export function NativeMarkdownBlock(props: {
return (
@@ -624,6 +634,7 @@ export function NativeMarkdownBlock(props: {
child.type === "image") ? (
) : (
@@ -673,6 +687,7 @@ export function NativeMarkdownBlock(props: {
>
@@ -690,6 +705,7 @@ export function NativeMarkdownBlock(props: {
diff --git a/apps/mobile/modules/t3-markdown-text/src/SelectableMarkdownText.ios.tsx b/apps/mobile/modules/t3-markdown-text/src/SelectableMarkdownText.ios.tsx
index 56321ba01ada..7860ff592a69 100644
--- a/apps/mobile/modules/t3-markdown-text/src/SelectableMarkdownText.ios.tsx
+++ b/apps/mobile/modules/t3-markdown-text/src/SelectableMarkdownText.ios.tsx
@@ -69,6 +69,7 @@ export function SelectableMarkdownText({
chunk.kind === "rich" ? (
{
]);
});
+ it("decorates known skill references inside blockquotes", () => {
+ const node: MarkdownNode = {
+ type: "blockquote",
+ children: [
+ {
+ type: "paragraph",
+ children: [{ type: "text", content: "Use $ui for this." }],
+ },
+ ],
+ };
+
+ expect(nativeMarkdownDocumentRuns(node, [{ name: "ui", displayName: "UI" }])).toContainEqual({
+ text: "$ui",
+ role: "body",
+ skillName: "ui",
+ skillLabel: "UI",
+ });
+ });
+
it("leaves unknown skill-like text unchanged", () => {
const node: MarkdownNode = {
type: "document",
@@ -328,7 +347,7 @@ describe("nativeMarkdownDocumentRuns", () => {
]);
});
- it("includes quotes and fenced code in the same selectable string", () => {
+ it("preserves quotes and fenced code in document runs", () => {
const node: MarkdownNode = {
type: "document",
children: [
@@ -414,6 +433,39 @@ describe("nativeMarkdownListItemBlocks", () => {
});
describe("nativeMarkdownDocumentChunks", () => {
+ it("renders plain blockquotes as rich blocks so their marker spans wrapped lines", () => {
+ const blockquote: MarkdownNode = {
+ type: "blockquote",
+ beg: 0,
+ end: 120,
+ children: [
+ {
+ type: "paragraph",
+ children: [
+ {
+ type: "text",
+ content:
+ "Persistent random per-result keys are the strongest design, even when this text wraps.",
+ },
+ ],
+ },
+ ],
+ };
+
+ expect(
+ nativeMarkdownDocumentChunks({
+ type: "document",
+ children: [blockquote],
+ }),
+ ).toEqual([
+ {
+ kind: "rich",
+ key: "rich:blockquote:0:120",
+ node: blockquote,
+ },
+ ]);
+ });
+
it("keeps headings and plain lists in one selectable document", () => {
const document: MarkdownNode = {
type: "document",
From 83ad26c3a3aeb877ee8bf07c05145ad804717e2e Mon Sep 17 00:00:00 2001
From: Simone
Date: Thu, 13 Aug 2026 21:08:13 +0200
Subject: [PATCH 06/10] fix(mobile): prevent invalid HTML entities from
crashing markdown (#6495)
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
---
.../t3-markdown-text/src/nativeMarkdownText.ts | 11 +++++++++--
apps/mobile/src/lib/nativeMarkdownText.test.ts | 16 ++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts b/apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts
index 719070f3dcd3..8db904b5a6ca 100644
--- a/apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts
+++ b/apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts
@@ -70,15 +70,22 @@ const EMPTY_CONTEXT: RunContext = {
const INLINE_HTML_TAG_PATTERN = /<\/?(?:kbd|mark|sub|sup|u)(?:\s[^>]*)?>/gi;
+function decodeCodePoint(codePoint: number, entity: string): string {
+ if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 0x10ffff) {
+ return entity;
+ }
+ return String.fromCodePoint(codePoint);
+}
+
function decodeHtmlEntitiesOnce(value: string): string {
return value.replace(
/&(?:#(\d+)|#x([0-9a-f]+)|amp|apos|gt|lt|nbsp|quot);/gi,
(entity, decimal: string | undefined, hexadecimal: string | undefined) => {
if (decimal) {
- return String.fromCodePoint(Number.parseInt(decimal, 10));
+ return decodeCodePoint(Number.parseInt(decimal, 10), entity);
}
if (hexadecimal) {
- return String.fromCodePoint(Number.parseInt(hexadecimal, 16));
+ return decodeCodePoint(Number.parseInt(hexadecimal, 16), entity);
}
switch (entity.toLowerCase()) {
case "&":
diff --git a/apps/mobile/src/lib/nativeMarkdownText.test.ts b/apps/mobile/src/lib/nativeMarkdownText.test.ts
index 5ad2cca26f07..867d9e983017 100644
--- a/apps/mobile/src/lib/nativeMarkdownText.test.ts
+++ b/apps/mobile/src/lib/nativeMarkdownText.test.ts
@@ -126,6 +126,22 @@ describe("nativeMarkdownTextRuns", () => {
]);
});
+ it.each([
+ ["😀", "😀"],
+ ["🚀", "🚀"],
+ ["", ""],
+ ["", ""],
+ ["�", ""],
+ ["�", ""],
+ ])("normalizes numeric entity %s without throwing", (content, expected) => {
+ const node: MarkdownNode = {
+ type: "paragraph",
+ children: [{ type: "text", content }],
+ };
+
+ expect(nativeMarkdownTextRuns(node)).toEqual([{ text: expected }]);
+ });
+
it("reads inline content from nested text nodes", () => {
const node: MarkdownNode = {
type: "paragraph",
From 1b16ed663ffe475490a644d1004873a8aae6bb90 Mon Sep 17 00:00:00 2001
From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com>
Date: Thu, 13 Aug 2026 15:08:28 -0400
Subject: [PATCH 07/10] fix(web): avoid Clerk close button overlap (#6442)
Co-authored-by: t3-code[bot] <236186684+t3-code[bot]@users.noreply.github.com>
Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
---
apps/web/src/components/clerk/ClerkUserProfilePage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/web/src/components/clerk/ClerkUserProfilePage.tsx b/apps/web/src/components/clerk/ClerkUserProfilePage.tsx
index 09021aaad51c..00f20e53fbe1 100644
--- a/apps/web/src/components/clerk/ClerkUserProfilePage.tsx
+++ b/apps/web/src/components/clerk/ClerkUserProfilePage.tsx
@@ -19,7 +19,7 @@ export function ClerkUserProfilePage({
}) {
return (