Skip to content

Commit 5024f4c

Browse files
Merge origin/main into fix/pr-body-video-tables
Cells of a media table now carry body-relative sourceOffset, so a task-list checkbox inside a cell writes back to the right place, and a CRLF cell drops its leading blank lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 parents 7b45384 + 6fe0fdf commit 5024f4c

30,952 files changed

Lines changed: 2163235 additions & 1695658 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/test-t3-app/SKILL.md‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ description: Test T3 Code's web and desktop UI through its built-in Browser pane
55

66
# Test T3 web and desktop
77

8-
Use T3's built-in Browser panel for verification. If its tools are absent or
9-
the panel reports unavailable, explain the blocker and stop verification.
10-
Do not install or switch to another automation system. For native mobile
11-
testing, use [test-t3-mobile](../test-t3-mobile/SKILL.md).
8+
Use T3's built-in Browser panel for verification. Follow the recovery steps
9+
below before declaring it unavailable. Do not install or switch to another
10+
automation system. For native mobile testing, use
11+
[test-t3-mobile](../test-t3-mobile/SKILL.md).
1212

1313
## Start the app
1414

@@ -36,8 +36,13 @@ model, such as Haiku for Claude or Luna for Codex.
3636

3737
## Use the Browser panel
3838

39-
Call `preview_status`, then `preview_open` if the Browser panel is
40-
closed. Navigate to the complete startup pairing URL once with
39+
Call `preview_status`. If no tab can be automated, call `preview_open`, including
40+
when status reports `available: false` or `tabId: null`. Status can report
41+
unavailable simply because no tab exists yet; opening a tab needs no user action.
42+
Stop verification and explain the blocker only if the tools are absent or
43+
`preview_open` reports unavailable or fails.
44+
45+
Navigate to the complete startup pairing URL once with
4146
`preview_navigate`, then use `preview_snapshot` and T3's interaction tools.
4247
If the token was consumed or expired, run `node apps/server/src/bin.ts pair`
4348
for a fresh one. Keep using the same tab.

‎.github/SECURITY.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Security policy
22

33
Report security vulnerabilities affecting T3 Code or T3 Tools-operated infrastructure to
4-
[security@ping.gg](mailto:security@ping.gg). Please do not disclose them publicly until we have had
4+
[security@t3.codes](mailto:security@t3.codes). Please do not disclose them publicly until we have had
55
a reasonable opportunity to investigate and remediate them.
66

