Skip to content

Commit fa3d27b

Browse files
Merge commit 'f09b7d2631fc7e32ce90548c7ff01ead2aa7828c' into takeover/8668
2 parents 3c61e6b + f09b7d2 commit fa3d27b

1,157 files changed

Lines changed: 75794 additions & 32748 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/actions/setup-ci-deps/action.yml‎

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,34 @@ runs:
1818
path: ~/.vite-plus
1919
key: vite-plus-home-v1-${{ runner.os }}-${{ runner.arch }}-${{ steps.vp.outputs.version }}
2020

21+
- name: Setup Vite+
22+
uses: voidzero-dev/setup-vp@v1
23+
with:
24+
node-version-file: package.json
25+
cache: false
26+
run-install: false
27+
28+
- name: Resolve pnpm store path
29+
id: pnpm_store
30+
shell: bash
31+
run: |
32+
store_path="$(vp pm cache dir)"
33+
echo "path=$store_path" >> "$GITHUB_OUTPUT"
34+
35+
# setup-vp's shared cache key ignores install filters. Keep full installs in a
36+
# separate namespace, including fallback restores.
2137
# The pnpm store stays a cache tarball on the runner's own disk. A store on a
2238
# Blacksmith sticky disk mounts in under a second, but pnpm then copies every
2339
# package across filesystems instead of hard-linking it: install took 28-49s
2440
# against 9s plus an 11s restore.
25-
- name: Setup Vite+
26-
uses: voidzero-dev/setup-vp@v1
41+
- name: Cache full pnpm store
42+
uses: actions/cache@v6
2743
with:
28-
node-version-file: package.json
29-
cache: true
30-
run-install: true
44+
path: ${{ steps.pnpm_store.outputs.path }}
45+
key: pnpm-full-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml', 'package.json') }}
46+
restore-keys: |
47+
pnpm-full-v1-${{ runner.os }}-${{ runner.arch }}-
48+
49+
- name: Install dependencies
50+
shell: bash
51+
run: vp install

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const EXTRA_OWNERS = [
3636
// scripts/build-desktop-artifact.ts reads the GNOME extension manifest.
3737
[/^apps\/desktop\/gnome-extension\//, ["@t3tools/scripts"]],
3838
[/^native\/browser-secret\//, ["@t3tools/desktop"]],
39+
[/^native\/kde-snap-shot\//, ["@t3tools/desktop"]],
3940
[/^native\/libghostty-vt\//, ["@t3tools/web"]],
4041
];
4142
const RUST = /^native\/(resource-monitor|kde-snap-shot|hyprland-snap-shot)\//;
@@ -112,10 +113,10 @@ function ownersOf(file, packages) {
112113
// A manifest can change dependencies or versions other packages read.
113114
if (path.posix.basename(file) === "package.json") return null;
114115
if (RUNS_EVERYTHING.some((pattern) => pattern.test(file))) return null;
116+
const extra = EXTRA_OWNERS.flatMap(([pattern, names]) => (pattern.test(file) ? names : []));
115117
// scripts/build-desktop-artifact.test.ts reads the crates' sources.
116-
if (RUST.test(file)) return ["@t3tools/scripts"];
118+
if (RUST.test(file)) return ["@t3tools/scripts", ...extra];
117119

118-
const extra = EXTRA_OWNERS.flatMap(([pattern, names]) => (pattern.test(file) ? names : []));
119120
const owner = packages
120121
.filter((pkg) => file.startsWith(`${pkg.dir}/`))
121122
.sort((a, b) => b.dir.length - a.dir.length)[0];

‎.github/workflows/ci.yml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,6 @@ jobs:
482482
!/apps/mobile/modules/t3-terminal/Vendor/**/*.a
483483
sparse-checkout-cone-mode: false
484484

485-
# A full install: a filtered one that misses the cache first saves its
486-
# partial store under the shared lockfile key for every later job.
487485
- name: Setup Vite+
488486
uses: ./.github/actions/setup-ci-deps
489487

‎.github/workflows/deploy-relay.yml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
deploy_relay:
2828
name: Deploy production relay
2929
# A manual run from another branch would deploy that branch to production.
30-
if: github.ref == 'refs/heads/main'
30+
if: github.repository == 'pingdotgg/t3code' && github.ref == 'refs/heads/main'
3131
runs-on: blacksmith-8vcpu-ubuntu-2404
3232
timeout-minutes: 15
3333
environment:
@@ -41,6 +41,8 @@ jobs:
4141
RELAY_TUNNEL_ZONE_NAME: ${{ vars.RELAY_TUNNEL_ZONE_NAME }}
4242
RELAY_TUNNEL_CLEANUP_MODE: ${{ vars.RELAY_TUNNEL_CLEANUP_MODE }}
4343
RELAY_LEGACY_TUNNEL_CLEANUP_MODE: ${{ vars.RELAY_LEGACY_TUNNEL_CLEANUP_MODE }}
44+
RELAY_ALERT_NOTIFIER_ID: ${{ vars.RELAY_ALERT_NOTIFIER_ID }}
45+
RELAY_WARNING_NOTIFIER_ID: ${{ vars.RELAY_WARNING_NOTIFIER_ID }}
4446
CLERK_PUBLISHABLE_KEY: ${{ vars.CLERK_PUBLISHABLE_KEY }}
4547
CLERK_JWT_AUDIENCE: ${{ vars.CLERK_JWT_AUDIENCE }}
4648
APNS_ENVIRONMENT: ${{ vars.APNS_ENVIRONMENT }}

‎.github/workflows/mobile-android-apk.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ concurrency:
1515
jobs:
1616
mirror:
1717
name: Mirror beta APK
18+
if: github.repository == 'pingdotgg/t3code'
1819
runs-on: blacksmith-2vcpu-ubuntu-2404
1920
timeout-minutes: 10
2021
permissions:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ concurrency:
7575
jobs:
7676
production:
7777
name: EAS ${{ inputs.profile || 'production' }} ${{ github.event_name == 'push' && 'auto' || inputs.mode }}
78+
if: github.repository == 'pingdotgg/t3code'
7879
runs-on: blacksmith-8vcpu-ubuntu-2404
7980
permissions:
8081
contents: read

‎.github/workflows/publish-aur.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ concurrency:
3737
jobs:
3838
publish:
3939
name: Validate and publish
40+
if: github.repository == 'pingdotgg/t3code'
4041
runs-on: blacksmith-8vcpu-ubuntu-2404
4142
timeout-minutes: 30
4243
container:

‎.github/workflows/release.yml‎

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
# have already run. Scheduled runs also decide here whether a nightly is due.
5151
resolve_commit:
5252
name: Resolve release commit
53+
if: github.repository == 'pingdotgg/t3code'
5354
runs-on: blacksmith-8vcpu-ubuntu-2404
5455
timeout-minutes: 5
5556
outputs:
@@ -128,12 +129,8 @@ jobs:
128129
!/.repos/
129130
sparse-checkout-cone-mode: false
130131

131-
- name: Setup Vite+
132-
uses: voidzero-dev/setup-vp@v1
133-
with:
134-
node-version-file: package.json
135-
cache: true
136-
run-install: true
132+
- name: Setup dependencies
133+
uses: ./.github/actions/setup-ci-deps
137134
env:
138135
pnpm_config_cache_dir: ${{ runner.temp }}/pnpm-metadata
139136

@@ -246,12 +243,8 @@ jobs:
246243
!/.repos/
247244
sparse-checkout-cone-mode: false
248245

249-
- name: Setup Vite+
250-
uses: voidzero-dev/setup-vp@v1
251-
with:
252-
node-version-file: package.json
253-
cache: true
254-
run-install: true
246+
- name: Setup dependencies
247+
uses: ./.github/actions/setup-ci-deps
255248

256249
- name: Ensure Electron runtime is installed
257250
run: vp run --filter @t3tools/desktop ensure:electron
@@ -280,12 +273,8 @@ jobs:
280273
!/.repos/
281274
sparse-checkout-cone-mode: false
282275

283-
- name: Setup Vite+
284-
uses: voidzero-dev/setup-vp@v1
285-
with:
286-
node-version-file: package.json
287-
cache: true
288-
run-install: true
276+
- name: Setup dependencies
277+
uses: ./.github/actions/setup-ci-deps
289278

290279
- name: Ensure Electron runtime is installed
291280
run: vp run --filter @t3tools/desktop ensure:electron
@@ -324,12 +313,8 @@ jobs:
324313
!/.repos/
325314
sparse-checkout-cone-mode: false
326315

327-
- name: Setup Vite+
328-
uses: voidzero-dev/setup-vp@v1
329-
with:
330-
node-version-file: package.json
331-
cache: true
332-
run-install: true
316+
- name: Setup dependencies
317+
uses: ./.github/actions/setup-ci-deps
333318

334319
# No Electron setup here: `t3` (apps/server) has no Electron dependency
335320
# and none of its tests touch the runtime. Only the non-server `test`

‎.macroscope/check-run-agents/effect-service-conventions.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ Review changed TypeScript for the conventions below. They apply when a pull requ
4444
- Use plain `make` and `layer` in a module named for its implementation (`BunPtyAdapter.ts`). Keep implementation-specific names when one abstract port module holds several implementations (`makeCloudflaredRelayClient`, `layerCloudflared` in `RelayClient.ts`). `infra/relay/src/db.ts` may keep its inline `Layer.succeed(RelayDb, db)`.
4545
- When a service moves, delete the old files and update every consumer, including orchestration, MCP, tests, and integration harnesses. Do not leave compatibility re-export shims.
4646

47+
## Effect functions and tracing
48+
49+
- Reusable functions use named `Effect.fn("Service.operation")`, not functions wrapping
50+
`Effect.gen`. Inline programs, callbacks, and layer construction can keep `Effect.gen`.
51+
- Named `Effect.fn` creates a span; the unnamed form does not. Default to named spans for service
52+
operations and I/O. `Effect.fnUntraced` is deliberate for per-chunk/per-event work, tight loops,
53+
or helpers duplicating an existing tracing boundary; require a nearby reason for new uses.
54+
- Preserve existing span names/options and avoid adding duplicate spans. Pass combinators after
55+
the generator body; transforms receive the original function arguments after the effect.
56+
- Preserve generic signatures, laziness, resource scope, and interruption behavior. An explicit
57+
generator return type is `Effect.fn.Return<A, E, R>`.
58+
4759
## Dependency acquisition and runtime boundaries
4860

4961
- Production service construction acquires its Effect dependencies from the environment with `yield* Foo.Foo`, and `make`/`layer` types expose those requirements. Flag a factory that takes `Foo["Service"]` (or an object of Effect-returning methods) as a parameter when that value is a service dependency. Passing service instances explicitly in tests is fine; passing pure configuration, immutable domain values, or deliberate callback strategies is not service injection.
@@ -57,6 +69,7 @@ Review changed TypeScript for the conventions below. They apply when a pull requ
5769
- Define service failures with `Schema.TaggedError` and structured attributes: operation or stage, resource path or entity identifier, normalized category or status. Derive `message` from those attributes only. Never derive it from `cause`, `cause.message`, or a stringified defect, and do not add a `detail` field that copies `cause.message`.
5870
- When wrapping a real failure, keep the immediate underlying error as `cause` so the chain and stack survive. Make `cause` required if every construction wraps a failure. Pure validation or domain errors created without an underlying failure need no cause.
5971
- Keep attributes and log annotations safe and bounded: no raw wire payloads, command arguments or output, signed URLs, credentials, query strings, or arbitrary defect text. Preserve the exact value only as `cause`; expose normalized categories, lengths, counts, and safe URL protocol or hostname where useful.
72+
The documented exception is `DeviceBootError.diagnostics`: device hub launch commands and failure text are intentionally exposed to authorized device users and agents, capped at 2,000 characters and included in the error message. Do not apply this exception to other service errors.
6073
- At a translation boundary, pass through an already structured domain error when it is part of the target error channel; wrap only unknown or lower-level failures. Map failures where the context is known instead of wrapping a whole multi-step pipeline in one generic error.
6174
- Do not encode the same distinction twice with both a specific error tag and a single-value `operation`, `reason`, `kind`, or `phase` literal. Split into separate error classes when a discriminator drives caller control flow or the user-facing message; a discriminator used only for diagnostics may stay a field. Caller-visible messages exposed through HTTP, RPC, persisted state, or UI are behavior and must survive a structural refactor.
6275
- Do not add a helper whose only behavior is `(...args) => new SomeError({ ...args })`. Construct the error at the failure boundary. Keep a mapper only when it performs real normalization, passes through domain errors, or adds reusable context; when such a mapper belongs to the target error type, prefer a static factory on that class.

‎AGENTS.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ Architecture and its constraints: `docs/internals/overview.md`. Glossary: `docs/
153153
- Client mutations use `createEnvironmentRpcCommand`. Add protected methods to `CLIENT_GUARDED_RPC_SCOPES` in contracts and use the command's `permissionAtom` for UI availability. Grants are checked at execution against the destination environment; the server remains authoritative. Keep raw RPC clients inside `rpc/`, and extend the permission behavior tests when adding a protected method.
154154
- Server features are services; transports stay thin. A `ws.ts` RPC handler, HTTP route, or MCP tool decodes input, calls one service method, and maps errors. See [Effect services](docs/internals/effect-services.md).
155155
- `apps/web/src/components/ui` exports own their look. Pick a `variant` or `size`; do not restyle one with `className`. If none fits and the look is a generic concept, add a variant to the component; a look that belongs to one feature stays in that feature's own component, not in `components/ui`. Layout classes (width, flex, margin, position) belong on the parent. `shadcn/no-restyle` fails lint on violations. See [Web UI](docs/internals/web-ui.md).
156+
- Reusable Effect functions use `Effect.fn("Service.operation")` with a stable span name, not a
157+
function wrapping `Effect.gen`. Keep `Effect.gen` for inline programs and layer construction.
158+
Use `Effect.fnUntraced` only when spans would be too frequent (stream chunks, per-event
159+
projection, tight loops) or duplicate an existing tracing boundary; explain that choice nearby.
160+
Named `Effect.fn` creates a span; the unnamed form does not. Preserve existing span names and
161+
options, and pass combinators as additional function-builder arguments.
156162
- Inferred types over annotations. `any` is the enemy.
157163
- 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.
158164
- 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.

0 commit comments

Comments
 (0)