Skip to content

Commit 6868dff

Browse files
committed
chore: merge main with upstream lint fix
2 parents 486f6f5 + 68d5b7a commit 6868dff

2,042 files changed

Lines changed: 27483 additions & 20940 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.

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

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,24 @@
1-
// Decides which CI jobs a change needs. Prints `key=value` lines for
2-
// $GITHUB_OUTPUT; a job runs unless its key is "false".
3-
//
4-
// node ci-changes.cjs --paths <file> gate by the listed paths
5-
// node ci-changes.cjs --paths <file> --full run every Linux job, gate only the macOS lint
6-
// node ci-changes.cjs changed paths unknown: run everything
7-
//
8-
// scripts/check-changed.ts requires the same decisions so local runs match CI.
9-
//
10-
// Every changed path maps to workspace packages, which then pull in their
11-
// dependents from package.json. A path this file does not recognize runs
12-
// everything, so a new root file or directory can only cost minutes.
1+
// Unknown paths run every job; recognized packages pull in their dependents.
2+
// scripts/check-changed.ts shares these decisions so local checks match CI.
133
const fs = require("node:fs");
144
const path = require("node:path");
155

166
const root = path.resolve(__dirname, "../..");
177

18-
// Never read by a build, typecheck, or test. Lint still formats them.
198
const INERT = [
209
/^docs\//,
2110
/^\.(agents|cursor|vscode|devcontainer|macroscope|repos)\//,
2211
/^[^/]+\.md$/,
2312
/^LICENSE$/,
2413
];
2514

26-
// Run everything: the root vite.config.ts loads the first as setup for every
27-
// package's tests, and the vendored mobile tarballs are installed dependencies.
15+
// Shared test setup and vendored mobile dependencies affect every package.
2816
const RUNS_EVERYTHING = [
2917
/^packages\/shared\/src\/(HostProcess|testing\/longTempDir)\.ts$/,
3018
/^apps\/mobile\/deps\//,
3119
];
3220

