Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
bb485ef
fix(server): treat git 2.56 broken-gitfile stderr as non-repository
Ali-Al1 Nov 9, 2026
25631c3
fix(server): new worktrees refresh their index once, so captures and …
josephv123 Nov 11, 2026
e2a7814
fix(usage): Grok and Cursor usage limits show pace and the even-spend…
wookiist Nov 11, 2026
996b43f
fix(web): retain diff selection across navigation (#22347)
aleo113 Nov 11, 2026
0d36f2b
fix(mobile): subscription widget no longer expires on a window that a…
juliusmarminge Nov 11, 2026
b5256ad
fix(opencode): verify CLI updates when loopback server is still runni…
intrepid37 Nov 11, 2026
729f675
fix(usage): Claude subagent output is no longer undercounted (#20276)
rfrost-xyz Nov 11, 2026
d0d0608
fix(server): a remote update points the service unit at the runtime i…
Marve10s Nov 11, 2026
8d23699
fix(server): a limited provider's queue stays held after another prov…
Marve10s Nov 11, 2026
9ef52de
fix(shared): keep spreadsheet shorthand as inline code (#23203)
juliusmarminge Nov 11, 2026
25f4c9d
fix(web): offer retry while an environment reconnects (#23194)
juliusmarminge Nov 11, 2026
c9dfc40
fix(server): custom Codex providers no longer report native quota (#1…
fixfon Nov 11, 2026
e93f6ea
fix(desktop): Cmd+F now searches the page in the integrated browser (…
armanarutiunov Nov 11, 2026
f6433db
fix(desktop): an SSH password prompt that ended leaves the dialog ins…
Umais-Adeed Nov 11, 2026
2c74ea6
fix(web): render Claude insight blocks as a callout (#22239)
macodev00 Nov 11, 2026
ba32aab
fix(scheduler): show short server timezone on fixed-time labels (#23111)
shawk08033 Nov 11, 2026
4382138
fix(web): focus the primary action when confirmation dialogs open (#1…
rgrvlsk Nov 11, 2026
49bab99
fix(web): Changes row matches the diff comparison (#19553)
whoisaldo Nov 11, 2026
75c7fb2
fix(server): imported ACP sessions show their native history (#22155)
only21mil Nov 11, 2026
c266631
fix(preview): always return evaluated results by value (#22948)
juliusmarminge Nov 11, 2026
afb4f91
fix(provider-core): a model reply of "title" no longer replaces the t…
juliusmarminge Nov 11, 2026
52d621a
fix(desktop,web): Open in runs locally for a background service shari…
KinanLak Nov 11, 2026
d835e43
fix(web): question answers submit while normal sends are blocked (#22…
t3dotgg Nov 11, 2026
fd9b2c3
fix(server): cancelling a background-only delegated task reports it i…
only21mil Nov 11, 2026
54a5c51
fix(web): fall back to a readable server for shared repositories (#21…
sanjaibalajee Nov 11, 2026
2828f28
fix(web): composer follows an optionless thread instead of the settin…
f4llenz Nov 11, 2026
fcddd73
fix(web): don't save retention age until committed (#22208)
macodev00 Nov 11, 2026
faa8ad6
fix(server): one dropped probe no longer lists a live linked peer as …
juliusmarminge Nov 11, 2026
ab9df1d
chore(release): prepare v0.1.9
t3-code-bot[bot] Nov 11, 2026
36f4e07
fix(server): preview automation reports ambiguous selectors instead o…
juliusmarminge Nov 11, 2026
1530bec
fix(opencode): a context overflow that OpenCode compacts no longer fa…
juliusmarminge Nov 11, 2026
691b970
fix(web): Ctrl + "+" zooms on keyboard layouts with a dedicated plus …
juliusmarminge Nov 11, 2026
ea5f85e
fix(ci): release version bump push retries when main moves (#34326)
t3dotgg Nov 11, 2026
5da53f8
fix(server): CLI commands no longer migrate the database of a running…
juliusmarminge Nov 11, 2026
d56b82c
fix(web): keep saved default model when changing effort (#22193)
macodev00 Nov 11, 2026
6700cf6
fix(web): reveal expanded work rows hidden behind the composer (#21968)
ln-bodicherla Nov 11, 2026
b3f5d52
fix(composer): steer instead of queueing during automatic compaction …
NikitaMGrimm Nov 11, 2026
f3da8ff
feat(gitlab): resolve overview threads from Summary and Timeline (#30…
TonybynMp4 Nov 11, 2026
2718827
fix(web): pull request search keeps partial-word matches after GitHub…
juliusmarminge Nov 11, 2026
835e726
fix(server): Claude subagents no longer show the parent's effort (#17…
juansuaya17 Nov 11, 2026
d806251
fix(server): runs cancelled by a server restart say why in the thread…
juliusmarminge Nov 11, 2026
a74ee4c
fix(client-runtime): server updates stop waiting 32 minutes when the …
juliusmarminge Nov 11, 2026
cbc68c9
fix(web): Stop shows a pending state and repeat clicks no longer resu…
voida6 Nov 11, 2026
e0379fb
fix(web): collapsed reasoning previews no longer process the whole bl…
juliusmarminge Nov 11, 2026
52e8788
fix(server): storage cleanup skips stale worktree paths under a regul…
juliusmarminge Nov 11, 2026
dab06c0
fix(terminal): use a byte budget for Ghostty scrollback (#8766)
zero-two-rafaeltab Nov 11, 2026
bc8583b
fix(server): storage cleanup keeps worktrees whose file listing excee…
juliusmarminge Nov 11, 2026
a577e94
fix(server): delete temporary ACP health probe sessions (#25397)
juliusmarminge Nov 11, 2026
ad0b2a9
perf(client): streamed text no longer republishes thread queue and ch…
juliusmarminge Nov 11, 2026
8f4166b
fix(web): convert composer list markers completed later (#22997)
juliusmarminge Nov 11, 2026
4901343
test: remove tests that repeat another case or restate the source (#3…
shivamhwp Nov 11, 2026
0af2d21
fix(server): drop stale queued pull-request watch wakes (#21239)
Sinan53x Nov 11, 2026
d50a6fd
fix(web): preview recordings stay decodable after a viewport resize (…
MansTomb Nov 11, 2026
896e64f
fix(server): only offer claude update for native Claude installs (#14…
AI091 Nov 11, 2026
d2c2595
fix(server): tell outside agents which MCP tools need a thread and th…
juliusmarminge Nov 11, 2026
f0dba6a
fix(fork): repair published nightly dialog test conflict
Nov 11, 2026
0e0882c
fix(fork): integrate upstream Git 2.56 repository detection fix
Nov 11, 2026
98cac97
fix(server): recognize structured non-repository Git errors
Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,18 @@ jobs:
git add apps/server/package.json apps/desktop/package.json apps/web/package.json packages/contracts/package.json pnpm-lock.yaml
git commit --no-verify -m "chore(release): prepare $RELEASE_TAG"
git push origin HEAD:main
# main moves while this job runs, so a rejected push rebases and retries.
for attempt in 1 2 3 4 5; do
if git push origin HEAD:main; then
exit 0
fi
echo "Push rejected (attempt $attempt). Rebasing onto latest main."
git pull --rebase origin main
done
echo "Could not push the version bump after 5 attempts." >&2
exit 1
announce_discord:
name: Announce release on Discord
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@t3tools/desktop",
"version": "0.1.8",
"version": "0.1.9",
"private": true,
"type": "module",
"main": "dist-electron/boot.cjs",
Expand Down
38 changes: 0 additions & 38 deletions apps/desktop/src/app/ClerkTokenStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import * as NodeFS from "node:fs";
import * as NodeOS from "node:os";
import * as NodePath from "node:path";
import { assert, describe, it } from "@effect/vitest";
import { vi } from "vite-plus/test";

vi.mock("node:fs", { spy: true });

import { openClerkTokenStorage, type ClerkTokenStorage } from "./ClerkTokenStore.ts";

Expand Down Expand Up @@ -91,24 +88,6 @@ describePosix("ClerkTokenStore", () => {
});
});

it("removes the legacy token file when the private copy already exists", async () => {
await withStateDir((stateDir) => {
const directory = NodePath.join(stateDir, "clerk");
const legacyPath = NodePath.join(stateDir, "clerk-tokens.json");
const tokenPath = NodePath.join(directory, "clerk-tokens.json");
NodeFS.mkdirSync(directory, { mode: 0o755 });
writeLoose(legacyPath, "stale-credential");
writeLoose(tokenPath, "kept-credential");

openClerkTokenStorage(stateDir, () => idleStorage());

assert.equal(NodeFS.existsSync(legacyPath), false);
assert.equal(modeOf(directory), 0o700);
assert.equal(modeOf(tokenPath), 0o600);
assert.equal(NodeFS.readFileSync(tokenPath, "utf8"), "kept-credential");
});
});

it("resolves a relative state directory before opening storage", async () => {
await withStateDir(async (stateDir) => {
const relativeStateDir = NodePath.relative(process.cwd(), stateDir);
Expand Down Expand Up @@ -150,23 +129,6 @@ describePosix("ClerkTokenStore", () => {
});
});

it("migrates tokens when the legacy directory is on another filesystem", async () => {
await withStateDir((stateDir) => {
const legacyPath = NodePath.join(stateDir, "clerk-tokens.json");
writeLoose(legacyPath, "existing-session");
using _rename = vi.spyOn(NodeFS, "renameSync").mockImplementation(() => {
throw Object.assign(new Error("cross-device link"), { code: "EXDEV" });
});

openClerkTokenStorage(stateDir, idleStorage);

const tokenPath = NodePath.join(stateDir, "clerk", "clerk-tokens.json");
assert.equal(NodeFS.readFileSync(tokenPath, "utf8"), "existing-session");
assert.equal(modeOf(tokenPath), 0o600);
assert.equal(NodeFS.existsSync(legacyPath), false);
});
});

it("does not follow a symlinked clerk directory or token file", async () => {
await withStateDir(async (stateDir) => {
const outsideDirectory = NodePath.join(stateDir, "outside-dir");
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/src/ipc/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const BOOTSTRAP_SSH_BEARER_SESSION_CHANNEL = "desktop:bootstrap-ssh-beare
export const FETCH_SSH_SESSION_STATE_CHANNEL = "desktop:fetch-ssh-session-state";
export const SSH_PASSWORD_PROMPT_CHANNEL = "desktop:ssh-password-prompt";
export const RESOLVE_SSH_PASSWORD_PROMPT_CHANNEL = "desktop:resolve-ssh-password-prompt";
export const SSH_PASSWORD_PROMPT_SETTLED_CHANNEL = "desktop:ssh-password-prompt-settled";
export const GET_SERVER_EXPOSURE_STATE_CHANNEL = "desktop:get-server-exposure-state";
export const SET_SERVER_EXPOSURE_MODE_CHANNEL = "desktop:set-server-exposure-mode";
export const SET_TAILSCALE_SERVE_ENABLED_CHANNEL = "desktop:set-tailscale-serve-enabled";
Expand All @@ -94,6 +95,8 @@ export const PREVIEW_SET_ZOOM_FACTOR_CHANNEL = "desktop:preview-set-zoom-factor"
export const PREVIEW_HARD_RELOAD_CHANNEL = "desktop:preview-hard-reload";
export const PREVIEW_SET_COLOR_SCHEME_CHANNEL = "desktop:preview-set-color-scheme";
export const PREVIEW_SET_AUDIO_MUTED_CHANNEL = "desktop:preview-set-audio-muted";
export const PREVIEW_FIND_IN_PAGE_CHANNEL = "desktop:preview-find-in-page";
export const PREVIEW_STOP_FIND_IN_PAGE_CHANNEL = "desktop:preview-stop-find-in-page";
export const PREVIEW_SET_SHOWN_CHANNEL = "desktop:preview-set-shown";
export const PREVIEW_OPEN_DEVTOOLS_CHANNEL = "desktop:preview-open-devtools";
export const PREVIEW_CLEAR_COOKIES_CHANNEL = "desktop:preview-clear-cookies";
Expand All @@ -118,6 +121,7 @@ export const PREVIEW_RECORDING_SAVE_CHANNEL = "desktop:preview-recording-save";
export const PREVIEW_STATE_CHANGE_CHANNEL = "desktop:preview-state-change";
export const PREVIEW_POINTER_EVENT_CHANNEL = "desktop:preview-pointer-event";
export const PREVIEW_OPEN_LINK_CHANNEL = "desktop:preview-open-link";
export const PREVIEW_FIND_RESULT_CHANNEL = "desktop:preview-find-result";

export const MAC_PERMISSION_HELPER_CHANNEL = "desktop:mac-permission-helper";

Expand Down
26 changes: 26 additions & 0 deletions apps/desktop/src/ipc/methods/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DesktopPreviewPickElementInputSchema,
DesktopPreviewArtifactInputSchema,
DesktopPreviewConfigInputSchema,
DesktopPreviewFindInPageInputSchema,
DesktopPreviewNavigateInputSchema,
DesktopPreviewRecordingArtifactSchema,
DesktopPreviewRecordingSaveInputSchema,
Expand Down Expand Up @@ -59,6 +60,9 @@ export const installPreviewEventForwarding = Effect.fn(
yield* manager.subscribeOpenLinks((event) =>
electronWindow.sendAll(IpcChannels.PREVIEW_OPEN_LINK_CHANNEL, event),
);
yield* manager.subscribeFindResults((event) =>
electronWindow.sendAll(IpcChannels.PREVIEW_FIND_RESULT_CHANNEL, event),
);
});

const setForwardedShortcuts = DesktopIpc.makeIpcMethod({
Expand Down Expand Up @@ -116,6 +120,21 @@ const navigate = DesktopIpc.makeIpcMethod({
}),
});

const findInPage = DesktopIpc.makeIpcMethod({
channel: IpcChannels.PREVIEW_FIND_IN_PAGE_CHANNEL,
payload: DesktopPreviewFindInPageInputSchema,
result: Schema.Void,
handler: Effect.fn("desktop.ipc.preview.findInPage")(function* ({
tabId,
text,
forward,
newSession,
}) {
const manager = yield* PreviewManager.PreviewManager;
yield* manager.findInPage(tabId, text, { forward, newSession });
}),
});

const tabMethod = (
channel: string,
name: string,
Expand Down Expand Up @@ -169,6 +188,11 @@ const hardReload = tabMethod(
"desktop.ipc.preview.hardReload",
(manager, tabId) => manager.hardReload(tabId),
);
const stopFindInPage = tabMethod(
IpcChannels.PREVIEW_STOP_FIND_IN_PAGE_CHANNEL,
"desktop.ipc.preview.stopFindInPage",
(manager, tabId) => manager.stopFindInPage(tabId),
);
const setZoomFactor = DesktopIpc.makeIpcMethod({
channel: IpcChannels.PREVIEW_SET_ZOOM_FACTOR_CHANNEL,
payload: DesktopPreviewSetZoomFactorInputSchema,
Expand Down Expand Up @@ -452,6 +476,8 @@ export const methods = [
zoomOut,
resetZoom,
hardReload,
findInPage,
stopFindInPage,
setColorScheme,
setZoomFactor,
setAudioMuted,
Expand Down
30 changes: 30 additions & 0 deletions apps/desktop/src/preload.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
DesktopBridge,
DesktopPreviewAnnotationVoiceEvent,
DesktopPreviewFindResultEvent,
DesktopPreviewOpenLinkEvent,
DesktopPreviewPointerEvent,
DesktopPreviewRecordingInputEvent,
Expand Down Expand Up @@ -194,6 +195,17 @@ contextBridge.exposeInMainWorld("desktopBridge", {
ipcRenderer.removeListener(IpcChannels.SSH_PASSWORD_PROMPT_CHANNEL, wrappedListener);
};
},
onSshPasswordPromptSettled: (listener) => {
const wrappedListener = (_event: Electron.IpcRendererEvent, requestId: unknown) => {
if (typeof requestId !== "string") return;
listener(requestId);
};

ipcRenderer.on(IpcChannels.SSH_PASSWORD_PROMPT_SETTLED_CHANNEL, wrappedListener);
return () => {
ipcRenderer.removeListener(IpcChannels.SSH_PASSWORD_PROMPT_SETTLED_CHANNEL, wrappedListener);
};
},
resolveSshPasswordPrompt: (requestId, password) =>
ipcRenderer.invoke(IpcChannels.RESOLVE_SSH_PASSWORD_PROMPT_CHANNEL, { requestId, password }),
getServerExposureState: () => ipcRenderer.invoke(IpcChannels.GET_SERVER_EXPOSURE_STATE_CHANNEL),
Expand Down Expand Up @@ -369,6 +381,15 @@ contextBridge.exposeInMainWorld("desktopBridge", {
ipcRenderer.invoke(IpcChannels.PREVIEW_SET_COLOR_SCHEME_CHANNEL, { tabId, colorScheme }),
setAudioMuted: (tabId, audioMuted) =>
ipcRenderer.invoke(IpcChannels.PREVIEW_SET_AUDIO_MUTED_CHANNEL, { tabId, audioMuted }),
findInPage: (tabId, text, { forward, newSession }) =>
ipcRenderer.invoke(IpcChannels.PREVIEW_FIND_IN_PAGE_CHANNEL, {
tabId,
text,
forward,
newSession,
}),
stopFindInPage: (tabId) =>
ipcRenderer.invoke(IpcChannels.PREVIEW_STOP_FIND_IN_PAGE_CHANNEL, { tabId }),
setShown: (tabId, shown) =>
ipcRenderer.invoke(IpcChannels.PREVIEW_SET_SHOWN_CHANNEL, { tabId, shown }),
openDevTools: (tabId) =>
Expand Down Expand Up @@ -469,5 +490,14 @@ contextBridge.exposeInMainWorld("desktopBridge", {
return () =>
ipcRenderer.removeListener(IpcChannels.PREVIEW_OPEN_LINK_CHANNEL, wrappedListener);
},
onFindResult: (listener) => {
const wrappedListener = (_event: Electron.IpcRendererEvent, findEvent: unknown) => {
if (typeof findEvent !== "object" || findEvent === null) return;
listener(findEvent as DesktopPreviewFindResultEvent);
};
ipcRenderer.on(IpcChannels.PREVIEW_FIND_RESULT_CHANNEL, wrappedListener);
return () =>
ipcRenderer.removeListener(IpcChannels.PREVIEW_FIND_RESULT_CHANNEL, wrappedListener);
},
},
} satisfies DesktopBridge);
1 change: 1 addition & 0 deletions apps/desktop/src/preview/GuestProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const ANNOTATION_THEME_CHANNEL = "preview:annotation-theme";
export const ANNOTATION_SEND_ENABLED_CHANNEL = "preview:annotation-send-enabled";
export const HUMAN_INPUT_CHANNEL = "preview:human-input";
export const MOUSE_NAVIGATE_CHANNEL = "preview:mouse-navigate";
export const PAGE_UNHANDLED_SHORTCUT_CHANNEL = "preview:page-unhandled-shortcut";
export const RECORDING_CURSOR_CHANNEL = "preview:recording-cursor";
export const RECORDING_POINTER_CHANNEL = "preview:recording-pointer";
export const RECORDING_KEY_CHANNEL = "preview:recording-key";
Expand Down
130 changes: 130 additions & 0 deletions apps/desktop/src/preview/Manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { it as effectIt } from "@effect/vitest";
import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
import * as NodeServices from "@effect/platform-node/NodeServices";
import type {
DesktopPreviewFindResultEvent,
DesktopPreviewRecordingInputEvent,
PreviewAnnotationPayload,
PreviewAnnotationRect,
Expand Down Expand Up @@ -812,6 +813,135 @@ describe("PreviewManager", () => {
),
);

effectIt.effect.each([
["darwin", true],
["linux", false],
["win32", false],
] as const)(
"lets the page and its iframes claim the find shortcut before the host opens find on %s",
([platform, usesMeta]) =>
withManager(
(manager) =>
Effect.gen(function* () {
const preview = makeFaviconWebContents();
const send = vi.fn();
const mainFrame = { processId: 1, routingId: 1 };
Object.assign(preview.webContents, {
hostWebContents: { isDestroyed: () => false, send },
mainFrame,
focusedFrame: mainFrame,
});
fromId.mockReturnValue(preview.webContents);
yield* manager.createTab("tab_page_find");
yield* manager.registerWebview("tab_page_find", 42);
yield* manager.setForwardedShortcuts([
{ command: "preview.find", shortcut: parseKeybindingShortcut("mod+f")! },
]);
const beforeInput = preview.listeners.get("before-input-event")!;
const findKey = {
type: "keyDown",
key: "f",
code: "KeyF",
meta: usesMeta,
control: !usesMeta,
};
const preventDefault = vi.fn();

beforeInput(
{ preventDefault } as never,
{ ...findKey, shift: false, alt: false } as never,
);
expect(preventDefault).not.toHaveBeenCalled();
expect(send).not.toHaveBeenCalled();

const ipcOn = (preview.webContents as Electron.WebContents).ipc.on as ReturnType<
typeof vi.fn
>;
const pageUnhandledShortcut = ipcOn.mock.calls.find(
([channel]) => channel === "preview:page-unhandled-shortcut",
)![1];
pageUnhandledShortcut(
{},
{
key: "f",
code: "KeyF",
metaKey: usesMeta,
ctrlKey: !usesMeta,
shiftKey: false,
altKey: false,
},
);
expect(send).toHaveBeenCalledExactlyOnceWith("desktop:menu-action", "preview.find");

Object.assign(preview.webContents, { focusedFrame: { processId: 1, routingId: 2 } });
beforeInput(
{ preventDefault } as never,
{ ...findKey, shift: false, alt: false } as never,
);
expect(preventDefault).not.toHaveBeenCalled();
expect(send).toHaveBeenCalledOnce();

Object.assign(preview.webContents, { focusedFrame: mainFrame });
yield* manager.setForwardedShortcuts([
{ command: "preview.find", shortcut: parseKeybindingShortcut("ctrl+alt+8")! },
]);
pageUnhandledShortcut(
{},
{
key: "[",
code: "Digit8",
metaKey: false,
ctrlKey: true,
shiftKey: false,
altKey: true,
},
);
expect(send).toHaveBeenCalledTimes(usesMeta ? 2 : 1);
}),
platform,
),
);

effectIt.effect("searches the guest page and reports its match counts", () =>
withManager((manager) =>
Effect.gen(function* () {
const preview = makeFaviconWebContents();
const findInPage = vi.fn();
const stopFindInPage = vi.fn();
Object.assign(preview.webContents, { findInPage, stopFindInPage });
fromId.mockReturnValue(preview.webContents);
yield* manager.createTab("tab_find");
yield* manager.registerWebview("tab_find", 42);
const reported = yield* Deferred.make<DesktopPreviewFindResultEvent>();
yield* manager.subscribeFindResults((event) => Deferred.succeed(reported, event));

yield* manager.findInPage("tab_find", "needle", { forward: true, newSession: true });
expect(findInPage).toHaveBeenCalledExactlyOnceWith("needle", {
forward: true,
findNext: true,
});

preview.listeners.get("found-in-page")!(
{} as never,
{
requestId: 1,
activeMatchOrdinal: 2,
matches: 5,
finalUpdate: true,
} as never,
);
expect(yield* Deferred.await(reported)).toEqual({
tabId: "tab_find",
activeMatchOrdinal: 2,
matches: 5,
});

yield* manager.stopFindInPage("tab_find");
expect(stopFindInPage).toHaveBeenCalledExactlyOnceWith("clearSelection");
}),
),
);

effectIt.effect("isolates failed state listeners and continues delivery", () => {
const loggedErrors: Array<unknown> = [];
const logger = Logger.make(({ message }) => {
Expand Down
Loading
Loading