authorgravatar for gabe@editmypodcast.agencyGabe Fletcher <gabe@editmypodcast.agency> 2026-08-07 00:14:50-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-06 21:14:50-07:00
logae7b27de824e890f2cdfc85018fc9301e7d45022
tree41805d63f3272ede48240845d7cfa8f89bdac793
parent6b73b3defe1dfb365de3b7bbb97ca56a26b50a43
signature Signed by PGP key B5690EEEBB952194

fix: prevent reconnect loops during server stalls (#5561)

Co-authored-by: t3-turbo-simulation <simulation@t3turbo.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Theo Browne <me@t3.gg>

13 files changed, 637 insertions(+), 235 deletions(-)

apps/server/src/process/externalLauncher.test.ts+61
...@@ -7,6 +7,7 @@ import * as Layer from "effect/Layer";...@@ -7,6 +7,7 @@ import * as Layer from "effect/Layer";
7import * as Path from "effect/Path";7import * as Path from "effect/Path";
8import * as Sink from "effect/Sink";8import * as Sink from "effect/Sink";
9import * as Stream from "effect/Stream";9import * as Stream from "effect/Stream";
10import * as TestClock from "effect/testing/TestClock";
10import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";11import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
1112
12import { HostProcessPlatform } from "@t3tools/shared/hostProcess";13import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
...@@ -155,6 +156,66 @@ it.effect("discovers editors through the service API", () =>...@@ -155,6 +156,66 @@ it.effect("discovers editors through the service API", () =>
155 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),156 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
156);157);
157158
159it.effect("memoizes editor discovery and refreshes after the cache window", () => {
160 let statCalls = 0;
161 const fileInfo = { type: "File" } as FileSystem.File.Info;
162 const launcherLayer = ExternalLauncher.layer.pipe(
163 Layer.provide(
164 Layer.mergeAll(
165 FileSystem.layerNoop({
166 stat: () =>
167 Effect.sync(() => {
168 statCalls += 1;
169 return fileInfo;
170 }),
171 }),
172 Path.layer,
173 Layer.succeed(
174 ChildProcessSpawner.ChildProcessSpawner,
175 ChildProcessSpawner.make(() => Effect.sync(() => makeMockDetachedHandle())),
176 ),
177 ),
178 ),
179 );
180
181 return Effect.gen(function* () {
182 const launcher = yield* ExternalLauncher.ExternalLauncher;
183
184 const first = yield* launcher.resolveAvailableEditors();
185 assert.equal(first.includes("vscode"), true);
186 const statCallsAfterFirstScan = statCalls;
187 assert.isAbove(statCallsAfterFirstScan, 0);
188
189 // Past the shared command-resolution cache TTL (30s) but within the
190 // discovery cache window: the memoized set is reused without any scan.
191 yield* TestClock.adjust("31 seconds");
192 const second = yield* launcher.resolveAvailableEditors();
193 assert.deepEqual([...second], [...first]);
194 assert.equal(statCalls, statCallsAfterFirstScan);
195
196 // Past the discovery cache window the next call rescans.
197 yield* TestClock.adjust("30 seconds");
198 yield* launcher.resolveAvailableEditors();
199 assert.isAbove(statCalls, statCallsAfterFirstScan);
200 }).pipe(
201 Effect.provide(
202 Layer.mergeAll(
203 launcherLayer,
204 Layer.succeed(HostProcessPlatform, "win32"),
205 ConfigProvider.layer(
206 ConfigProvider.fromEnv({
207 env: {
208 PATH: "C:\\t3-editor-discovery-cache-test",
209 PATHEXT: ".COM;.EXE;.BAT;.CMD",
210 },
211 }),
212 ),
213 TestClock.layer(),
214 ),
215 ),
216 );
217});
218
158it.effect("rejects unknown editors through the service API", () =>219it.effect("rejects unknown editors through the service API", () =>
159 Effect.gen(function* () {220 Effect.gen(function* () {
160 const launcher = yield* ExternalLauncher.ExternalLauncher;221 const launcher = yield* ExternalLauncher.ExternalLauncher;
apps/server/src/process/externalLauncher.ts+12-1
...@@ -298,6 +298,12 @@ const resolveAvailableEditors = Effect.fn("externalLauncher.resolveAvailableEdit...@@ -298,6 +298,12 @@ const resolveAvailableEditors = Effect.fn("externalLauncher.resolveAvailableEdit
298 return yield* buildAvailableEditors(platform, env);298 return yield* buildAvailableEditors(platform, env);
299});299});
300300
301// Editor discovery walks PATH for every known editor and runs for every
302// client connect (the server config embeds the available editors). Memoize
303// the discovered set for a bounded window so repeat connects skip even the
304// per-command cache lookups in @t3tools/shared/shell.
305const EDITOR_DISCOVERY_CACHE_TTL = "60 seconds";
306
301/**307/**
302 * ExternalLauncher - Service tag for browser/editor launch operations.308 * ExternalLauncher - Service tag for browser/editor launch operations.
303 */309 */
...@@ -443,8 +449,13 @@ export const make = Effect.gen(function* () {...@@ -443,8 +449,13 @@ export const make = Effect.gen(function* () {
443 Effect.provideService(Path.Path, path),449 Effect.provideService(Path.Path, path),
444 );450 );
445451
452 const cachedAvailableEditors = yield* Effect.cachedWithTTL(
453 provideCommandResolutionServices(resolveAvailableEditors()),
454 EDITOR_DISCOVERY_CACHE_TTL,
455 );
456
446 return ExternalLauncher.of({457 return ExternalLauncher.of({
447 resolveAvailableEditors: () => provideCommandResolutionServices(resolveAvailableEditors()),458 resolveAvailableEditors: () => cachedAvailableEditors,
448 launchBrowser: (target) =>459 launchBrowser: (target) =>
449 launchBrowser(target).pipe(460 launchBrowser(target).pipe(
450 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),461 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),
apps/web/src/components/ChatView.tsx+10-1
...@@ -4732,12 +4732,21 @@ function ChatViewContent(props: ChatViewProps) {...@@ -4732,12 +4732,21 @@ function ChatViewContent(props: ChatViewProps) {
4732 isSendBusy ||4732 isSendBusy ||
4733 isConnecting ||4733 isConnecting ||
4734 threadDetailLoading ||4734 threadDetailLoading ||
4735 activeEnvironmentUnavailable ||
4736 sendInFlightRef.current4735 sendInFlightRef.current
4737 ) {4736 ) {
4738 notifyDirectAnnotationAttached();4737 notifyDirectAnnotationAttached();
4739 return;4738 return;
4740 }4739 }
4740 if (activeEnvironmentUnavailable) {
4741 toastManager.add(
4742 stackedThreadToast({
4743 type: "warning",
4744 title: "Not connected: message not sent",
4745 description: "Reconnecting to the environment. Try again once it is connected.",
4746 }),
4747 );
4748 return;
4749 }
4741 if (activePendingProgress) {4750 if (activePendingProgress) {
4742 if (directAnnotation) {4751 if (directAnnotation) {
4743 notifyDirectAnnotationAttached();4752 notifyDirectAnnotationAttached();
packages/client-runtime/src/connection/supervisor.test.ts+89-23
...@@ -248,7 +248,7 @@ describe("EnvironmentSupervisor", () => {...@@ -248,7 +248,7 @@ describe("EnvironmentSupervisor", () => {
248 const firstAttempt = spans.find((span) => span.name === "relay.connection.attempt");248 const firstAttempt = spans.find((span) => span.name === "relay.connection.attempt");
249 expect(firstAttempt).toBeDefined();249 expect(firstAttempt).toBeDefined();
250250
251 yield* TestClock.adjust("1 second");251 yield* TestClock.adjust("3 seconds");
252 yield* awaitState(supervisor.state, (state) => state.phase === "connected");252 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
253253
254 const attempts = spans.filter((span) => span.name === "relay.connection.attempt");254 const attempts = spans.filter((span) => span.name === "relay.connection.attempt");
...@@ -358,7 +358,7 @@ describe("EnvironmentSupervisor", () => {...@@ -358,7 +358,7 @@ describe("EnvironmentSupervisor", () => {
358 );358 );
359 expect(yield* Ref.get(harness.prepareCount)).toBe(1);359 expect(yield* Ref.get(harness.prepareCount)).toBe(1);
360360
361 for (const [index, delay] of [1_000, 2_000, 4_000, 8_000, 16_000, 16_000].entries()) {361 for (const [index, delay] of [3_000, 4_000, 8_000, 16_000, 16_000, 16_000].entries()) {
362 yield* TestClock.adjust(delay);362 yield* TestClock.adjust(delay);
363 yield* eventuallyState(363 yield* eventuallyState(
364 supervisor.state,364 supervisor.state,
...@@ -384,7 +384,7 @@ describe("EnvironmentSupervisor", () => {...@@ -384,7 +384,7 @@ describe("EnvironmentSupervisor", () => {
384 supervisor.state,384 supervisor.state,
385 (state) => state.phase === "backoff" && state.attempt === 1,385 (state) => state.phase === "backoff" && state.attempt === 1,
386 );386 );
387 yield* TestClock.adjust("1 second");387 yield* TestClock.adjust("3 seconds");
388388
389 const retrying = yield* awaitState(389 const retrying = yield* awaitState(
390 supervisor.state,390 supervisor.state,
...@@ -489,7 +489,7 @@ describe("EnvironmentSupervisor", () => {...@@ -489,7 +489,7 @@ describe("EnvironmentSupervisor", () => {
489 },489 },
490 });490 });
491491
492 yield* TestClock.adjust("1 second");492 yield* TestClock.adjust("3 seconds");
493 yield* awaitState(supervisor.state, (state) => state.phase === "connected");493 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
494 expect(yield* Ref.get(harness.prepareCount)).toBe(2);494 expect(yield* Ref.get(harness.prepareCount)).toBe(2);
495 }).pipe(Effect.provide(TestClock.layer())),495 }).pipe(Effect.provide(TestClock.layer())),
...@@ -526,7 +526,7 @@ describe("EnvironmentSupervisor", () => {...@@ -526,7 +526,7 @@ describe("EnvironmentSupervisor", () => {
526 supervisor.state,526 supervisor.state,
527 (state) => state.phase === "backoff" && state.attempt === 1,527 (state) => state.phase === "backoff" && state.attempt === 1,
528 );528 );
529 yield* TestClock.adjust("1 second");529 yield* TestClock.adjust("3 seconds");
530 yield* eventuallyState(530 yield* eventuallyState(
531 supervisor.state,531 supervisor.state,
532 (state) => state.phase === "backoff" && state.attempt === 2,532 (state) => state.phase === "backoff" && state.attempt === 2,
...@@ -539,7 +539,7 @@ describe("EnvironmentSupervisor", () => {...@@ -539,7 +539,7 @@ describe("EnvironmentSupervisor", () => {
539 );539 );
540 expect(yield* Ref.get(harness.prepareCount)).toBe(3);540 expect(yield* Ref.get(harness.prepareCount)).toBe(3);
541541
542 yield* TestClock.adjust("999 millis");542 yield* TestClock.adjust("2999 millis");
543 expect(yield* Ref.get(harness.prepareCount)).toBe(3);543 expect(yield* Ref.get(harness.prepareCount)).toBe(3);
544 yield* TestClock.adjust("1 milli");544 yield* TestClock.adjust("1 milli");
545 yield* eventuallyState(545 yield* eventuallyState(
...@@ -588,7 +588,7 @@ describe("EnvironmentSupervisor", () => {...@@ -588,7 +588,7 @@ describe("EnvironmentSupervisor", () => {
588 supervisor.state,588 supervisor.state,
589 (state) => state.phase === "backoff" && state.attempt === 1,589 (state) => state.phase === "backoff" && state.attempt === 1,
590 );590 );
591 yield* TestClock.adjust("1 second");591 yield* TestClock.adjust("3 seconds");
592 yield* awaitState(592 yield* awaitState(
593 supervisor.state,593 supervisor.state,
594 (state) => state.phase === "blocked" && state.attempt === 2,594 (state) => state.phase === "blocked" && state.attempt === 2,
...@@ -703,7 +703,7 @@ describe("EnvironmentSupervisor", () => {...@@ -703,7 +703,7 @@ describe("EnvironmentSupervisor", () => {
703 );703 );
704 expect(Option.isNone(yield* SubscriptionRef.get(supervisor.prepared))).toBe(true);704 expect(Option.isNone(yield* SubscriptionRef.get(supervisor.prepared))).toBe(true);
705705
706 yield* TestClock.adjust("1 second");706 yield* TestClock.adjust("3 seconds");
707 yield* awaitState(707 yield* awaitState(
708 supervisor.state,708 supervisor.state,
709 (state) => state.phase === "connected" && state.generation === 2,709 (state) => state.phase === "connected" && state.generation === 2,
...@@ -728,7 +728,7 @@ describe("EnvironmentSupervisor", () => {...@@ -728,7 +728,7 @@ describe("EnvironmentSupervisor", () => {
728 (state) => state.phase === "backoff" && state.attempt === 1,728 (state) => state.phase === "backoff" && state.attempt === 1,
729 );729 );
730730
731 yield* TestClock.adjust("1 second");731 yield* TestClock.adjust("3 seconds");
732 yield* awaitState(732 yield* awaitState(
733 supervisor.state,733 supervisor.state,
734 (state) => state.phase === "connected" && state.generation === 2,734 (state) => state.phase === "connected" && state.generation === 2,
...@@ -741,7 +741,7 @@ describe("EnvironmentSupervisor", () => {...@@ -741,7 +741,7 @@ describe("EnvironmentSupervisor", () => {
741741
742 expect(secondFailure.retryAt).not.toBeNull();742 expect(secondFailure.retryAt).not.toBeNull();
743743
744 yield* TestClock.adjust("1 second");744 yield* TestClock.adjust("3 seconds");
745 expect(yield* Ref.get(harness.sessionCount)).toBe(2);745 expect(yield* Ref.get(harness.sessionCount)).toBe(2);
746746
747 yield* TestClock.adjust("1 second");747 yield* TestClock.adjust("1 second");
...@@ -766,7 +766,7 @@ describe("EnvironmentSupervisor", () => {...@@ -766,7 +766,7 @@ describe("EnvironmentSupervisor", () => {
766 supervisor.state,766 supervisor.state,
767 (state) => state.phase === "backoff" && state.attempt === 1,767 (state) => state.phase === "backoff" && state.attempt === 1,
768 );768 );
769 yield* TestClock.adjust("1 second");769 yield* TestClock.adjust("3 seconds");
770 yield* awaitState(770 yield* awaitState(
771 supervisor.state,771 supervisor.state,
772 (state) => state.phase === "connected" && state.generation === 2,772 (state) => state.phase === "connected" && state.generation === 2,
...@@ -805,7 +805,7 @@ describe("EnvironmentSupervisor", () => {...@@ -805,7 +805,7 @@ describe("EnvironmentSupervisor", () => {
805 supervisor.state,805 supervisor.state,
806 (state) => state.phase === "backoff" && state.attempt === 1,806 (state) => state.phase === "backoff" && state.attempt === 1,
807 );807 );
808 yield* TestClock.adjust("1 second");808 yield* TestClock.adjust("3 seconds");
809 yield* awaitState(809 yield* awaitState(
810 supervisor.state,810 supervisor.state,
811 (state) => state.phase === "connected" && state.generation === 2 && state.attempt === 2,811 (state) => state.phase === "connected" && state.generation === 2 && state.attempt === 2,
...@@ -834,7 +834,7 @@ describe("EnvironmentSupervisor", () => {...@@ -834,7 +834,7 @@ describe("EnvironmentSupervisor", () => {
834 supervisor.state,834 supervisor.state,
835 (state) => state.phase === "backoff" && state.attempt === 1,835 (state) => state.phase === "backoff" && state.attempt === 1,
836 );836 );
837 yield* TestClock.adjust("1 second");837 yield* TestClock.adjust("3 seconds");
838 yield* awaitState(838 yield* awaitState(
839 supervisor.state,839 supervisor.state,
840 (state) => state.phase === "connecting" && state.attempt === 2,840 (state) => state.phase === "connecting" && state.attempt === 2,
...@@ -925,9 +925,14 @@ describe("EnvironmentSupervisor", () => {...@@ -925,9 +925,14 @@ describe("EnvironmentSupervisor", () => {
925 }),925 }),
926 );926 );
927927
928 it.effect("reconnects when the foreground liveness probe fails", () =>928 it.effect("reconnects immediately when the foreground liveness probe fails", () =>
929 Effect.gen(function* () {929 Effect.gen(function* () {
930 const allowReconnect = yield* Deferred.make<void>();
930 const harness = yield* makeHarness({931 const harness = yield* makeHarness({
932 prepare: (attempt) =>
933 attempt === 2
934 ? Deferred.await(allowReconnect).pipe(Effect.as(PREPARED_CONNECTION))
935 : Effect.succeed(PREPARED_CONNECTION),
931 probe: (attempt) =>936 probe: (attempt) =>
932 attempt === 1 ? Effect.fail(transient("The live session is stale.")) : Effect.void,937 attempt === 1 ? Effect.fail(transient("The live session is stale.")) : Effect.void,
933 });938 });
...@@ -937,15 +942,77 @@ describe("EnvironmentSupervisor", () => {...@@ -937,15 +942,77 @@ describe("EnvironmentSupervisor", () => {
937942
938 yield* awaitState(supervisor.state, (state) => state.phase === "connected");943 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
939 yield* harness.wake("application-active");944 yield* harness.wake("application-active");
940 yield* awaitState(supervisor.state, (state) => state.phase === "backoff");945 const reconnecting = yield* awaitState(
941 yield* TestClock.adjust("1 second");946 supervisor.state,
947 (state) => state.phase === "connecting",
948 );
949 expect(reconnecting.attempt).toBe(1);
950 expect(Option.isNone(yield* SubscriptionRef.get(supervisor.session))).toBe(true);
951
952 // No TestClock advance: a failed wake probe skips the first backoff rung.
953 yield* Deferred.succeed(allowReconnect, undefined);
954 yield* awaitState(
955 supervisor.state,
956 (state) => state.phase === "connected" && state.generation === 2 && state.attempt === 1,
957 );
958
959 expect(yield* Ref.get(harness.sessionCount)).toBe(2);
960 expect(yield* Ref.get(harness.releaseCount)).toBe(1);
961 }).pipe(Effect.provide(TestClock.layer())),
962 );
963
964 it.effect("keeps normal backoff when a reconnect after a failed wake probe also fails", () =>
965 Effect.gen(function* () {
966 const harness = yield* makeHarness({
967 prepare: (attempt) =>
968 attempt === 2 ? Effect.fail(transient()) : Effect.succeed(PREPARED_CONNECTION),
969 probe: (attempt) =>
970 attempt === 1 ? Effect.fail(transient("The live session is stale.")) : Effect.void,
971 });
972 const supervisor = yield* EnvironmentSupervisor.make(TARGET_ENTRY, {
973 initiallyDesired: true,
974 }).pipe(Effect.provide(harness.dependencies));
975
976 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
977 yield* harness.wake("application-active");
978 // The immediate follow-up attempt fails: only the first attempt after
979 // the wake probe skips the ladder, so this failure backs off normally.
980 yield* awaitState(
981 supervisor.state,
982 (state) => state.phase === "backoff" && state.attempt === 1,
983 );
984 yield* TestClock.adjust("2999 millis");
985 expect(yield* Ref.get(harness.prepareCount)).toBe(2);
986 yield* TestClock.adjust("1 milli");
942 yield* eventuallyState(987 yield* eventuallyState(
943 supervisor.state,988 supervisor.state,
944 (state) => state.phase === "connected" && state.generation === 2,989 (state) => state.phase === "connected" && state.generation === 2,
945 );990 );
946991
992 expect(yield* Ref.get(harness.prepareCount)).toBe(3);
993 }).pipe(Effect.provide(TestClock.layer())),
994 );
995
996 it.effect("uses the full tolerance window for a stalled desktop foreground probe", () =>
997 Effect.gen(function* () {
998 const harness = yield* makeHarness({
999 probe: (attempt) => (attempt === 1 ? Effect.never : Effect.void),
1000 });
1001 const supervisor = yield* EnvironmentSupervisor.make(TARGET_ENTRY, {
1002 initiallyDesired: true,
1003 }).pipe(Effect.provide(harness.dependencies));
1004
1005 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
1006 yield* harness.wake("application-active");
1007 yield* TestClock.adjust("14999 millis");
1008 expect(yield* Ref.get(harness.sessionCount)).toBe(1);
1009 yield* TestClock.adjust("1 milli");
1010 yield* awaitState(
1011 supervisor.state,
1012 (state) => state.phase === "connected" && state.generation === 2 && state.attempt === 1,
1013 );
1014
947 expect(yield* Ref.get(harness.sessionCount)).toBe(2);1015 expect(yield* Ref.get(harness.sessionCount)).toBe(2);
948 expect(yield* Ref.get(harness.releaseCount)).toBe(1);
949 }).pipe(Effect.provide(TestClock.layer())),1016 }).pipe(Effect.provide(TestClock.layer())),
950 );1017 );
9511018
...@@ -961,15 +1028,14 @@ describe("EnvironmentSupervisor", () => {...@@ -961,15 +1028,14 @@ describe("EnvironmentSupervisor", () => {
961 yield* awaitState(supervisor.state, (state) => state.phase === "connected");1028 yield* awaitState(supervisor.state, (state) => state.phase === "connected");
962 yield* harness.wake("application-active-probe");1029 yield* harness.wake("application-active-probe");
963 yield* TestClock.adjust("3 seconds");1030 yield* TestClock.adjust("3 seconds");
1031 // The timed-out wake probe reconnects immediately without a backoff
1032 // sleep: no further clock advance is needed.
964 yield* awaitState(1033 yield* awaitState(
965 supervisor.state,1034 supervisor.state,
966 (state) => state.phase === "backoff" && state.lastFailure?.reason === "timeout",1035 (state) => state.phase === "connected" && state.generation === 2 && state.attempt === 1,
967 );
968 yield* TestClock.adjust("1 second");
969 yield* eventuallyState(
970 supervisor.state,
971 (state) => state.phase === "connected" && state.generation === 2,
972 );1036 );
1037
1038 expect(yield* Ref.get(harness.sessionCount)).toBe(2);
973 }).pipe(Effect.provide(TestClock.layer())),1039 }).pipe(Effect.provide(TestClock.layer())),
974 );1040 );
9751041
packages/client-runtime/src/connection/supervisor.ts+21-1
...@@ -29,7 +29,7 @@ import * as RpcSession from "../rpc/session.ts";...@@ -29,7 +29,7 @@ import * as RpcSession from "../rpc/session.ts";
29import { safeErrorLogAttributes } from "../errors/safeLog.ts";29import { safeErrorLogAttributes } from "../errors/safeLog.ts";
30import * as ConnectionWakeups from "./wakeups.ts";30import * as ConnectionWakeups from "./wakeups.ts";
3131
32const RETRY_DELAYS_MS = [1_000, 2_000, 4_000, 8_000, 16_000] as const;32const RETRY_DELAYS_MS = [3_000, 4_000, 8_000, 16_000] as const;
33const CONNECTION_ESTABLISHMENT_TIMEOUT = "15 seconds";33const CONNECTION_ESTABLISHMENT_TIMEOUT = "15 seconds";
34const CONNECTION_PROBE_TIMEOUT = "15 seconds";34const CONNECTION_PROBE_TIMEOUT = "15 seconds";
35const MOBILE_CONNECTION_PROBE_TIMEOUT = "3 seconds";35const MOBILE_CONNECTION_PROBE_TIMEOUT = "3 seconds";
...@@ -232,6 +232,10 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (...@@ -232,6 +232,10 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (
232 const intent = yield* Ref.make(initialIntent);232 const intent = yield* Ref.make(initialIntent);
233 const signals = yield* Queue.unbounded<SupervisorSignal>();233 const signals = yield* Queue.unbounded<SupervisorSignal>();
234 const resetRetryState = yield* Ref.make(false);234 const resetRetryState = yield* Ref.make(false);
235 // Set when a foreground wake probe fails or times out: the user is actively
236 // returning to the app on a dead transport, so the follow-up reconnect skips
237 // the first backoff rung instead of sleeping.
238 const wakeProbeFailed = yield* Ref.make(false);
235 const state = yield* SubscriptionRef.make<SupervisorConnectionState>(239 const state = yield* SubscriptionRef.make<SupervisorConnectionState>(
236 !initialIntent.desired240 !initialIntent.desired
237 ? availableState(initialIntent, 0)241 ? availableState(initialIntent, 0)
...@@ -441,6 +445,9 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (...@@ -441,6 +445,9 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (
441 ),445 ),
442 );446 );
443 if (probeEvent._tag === "ProbeCompleted") {447 if (probeEvent._tag === "ProbeCompleted") {
448 if (Exit.isFailure(probeEvent.exit)) {
449 yield* Ref.set(wakeProbeFailed, true);
450 }
444 yield* probeEvent.exit;451 yield* probeEvent.exit;
445 break;452 break;
446 }453 }
...@@ -673,6 +680,9 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (...@@ -673,6 +680,9 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (
673 const outcome: AttemptOutcome = yield* Effect.scoped(680 const outcome: AttemptOutcome = yield* Effect.scoped(
674 runAttempt(attempt, nextGeneration, latestFailure, pendingRetry),681 runAttempt(attempt, nextGeneration, latestFailure, pendingRetry),
675 );682 );
683 // Consumed on every iteration so a stale marker can never leak into a
684 // later, unrelated failure.
685 const failedWakeProbe = yield* Ref.getAndSet(wakeProbeFailed, false);
676 if (outcome.established) {686 if (outcome.established) {
677 generation = nextGeneration;687 generation = nextGeneration;
678 if (outcome.stable) {688 if (outcome.stable) {
...@@ -709,6 +719,16 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (...@@ -709,6 +719,16 @@ export const make = Effect.fn("EnvironmentSupervisor.make")(function* (
709 continue;719 continue;
710 }720 }
711721
722 if (failedWakeProbe) {
723 // The wake probe found a dead transport while the user is returning to
724 // the app, so reconnect immediately instead of sleeping the first
725 // backoff rung. Only this first attempt skips the ladder; if it fails
726 // too, normal backoff resumes.
727 resetRetryLadder();
728 yield* setState(connectingState(yield* Ref.get(intent), generation, 1, error));
729 continue;
730 }
731
712 failureCount += 1;732 failureCount += 1;
713 const delayMs = retryDelayMs(failureCount - 1);733 const delayMs = retryDelayMs(failureCount - 1);
714 pendingRetry = Option.map(attemptSpan, (previousAttempt) => ({734 pendingRetry = Option.map(attemptSpan, (previousAttempt) => ({
packages/client-runtime/src/rpc/session.test.ts+27
...@@ -287,6 +287,33 @@ describe("RpcSessionFactory", () => {...@@ -287,6 +287,33 @@ describe("RpcSessionFactory", () => {
287 }),287 }),
288 );288 );
289289
290 it.effect("tolerates two missed pong windows before closing the session", () =>
291 Effect.gen(function* () {
292 const { factory, sockets } = yield* makeFactory();
293 const session = yield* factory.connect(PREPARED);
294 const readyFiber = yield* Effect.forkChild(session.ready);
295 const closedFiber = yield* Effect.forkChild(Effect.flip(session.closed));
296 const socket = yield* awaitSocket(sockets);
297
298 socket.open();
299 yield* completeInitialConfig(socket);
300 yield* Fiber.join(readyFiber);
301
302 yield* TestClock.adjust("15 seconds");
303 expect(closedFiber.pollUnsafe()).toBeUndefined();
304 expect(socket.sent.slice(1).map((request) => decodeJson(request))).toEqual([
305 { _tag: "Ping" },
306 { _tag: "Ping" },
307 { _tag: "Ping" },
308 ]);
309
310 yield* TestClock.adjust("5 seconds");
311 const error = yield* Fiber.join(closedFiber);
312 expect(error).toBeInstanceOf(ConnectionTransientError);
313 expect(error).toMatchObject({ reason: "transport" });
314 }).pipe(Effect.scoped, Effect.provide(TestClock.layer())),
315 );
316
290 it.effect("reaches ready when a newer server sends unknown config members", () =>317 it.effect("reaches ready when a newer server sends unknown config members", () =>
291 Effect.gen(function* () {318 Effect.gen(function* () {
292 const { factory, sockets } = yield* makeFactory();319 const { factory, sockets } = yield* makeFactory();
packages/client-runtime/src/state/shell-sync.test.ts+70-55
...@@ -150,34 +150,34 @@ describe("environment shell synchronization", () => {...@@ -150,34 +150,34 @@ describe("environment shell synchronization", () => {
150 }),150 }),
151 );151 );
152152
153 it.effect("replaces a warm shell cache with an authoritative HTTP snapshot", () =>153 it.effect("requests a full socket snapshot when the HTTP refresh fails", () =>
154 Effect.gen(function* () {154 Effect.gen(function* () {
155 const cachedSnapshot: OrchestrationShellSnapshot = {155 const cachedSnapshot: OrchestrationShellSnapshot = {
156 snapshotSequence: 5,156 snapshotSequence: 5,
157 projects: [],157 projects: [],
158 threads: [{ id: "stale-thread" } as never],158 threads: [{ id: "cached-thread" } as never],
159 updatedAt: "2026-06-06T00:00:00.000Z",159 updatedAt: "2026-06-06T00:00:00.000Z",
160 };160 };
161 const httpSnapshot: OrchestrationShellSnapshot = {161 const resetSnapshot: OrchestrationShellSnapshot = {
162 ...cachedSnapshot,162 ...cachedSnapshot,
163 snapshotSequence: 9,163 snapshotSequence: 9_999,
164 threads: [],164 threads: [],
165 updatedAt: "2026-06-07T00:00:00.000Z",165 updatedAt: "2026-06-07T00:00:00.000Z",
166 };166 };
167 const events = yield* Queue.unbounded<OrchestrationShellStreamItem>();167 const events = yield* Queue.unbounded<OrchestrationShellStreamItem>();
168 const capturedAfterSequence = yield* SubscriptionRef.make<number | undefined>(undefined);168 const wakeups = yield* Queue.unbounded<ConnectionWakeups.ConnectionWakeup>();
169 const capturedCompletionMarker = yield* Ref.make<boolean | undefined>(undefined);169 const subscribeInputs = yield* Queue.unbounded<{
170 const loaderCalls = yield* SubscriptionRef.make(0);170 readonly afterSequence?: number;
171 readonly requestCompletionMarker?: boolean;
172 }>();
173 const loaderCalls = yield* Ref.make(0);
171 const client = {174 const client = {
172 [ORCHESTRATION_WS_METHODS.subscribeShell]: (input: {175 [ORCHESTRATION_WS_METHODS.subscribeShell]: (input: {
173 readonly afterSequence?: number;176 readonly afterSequence?: number;
174 readonly requestCompletionMarker?: boolean;177 readonly requestCompletionMarker?: boolean;
175 }) =>178 }) =>
176 Stream.unwrap(179 Stream.unwrap(
177 Ref.set(capturedCompletionMarker, input.requestCompletionMarker).pipe(180 Queue.offer(subscribeInputs, input).pipe(Effect.as(Stream.fromQueue(events))),
178 Effect.andThen(SubscriptionRef.set(capturedAfterSequence, input.afterSequence)),
179 Effect.as(Stream.fromQueue(events)),
180 ),
181 ),181 ),
182 } as unknown as WsRpcProtocolClient;182 } as unknown as WsRpcProtocolClient;
183 const supervisorState = yield* SubscriptionRef.make(AVAILABLE_CONNECTION_STATE);183 const supervisorState = yield* SubscriptionRef.make(AVAILABLE_CONNECTION_STATE);
...@@ -208,57 +208,66 @@ describe("environment shell synchronization", () => {...@@ -208,57 +208,66 @@ describe("environment shell synchronization", () => {
208 clear: () => Effect.void,208 clear: () => Effect.void,
209 });209 });
210 const snapshotLoader = ShellSnapshotLoader.of({210 const snapshotLoader = ShellSnapshotLoader.of({
211 load: () =>211 load: () => Ref.update(loaderCalls, (count) => count + 1).pipe(Effect.as(Option.none())),
212 SubscriptionRef.update(loaderCalls, (count) => count + 1).pipe(
213 Effect.as(Option.some(httpSnapshot)),
214 ),
215 });212 });
216 const shellState = yield* makeEnvironmentShellState().pipe(213 const shellState = yield* makeEnvironmentShellState().pipe(
217 Effect.provideService(EnvironmentSupervisor.EnvironmentSupervisor, supervisor),214 Effect.provideService(EnvironmentSupervisor.EnvironmentSupervisor, supervisor),
218 Effect.provideService(Persistence.EnvironmentCacheStore, cache),215 Effect.provideService(Persistence.EnvironmentCacheStore, cache),
219 Effect.provideService(ShellSnapshotLoader, snapshotLoader),216 Effect.provideService(ShellSnapshotLoader, snapshotLoader),
217 Effect.provideService(
218 ConnectionWakeups.ConnectionWakeups,
219 ConnectionWakeups.ConnectionWakeups.of({ changes: Stream.fromQueue(wakeups) }),
220 ),
220 );221 );
221222
222 // Wait until the subscription is established from the warm cache.223 const subscribeInput = yield* Queue.take(subscribeInputs);
223 yield* SubscriptionRef.changes(capturedAfterSequence).pipe(224 expect(subscribeInput.afterSequence).toBeUndefined();
224 Stream.filter((value) => value !== undefined),225 expect(subscribeInput.requestCompletionMarker).toBe(true);
225 Stream.runHead,226 expect(yield* Ref.get(loaderCalls)).toBe(1);
226 );
227
228 expect(yield* SubscriptionRef.get(capturedAfterSequence)).toBe(9);
229 expect(yield* Ref.get(capturedCompletionMarker)).toBe(true);
230 expect(yield* SubscriptionRef.get(loaderCalls)).toBe(1);
231 const synchronizing = yield* SubscriptionRef.get(shellState);227 const synchronizing = yield* SubscriptionRef.get(shellState);
232 expect(synchronizing.status).toBe("synchronizing");228 expect(synchronizing.status).toBe("synchronizing");
233 expect(Option.getOrThrow(synchronizing.snapshot)).toEqual(httpSnapshot);229 expect(Option.getOrThrow(synchronizing.snapshot)).toEqual(cachedSnapshot);
234230
231 yield* Queue.offer(events, { kind: "snapshot", snapshot: resetSnapshot });
235 yield* Queue.offer(events, { kind: "synchronized" });232 yield* Queue.offer(events, { kind: "synchronized" });
236 yield* SubscriptionRef.changes(shellState).pipe(233 yield* SubscriptionRef.changes(shellState).pipe(
237 Stream.filter((value) => value.status === "live"),234 Stream.filter((value) => value.status === "live"),
238 Stream.runHead,235 Stream.runHead,
239 );236 );
237
238 const live = yield* SubscriptionRef.get(shellState);
239 expect(Option.getOrThrow(live.snapshot)).toEqual(resetSnapshot);
240 expect(yield* Ref.get(loaderCalls)).toBe(1);
241
242 yield* Queue.offer(wakeups, "application-active");
243 const resumedInput = yield* Queue.take(subscribeInputs);
244 expect(resumedInput.afterSequence).toBe(resetSnapshot.snapshotSequence);
245 expect(resumedInput.requestCompletionMarker).toBe(true);
246 expect(yield* Ref.get(loaderCalls)).toBe(1);
240 }),247 }),
241 );248 );
242249
243 it.effect("refreshes the authoritative shell snapshot when the app becomes active", () =>250 it.effect("resubscribes from the in-memory shell cursor when the app becomes active", () =>
244 Effect.gen(function* () {251 Effect.gen(function* () {
245 const events = yield* Queue.unbounded<OrchestrationShellStreamItem>();252 const events = yield* Queue.unbounded<OrchestrationShellStreamItem>();
246 const wakeups = yield* Queue.unbounded<ConnectionWakeups.ConnectionWakeup>();253 const wakeups = yield* Queue.unbounded<ConnectionWakeups.ConnectionWakeup>();
247 const loaderCalls = yield* Ref.make(0);254 const loaderCalls = yield* Ref.make(0);
248 const subscriptionCount = yield* Ref.make(0);255 const capturedAfterSequences = yield* Ref.make<ReadonlyArray<number | undefined>>([]);
249 const client = {256 const client = {
250 [ORCHESTRATION_WS_METHODS.subscribeShell]: () =>257 [ORCHESTRATION_WS_METHODS.subscribeShell]: (input: { readonly afterSequence?: number }) =>
251 Stream.unwrap(258 Stream.unwrap(
252 Ref.update(subscriptionCount, (count) => count + 1).pipe(259 Ref.update(capturedAfterSequences, (captured) => [
253 Effect.as(Stream.fromQueue(events)),260 ...captured,
254 ),261 input.afterSequence,
262 ]).pipe(Effect.as(Stream.fromQueue(events))),
255 ),263 ),
256 } as unknown as WsRpcProtocolClient;264 } as unknown as WsRpcProtocolClient;
257 const supervisorState = yield* SubscriptionRef.make(AVAILABLE_CONNECTION_STATE);265 const supervisorState = yield* SubscriptionRef.make(AVAILABLE_CONNECTION_STATE);
266 const activeSession = yield* SubscriptionRef.make(Option.some(session(client)));
258 const supervisor = EnvironmentSupervisor.EnvironmentSupervisor.of({267 const supervisor = EnvironmentSupervisor.EnvironmentSupervisor.of({
259 target: TARGET,268 target: TARGET,
260 state: supervisorState,269 state: supervisorState,
261 session: yield* SubscriptionRef.make(Option.some(session(client))),270 session: activeSession,
262 prepared: yield* SubscriptionRef.make(Option.some(PREPARED)),271 prepared: yield* SubscriptionRef.make(Option.some(PREPARED)),
263 connect: Effect.void,272 connect: Effect.void,
264 disconnect: Effect.void,273 disconnect: Effect.void,
...@@ -296,54 +305,60 @@ describe("environment shell synchronization", () => {...@@ -296,54 +305,60 @@ describe("environment shell synchronization", () => {
296 ),305 ),
297 );306 );
298307
299 yield* SubscriptionRef.changes(shellState).pipe(308 // A new session starts from an authoritative HTTP snapshot.
300 Stream.filter(309 for (let attempt = 0; attempt < 100; attempt += 1) {
301 (value) =>310 if ((yield* Ref.get(capturedAfterSequences)).length >= 1) break;
302 value.status === "synchronizing" &&311 yield* Effect.yieldNow;
303 Option.isSome(value.snapshot) &&312 }
304 value.snapshot.value.snapshotSequence === 10,313 expect(yield* Ref.get(capturedAfterSequences)).toEqual([10]);
305 ),
306 Stream.runHead,
307 );
308 yield* Queue.offer(events, { kind: "synchronized" });314 yield* Queue.offer(events, { kind: "synchronized" });
309 yield* SubscriptionRef.changes(shellState).pipe(315 yield* SubscriptionRef.changes(shellState).pipe(
310 Stream.filter((value) => value.status === "live"),316 Stream.filter((value) => value.status === "live"),
311 Stream.runHead,317 Stream.runHead,
312 );318 );
313319
314 yield* Queue.offer(wakeups, "application-active");320 // A newer snapshot arrives on the stream and advances the cursor.
321 yield* Queue.offer(events, {
322 kind: "snapshot",
323 snapshot: { ...LIVE_SHELL_SNAPSHOT, snapshotSequence: 40 },
324 });
315 yield* SubscriptionRef.changes(shellState).pipe(325 yield* SubscriptionRef.changes(shellState).pipe(
316 Stream.filter(326 Stream.filter(
317 (value) =>327 (value) => Option.isSome(value.snapshot) && value.snapshot.value.snapshotSequence === 40,
318 value.status === "synchronizing" &&
319 Option.isSome(value.snapshot) &&
320 value.snapshot.value.snapshotSequence === 20,
321 ),328 ),
322 Stream.runHead,329 Stream.runHead,
323 );330 );
324331
332 yield* Queue.offer(wakeups, "application-active");
325 for (let attempt = 0; attempt < 100; attempt += 1) {333 for (let attempt = 0; attempt < 100; attempt += 1) {
326 if ((yield* Ref.get(subscriptionCount)) >= 2) break;334 if ((yield* Ref.get(capturedAfterSequences)).length >= 2) break;
327 yield* Effect.yieldNow;335 yield* Effect.yieldNow;
328 }336 }
329337 expect(yield* Ref.get(capturedAfterSequences)).toEqual([10, 40]);
330 expect(yield* Ref.get(loaderCalls)).toBe(2);338 yield* Queue.offer(events, { kind: "synchronized" });
331 expect(yield* Ref.get(subscriptionCount)).toBe(2);
332339
333 yield* Queue.offer(wakeups, "application-active-probe");340 yield* Queue.offer(wakeups, "application-active-probe");
334 for (let attempt = 0; attempt < 100; attempt += 1) {341 for (let attempt = 0; attempt < 100; attempt += 1) {
335 if ((yield* Ref.get(subscriptionCount)) >= 3) break;342 if ((yield* Ref.get(capturedAfterSequences)).length >= 3) break;
336 yield* Effect.yieldNow;343 yield* Effect.yieldNow;
337 }344 }
338 expect(yield* Ref.get(loaderCalls)).toBe(3);345 expect(yield* Ref.get(capturedAfterSequences)).toEqual([10, 40, 40]);
339 expect(yield* Ref.get(subscriptionCount)).toBe(3);
340346
341 yield* Queue.offer(wakeups, "application-active-reconnect");347 yield* Queue.offer(wakeups, "application-active-reconnect");
342 for (let attempt = 0; attempt < 10; attempt += 1) {348 for (let attempt = 0; attempt < 10; attempt += 1) {
343 yield* Effect.yieldNow;349 yield* Effect.yieldNow;
344 }350 }
345 expect(yield* Ref.get(loaderCalls)).toBe(3);351 expect((yield* Ref.get(capturedAfterSequences)).length).toBe(3);
346 expect(yield* Ref.get(subscriptionCount)).toBe(3);352 expect(yield* Ref.get(loaderCalls)).toBe(1);
353
354 // Replacing the session performs another authoritative refresh.
355 yield* SubscriptionRef.set(activeSession, Option.some(session(client)));
356 for (let attempt = 0; attempt < 100; attempt += 1) {
357 if ((yield* Ref.get(capturedAfterSequences)).length >= 4) break;
358 yield* Effect.yieldNow;
359 }
360 expect(yield* Ref.get(capturedAfterSequences)).toEqual([10, 40, 40, 20]);
361 expect(yield* Ref.get(loaderCalls)).toBe(2);
347 }),362 }),
348 );363 );
349});364});
packages/client-runtime/src/state/shell.ts+55-22
...@@ -21,6 +21,7 @@ import * as ConnectionWakeups from "../connection/wakeups.ts";...@@ -21,6 +21,7 @@ import * as ConnectionWakeups from "../connection/wakeups.ts";
21import { safeErrorLogAttributes } from "../errors/safeLog.ts";21import { safeErrorLogAttributes } from "../errors/safeLog.ts";
22import { EnvironmentCacheStore } from "../platform/persistence.ts";22import { EnvironmentCacheStore } from "../platform/persistence.ts";
23import { subscribeDynamic } from "../rpc/client.ts";23import { subscribeDynamic } from "../rpc/client.ts";
24import type { RpcSession } from "../rpc/session.ts";
24import { ShellSnapshotLoader } from "./shellSnapshotHttp.ts";25import { ShellSnapshotLoader } from "./shellSnapshotHttp.ts";
25import { applyShellStreamEvent } from "./shellReducer.ts";26import { applyShellStreamEvent } from "./shellReducer.ts";
26import type { EnvironmentCatalogState } from "./connections.ts";27import type { EnvironmentCatalogState } from "./connections.ts";
...@@ -71,6 +72,8 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")...@@ -71,6 +72,8 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")
71 error: Option.none(),72 error: Option.none(),
72 });73 });
73 const awaitingCompletion = yield* Ref.make(false);74 const awaitingCompletion = yield* Ref.make(false);
75 const lastAuthoritativeSession = yield* Ref.make<RpcSession | null>(null);
76 const activeSubscriptionSession = yield* Ref.make<RpcSession | null>(null);
74 const persistence = yield* Queue.sliding<OrchestrationShellSnapshot>(1);77 const persistence = yield* Queue.sliding<OrchestrationShellSnapshot>(1);
7578
76 const persist = Effect.fn("EnvironmentShellState.persist")(function* (79 const persist = Effect.fn("EnvironmentShellState.persist")(function* (
...@@ -166,6 +169,12 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")...@@ -166,6 +169,12 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")
166 status: waiting ? "synchronizing" : "live",169 status: waiting ? "synchronizing" : "live",
167 error: Option.none(),170 error: Option.none(),
168 });171 });
172 if (item.kind === "snapshot") {
173 const session = yield* Ref.get(activeSubscriptionSession);
174 if (session !== null) {
175 yield* Ref.set(lastAuthoritativeSession, session);
176 }
177 }
169 yield* Queue.offer(persistence, nextSnapshot);178 yield* Queue.offer(persistence, nextSnapshot);
170 });179 });
171180
...@@ -180,6 +189,7 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")...@@ -180,6 +189,7 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")
180 subscribeDynamic(189 subscribeDynamic(
181 ORCHESTRATION_WS_METHODS.subscribeShell,190 ORCHESTRATION_WS_METHODS.subscribeShell,
182 Effect.fn("EnvironmentShellState.makeSubscribeInput")(function* (session) {191 Effect.fn("EnvironmentShellState.makeSubscribeInput")(function* (session) {
192 yield* Ref.set(activeSubscriptionSession, session);
183 const supportsCompletionMarker = yield* session.initialConfig.pipe(193 const supportsCompletionMarker = yield* session.initialConfig.pipe(
184 Effect.map((config) => config.shellResumeCompletionMarker === true),194 Effect.map((config) => config.shellResumeCompletionMarker === true),
185 Effect.orElseSucceed(() => false),195 Effect.orElseSucceed(() => false),
...@@ -187,30 +197,53 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")...@@ -187,30 +197,53 @@ export const makeEnvironmentShellState = Effect.fn("EnvironmentShellState.make")
187 yield* Ref.set(awaitingCompletion, supportsCompletionMarker);197 yield* Ref.set(awaitingCompletion, supportsCompletionMarker);
188 yield* setSynchronizing;198 yield* setSynchronizing;
189199
190 const prepared = yield* SubscriptionRef.get(supervisor.prepared).pipe(200 // Foreground resubscriptions on the same live session can resume from
191 Effect.flatMap(201 // the in-memory cursor. A new session reloads the authoritative HTTP
192 Option.match({202 // snapshot so a valid cursor cannot preserve incomplete cached data.
193 onSome: Effect.succeed,203 const hasAuthoritativeSnapshot = (yield* Ref.get(lastAuthoritativeSession)) === session;
194 onNone: () =>204 let canResume = hasAuthoritativeSnapshot;
195 SubscriptionRef.changes(supervisor.prepared).pipe(205 let current = yield* SubscriptionRef.get(state);
196 Stream.filter(Option.isSome),206 if (!hasAuthoritativeSnapshot || Option.isNone(current.snapshot)) {
197 Stream.map((value) => value.value),207 const prepared = yield* SubscriptionRef.get(supervisor.prepared).pipe(
198 Stream.runHead,208 Effect.flatMap(
199 Effect.map(Option.getOrThrow),209 Option.match({
200 ),210 onSome: Effect.succeed,
201 }),211 onNone: () =>
202 ),212 SubscriptionRef.changes(supervisor.prepared).pipe(
203 );213 Stream.filter(Option.isSome),
204 const httpSnapshot = yield* snapshotLoader.load(prepared);214 Stream.map((value) => value.value),
205 if (Option.isSome(httpSnapshot)) {215 Stream.runHead,
206 yield* applyItem({ kind: "snapshot", snapshot: httpSnapshot.value });216 Effect.map(Option.getOrThrow),
207 return {217 ),
208 afterSequence: httpSnapshot.value.snapshotSequence,218 }),
209 ...(supportsCompletionMarker ? { requestCompletionMarker: true as const } : {}),219 ),
210 };220 );
221 const httpSnapshot = yield* snapshotLoader.load(prepared);
222 if (Option.isSome(httpSnapshot)) {
223 yield* applyItem({ kind: "snapshot", snapshot: httpSnapshot.value });
224 canResume = true;
225 current = yield* SubscriptionRef.get(state);
226 }
211 }227 }
212228
213 return supportsCompletionMarker ? { requestCompletionMarker: true as const } : {};229 // If the authoritative refresh failed, omit the cached cursor so the
230 // socket fallback sends a complete snapshot for this new session.
231 if (!canResume || Option.isNone(current.snapshot)) {
232 return supportsCompletionMarker ? { requestCompletionMarker: true as const } : {};
233 }
234 if (!supportsCompletionMarker) {
235 // Without a completion marker there is no synchronized signal for a
236 // resumed subscription, so report live immediately, like threads.
237 yield* SubscriptionRef.update(state, (value) => ({
238 ...value,
239 status: "live" as const,
240 error: Option.none(),
241 }));
242 }
243 return {
244 afterSequence: current.snapshot.value.snapshotSequence,
245 ...(supportsCompletionMarker ? { requestCompletionMarker: true as const } : {}),
246 };
214 }),247 }),
215 {248 {
216 onExpectedFailure: (cause) => setStreamError(Cause.squash(cause)),249 onExpectedFailure: (cause) => setStreamError(Cause.squash(cause)),
packages/shared/src/observability.test.ts+26
...@@ -21,6 +21,7 @@ import {...@@ -21,6 +21,7 @@ import {
21 makeTraceSink,21 makeTraceSink,
22 type TraceRecord,22 type TraceRecord,
23 type TraceSinkFlushStats,23 type TraceSinkFlushStats,
24 truncateTraceAttributes,
24} from "./observability.ts";25} from "./observability.ts";
2526
26describe("errorTag", () => {27describe("errorTag", () => {
...@@ -111,6 +112,31 @@ const makeTestLayer = (tracePath: string) =>...@@ -111,6 +112,31 @@ const makeTestLayer = (tracePath: string) =>
111112
112const nodeServicesIt = it.layer(NodeServices.layer);113const nodeServicesIt = it.layer(NodeServices.layer);
113114
115describe("truncateTraceAttributes", () => {
116 it("clamps oversized strings at any depth without mutating the input", () => {
117 const stack = "s".repeat(2_000);
118 const attributes = {
119 "db.query.text": "q".repeat(2_000),
120 short: "ok",
121 error: { name: "Error", stack, nested: ["a".repeat(2_000)] },
122 };
123 const truncated = truncateTraceAttributes(attributes);
124
125 assert.equal((truncated["db.query.text"] as string).length, 200 + "…[truncated]".length);
126 assert.equal(truncated["short"], "ok");
127 const error = truncated["error"] as { stack: string; nested: Array<string> };
128 assert.equal(error.stack.length, 500 + "…[truncated]".length);
129 assert.equal(error.nested[0]?.length, 500 + "…[truncated]".length);
130 // Input is untouched: the live span's attributes are shared.
131 assert.equal(attributes.error.stack, stack);
132 });
133
134 it("returns the same reference when nothing exceeds the limits", () => {
135 const attributes = { short: "ok", nested: { fine: "also ok" } };
136 assert.equal(truncateTraceAttributes(attributes), attributes);
137 });
138});
139
114describe("observability", () => {140describe("observability", () => {
115 it("normalizes circular arrays, maps, and sets without recursing forever", () => {141 it("normalizes circular arrays, maps, and sets without recursing forever", () => {
116 const array: Array<unknown> = ["alpha"];142 const array: Array<unknown> = ["alpha"];
packages/shared/src/observability.ts+60-3
...@@ -248,6 +248,61 @@ function formatTraceExit(exit: Exit.Exit<unknown, unknown>): EffectTraceRecord["...@@ -248,6 +248,61 @@ function formatTraceExit(exit: Exit.Exit<unknown, unknown>): EffectTraceRecord["
248 };248 };
249}249}
250250
251const TRACE_ATTRIBUTE_MAX_LENGTH = 500;
252const TRACE_ATTRIBUTE_TRUNCATED_LENGTH = 200;
253const TRACE_ATTRIBUTE_TRUNCATION_SUFFIX = "…[truncated]";
254const ALWAYS_TRUNCATED_TRACE_ATTRIBUTES: ReadonlySet<string> = new Set(["db.query.text"]);
255
256// Clamps strings nested inside already-normalized attribute values (arrays and
257// plain objects from normalizeJsonValue, e.g. an Error's `stack`). Returns the
258// input reference when nothing was clamped.
259function truncateNestedValue(value: unknown): unknown {
260 if (typeof value === "string") {
261 return value.length <= TRACE_ATTRIBUTE_MAX_LENGTH
262 ? value
263 : `${value.slice(0, TRACE_ATTRIBUTE_MAX_LENGTH)}${TRACE_ATTRIBUTE_TRUNCATION_SUFFIX}`;
264 }
265 if (Array.isArray(value)) {
266 const truncated = value.map(truncateNestedValue);
267 return truncated.some((entry, index) => entry !== value[index]) ? truncated : value;
268 }
269 if (isPlainObject(value)) {
270 let truncated: Record<string, unknown> | undefined;
271 for (const [key, entry] of Object.entries(value)) {
272 const next = truncateNestedValue(entry);
273 if (next === entry) continue;
274 truncated ??= { ...value };
275 truncated[key] = next;
276 }
277 return truncated ?? value;
278 }
279 return value;
280}
281
282/**
283 * Clamps oversized attribute values on the serialized trace record so the file
284 * sink stays small, including strings nested inside arrays and objects (e.g.
285 * error stacks). Returns a new record when anything was clamped; never
286 * mutates the input (the live span's attributes are shared with other tracers).
287 */
288export function truncateTraceAttributes(attributes: TraceAttributes): TraceAttributes {
289 let truncated: Record<string, unknown> | undefined;
290 for (const [key, value] of Object.entries(attributes)) {
291 if (typeof value === "string" && ALWAYS_TRUNCATED_TRACE_ATTRIBUTES.has(key)) {
292 if (value.length <= TRACE_ATTRIBUTE_TRUNCATED_LENGTH) continue;
293 truncated ??= { ...attributes };
294 truncated[key] =
295 `${value.slice(0, TRACE_ATTRIBUTE_TRUNCATED_LENGTH)}${TRACE_ATTRIBUTE_TRUNCATION_SUFFIX}`;
296 continue;
297 }
298 const next = truncateNestedValue(value);
299 if (next === value) continue;
300 truncated ??= { ...attributes };
301 truncated[key] = next;
302 }
303 return truncated ?? attributes;
304}
305
251export function spanToTraceRecord(span: SerializableSpan): EffectTraceRecord {306export function spanToTraceRecord(span: SerializableSpan): EffectTraceRecord {
252 const status = span.status as Extract<Tracer.SpanStatus, { _tag: "Ended" }>;307 const status = span.status as Extract<Tracer.SpanStatus, { _tag: "Ended" }>;
253 const parentSpanId = Option.getOrUndefined(span.parent)?.spanId;308 const parentSpanId = Option.getOrUndefined(span.parent)?.spanId;
...@@ -263,16 +318,18 @@ export function spanToTraceRecord(span: SerializableSpan): EffectTraceRecord {...@@ -263,16 +318,18 @@ export function spanToTraceRecord(span: SerializableSpan): EffectTraceRecord {
263 startTimeUnixNano: String(status.startTime),318 startTimeUnixNano: String(status.startTime),
264 endTimeUnixNano: String(status.endTime),319 endTimeUnixNano: String(status.endTime),
265 durationMs: Number(status.endTime - status.startTime) / 1_000_000,320 durationMs: Number(status.endTime - status.startTime) / 1_000_000,
266 attributes: compactTraceAttributes(Object.fromEntries(span.attributes)),321 attributes: truncateTraceAttributes(
322 compactTraceAttributes(Object.fromEntries(span.attributes)),
323 ),
267 events: span.events.map(([name, startTime, attributes]) => ({324 events: span.events.map(([name, startTime, attributes]) => ({
268 name,325 name,
269 timeUnixNano: String(startTime),326 timeUnixNano: String(startTime),
270 attributes: compactTraceAttributes(attributes),327 attributes: truncateTraceAttributes(compactTraceAttributes(attributes)),
271 })),328 })),
272 links: span.links.map((link) => ({329 links: span.links.map((link) => ({
273 traceId: link.span.traceId,330 traceId: link.span.traceId,
274 spanId: link.span.spanId,331 spanId: link.span.spanId,
275 attributes: compactTraceAttributes(link.attributes),332 attributes: truncateTraceAttributes(compactTraceAttributes(link.attributes)),
276 })),333 })),
277 exit: formatTraceExit(status.exit),334 exit: formatTraceExit(status.exit),
278 };335 };
packages/shared/src/shell.ts+65
...@@ -3,6 +3,7 @@ import * as NodeOS from "node:os";...@@ -3,6 +3,7 @@ import * as NodeOS from "node:os";
3import * as NodePath from "node:path";3import * as NodePath from "node:path";
4import * as NodeChildProcess from "node:child_process";4import * as NodeChildProcess from "node:child_process";
5import * as NodeFS from "node:fs";5import * as NodeFS from "node:fs";
6import * as Clock from "effect/Clock";
6import * as Data from "effect/Data";7import * as Data from "effect/Data";
7import * as Effect from "effect/Effect";8import * as Effect from "effect/Effect";
8import * as FileSystem from "effect/FileSystem";9import * as FileSystem from "effect/FileSystem";
...@@ -491,6 +492,54 @@ function resolveCommandCandidates(...@@ -491,6 +492,54 @@ function resolveCommandCandidates(
491 return Array.from(new Set(candidates));492 return Array.from(new Set(candidates));
492}493}
493494
495// Session bootstrap resolves the same commands over and over, each PATH scan
496// costing hundreds of 'shell.isExecutableFile' filesystem probes (tens of
497// thousands per connect). Memoize the scan outcome per
498// (platform, PATH, PATHEXT, command) for a short window: repeat scans hit the
499// cache while any change to the search environment invalidates immediately.
500// Explicit-path resolution is never cached - callers probe paths they have
501// just written (e.g. managed binary installs). A "not-found" outcome is also
502// cached for the TTL, so a just-installed binary can stay invisible for up to
503// 30s unless resolved by explicit path.
504// TTL expiry uses the monotonic clock (Clock.currentTimeNanos) so backward
505// wall-clock adjustments cannot keep expired entries alive.
506const COMMAND_RESOLUTION_CACHE_TTL_NANOS = 30_000_000_000n;
507const COMMAND_RESOLUTION_CACHE_MAX_ENTRIES = 512;
508const COMMAND_RESOLUTION_CACHE_KEY_SEPARATOR = String.fromCharCode(0);
509
510interface CommandResolutionCacheEntry {
511 readonly resolvedPath: string | null;
512 readonly expiresAtNanos: bigint;
513}
514
515// The cache lives in the Effect environment (like HostProcessPlatform above)
516// so tests and embedders can provide an isolated instance; the default is a
517// single process-wide map shared by all consumers.
518export const CommandResolutionCache = Context.Reference<Map<string, CommandResolutionCacheEntry>>(
519 "@t3tools/shared/shell/CommandResolutionCache",
520 {
521 defaultValue: () => new Map(),
522 },
523);
524
525function cacheCommandResolution(
526 cache: Map<string, CommandResolutionCacheEntry>,
527 cacheKey: string,
528 resolvedPath: string | null,
529 nowNanos: bigint,
530): void {
531 if (cache.size >= COMMAND_RESOLUTION_CACHE_MAX_ENTRIES) {
532 const oldestKey = cache.keys().next().value;
533 if (oldestKey !== undefined) {
534 cache.delete(oldestKey);
535 }
536 }
537 cache.set(cacheKey, {
538 resolvedPath,
539 expiresAtNanos: nowNanos + COMMAND_RESOLUTION_CACHE_TTL_NANOS,
540 });
541}
542
494const isExecutableFile = Effect.fn("shell.isExecutableFile")(function* (543const isExecutableFile = Effect.fn("shell.isExecutableFile")(function* (
495 filePath: string,544 filePath: string,
496 platform: NodeJS.Platform,545 platform: NodeJS.Platform,
...@@ -538,6 +587,20 @@ const resolveCommandPathForPlatform = Effect.fn("shell.resolveCommandPathForPlat...@@ -538,6 +587,20 @@ const resolveCommandPathForPlatform = Effect.fn("shell.resolveCommandPathForPlat
538 if (pathValue.length === 0) {587 if (pathValue.length === 0) {
539 return yield* new CommandResolutionError({ command, reason: "not-found" });588 return yield* new CommandResolutionError({ command, reason: "not-found" });
540 }589 }
590
591 const cacheKey = [platform, pathValue, windowsPathExtensions.join(";"), command].join(
592 COMMAND_RESOLUTION_CACHE_KEY_SEPARATOR,
593 );
594 const cache = yield* CommandResolutionCache;
595 const nowNanos = yield* Clock.currentTimeNanos;
596 const cached = cache.get(cacheKey);
597 if (cached !== undefined && cached.expiresAtNanos > nowNanos) {
598 if (cached.resolvedPath === null) {
599 return yield* new CommandResolutionError({ command, reason: "not-found" });
600 }
601 return cached.resolvedPath;
602 }
603
541 const pathEntries: string[] = [];604 const pathEntries: string[] = [];
542 for (const entry of pathValue.split(pathDelimiterForPlatform(platform))) {605 for (const entry of pathValue.split(pathDelimiterForPlatform(platform))) {
543 const pathEntry = stripWrappingQuotes(entry.trim());606 const pathEntry = stripWrappingQuotes(entry.trim());
...@@ -550,10 +613,12 @@ const resolveCommandPathForPlatform = Effect.fn("shell.resolveCommandPathForPlat...@@ -550,10 +613,12 @@ const resolveCommandPathForPlatform = Effect.fn("shell.resolveCommandPathForPlat
550 for (const candidate of commandCandidates) {613 for (const candidate of commandCandidates) {
551 const candidatePath = path.join(pathEntry, candidate);614 const candidatePath = path.join(pathEntry, candidate);
552 if (yield* isExecutableFile(candidatePath, platform, windowsPathExtensions)) {615 if (yield* isExecutableFile(candidatePath, platform, windowsPathExtensions)) {
616 cacheCommandResolution(cache, cacheKey, candidatePath, nowNanos);
553 return candidatePath;617 return candidatePath;
554 }618 }
555 }619 }
556 }620 }
621 cacheCommandResolution(cache, cacheKey, null, nowNanos);
557 return yield* new CommandResolutionError({ command, reason: "not-found" });622 return yield* new CommandResolutionError({ command, reason: "not-found" });
558});623});
559624
patches/effect@4.0.0-beta.103.patch+17-6
...@@ -278,32 +278,43 @@ index b536d0a..12ffac0 100644...@@ -278,32 +278,43 @@ index b536d0a..12ffac0 100644
278 }).pipe(Effect.flatMap(() => Effect.fail(new Socket.SocketError({278 }).pipe(Effect.flatMap(() => Effect.fail(new Socket.SocketError({
279 reason: new Socket.SocketCloseError({279 reason: new Socket.SocketCloseError({
280 code: 1000280 code: 1000
281@@ -687,20 +716,20 @@ export const makeProtocolSocket = options => Protocol.make(Effect.fnUntraced(fun281@@ -687,20 +716,28 @@ export const makeProtocolSocket = options => Protocol.make(Effect.fnUntraced(fun
282 };282 };
283 }));283 }));
284 const defaultRetryPolicy = /*#__PURE__*/Schedule.min([/*#__PURE__*/Schedule.exponential(500, 1.5), /*#__PURE__*/Schedule.spaced(5000)]);284 const defaultRetryPolicy = /*#__PURE__*/Schedule.min([/*#__PURE__*/Schedule.exponential(500, 1.5), /*#__PURE__*/Schedule.spaced(5000)]);
285-const makePinger = /*#__PURE__*/Effect.fnUntraced(function* (writePing) {285-const makePinger = /*#__PURE__*/Effect.fnUntraced(function* (writePing) {
286+const makePinger = /*#__PURE__*/Effect.fnUntraced(function* (writePing, hooks) {286+const makePinger = /*#__PURE__*/Effect.fnUntraced(function* (writePing, hooks) {
287 let recievedPong = true;287 let recievedPong = true;
288+ let missedPongs = 0;
288 const latch = Latch.makeUnsafe();289 const latch = Latch.makeUnsafe();
289 const reset = () => {290 const reset = () => {
290 recievedPong = true;291 recievedPong = true;
292+ missedPongs = 0;
291 latch.closeUnsafe();293 latch.closeUnsafe();
292 };294 };
293- const onPong = () => {295- const onPong = () => {
294+ const onPong = Effect.sync(() => {296- recievedPong = true;
295 recievedPong = true;
296- };297- };
298+ const onPong = Effect.sync(() => {
299+ recievedPong = true;
300+ missedPongs = 0;
297+ }).pipe(Effect.andThen(hooks?.onPong ?? Effect.void));301+ }).pipe(Effect.andThen(hooks?.onPong ?? Effect.void));
298 yield* Effect.suspend(() => {302 yield* Effect.suspend(() => {
299 if (!recievedPong) return latch.open;303- if (!recievedPong) return latch.open;
300 recievedPong = false;304- recievedPong = false;
301- return writePing;305- return writePing;
306+ if (!recievedPong) {
307+ missedPongs += 1;
308+ if (missedPongs >= 3) return latch.open;
309+ return (hooks?.onPing ?? Effect.void).pipe(Effect.andThen(writePing));
310+ }
311+ recievedPong = false;
312+ missedPongs = 0;
302+ return (hooks?.onPing ?? Effect.void).pipe(Effect.andThen(writePing));313+ return (hooks?.onPing ?? Effect.void).pipe(Effect.andThen(writePing));
303 }).pipe(Effect.delay("5 seconds"), Effect.ignore, Effect.forever, Effect.interruptible, Effect.forkScoped);314 }).pipe(Effect.delay("5 seconds"), Effect.ignore, Effect.forever, Effect.interruptible, Effect.forkScoped);
304 return {315 return {
305 timeout: latch.await,316 timeout: latch.await,
306@@ -843,6 +872,11 @@ export const makeProtocolWorker = options => Protocol.make(Effect.fnUntraced(fun317@@ -843,6 +880,11 @@ export const makeProtocolWorker = options => Protocol.make(Effect.fnUntraced(fun
307 * @since 4.0.0318 * @since 4.0.0
308 */319 */
309 export const layerProtocolWorker = /*#__PURE__*/flow(makeProtocolWorker, /*#__PURE__*/Layer.effect(Protocol));320 export const layerProtocolWorker = /*#__PURE__*/flow(makeProtocolWorker, /*#__PURE__*/Layer.effect(Protocol));
pnpm-lock.yaml+124-123
...@@ -76,7 +76,7 @@ patchedDependencies:...@@ -76,7 +76,7 @@ patchedDependencies:
76 '@pierre/diffs@1.3.0-beta.10': 7ef7cb0cbabb17c15cdb137554068b36f15f6f5265e73fb51452aa3380db91aa76 '@pierre/diffs@1.3.0-beta.10': 7ef7cb0cbabb17c15cdb137554068b36f15f6f5265e73fb51452aa3380db91aa
77 '@react-native-menu/menu@2.0.0': 5ea3ae4bf1d9baf5443b65c269bb09621c27a68d556f713778f37b1e8d46aaae77 '@react-native-menu/menu@2.0.0': 5ea3ae4bf1d9baf5443b65c269bb09621c27a68d556f713778f37b1e8d46aaae
78 '@react-navigation/native-stack@7.17.6': c7fc101b78d434904425e5a24c22fb0042298dec6f807250486e784f3c71727378 '@react-navigation/native-stack@7.17.6': c7fc101b78d434904425e5a24c22fb0042298dec6f807250486e784f3c717273
79 effect@4.0.0-beta.103: a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a979 effect@4.0.0-beta.103: af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6
80 expo-modules-jsi@56.0.10: 9170f8074ae4e35a0a086e756c8f815794fd3abe51eac67ca3ba02804225ec1f80 expo-modules-jsi@56.0.10: 9170f8074ae4e35a0a086e756c8f815794fd3abe51eac67ca3ba02804225ec1f
81 react-native-gesture-handler@2.31.2: 808eb26f9e57cf4945efd3985af4d9c764da6f91f4c9764433cc868602bbf4d381 react-native-gesture-handler@2.31.2: 808eb26f9e57cf4945efd3985af4d9c764da6f91f4c9764433cc868602bbf4d3
82 react-native-keyboard-controller@1.21.13: 20be72c84d74253acdcfefbc6defe36dc396944f1a44cab2bdd0e3cd572ae00882 react-native-keyboard-controller@1.21.13: 20be72c84d74253acdcfefbc6defe36dc396944f1a44cab2bdd0e3cd572ae008
...@@ -116,7 +116,7 @@ importers:...@@ -116,7 +116,7 @@ importers:
116 version: 0.0.3116 version: 0.0.3
117 '@effect/platform-node':117 '@effect/platform-node':
118 specifier: 4.0.0-beta.103118 specifier: 4.0.0-beta.103
119 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)119 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
120 '@t3tools/client-runtime':120 '@t3tools/client-runtime':
121 specifier: workspace:*121 specifier: workspace:*
122 version: link:../../packages/client-runtime122 version: link:../../packages/client-runtime
...@@ -134,7 +134,7 @@ importers:...@@ -134,7 +134,7 @@ importers:
134 version: link:../../packages/tailscale134 version: link:../../packages/tailscale
135 effect:135 effect:
136 specifier: 4.0.0-beta.103136 specifier: 4.0.0-beta.103
137 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)137 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
138 electron:138 electron:
139 specifier: 41.5.0139 specifier: 41.5.0
140 version: 41.5.0140 version: 41.5.0
...@@ -153,7 +153,7 @@ importers:...@@ -153,7 +153,7 @@ importers:
153 devDependencies:153 devDependencies:
154 '@effect/vitest':154 '@effect/vitest':
155 specifier: 4.0.0-beta.103155 specifier: 4.0.0-beta.103
156 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))156 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
157 '@types/node':157 '@types/node':
158 specifier: 24.12.4158 specifier: 24.12.4
159 version: 24.12.4159 version: 24.12.4
...@@ -199,7 +199,7 @@ importers:...@@ -199,7 +199,7 @@ importers:
199 version: 4.1.2(expo-auth-session@56.0.14(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3))(expo-constants@56.0.18)(expo-crypto@56.0.4(expo@56.0.12))(expo-secure-store@56.0.4(expo@56.0.12))(expo-web-browser@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)))(expo@56.0.12)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3)199 version: 4.1.2(expo-auth-session@56.0.14(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3))(expo-constants@56.0.18)(expo-crypto@56.0.4(expo@56.0.12))(expo-secure-store@56.0.4(expo@56.0.12))(expo-web-browser@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)))(expo@56.0.12)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3)
200 '@effect/atom-react':200 '@effect/atom-react':
201 specifier: 4.0.0-beta.103201 specifier: 4.0.0-beta.103
202 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(react@19.2.3)(scheduler@0.27.0)202 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(react@19.2.3)(scheduler@0.27.0)
203 '@expo-google-fonts/dm-sans':203 '@expo-google-fonts/dm-sans':
204 specifier: ^0.4.2204 specifier: ^0.4.2
205 version: 0.4.2205 version: 0.4.2
...@@ -274,7 +274,7 @@ importers:...@@ -274,7 +274,7 @@ importers:
274 version: 8.0.3274 version: 8.0.3
275 effect:275 effect:
276 specifier: 4.0.0-beta.103276 specifier: 4.0.0-beta.103
277 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)277 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
278 expo:278 expo:
279 specifier: ~56.0.12279 specifier: ~56.0.12
280 version: 56.0.12(8895228379997a2a064f9644cda56ed0)280 version: 56.0.12(8895228379997a2a064f9644cda56ed0)
...@@ -422,7 +422,7 @@ importers:...@@ -422,7 +422,7 @@ importers:
422 devDependencies:422 devDependencies:
423 '@effect/vitest':423 '@effect/vitest':
424 specifier: 4.0.0-beta.103424 specifier: 4.0.0-beta.103
425 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))425 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
426 '@pierre/trees':426 '@pierre/trees':
427 specifier: 1.0.0-beta.4427 specifier: 1.0.0-beta.4
428 version: 1.0.0-beta.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)428 version: 1.0.0-beta.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
...@@ -446,16 +446,16 @@ importers:...@@ -446,16 +446,16 @@ importers:
446 version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)446 version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)
447 '@effect/platform-bun':447 '@effect/platform-bun':
448 specifier: 4.0.0-beta.103448 specifier: 4.0.0-beta.103
449 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)449 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
450 '@effect/platform-node':450 '@effect/platform-node':
451 specifier: 4.0.0-beta.103451 specifier: 4.0.0-beta.103
452 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)452 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
453 '@effect/platform-node-shared':453 '@effect/platform-node-shared':
454 specifier: 4.0.0-beta.103454 specifier: 4.0.0-beta.103
455 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)455 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
456 '@effect/sql-sqlite-bun':456 '@effect/sql-sqlite-bun':
457 specifier: 4.0.0-beta.103457 specifier: 4.0.0-beta.103
458 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))458 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
459 '@ff-labs/fff-node':459 '@ff-labs/fff-node':
460 specifier: 0.9.4460 specifier: 0.9.4
461 version: 0.9.4(patch_hash=2b16019ce7ab61aec6478dd02f79ef468cc1d5c51e9d00764f7d2ab8167210c8)461 version: 0.9.4(patch_hash=2b16019ce7ab61aec6478dd02f79ef468cc1d5c51e9d00764f7d2ab8167210c8)
...@@ -467,7 +467,7 @@ importers:...@@ -467,7 +467,7 @@ importers:
467 version: 1.3.0-beta.10(patch_hash=7ef7cb0cbabb17c15cdb137554068b36f15f6f5265e73fb51452aa3380db91aa)(@shikijs/themes@4.3.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)467 version: 1.3.0-beta.10(patch_hash=7ef7cb0cbabb17c15cdb137554068b36f15f6f5265e73fb51452aa3380db91aa)(@shikijs/themes@4.3.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
468 effect:468 effect:
469 specifier: 4.0.0-beta.103469 specifier: 4.0.0-beta.103
470 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)470 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
471 node-pty:471 node-pty:
472 specifier: ^1.1.0472 specifier: ^1.1.0
473 version: 1.1.0473 version: 1.1.0
...@@ -477,7 +477,7 @@ importers:...@@ -477,7 +477,7 @@ importers:
477 devDependencies:477 devDependencies:
478 '@effect/vitest':478 '@effect/vitest':
479 specifier: 4.0.0-beta.103479 specifier: 4.0.0-beta.103
480 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))480 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
481 '@t3tools/contracts':481 '@t3tools/contracts':
482 specifier: workspace:*482 specifier: workspace:*
483 version: link:../../packages/contracts483 version: link:../../packages/contracts
...@@ -531,7 +531,7 @@ importers:...@@ -531,7 +531,7 @@ importers:
531 version: 3.2.2(react@19.2.6)531 version: 3.2.2(react@19.2.6)
532 '@effect/atom-react':532 '@effect/atom-react':
533 specifier: 4.0.0-beta.103533 specifier: 4.0.0-beta.103
534 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(react@19.2.6)(scheduler@0.27.0)534 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(react@19.2.6)(scheduler@0.27.0)
535 '@formkit/auto-animate':535 '@formkit/auto-animate':
536 specifier: ^0.9.0536 specifier: ^0.9.0
537 version: 0.9.0537 version: 0.9.0
...@@ -567,7 +567,7 @@ importers:...@@ -567,7 +567,7 @@ importers:
567 version: 0.7.1567 version: 0.7.1
568 effect:568 effect:
569 specifier: 4.0.0-beta.103569 specifier: 4.0.0-beta.103
570 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)570 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
571 jose:571 jose:
572 specifier: 'catalog:'572 specifier: 'catalog:'
573 version: 6.2.2573 version: 6.2.2
...@@ -607,10 +607,10 @@ importers:...@@ -607,10 +607,10 @@ importers:
607 devDependencies:607 devDependencies:
608 '@effect/platform-node':608 '@effect/platform-node':
609 specifier: 4.0.0-beta.103609 specifier: 4.0.0-beta.103
610 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)610 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
611 '@effect/vitest':611 '@effect/vitest':
612 specifier: 4.0.0-beta.103612 specifier: 4.0.0-beta.103
613 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))613 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
614 '@rolldown/plugin-babel':614 '@rolldown/plugin-babel':
615 specifier: ^0.2.0615 specifier: ^0.2.0
616 version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)616 version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)
...@@ -658,7 +658,7 @@ importers:...@@ -658,7 +658,7 @@ importers:
658 version: 3.14.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)658 version: 3.14.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
659 '@effect/sql-pg':659 '@effect/sql-pg':
660 specifier: 4.0.0-beta.103660 specifier: 4.0.0-beta.103
661 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))661 version: 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
662 '@noble/curves':662 '@noble/curves':
663 specifier: 'catalog:'663 specifier: 'catalog:'
664 version: 1.9.1664 version: 1.9.1
...@@ -676,23 +676,23 @@ importers:...@@ -676,23 +676,23 @@ importers:
676 version: link:../../packages/shared676 version: link:../../packages/shared
677 alchemy:677 alchemy:
678 specifier: 2.0.0-beta.65678 specifier: 2.0.0-beta.65
679 version: 2.0.0-beta.65(a455401069e1fee89f31a277c51247f6)679 version: 2.0.0-beta.65(75567d8add6e3362e26fe00f83a97bee)
680 drizzle-orm:680 drizzle-orm:
681 specifier: 1.0.0-rc.4681 specifier: 1.0.0-rc.4
682 version: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3)682 version: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3)
683 effect:683 effect:
684 specifier: 4.0.0-beta.103684 specifier: 4.0.0-beta.103
685 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)685 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
686 devDependencies:686 devDependencies:
687 '@cloudflare/workers-types':687 '@cloudflare/workers-types':
688 specifier: ^4.20260601.1688 specifier: ^4.20260601.1
689 version: 4.20260604.1689 version: 4.20260604.1
690 '@effect/platform-node':690 '@effect/platform-node':
691 specifier: 4.0.0-beta.103691 specifier: 4.0.0-beta.103
692 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)692 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
693 '@effect/vitest':693 '@effect/vitest':
694 specifier: 4.0.0-beta.103694 specifier: 4.0.0-beta.103
695 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))695 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
696 '@types/node':696 '@types/node':
697 specifier: 24.12.4697 specifier: 24.12.4
698 version: 24.12.4698 version: 24.12.4
...@@ -710,17 +710,17 @@ importers:...@@ -710,17 +710,17 @@ importers:
710 dependencies:710 dependencies:
711 '@effect/platform-node':711 '@effect/platform-node':
712 specifier: 4.0.0-beta.103712 specifier: 4.0.0-beta.103
713 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)713 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
714 '@oxlint/plugins':714 '@oxlint/plugins':
715 specifier: ^1.63.0715 specifier: ^1.63.0
716 version: 1.68.0716 version: 1.68.0
717 effect:717 effect:
718 specifier: 4.0.0-beta.103718 specifier: 4.0.0-beta.103
719 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)719 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
720 devDependencies:720 devDependencies:
721 '@effect/vitest':721 '@effect/vitest':
722 specifier: 4.0.0-beta.103722 specifier: 4.0.0-beta.103
723 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))723 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
724 vite-plus:724 vite-plus:
725 specifier: 'catalog:'725 specifier: 'catalog:'
726 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)726 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)
...@@ -735,11 +735,11 @@ importers:...@@ -735,11 +735,11 @@ importers:
735 version: link:../shared735 version: link:../shared
736 effect:736 effect:
737 specifier: 4.0.0-beta.103737 specifier: 4.0.0-beta.103
738 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)738 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
739 devDependencies:739 devDependencies:
740 '@effect/vitest':740 '@effect/vitest':
741 specifier: 4.0.0-beta.103741 specifier: 4.0.0-beta.103
742 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))742 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
743 vite-plus:743 vite-plus:
744 specifier: 'catalog:'744 specifier: 'catalog:'
745 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)745 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)
...@@ -748,11 +748,11 @@ importers:...@@ -748,11 +748,11 @@ importers:
748 dependencies:748 dependencies:
749 effect:749 effect:
750 specifier: 4.0.0-beta.103750 specifier: 4.0.0-beta.103
751 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)751 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
752 devDependencies:752 devDependencies:
753 '@effect/vitest':753 '@effect/vitest':
754 specifier: 4.0.0-beta.103754 specifier: 4.0.0-beta.103
755 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))755 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
756 vite-plus:756 vite-plus:
757 specifier: 'catalog:'757 specifier: 'catalog:'
758 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)758 version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)
...@@ -761,17 +761,17 @@ importers:...@@ -761,17 +761,17 @@ importers:
761 dependencies:761 dependencies:
762 effect:762 effect:
763 specifier: 4.0.0-beta.103763 specifier: 4.0.0-beta.103
764 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)764 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
765 devDependencies:765 devDependencies:
766 '@effect/openapi-generator':766 '@effect/openapi-generator':
767 specifier: 'catalog:'767 specifier: 'catalog:'
768 version: 4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))768 version: 4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
769 '@effect/platform-node':769 '@effect/platform-node':
770 specifier: 4.0.0-beta.103770 specifier: 4.0.0-beta.103
771 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)771 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
772 '@effect/vitest':772 '@effect/vitest':
773 specifier: 4.0.0-beta.103773 specifier: 4.0.0-beta.103
774 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))774 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
775 '@types/node':775 '@types/node':
776 specifier: 24.12.4776 specifier: 24.12.4
777 version: 24.12.4777 version: 24.12.4
...@@ -783,17 +783,17 @@ importers:...@@ -783,17 +783,17 @@ importers:
783 dependencies:783 dependencies:
784 effect:784 effect:
785 specifier: 4.0.0-beta.103785 specifier: 4.0.0-beta.103
786 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)786 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
787 devDependencies:787 devDependencies:
788 '@effect/openapi-generator':788 '@effect/openapi-generator':
789 specifier: 'catalog:'789 specifier: 'catalog:'
790 version: 4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))790 version: 4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
791 '@effect/platform-node':791 '@effect/platform-node':
792 specifier: 4.0.0-beta.103792 specifier: 4.0.0-beta.103
793 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)793 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
794 '@effect/vitest':794 '@effect/vitest':
795 specifier: 4.0.0-beta.103795 specifier: 4.0.0-beta.103
796 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))796 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
797 '@types/node':797 '@types/node':
798 specifier: 24.12.4798 specifier: 24.12.4
799 version: 24.12.4799 version: 24.12.4
...@@ -814,7 +814,7 @@ importers:...@@ -814,7 +814,7 @@ importers:
814 version: link:../contracts814 version: link:../contracts
815 effect:815 effect:
816 specifier: 4.0.0-beta.103816 specifier: 4.0.0-beta.103
817 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)817 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
818 jose:818 jose:
819 specifier: 'catalog:'819 specifier: 'catalog:'
820 version: 6.2.2820 version: 6.2.2
...@@ -824,10 +824,10 @@ importers:...@@ -824,10 +824,10 @@ importers:
824 devDependencies:824 devDependencies:
825 '@effect/platform-node':825 '@effect/platform-node':
826 specifier: 4.0.0-beta.103826 specifier: 4.0.0-beta.103
827 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)827 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
828 '@effect/vitest':828 '@effect/vitest':
829 specifier: 4.0.0-beta.103829 specifier: 4.0.0-beta.103
830 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))830 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
831 '@types/node':831 '@types/node':
832 specifier: 24.12.4832 specifier: 24.12.4
833 version: 24.12.4833 version: 24.12.4
...@@ -845,14 +845,14 @@ importers:...@@ -845,14 +845,14 @@ importers:
845 version: link:../shared845 version: link:../shared
846 effect:846 effect:
847 specifier: 4.0.0-beta.103847 specifier: 4.0.0-beta.103
848 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)848 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
849 devDependencies:849 devDependencies:
850 '@effect/platform-node':850 '@effect/platform-node':
851 specifier: 4.0.0-beta.103851 specifier: 4.0.0-beta.103
852 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)852 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
853 '@effect/vitest':853 '@effect/vitest':
854 specifier: 4.0.0-beta.103854 specifier: 4.0.0-beta.103
855 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))855 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
856 '@types/node':856 '@types/node':
857 specifier: 24.12.4857 specifier: 24.12.4
858 version: 24.12.4858 version: 24.12.4
...@@ -864,17 +864,17 @@ importers:...@@ -864,17 +864,17 @@ importers:
864 dependencies:864 dependencies:
865 '@effect/platform-node':865 '@effect/platform-node':
866 specifier: 4.0.0-beta.103866 specifier: 4.0.0-beta.103
867 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)867 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
868 '@t3tools/shared':868 '@t3tools/shared':
869 specifier: workspace:*869 specifier: workspace:*
870 version: link:../shared870 version: link:../shared
871 effect:871 effect:
872 specifier: 4.0.0-beta.103872 specifier: 4.0.0-beta.103
873 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)873 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
874 devDependencies:874 devDependencies:
875 '@effect/vitest':875 '@effect/vitest':
876 specifier: 4.0.0-beta.103876 specifier: 4.0.0-beta.103
877 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))877 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
878 '@types/node':878 '@types/node':
879 specifier: 24.12.4879 specifier: 24.12.4
880 version: 24.12.4880 version: 24.12.4
...@@ -886,7 +886,7 @@ importers:...@@ -886,7 +886,7 @@ importers:
886 dependencies:886 dependencies:
887 '@effect/platform-node':887 '@effect/platform-node':
888 specifier: 4.0.0-beta.103888 specifier: 4.0.0-beta.103
889 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)889 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
890 '@t3tools/contracts':890 '@t3tools/contracts':
891 specifier: workspace:*891 specifier: workspace:*
892 version: link:../packages/contracts892 version: link:../packages/contracts
...@@ -898,7 +898,7 @@ importers:...@@ -898,7 +898,7 @@ importers:
898 version: link:../packages/tailscale898 version: link:../packages/tailscale
899 effect:899 effect:
900 specifier: 4.0.0-beta.103900 specifier: 4.0.0-beta.103
901 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)901 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
902 pngjs:902 pngjs:
903 specifier: 7.0.0903 specifier: 7.0.0
904 version: 7.0.0904 version: 7.0.0
...@@ -908,7 +908,7 @@ importers:...@@ -908,7 +908,7 @@ importers:
908 devDependencies:908 devDependencies:
909 '@effect/vitest':909 '@effect/vitest':
910 specifier: 4.0.0-beta.103910 specifier: 4.0.0-beta.103
911 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))911 version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
912 '@types/pngjs':912 '@types/pngjs':
913 specifier: 6.0.5913 specifier: 6.0.5
914 version: 6.0.5914 version: 6.0.5
...@@ -5947,6 +5947,7 @@ packages:...@@ -5947,6 +5947,7 @@ packages:
59475947
5948 crypto-js@4.2.0:5948 crypto-js@4.2.0:
5949 resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}5949 resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
5950 deprecated: Active development of CryptoJS has been discontinued. This library is no longer maintained.
59505951
5951 css-select@5.2.2:5952 css-select@5.2.2:
5952 resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}5953 resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
...@@ -11640,24 +11641,24 @@ snapshots:...@@ -11640,24 +11641,24 @@ snapshots:
1164011641
11641 '@cloudflare/workers-types@5.20260726.1': {}11642 '@cloudflare/workers-types@5.20260726.1': {}
1164211643
11643 '@distilled.cloud/aws@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11644 '@distilled.cloud/aws@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11644 dependencies:11645 dependencies:
11645 '@aws-crypto/crc32': 5.2.011646 '@aws-crypto/crc32': 5.2.0
11646 '@aws-crypto/util': 5.2.011647 '@aws-crypto/util': 5.2.0
11647 '@aws-sdk/credential-providers': 3.1062.011648 '@aws-sdk/credential-providers': 3.1062.0
11648 '@aws-sdk/types': 3.973.1011649 '@aws-sdk/types': 3.973.10
11649 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11650 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11650 '@smithy/shared-ini-file-loader': 4.5.611651 '@smithy/shared-ini-file-loader': 4.5.6
11651 '@smithy/types': 4.14.311652 '@smithy/types': 4.14.3
11652 '@smithy/util-base64': 4.4.611653 '@smithy/util-base64': 4.4.6
11653 aws4fetch: 1.0.2011654 aws4fetch: 1.0.20
11654 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11655 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11655 fast-xml-parser: 5.8.011656 fast-xml-parser: 5.8.0
1165611657
11657 '@distilled.cloud/axiom@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11658 '@distilled.cloud/axiom@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11658 dependencies:11659 dependencies:
11659 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11660 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11660 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11661 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1166111662
11662 '@distilled.cloud/cloudflare-rolldown-plugin@0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)':11663 '@distilled.cloud/cloudflare-rolldown-plugin@0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)':
11663 dependencies:11664 dependencies:
...@@ -11670,48 +11671,48 @@ snapshots:...@@ -11670,48 +11671,48 @@ snapshots:
11670 transitivePeerDependencies:11671 transitivePeerDependencies:
11671 - workerd11672 - workerd
1167211673
11673 '@distilled.cloud/cloudflare-runtime@0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11674 '@distilled.cloud/cloudflare-runtime@0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11674 dependencies:11675 dependencies:
11675 '@alchemy.run/node-utils': 0.0.511676 '@alchemy.run/node-utils': 0.0.5
11676 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11677 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11677 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11678 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11678 workerd: 1.20260704.111679 workerd: 1.20260704.1
11679 optionalDependencies:11680 optionalDependencies:
11680 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)11681 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
11681 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)11682 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
1168211683
11683 '@distilled.cloud/cloudflare-vite-plugin@0.13.10(8bf551e378e9cbc11f8bf1003fbc14a8)':11684 '@distilled.cloud/cloudflare-vite-plugin@0.13.10(f97c3167f1a1990dddb83bff73e575e5)':
11684 dependencies:11685 dependencies:
11685 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11686 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11686 '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)11687 '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)
11687 '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11688 '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11688 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11689 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11689 vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)'11690 vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)'
11690 optionalDependencies:11691 optionalDependencies:
11691 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)11692 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
11692 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)11693 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
11693 transitivePeerDependencies:11694 transitivePeerDependencies:
11694 - rolldown11695 - rolldown
11695 - workerd11696 - workerd
1169611697
11697 '@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11698 '@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11698 dependencies:11699 dependencies:
11699 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11700 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11700 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11701 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1170111702
11702 '@distilled.cloud/core@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11703 '@distilled.cloud/core@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11703 dependencies:11704 dependencies:
11704 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11705 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1170511706
11706 '@distilled.cloud/neon@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11707 '@distilled.cloud/neon@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11707 dependencies:11708 dependencies:
11708 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11709 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11709 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11710 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1171011711
11711 '@distilled.cloud/planetscale@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11712 '@distilled.cloud/planetscale@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11712 dependencies:11713 dependencies:
11713 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))11714 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
11714 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11715 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1171511716
11716 '@dnd-kit/accessibility@3.1.1(react@19.2.6)':11717 '@dnd-kit/accessibility@3.1.1(react@19.2.6)':
11717 dependencies:11718 dependencies:
...@@ -11747,47 +11748,47 @@ snapshots:...@@ -11747,47 +11748,47 @@ snapshots:
1174711748
11748 '@drizzle-team/brocli@0.12.0': {}11749 '@drizzle-team/brocli@0.12.0': {}
1174911750
11750 '@effect/atom-react@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(react@19.2.3)(scheduler@0.27.0)':11751 '@effect/atom-react@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(react@19.2.3)(scheduler@0.27.0)':
11751 dependencies:11752 dependencies:
11752 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11753 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11753 react: 19.2.311754 react: 19.2.3
11754 scheduler: 0.27.011755 scheduler: 0.27.0
1175511756
11756 '@effect/atom-react@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(react@19.2.6)(scheduler@0.27.0)':11757 '@effect/atom-react@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(react@19.2.6)(scheduler@0.27.0)':
11757 dependencies:11758 dependencies:
11758 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11759 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11759 react: 19.2.611760 react: 19.2.6
11760 scheduler: 0.27.011761 scheduler: 0.27.0
1176111762
11762 '@effect/openapi-generator@4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11763 '@effect/openapi-generator@4.0.0-beta.103(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11763 dependencies:11764 dependencies:
11764 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)11765 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
11765 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11766 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11766 swagger2openapi: 7.0.811767 swagger2openapi: 7.0.8
11767 transitivePeerDependencies:11768 transitivePeerDependencies:
11768 - encoding11769 - encoding
1176911770
11770 '@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)':11771 '@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)':
11771 dependencies:11772 dependencies:
11772 '@effect/platform-node-shared': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)11773 '@effect/platform-node-shared': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
11773 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11774 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11774 transitivePeerDependencies:11775 transitivePeerDependencies:
11775 - bufferutil11776 - bufferutil
11776 - utf-8-validate11777 - utf-8-validate
1177711778
11778 '@effect/platform-node-shared@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)':11779 '@effect/platform-node-shared@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)':
11779 dependencies:11780 dependencies:
11780 '@types/ws': 8.18.111781 '@types/ws': 8.18.1
11781 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11782 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11782 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)11783 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
11783 transitivePeerDependencies:11784 transitivePeerDependencies:
11784 - bufferutil11785 - bufferutil
11785 - utf-8-validate11786 - utf-8-validate
1178611787
11787 '@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)':11788 '@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)':
11788 dependencies:11789 dependencies:
11789 '@effect/platform-node-shared': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)11790 '@effect/platform-node-shared': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
11790 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11791 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11791 ioredis: 5.11.011792 ioredis: 5.11.0
11792 mime: 4.1.011793 mime: 4.1.0
11793 undici: 8.9.011794 undici: 8.9.0
...@@ -11795,14 +11796,14 @@ snapshots:...@@ -11795,14 +11796,14 @@ snapshots:
11795 - bufferutil11796 - bufferutil
11796 - utf-8-validate11797 - utf-8-validate
1179711798
11798 '@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11799 '@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11799 dependencies:11800 dependencies:
11800 '@cloudflare/workers-types': 5.20260726.111801 '@cloudflare/workers-types': 5.20260726.1
11801 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11802 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1180211803
11803 '@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11804 '@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11804 dependencies:11805 dependencies:
11805 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11806 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
11806 pg: 8.22.011807 pg: 8.22.0
11807 pg-connection-string: 2.14.011808 pg-connection-string: 2.14.0
11808 pg-cursor: 2.21.0(pg@8.22.0)11809 pg-cursor: 2.21.0(pg@8.22.0)
...@@ -11811,9 +11812,9 @@ snapshots:...@@ -11811,9 +11812,9 @@ snapshots:
11811 transitivePeerDependencies:11812 transitivePeerDependencies:
11812 - pg-native11813 - pg-native
1181311814
11814 '@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11815 '@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11815 dependencies:11816 dependencies:
11816 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11817 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1181711818
11818 '@effect/tsgo-darwin-arm64@0.13.2':11819 '@effect/tsgo-darwin-arm64@0.13.2':
11819 optional: true11820 optional: true
...@@ -11846,9 +11847,9 @@ snapshots:...@@ -11846,9 +11847,9 @@ snapshots:
11846 '@effect/tsgo-win32-arm64': 0.13.211847 '@effect/tsgo-win32-arm64': 0.13.2
11847 '@effect/tsgo-win32-x64': 0.13.211848 '@effect/tsgo-win32-x64': 0.13.2
1184811849
11849 '@effect/vitest@4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))':11850 '@effect/vitest@4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))':
11850 dependencies:11851 dependencies:
11851 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)11852 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
1185211853
11853 '@egjs/hammerjs@2.0.17':11854 '@egjs/hammerjs@2.0.17':
11854 dependencies:11855 dependencies:
...@@ -15350,22 +15351,22 @@ snapshots:...@@ -15350,22 +15351,22 @@ snapshots:
15350 json-schema-traverse: 1.0.015351 json-schema-traverse: 1.0.0
15351 require-from-string: 2.0.215352 require-from-string: 2.0.2
1535215353
15353 alchemy@2.0.0-beta.65(a455401069e1fee89f31a277c51247f6):15354 alchemy@2.0.0-beta.65(75567d8add6e3362e26fe00f83a97bee):
15354 dependencies:15355 dependencies:
15355 '@alchemy.run/node-utils': 0.0.515356 '@alchemy.run/node-utils': 0.0.5
15356 '@aws-sdk/credential-providers': 3.1062.015357 '@aws-sdk/credential-providers': 3.1062.0
15357 '@clack/prompts': 0.11.015358 '@clack/prompts': 0.11.0
15358 '@distilled.cloud/aws': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15359 '@distilled.cloud/aws': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15359 '@distilled.cloud/axiom': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15360 '@distilled.cloud/axiom': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15360 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15361 '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15361 '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)15362 '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)
15362 '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15363 '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15363 '@distilled.cloud/cloudflare-vite-plugin': 0.13.10(8bf551e378e9cbc11f8bf1003fbc14a8)15364 '@distilled.cloud/cloudflare-vite-plugin': 0.13.10(f97c3167f1a1990dddb83bff73e575e5)
15364 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15365 '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15365 '@distilled.cloud/neon': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15366 '@distilled.cloud/neon': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15366 '@distilled.cloud/planetscale': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15367 '@distilled.cloud/planetscale': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15367 '@effect/sql-d1': 4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15368 '@effect/sql-d1': 4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15368 '@effect/vitest': 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15369 '@effect/vitest': 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15369 '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)15370 '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)
15370 '@octokit/rest': 22.0.115371 '@octokit/rest': 22.0.1
15371 '@octokit/webhooks': 14.2.015372 '@octokit/webhooks': 14.2.0
...@@ -15375,7 +15376,7 @@ snapshots:...@@ -15375,7 +15376,7 @@ snapshots:
15375 '@types/aws-lambda': 8.10.16115376 '@types/aws-lambda': 8.10.161
15376 aws4fetch: 1.0.2015377 aws4fetch: 1.0.20
15377 capnweb: 0.6.115378 capnweb: 0.6.1
15378 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)15379 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
15379 fast-glob: 3.3.315380 fast-glob: 3.3.3
15380 fast-xml-parser: 5.8.015381 fast-xml-parser: 5.8.0
15381 ink: 6.8.0(@types/react@19.2.16)(bufferutil@4.1.0)(react-devtools-core@6.1.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react@19.2.6)(utf-8-validate@6.0.6)15382 ink: 6.8.0(@types/react@19.2.16)(bufferutil@4.1.0)(react-devtools-core@6.1.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react@19.2.6)(utf-8-validate@6.0.6)
...@@ -15391,11 +15392,11 @@ snapshots:...@@ -15391,11 +15392,11 @@ snapshots:
15391 undici: 7.27.115392 undici: 7.27.1
15392 yaml: 2.9.015393 yaml: 2.9.0
15393 optionalDependencies:15394 optionalDependencies:
15394 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6)15395 '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6)
15395 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6)15396 '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6)
15396 '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))15397 '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
15397 drizzle-kit: 1.0.0-rc.415398 drizzle-kit: 1.0.0-rc.4
15398 drizzle-orm: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3)15399 drizzle-orm: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3)
15399 vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)'15400 vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)'
15400 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)15401 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)
15401 transitivePeerDependencies:15402 transitivePeerDependencies:
...@@ -16418,15 +16419,15 @@ snapshots:...@@ -16418,15 +16419,15 @@ snapshots:
16418 get-tsconfig: 4.14.016419 get-tsconfig: 4.14.0
16419 jiti: 2.7.016420 jiti: 2.7.0
1642016421
16421 drizzle-orm@1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3):16422 drizzle-orm@1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3):
16422 optionalDependencies:16423 optionalDependencies:
16423 '@cloudflare/workers-types': 4.20260604.116424 '@cloudflare/workers-types': 4.20260604.1
16424 '@effect/sql-d1': 4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))16425 '@effect/sql-d1': 4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
16425 '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))16426 '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
16426 '@effect/sql-sqlite-bun': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))16427 '@effect/sql-sqlite-bun': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))
16427 '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)16428 '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)
16428 bun-types: 1.3.1416429 bun-types: 1.3.14
16429 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)16430 effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
16430 expo-sqlite: 56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)16431 expo-sqlite: 56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
16431 mysql2: 3.22.4(@types/node@24.12.4)16432 mysql2: 3.22.4(@types/node@24.12.4)
16432 pg: 8.21.016433 pg: 8.21.0
...@@ -16446,7 +16447,7 @@ snapshots:...@@ -16446,7 +16447,7 @@ snapshots:
1644616447
16447 ee-first@1.1.1: {}16448 ee-first@1.1.1: {}
1644816449
16449 effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9):16450 effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6):
16450 dependencies:16451 dependencies:
16451 '@standard-schema/spec': 1.1.016452 '@standard-schema/spec': 1.1.0
16452 fast-check: 4.9.016453 fast-check: 4.9.0