77
See the [full security policy](https://t3.codes/security-policy) for reporting details, scope,

‎.github/actions/setup-ci-deps/action.yml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,12 @@ runs:
123123
key: ${{ steps.pnpm_verified.outputs.cache-primary-key }}
124124

125125
# A filtered install that started from the current full store adds nothing
126-
# worth a second copy of it.
126+
# worth a second copy of it. A stacked PR, based on a branch other than the
127+
# default, saves a ~1 GB store only its own reruns can read, so it only restores.
127128
- name: Save pnpm store
128129
if: >-
129130
inputs.install == 'true' &&
131+
(github.event_name != 'pull_request' || github.base_ref == github.event.repository.default_branch) &&
130132
steps.pnpm_cache.outputs.cache-hit != 'true' &&
131133
(steps.pnpm_store.outputs.namespace == 'full' ||
132134
steps.pnpm_cache.outputs.cache-matched-key != format('pnpm-full-v1-{0}-{1}-{2}', runner.os, runner.arch, hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml', 'package.json')))

‎.github/scripts/ci-changes.cjs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const INERT = [
1414

1515
// Shared test setup and vendored mobile dependencies affect every package.
1616
const RUNS_EVERYTHING = [
17-
/^packages\/shared\/src\/(HostProcess|testing\/longTempDir)\.ts$/,
17+
/^packages\/shared\/src\/(HostProcess|testing\/(longTempDir|providerEnv))\.ts$/,
1818
/^apps\/mobile\/deps\//,
1919
];
2020

@@ -27,6 +27,8 @@ const EXTRA_OWNERS = [
2727
[/^native\/browser-secret\//, ["@t3tools/desktop"]],
2828
[/^native\/kde-snap-shot\//, ["@t3tools/desktop"]],
2929
[/^native\/libghostty-vt\//, ["@t3tools/web"]],
30+
// apps/server/src/cloud/ConnectReachability.test.ts checks the guide's headings.
31+
[/^docs\/user\/t3-connect-troubleshooting\.md$/, ["t3"]],
3032
];
3133
const RUST = /^native\/(resource-monitor|kde-snap-shot|hyprland-snap-shot)\//;
3234

@@ -92,11 +94,11 @@ function readWorkspace() {
9294

9395
// [] means inert; null means unknown and requires every job.
9496
function ownersOf(file, packages) {
95-
if (INERT.some((pattern) => pattern.test(file))) return [];
97+
const extra = EXTRA_OWNERS.flatMap(([pattern, names]) => (pattern.test(file) ? names : []));
98+
if (INERT.some((pattern) => pattern.test(file))) return extra;
9699
// A manifest can change dependencies or versions other packages read.
97100
if (path.posix.basename(file) === "package.json") return null;
98101
if (RUNS_EVERYTHING.some((pattern) => pattern.test(file))) return null;
99-
const extra = EXTRA_OWNERS.flatMap(([pattern, names]) => (pattern.test(file) ? names : []));
100102
// scripts/build-desktop-artifact.test.ts reads the crates' sources.
101103
if (RUST.test(file)) return ["@t3tools/scripts", ...extra];
102104

‎.github/scripts/thread-transfer-report.cjs‎

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -300,18 +300,28 @@ async function resolve({ github, context, core }) {
300300
core.setOutput("publish", "false");
301301
return;
302302
}
303-
const workflowRuns = await github.paginate(github.rest.actions.listWorkflowRuns, {
304-
owner,
305-
repo,
306-
workflow_id: source.workflow_id,
307-
branch: pull.base.ref,
308-
event: "push",
309-
status: "success",
310-
per_page: 100,
311-
});
303+
// One page each for the exact base and the newest runs; paging through
304+
// every successful main run costs up to ten requests to keep 20.
305+
const listRuns = async (filters) => {
306+
const { data } = await github.rest.actions.listWorkflowRuns({
307+
owner,
308+
repo,
309+
workflow_id: source.workflow_id,
310+
branch: pull.base.ref,
311+
event: "push",
312+
status: "success",
313+
per_page: 20,
314+
...filters,
315+
});
316+
return data.workflow_runs;
317+
};
318+
const [baseRuns, recentRuns] = await Promise.all([
319+
listRuns({ head_sha: pull.base.sha }),
320+
listRuns({}),
321+
]);
312322
const orderedRuns = [
313-
...workflowRuns.filter((run) => run.head_sha === pull.base.sha),
314-
...workflowRuns.filter((run) => run.head_sha !== pull.base.sha),
323+
...baseRuns,
324+
...recentRuns.filter((run) => run.head_sha !== pull.base.sha),
315325
].slice(0, 20);
316326

317327
let baselineRun;

‎.github/scripts/thread-transfer-report.test.cjs‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,18 @@ test("validates the fixed artifact schema", () => {
5555
test("resolves a fallback PR with a redacted head repo and exact main baseline", async () => {
5656
const outputs = {};
5757
const listWorkflowRunArtifacts = () => {};
58-
const listWorkflowRuns = () => {};
58+
// The exact base run sits far past the newest page of main CI runs.
59+
const mainRuns = Array.from({ length: 1_000 }, (_, index) => ({
60+
id: 1_000 - index,
61+
head_sha: index === 900 ? "base-sha" : `main-sha-${index}`,
62+
}));
63+
const listWorkflowRuns = async ({ head_sha, per_page }) => ({
64+
data: {
65+
workflow_runs: mainRuns
66+
.filter((run) => head_sha === undefined || run.head_sha === head_sha)
67+
.slice(0, per_page),
68+
},
69+
});
5970
const listPullRequestsAssociatedWithCommit = () => {};
6071
const github = {
6172
paginate: async (method, input) => {
@@ -77,9 +88,6 @@ test("resolves a fallback PR with a redacted head repo and exact main baseline",
7788
},
7889
];
7990
}
80-
if (method === listWorkflowRuns) {
81-
return [{ id: 1, head_sha: "base-sha" }];
82-
}
8391
throw new Error("unexpected pagination call");
8492
},
8593
rest: {
@@ -123,7 +131,7 @@ test("resolves a fallback PR with a redacted head repo and exact main baseline",
123131
assert.equal(outputs.publish, "true");
124132
assert.equal(outputs.pull_number, "5350");
125133
assert.equal(outputs.pr_artifact, "true");
126-
assert.equal(outputs.baseline_run_id, "1");
134+
assert.equal(outputs.baseline_run_id, "100");
127135
assert.equal(outputs.baseline_matches_base, "true");
128136
});
129137

‎.github/triage/PLAYBOOK.md‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,16 @@ of `main` for that work, never the tag-pinned diagnosis clone.
125125
- Show the user the complete final issue text and get an explicit yes before
126126
posting. Never post without it.
127127
- Note at the end of the issue which model and agent produced it.
128-
- If `gh` is not authenticated, offer `gh auth login`, or build a prefilled
129-
https://github.com/pingdotgg/t3code/issues/new URL with title and body query
130-
parameters; print the URL, and open it in their browser only after they
131-
approve.
128+
- Post with `gh issue create --repo pingdotgg/t3code --label via-triage` only
129+
if `gh api repos/pingdotgg/t3code --jq .permissions.triage` prints `true`.
130+
- Otherwise, or if `gh` is not authenticated, build a prefilled
131+
https://github.com/pingdotgg/t3code/issues/new?template=via-triage.yml URL.
132+
The form applies the label whoever submits it. Add `title` plus one
133+
URL-encoded query parameter per form field id: `what-happened`, `diagnosis`,
134+
`steps`, `version`, `environment`, `evidence`, `related`, `workaround` and
135+
`agent`. Keep the full encoded URL below 6,000 characters by shortening any
136+
fields as needed. Give the user any omitted text to paste into the form before
137+
submitting. Print the URL, and open it in their browser only after they approve.
132138
- If the user pasted screenshots, remind them to drag the images into the issue
133139
after it is created; they cannot be attached from here.
134140

‎.github/workflows/ci.yml‎

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,41 @@ jobs:
192192
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
193193
run: node apps/desktop/scripts/verify-preload-bundle.mjs
194194

195+
# Browser tests run source modules; this boots the production chunk graph. The
196+
# desktop build above already produced apps/web/dist, and the client waits about
197+
# 15s for a session that never comes, so this runs here instead of in Test Web,
198+
# which gates the whole run. Chromium comes from the cache Test Web shares.
199+
- name: Resolve Playwright version
200+
id: playwright_version
201+
if: ${{ !cancelled() && steps.build.outcome == 'success' && needs.changes.outputs.test_web != 'false' }}
202+
run: echo "version=$(node -p "require('./apps/web/node_modules/playwright/package.json').version")" >> "$GITHUB_OUTPUT"
203+
204+
- name: Cache Chromium
205+
id: chromium_cache
206+
if: ${{ !cancelled() && steps.build.outcome == 'success' && needs.changes.outputs.test_web != 'false' }}
207+
uses: actions/cache@v6
208+
with:
209+
path: ~/.cache/ms-playwright
210+
key: playwright-chromium-shell-${{ runner.os }}-${{ runner.arch }}-${{ steps.playwright_version.outputs.version }}
211+
212+
- name: Install Chromium for the built web client boot check
213+
if: ${{ !cancelled() && steps.build.outcome == 'success' && needs.changes.outputs.test_web != 'false' && steps.chromium_cache.outputs.cache-hit != 'true' }}
214+
run: node apps/web/node_modules/playwright/cli.js install --only-shell chromium
215+
216+
- name: Install missing Chromium system dependencies
217+
if: ${{ !cancelled() && steps.build.outcome == 'success' && needs.changes.outputs.test_web != 'false' }}
218+
run: |
219+
browser=$(find "$HOME/.cache/ms-playwright" -name chrome-headless-shell -type f -print -quit)
220+
test -n "$browser"
221+
if ldd "$browser" | grep '=> not found'; then
222+
node apps/web/node_modules/playwright/cli.js install-deps chromium
223+
fi
224+
225+
- name: Boot the built web client
226+
if: ${{ !cancelled() && steps.build.outcome == 'success' && needs.changes.outputs.test_web != 'false' }}
227+
timeout-minutes: 3
228+
run: node apps/web/scripts/verify-built-boot.ts
229+
195230
- name: Typecheck
196231
if: ${{ !cancelled() && steps.typecheck.outcome == 'success' }}
197232
timeout-minutes: 5
@@ -272,12 +307,18 @@ jobs:
272307
env:
273308
TEST_PACKAGES: ${{ needs.changes.outputs.test_packages }}
274309
run: |
310+
set -o pipefail
275311
filters=(--filter '!t3' --filter '!@t3tools/monorepo' --filter '!@t3tools/web')
276312
if [[ -n "$TEST_PACKAGES" ]]; then
277313
filters=()
278314
for package in $TEST_PACKAGES; do filters+=(--filter "$package"); done
279315
fi
280-
vp run --parallel --concurrency-limit 4 "${filters[@]}" test
316+
# The runner's trace writer can crash on surrogate pairs in test output.
317+
vp run --parallel --concurrency-limit 4 "${filters[@]}" test 2>&1 | python3 -u -c '
318+
import sys
319+
for line in sys.stdin:
320+
sys.stdout.write(line.encode("ascii", "backslashreplace").decode("ascii"))
321+
'
281322
282323
# The web suite is the largest outside the server. In the shared Test job it
283324
# started last and ran alone for about 40s after everything else finished.
@@ -334,12 +375,6 @@ jobs:
334375
- name: Test
335376
run: vp run --filter @t3tools/web test
336377

337-
# Browser tests run source modules; this boots the production chunk graph.
338-
- name: Boot the built web client
339-
run: |
340-
vp run --filter @t3tools/web build
341-
node apps/web/scripts/verify-built-boot.ts
342-
343378
# apps/server sets `fileParallelism: false`, so its test files run strictly
344379
# one at a time. Sharding spreads them over separate runners instead of
345380
# separate workers, so no two server test files ever share a machine and the

‎.github/workflows/desktop-macos-preview.yml‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,27 @@ jobs:
7373
# Public T3 Connect identifiers (Clerk publishable key, relay URL).
7474
cp .env.example .env
7575
76-
- uses: ./.github/actions/setup-apt-mirrors
76+
# PR heads from before build:desktop:bundle use the full build, which
77+
# compiles the Linux browser secret helper and needs libsecret.
78+
- name: Check bundle-only build support
79+
id: bundle_build
80+
run: |
81+
script="$(node -p "require('./package.json').scripts['build:desktop:bundle'] ? 'build:desktop:bundle' : 'build:desktop'")"
82+
echo "script=$script" >> "$GITHUB_OUTPUT"
83+
84+
- if: steps.bundle_build.outputs.script == 'build:desktop'
85+
uses: ./.github/actions/setup-apt-mirrors
7786

7887
- name: Install browser secret helper build libraries
88+
if: steps.bundle_build.outputs.script == 'build:desktop'
7989
run: sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config
8090

81-
# desktop-macos-preview-publish.yml packages this bundle as the preview channel.
91+
# desktop-macos-preview-publish.yml packages this bundle as the preview
92+
# channel. The Linux browser secret helper is not part of a macOS app.
8293
- name: Build JS bundle
8394
env:
8495
T3CODE_TELEMETRY_CHANNEL: ${{ github.repository == 'pingdotgg/t3code' && 'preview' || 'dev' }}
85-
run: vp run build:desktop
96+
run: vp run ${{ steps.bundle_build.outputs.script }}
8697

8798
# Same layout as release.yml's js-bundle so release-desktop.yml can
8899
# package it unchanged.

‎.github/workflows/mobile-eas-production.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ jobs:
215215
git config user.name "${APP_SLUG}[bot]"
216216
git config user.email "${user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
217217
git add apps/mobile/app.config.ts
218-
git commit \
218+
git commit --no-verify \
219219
-m "chore(mobile): bump app version to $RELEASE_VERSION" \
220220
-m "Co-authored-by: codex <codex@users.noreply.github.com>"
221221
git push origin "HEAD:refs/heads/${GITHUB_REF_NAME}"

0 commit comments

Comments
 (0)