From e088923afc2d49237c6751d89ae3a2b3b9374af3 Mon Sep 17 00:00:00 2001
From: Codex
Date: Wed, 14 Oct 2026 00:32:05 +0000
Subject: [PATCH 1/3] fix(workspace): refetch failed route reads and contain
editor width
Refs sass-maker/saas-maker#244, sass-maker/saas-maker#242 and sass-maker/saas-maker#241.
Synthetic local acceptance only; production identity and device gates remain separate.
---
__tests__/route-error-retry.test.tsx | 38 ++++++++++++++++++++++++
src/app/cover-letter/[jobId]/error.tsx | 6 ++--
src/app/dashboard/error.tsx | 6 ++--
src/app/editor/[id]/error.tsx | 6 ++--
src/app/error.tsx | 6 ++--
src/app/global-error.tsx | 6 ++--
src/app/interview-prep/[jobId]/error.tsx | 6 ++--
src/app/tailor/[jobId]/error.tsx | 6 ++--
src/components/workspace-interior.tsx | 2 +-
9 files changed, 60 insertions(+), 22 deletions(-)
create mode 100644 __tests__/route-error-retry.test.tsx
diff --git a/__tests__/route-error-retry.test.tsx b/__tests__/route-error-retry.test.tsx
new file mode 100644
index 0000000..73ce8a6
--- /dev/null
+++ b/__tests__/route-error-retry.test.tsx
@@ -0,0 +1,38 @@
+import { act, createElement } from 'react';
+import { createRoot } from 'react-dom/client';
+import { afterEach, expect, it, vi } from 'vitest';
+import RootError from '@/app/error';
+import GlobalError from '@/app/global-error';
+import DashboardError from '@/app/dashboard/error';
+import EditorError from '@/app/editor/[id]/error';
+import TailorError from '@/app/tailor/[jobId]/error';
+import CoverLetterError from '@/app/cover-letter/[jobId]/error';
+import InterviewError from '@/app/interview-prep/[jobId]/error';
+
+vi.mock('@/lib/foundry-monitoring', () => ({ captureError: vi.fn() }));
+afterEach(() => vi.restoreAllMocks());
+for (const [name, Boundary] of [
+ ['root', RootError],
+ ['global', GlobalError],
+ ['dashboard', DashboardError],
+ ['editor', EditorError],
+ ['tailor', TailorError],
+ ['cover letter', CoverLetterError],
+ ['interview', InterviewError],
+] as const) {
+ it(`${name} retries the failed server segment instead of merely clearing its cached error`, async () => {
+ vi.spyOn(console, 'error').mockImplementation(() => {});
+ const retry = vi.fn();
+ const reset = vi.fn();
+ const node = document.createElement('div');
+ document.body.append(node);
+ const root = createRoot(node);
+ const props = { error: new Error('Synthetic read failure'), retry, reset };
+ await act(async () => root.render(createElement(Boundary, props)));
+ await act(async () => node.querySelector('button')!.click());
+ expect(retry).toHaveBeenCalledOnce();
+ expect(reset).not.toHaveBeenCalled();
+ await act(async () => root.unmount());
+ node.remove();
+ });
+}
diff --git a/src/app/cover-letter/[jobId]/error.tsx b/src/app/cover-letter/[jobId]/error.tsx
index 8e5be45..fdf67cd 100644
--- a/src/app/cover-letter/[jobId]/error.tsx
+++ b/src/app/cover-letter/[jobId]/error.tsx
@@ -7,10 +7,10 @@ import { captureError } from '@/lib/foundry-monitoring';
export default function CoverLetterError({
error,
- reset,
+ retry,
}: {
error: Error & { digest?: string };
- reset: () => void;
+ retry: () => void;
}) {
useEffect(() => {
console.error(error);
@@ -25,7 +25,7 @@ export default function CoverLetterError({
Something went wrong while preparing this page. Any saved drafts are safe — try again.
-