diff --git a/docs/infrastructure/2026-10-20-confirm-transition-focus.md b/docs/infrastructure/2026-10-20-confirm-transition-focus.md
new file mode 100644
index 0000000..eea58fb
--- /dev/null
+++ b/docs/infrastructure/2026-10-20-confirm-transition-focus.md
@@ -0,0 +1,13 @@
+# Confirmation transition must preserve deliberate focus
+
+Release833 at main `f7dc22e5e7efe1fd1d64f6ace2c04cf2f95bf558` exposes a distinct confirmation failure after the earlier complete tab-cycle test correction: Cancel initially receives focus and reverse traversal succeeds, but the later opening-transition callback can reset focus while forward keyboard traversal is already under way. This is a user-visible shared-owner race, not permission to relax the tab sequence or increase its timeout.
+
+A deterministic new component regression focuses the named scroll body before advancing the opening transition. Existing code fails with focus moved back to Cancel:2existing cases pass/1new case fails (`p712-confirm-transition-red-20261020T184351Z`). Removing the redundant `onEntered` forced focus and its button ref leaves the existing Cancel `autoFocus` and MUI focus trap/restoration in place. All3component cases then pass (`p712-confirm-transition-green-20261020T184416Z`). No confirmation resolution, destructive guard, data write or dialog body accessibility changes.
+
+All5affected native journeys pass after this repair on20October18:44–18:46UTC, with zero skips/flaky/retries. They retain explicit Cancel → reverse Tab body → reverse Tab Confirm → forward Tab body → forward Tab Cancel, the original cancellation/focus/draft assertions, and Discovery create/delete persistence. App/browser TypeScript, lint and production build pass. Full integrated successor validation follows; Linux CI/deployed acceptance is not inferred from Windows.
+
+The interrupted P7-12 whole-browser attempt also exposed two stale English-only `Technical` template selectors after the approved Bokmål gallery localisation. That separate development test consumer now uses the existing locale key without changing template entitlement or any assertion. Original failing evidence is retained and the fresh successor run must use the repaired committed source.
+
+Release833 also records Chromium page crashes in the CV-controls and administrator route census. An18:39UTC runner observation reports no cgroup OOM events, no container memory limit,1GiB shared memory and no kernel errors in the queried interval. This observation neither explains the crashes nor proves hardware health. Keep this infrastructure/reliability qualification separate from the deterministically reproduced focus race.
+
+Production readiness remains NO-GO independently of the owner's release authorization. No model activation or P5-13 qualification is part of this repair.
diff --git a/job-tracker-ui/src/confirm.test.tsx b/job-tracker-ui/src/confirm.test.tsx
index 571415c..bd69952 100644
--- a/job-tracker-ui/src/confirm.test.tsx
+++ b/job-tracker-ui/src/confirm.test.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import '@testing-library/jest-dom';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, act } from '@testing-library/react';
import { ConfirmProvider, useConfirm } from './confirm';
import { I18nProvider } from './i18n/I18nProvider';
@@ -52,3 +52,18 @@ test('uses the selected language for shared dialog defaults', async () => {
expect(screen.getByRole('button', { name: 'Bekreft' })).toBeInTheDocument();
window.localStorage.removeItem('uiLanguage');
});
+
+test('finishing the opening transition preserves focus already moved inside the dialog', async () => {
+ jest.useFakeTimers();
+ try {
+ render();
+ fireEvent.click(screen.getByRole('button', { name: /open confirm/i }));
+ expect(screen.getByRole('button', { name: 'Cancel' })).toHaveFocus();
+ const message = screen.getByRole('region', { name: 'Delete job' });
+ act(() => message.focus());
+ await act(async () => { jest.advanceTimersByTime(1000); });
+ expect(message).toHaveFocus();
+ } finally {
+ jest.useRealTimers();
+ }
+});
diff --git a/job-tracker-ui/src/confirm.tsx b/job-tracker-ui/src/confirm.tsx
index 229dd7e..a9c2750 100644
--- a/job-tracker-ui/src/confirm.tsx
+++ b/job-tracker-ui/src/confirm.tsx
@@ -25,7 +25,6 @@ export function ConfirmProvider({ children }: { children: React.ReactNode }) {
const messageId = useId();
const titleId = useId();
const resolverRef = useRef<((value: boolean) => void) | null>(null);
- const cancelButtonRef = useRef(null);
const [state, setState] = useState({
open: false,
message: "",
@@ -64,7 +63,6 @@ export function ConfirmProvider({ children }: { children: React.ReactNode }) {