33-
// Paths outside a package, or files inside one that other packages read
34-
// through relative imports rather than a package.json dependency.
21+
// Includes cross-package reads absent from package.json dependencies.
3522
const EXTRA_OWNERS = [
3623
// Vite configs and tsconfigs of these apps import scripts/lib directly.
3724
[/^scripts\/lib\//, ["@t3tools/desktop", "@t3tools/mobile", "@t3tools/web", "t3"]],
@@ -43,9 +30,7 @@ const EXTRA_OWNERS = [
4330
];
4431
const RUST = /^native\/(resource-monitor|kde-snap-shot|hyprland-snap-shot)\//;
4532

46-
// Tests that read another package's files without declaring it. The scripts
47-
// tests read app manifests, assets, and sources (cursor-sdk-packaging,
48-
// third-party-licenses, brand-assets, build-desktop-artifact).
33+
// These tests read other packages without declaring dependencies.
4934
const TEST_ONLY_DEPS = {
5035
"@t3tools/provider-pi": ["@t3tools/client-runtime"],
5136
"@t3tools/scripts": [
@@ -56,17 +41,12 @@ const TEST_ONLY_DEPS = {
5641
"@t3tools/provider-cursor",
5742
],
5843
};
59-
// Declared dependencies that only feed a build step: the server bundles the
60-
// built web app (apps/server/vite.config.ts) but never imports it.
44+
// The server bundles the web build without importing it.
6145
const BUILD_ONLY_DEPS = { t3: ["@t3tools/web"] };
6246

63-
// Sources scripts/mobile-native-static-check.ts lints, plus the tool and rule
64-
// configuration that decides how it lints them, plus the root package.json
65-
// that defines the lint:mobile command.
6647
const MOBILE_NATIVE =
6748
/^apps\/mobile\/.*\.(swift|kt|kts)$|^apps\/mobile\/(\.swiftlint\.yml|detekt\.yml|\.editorconfig|Brewfile)$|^scripts\/mobile-native-static-check\.ts$|^package\.json$|^\.github\/workflows\/ci\.yml$|^\.github\/scripts\/ci-changes\.cjs$|^\.github\/actions\/ci-changes\//;
6849

69-
// Jobs that test every package except these, which have jobs of their own.
7050
const OWN_TEST_JOB = new Set(["t3", "@t3tools/web", "@t3tools/monorepo"]);
7151

7252
function readWorkspace() {
@@ -108,8 +88,7 @@ function readWorkspace() {
10888
return packages;
10989
}
11090

111-
// Returns the packages a path touches, [] for an inert path, or null when the
112-
// path is not understood and everything must run.
91+
// [] means inert; null means unknown and requires every job.
11392
function ownersOf(file, packages) {
11493
if (INERT.some((pattern) => pattern.test(file))) return [];
11594
// A manifest can change dependencies or versions other packages read.
@@ -148,7 +127,6 @@ function decide(files, packages, full) {
148127
if (everything) {
149128
affected = all;
150129
} else {
151-
// Add dependents until nothing changes.
152130
let grew = true;
153131
while (grew) {
154132
grew = false;

‎.github/scripts/mirror-play-apk.cjs‎

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
// Publishes closed-testing betas, or downloads the internal APK for a normal
2-
// nightly release. Play generates and signs the APK from the
3-
// uploaded bundle with the app signing key, so it carries the same signature
4-
// as the Play Store install. Run by .github/workflows/mobile-android-apk.yml.
1+
// Play signs generated APKs with the app signing key, matching Play Store installs.
52
const { execFileSync } = require("node:child_process");
63
const crypto = require("node:crypto");
74
const fs = require("node:fs");
@@ -50,10 +47,7 @@ async function play(token, method, url) {
5047
return response;
5148
}
5249

53-
// Highest version code the track serves, with its release name. Play names a
54-
// release after the bundle's versionName unless the uploader sets one. This
55-
// endpoint reads without opening an edit; an edit would invalidate any open
56-
// EAS Submit edit made with the same service account.
50+
// Opening an edit would invalidate any EAS Submit edit using the same service account.
5751
async function newestTrackBuild(token, appUrl, trackName) {
5852
const { releases = [] } = await (
5953
await play(token, "GET", `${appUrl}/tracks/${trackName}/releases`)
@@ -82,8 +76,7 @@ function readRelease(tag) {
8276
}
8377
}
8478

85-
// Download to a temporary directory so a failed request cannot leave a partial
86-
// APK among the release assets.
79+
// Stage downloads so failed requests cannot leave partial release assets.
8780
async function downloadApk({ token, appUrl, build, apkName }) {
8881
const generated = await (
8982
await play(token, "GET", `${appUrl}/generatedApks/${build.versionCode}`)

‎.github/scripts/stage-preview-bundle.py‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
"server/dist/client/index.html",
1313
"desktop/dist-electron/main.cjs",
1414
}
15-
# The current bundle is about 32 MiB compressed. Bound extraction on the
16-
# trusted runner even when the PR replaces the uploader entirely.
15+
# Bound trusted-runner extraction even when a PR replaces the uploader.
1716
MAX_ARCHIVE_BYTES = 512 * 1024 * 1024
1817
MAX_EXPANDED_BYTES = 2 * 1024 * 1024 * 1024
1918
MAX_ENTRIES = 50_000
@@ -58,9 +57,7 @@ def stage_bundle(archive: Path, destination: Path):
5857
files.add(name)
5958
if not REQUIRED_FILES <= files:
6059
raise ValueError("Preview bundle is missing required entry points")
61-
# Validate all names before writing anything. This is a fresh directory
62-
# outside the checkout; neither pre-existing links nor trusted files
63-
# can be followed or overwritten. ZIP permissions are never restored.
60+
# Validate before writing into a fresh directory so existing links/files cannot be followed or overwritten.
6461
destination.mkdir(parents=True, exist_ok=False)
6562
for entry in entries:
6663
target = destination / entry.filename

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,7 @@ async function resolve({ github, context, core }) {
294294

295295
const sourceArtifacts = await artifactsForRun(github, owner, repo, source.id);
296296
const sourceArtifact = findResultArtifact(sourceArtifacts);
297-
// CI requires the artifact whenever the server tests run, so a passing run
298-
// without one skipped them because the PR cannot affect the server.
297+
// Successful server tests require this artifact; its absence means CI skipped them.
299298
if (!sourceArtifact && source.conclusion === "success") {
300299
core.info("CI skipped the server tests for this change; nothing to report.");
301300
core.setOutput("publish", "false");

‎.pnpmfile.cjs‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
// Windows WSL dev mode runs the server under Linux from the same node_modules
2-
// as the Windows client, so Windows installs also need Linux x64 glibc native
3-
// modules. Other platforms install only their own binaries; setting this
4-
// everywhere added ~2.2 GB of foreign binaries to every macOS install.
5-
// Release scripts stage their own installs with explicit architectures.
1+
// Windows installs need Linux x64 glibc binaries because WSL shares node_modules.
2+
// Keep other platforms native; release scripts set their own architectures.
63
module.exports = {
74
hooks: {
85
// `typescript` is @tsc-rs/typescript (the catalog entry). Its npm version (0.8.x) is outside

‎AGENTS.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ Most code changes do not need an internal documentation change. Agents can read
153153

154154
- `docs/internals/` is for architectural decisions and their reasons, constraints that span components, and implementation traps that are hard to discover from the source. Before adding a paragraph, ask what a maintainer would get wrong without it. If reading the relevant code answers the question, leave it out.
155155
- Do not document every feature, enumerate fields or methods, narrate control flow, maintain file catalogs, or append PR summaries. Types, tests, and code already record the implementation. The glossary defines shared vocabulary; it is not a feature index.
156-
- Keep a local implementation explanation in a nearby code comment. Use an internal doc when the reasoning crosses boundaries or needs context the code cannot carry well. Link to the relevant source instead of copying it.
156+
- A local reason the code can't show goes in a short nearby code comment. Use an internal doc when the reasoning crosses boundaries or needs context the code cannot carry well. Link to the relevant source instead of copying it.
157157
- When a documented decision or constraint changes, rewrite or remove the affected text. Do not append another account of the new behavior. A new internal page needs a distinct, durable reason to exist.
158158
- `docs/user/` helps users accomplish tasks. Give each major feature a concise section explaining what it does, how to start, and anything unintuitive. A settings path is useful; descriptions of visible buttons, icons, layouts, animations, or every UI state are not. Before adding text, ask what task or decision it helps the user with.
159159
- Keep user docs in the shipped product's voice, without implementation details or contributor tooling. Update the relevant feature section when how to use it changes. A UI tweak does not need a documentation entry, and a new control does not need its own page.
@@ -193,7 +193,7 @@ Architecture and its constraints: `docs/internals/overview.md`. Glossary: `docs/
193193
Named `Effect.fn` creates a span; the unnamed form does not. Preserve existing span names and
194194
options, and pass combinators as additional function-builder arguments.
195195
- Inferred types over annotations. `any` is the enemy.
196-
- Comments say why: a constraint, an external quirk, or an invariant the code can't show. Don't restate names or signatures, narrate steps, or record history. `t3code/no-low-value-comments` catches the mechanical cases.
196+
- Default to no comment. Write one only for a constraint, an external quirk, or an invariant the code can't show, in one line where you can and four at most. Don't restate names or signatures, narrate steps, record history, or explain the fix you just made; the PR carries that. `t3code/no-low-value-comments` enforces the length cap and the mechanical cases.
197197
- Our users drive agents all day and notice a dropped frame, a lying spinner, and a stale label. No continuously repainting animations; they peg the GPU on high-refresh displays.
198198
- If a rule here fights the task in front of you, say so loudly and get a human sign-off before breaking it.
199199

‎apps/desktop/scripts/electron-launcher.mjs‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,7 @@ function buildMacLauncher(electronBinaryPath) {
372372
JSON.stringify(currentMetadata) === JSON.stringify(expectedMetadata)
373373
) {
374374
if (isDevelopment) {
375-
// The launcher also handles protocol activations outside the dev runner,
376-
// so refresh its fallback environment on every launch. Never let a value
377-
// captured by an older parent app override the live dev-runner environment.
375+
// Protocol activations bypass the dev runner, so refresh the fallback environment on every launch.
378376
writeDevelopmentEnvironmentScript();
379377
if (writeDevelopmentLauncherScript(launcherBinaryPath, runtimeElectronBinaryPath)) {
380378
signMacLauncherBundle(targetAppBundlePath);
@@ -385,10 +383,7 @@ function buildMacLauncher(electronBinaryPath) {
385383
}
386384

387385
NodeFS.rmSync(targetAppBundlePath, { recursive: true, force: true });
388-
// verbatimSymlinks keeps the framework's relative symlinks intact
389-
// (e.g. Resources -> Versions/Current/Resources). Without it cpSync
390-
// rewrites them to absolute paths into node_modules, which escape the
391-
// bundle and crash sandboxed helper processes (icudtl.dat not found).
386+
// Without verbatimSymlinks, cpSync makes framework symlinks point outside the bundle and crashes helpers.
392387
NodeFS.cpSync(sourceAppBundlePath, targetAppBundlePath, {
393388
recursive: true,
394389
verbatimSymlinks: true,
@@ -400,10 +395,7 @@ function buildMacLauncher(electronBinaryPath) {
400395
);
401396
patchHelperBundleInfoPlists(targetAppBundlePath);
402397
if (isDevelopment) {
403-
// Launching the node_modules copy makes macOS associate the process (and Dock label) with
404-
// Electron.app even though this bundle's Info.plist has the T3 Code name. Its conventional
405-
// executable name also keeps Electron's default-app runtime in development mode instead of
406-
// making app.isPackaged report true.
398+
// Electron.app's executable name keeps default-app mode active without making app.isPackaged true.
407399
writeDevelopmentEnvironmentScript();
408400
writeDevelopmentLauncherScript(launcherBinaryPath, runtimeElectronBinaryPath);
409401
}

‎apps/desktop/src/app/DesktopApp.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,7 @@ const scopedProgram = Effect.scoped(
339339
const rendererHistory = yield* DesktopRendererHistory.DesktopRendererHistory;
340340

341341
yield* Effect.addFinalizer(() =>
342-
// Stop every backend in the pool, not just the primary. The
343-
// electronApp.quit() path can race ahead of the layer-scope
344-
// cascade, so leaving the WSL instance for its parent scope
345-
// finalizer means it gets hard-killed by the OS instead of
346-
// receiving SIGTERM + grace.
342+
// Quit can outrun layer finalizers; stop pooled backends here so they receive SIGTERM before OS teardown.
347343
stopAllPoolInstances().pipe(
348344
Effect.ensuring(rendererHistory.shutdown),
349345
Effect.ensuring(shutdown.markComplete),

‎apps/desktop/src/app/DesktopAppActivation.ts‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,7 @@ export async function startDesktopAppControlServer(input: {
186186
server.listen(address);
187187
});
188188

189-
// Closing a Unix socket server unlinks the path it was bound to, even when
190-
// another app's socket lives there now. Bind a staging path and move it onto
191-
// the address instead, so a later close only unlinks the staging path, which
192-
// is already gone.
189+
// Closing unlinks the original bind path, even if another app replaced it. Bind a staging path first.
193190

194191
const bindUnix = async (directory: string, mode: "take-over" | "claim-free") => {
195192
const staging = NodePath.join(directory, `${NodeCrypto.randomBytes(6).toString("hex")}.tmp`);
@@ -213,7 +210,6 @@ export async function startDesktopAppControlServer(input: {
213210
let server: NodeNet.Server;
214211
let inode: number | null = null;
215212
if (input.directory === null) {
216-
// Named pipes close with the app that owns them, so no other app can remove this one.
217213
server = await listen(input.address);
218214
} else {
219215
await prepareUnixDirectory({ directory: input.directory, userId: input.userId });
@@ -222,10 +218,10 @@ export async function startDesktopAppControlServer(input: {
222218

223219
let closed = false;
224220
const reclaimOnce = async () => {
225-
// Never replace a socket that exists, so two apps cannot trade the path back and forth.
221+
// Replacing an existing socket would let two apps trade the path indefinitely.
226222
if (closed || input.directory === null || (await inodeAt(input.address)) !== null) return;
227223
if (await prepareUnixDirectory({ directory: input.directory, userId: input.userId })) {
228-
// A watch follows the directory's inode, so a recreated directory needs a new one.
224+
// Directory watches follow inodes, so recreate the watch after directory replacement.
229225
watchDirectory(input.directory);
230226
}
231227
const next = await bindUnix(input.directory, "claim-free").catch(
@@ -269,7 +265,7 @@ export async function startDesktopAppControlServer(input: {
269265
close: async () => {
270266
if (closed) return;
271267
closed = true;
272-
// A running reclaim can replace the watcher, so close the watcher after it.
268+
// Reclaim can replace the watcher; close it afterward.
273269
await pendingReclaim;
274270
watcher?.close();
275271
for (const socket of sockets) socket.destroy();

‎apps/desktop/src/app/DesktopAppIdentity.ts‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const normalizeCommitHash = (value: string): Option.Option<string> => {
3838
: Option.none();
3939
};
4040

41-
/** @public Service construction is part of the canonical Effect module API. */
41+
/** @public */
4242
export const make = Effect.gen(function* () {
4343
const assets = yield* DesktopAssets.DesktopAssets;
4444
const electronApp = yield* ElectronApp.ElectronApp;
@@ -91,9 +91,7 @@ export const make = Effect.gen(function* () {
9191

9292
const configure = Effect.gen(function* () {
9393
const commitHash = yield* resolveAboutCommitHash;
94-
// Electron removes spaces from this name to build the native User-Agent
95-
// product token, but leaves parentheses intact. Keep the runtime name valid
96-
// without rewriting preview sessions (which breaks Turnstile, #7110).
94+
// Electron strips spaces but keeps parentheses in its User-Agent token, breaking Turnstile in preview sessions.
9795
yield* electronApp.setName(
9896
`${environment.branding.baseName} ${environment.branding.stageLabel}`,
9997
);
@@ -107,9 +105,7 @@ export const make = Effect.gen(function* () {
107105
yield* electronApp.setAppUserModelId(environment.appUserModelId);
108106
}
109107

110-
// Unpackaged runs only. A packaged bundle already carries its icon in
111-
// Info.plist, so setting the dock tile again changes nothing except to
112-
// overwrite a custom icon the user attached to the app themselves.
108+
// Packaged bundles carry their icon in Info.plist; setting it again overwrites the user's custom icon.
113109
if (environment.platform === "darwin" && !environment.isPackaged) {
114110
const iconPaths = yield* assets.iconPaths;
115111
yield* Option.match(iconPaths.png, {

0 commit comments

Comments
 (0)