fix(tui): localize the engine-switch Making room receipts and toast the purge one

Follow-up to 8f54845f78 (Refs #6981). It fixes three review findings.

What
- The two receipts that retire_tui_engine writes are now typed MessageIds,
  not English literals:
  - ContextCompactionStoppedOnEngineSwitch, "Making room stopped; the
    conversation was not changed". This is the same text as the engine's
    cancel literal.
  - ContextPurgeAbandonedOnEngineSwitch, "Session cleanup was abandoned with
    the replaced engine; the conversation was not changed".
  Both sit next to ContextCompactionRouteInvalid in the enum, in
  ALL_MESSAGE_IDS and in en.json. Each of the 14 other complete packs has its
  own translation: ja, zh-Hans, zh-Hant, pt-BR, es-419, vi, ko, ca, de, fr,
  id, hi, ru and uk.
- The purge branch now calls app.push_status_toast(text, Warning,
  Some(5_000)) instead of set_explicit_compaction_status. It keeps the
  transcript receipt but no longer adds a write to the legacy status_message
  sink (crates/tui/AGENTS.md). The compaction branch is unchanged: it still
  settles through apply_compaction_cancelled.
- CHANGELOG.md and its synced copy in crates/tui had a wrong "before"
  sentence. /compact was never refused by the session-transition gate.
  try_queue_manual_compaction answered it with "Already making room."
  (ContextCompactionAlreadyRunning). The sentence now says so. The headline
  now reads "while a `/compact` is running or queued", because an automatic
  pass runs only inside a turn and the existing qualifier already says a
  running turn can keep /new refused.

Correction to the 8f54845f78 message (history is not rewritten). Its Why
section should read: "The session_transition_blockers gate then refused
/new, /new --force and /resume, and try_queue_manual_compaction answered
/compact with "Already making room.", until restart." Also drop its bullet
"The receipts are English literals, like the engine's existing compaction
strings". That is no longer true.

Verification (source = 9ded7ce896 + this diff. The tree was clean before the
edit. HEAD includes another writer's release commits 8b92463a2c and
9ded7ce896, which this change does not touch.)
- TUI probe, rerun from the i6981b V6b setup on a new debug build of this
  tree (scripts/dev-cargo.sh build -p codewhale-cli -p codewhale-tui
  --locked). It ran in an isolated tmux socket with a scratch HOME and
  CODEWHALE_HOME, CODEWHALE_TELEMETRY=0, and the local mock on
  127.0.0.1:18983 (error envelope, 8 s non-streaming delay). Steps: hi,
  /compact, then /provider deepseek during the pass, /new, /new --force, Esc,
  /new. The locale was chosen with LC_ALL/LANG; settings locale is auto.
  - en_US.UTF-8: "Making room…", then "Making room stopped; the conversation
    was not changed", then "Provider switched: sub2api → deepseek". Each of
    the three /new commands printed "Started new session …". The mock got
    one non-streaming request.
  - zh_CN.UTF-8: the receipt read "已停止压缩上下文;对话未被更改". The footer
    was in Chinese and all three /new commands started new sessions.
  - Purge variant (/purge in place of /compact). This branch was only
    code-read for 8f54845f78.
    - en: the transcript showed "Session cleanup was abandoned with the
      replaced engine; the conversation was not changed". The footer showed
      the Warning toast, "Session cleanup was abandoned with the replaced
      engine", cut off at the toast width. /new, /new --force and /new
      after Esc all started new sessions.
    - zh-Hans: the transcript and the toast both read
      "会话清理已随被替换的引擎一同放弃;对话未被更改". /new started a new
      session.
    - The old engine still sent its non-streaming purge request, as the
      8f54845f78 message says.
- Localization:
  - scripts/with-hermetic-test-home.sh scripts/dev-cargo.sh nextest run -p
    codewhale-localization --lib --locked: "54 tests run: 54 passed".
    scripts/dev-test.sh has no localization area, so it could not be used.
  - python3 scripts/check-tui-locale-parity.py: PASS. Each pack has
    2554/2554 keys.
- scripts/dev-test.sh tui provider_switch compaction transition_blockers
  new_session redaction_gate workspace_switch provider_fallback
  profile_switch spawn_tui_engine: "232 tests run: 232 passed, 15119
  skipped".
- scripts/dev-cargo.sh clippy -p codewhale-tui -p codewhale-localization
  --all-targets --all-features --locked -- -D warnings
  -A clippy::uninlined_format_args -A clippy::too_many_arguments
  -A clippy::unnecessary_map_or: exit 0, no warnings.
- cargo fmt --all -- --check: clean.
- ./scripts/sync-changelog.sh --check: up to date.
- ./scripts/release/check-versions.sh --require-dated-release: exit 0.
- npm test && npm run check:web: exit 0. root 101/101;
  runtime-sdk 19/19; extension-host 420 tests, 413 pass, 0 fail, 7 skipped;
  web node 7/7; vitest 74 files, 772/772; check:web passed (next build
  994 pages).

Not verified:
- Whether the translations read naturally to a native speaker. Only en and
  zh-Hans were rendered in the TUI.
- The 5 s toast was still on screen at the capture 10 s after the switch.
  It was gone after the next input. I did not look into why.
- The reporter's actual blocker, Windows, other ways to replace the engine,
  the full workspace suite and hosted CI. These are the same limits as
  8f54845f78.

No new tests or code comments.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NBKbhx19BRbZtvWK8rVKjz
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-10-16 09:20:59 -07:00
1 parent 9ded7ce896
commit 856eefaa53
19 files changed
+68 -32

No files matched your search

+13 -12
View File
@@ -37,20 +37,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
tools (scp, rsync, nc, httpie, `aws s3 cp`) and secrets inside an ordinary
file are not detected. Full Access is unchanged (Refs CW-7236).
- Switching provider, model route, profile or workspace, or changing plugins,
while Making room is running or queued no longer leaves the session stuck.
while a `/compact` is running or queued no longer leaves the session stuck.
The pass on the replaced engine is stopped and the transcript says "Making
room stopped; the conversation was not changed". Before, `/new`,
`/new --force`, `/resume` and `/compact` were refused with "context
compaction is running" or "a manual compaction is queued" until Codewhale
was restarted. A `/compact` still waiting for a free engine slot is carried
to the new engine as before. A context purge caught by a switch cannot be
stopped: the replaced engine may still finish and bill its request, and the
transcript now says "Session cleanup was abandoned with the replaced engine;
the conversation was not changed" instead of blocking `/new` with "session
cleanup is running". A turn still running when the engine is replaced is not
covered and can keep `/new` refused. Thanks @luestr for reporting the
refusal in #6981; this is one way to reach it, and the report stays open
until the blocker that 0.10.2 names confirms its cause (Refs #6981).
`/new --force` and `/resume` were refused with "context compaction is
running" or "a manual compaction is queued", and `/compact` answered
"Already making room.", until Codewhale was restarted. A `/compact` still
waiting for a free engine slot is carried to the new engine as before. A
context purge caught by a switch cannot be stopped: the replaced engine may
still finish and bill its request, and the transcript now says "Session
cleanup was abandoned with the replaced engine; the conversation was not
changed" instead of blocking `/new` with "session cleanup is running". A
turn still running when the engine is replaced is not covered and can keep
`/new` refused. Thanks @luestr for reporting the refusal in #6981; this is
one way to reach it, and the report stays open until the blocker that
0.10.2 names confirms its cause (Refs #6981).
## [0.10.2] - 2026-10-13
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "No s'ha pogut posar la compactació del context a la cua perquè el motor està ocupat; torna-ho a provar quan acabi el torn.",
"ContextCompactionQueueClosed": "La compactació del context no està disponible perquè el motor ja no s'està executant.",
"ContextCompactionRouteInvalid": "No es pot compactar perquè la ruta del proveïdor actiu no és vàlida: {error}",
"ContextCompactionStoppedOnEngineSwitch": "S'ha aturat la compactació del context; la conversa no s'ha modificat",
"ContextPurgeAbandonedOnEngineSwitch": "La neteja de la sessió s'ha abandonat amb el motor substituït; la conversa no s'ha modificat",
"CtxInspTitle": "Inspector de context",
"CtxInspSessionContext": "Context de la sessió",
"CtxInspSystemPrompt": "Estructura del prompt del sistema",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "Die Kontextkomprimierung konnte nicht eingereiht werden, weil die Engine ausgelastet ist; versuche es nach Abschluss des Zugs erneut.",
"ContextCompactionQueueClosed": "Die Kontextkomprimierung ist nicht verfügbar, weil die Engine nicht mehr läuft.",
"ContextCompactionRouteInvalid": "Die Komprimierung ist nicht möglich, weil die aktive Provider-Route ungültig ist: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Kontextkomprimierung gestoppt; die Unterhaltung wurde nicht geändert",
"ContextPurgeAbandonedOnEngineSwitch": "Die Sitzungsbereinigung wurde mit der ersetzten Engine abgebrochen; die Unterhaltung wurde nicht geändert",
"CtxInspTitle": "Kontext-Inspektor",
"CtxInspSessionContext": "Sitzungskontext",
"CtxInspSystemPrompt": "System-Prompt-Struktur",
+2
View File
@@ -1290,6 +1290,8 @@
"ContextCompactionQueueFull": "Making room has to wait — the engine is busy. Try again after this turn.",
"ContextCompactionQueueClosed": "Can't make room — the engine stopped.",
"ContextCompactionRouteInvalid": "Can't compact — the active provider route is invalid: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Making room stopped; the conversation was not changed",
"ContextPurgeAbandonedOnEngineSwitch": "Session cleanup was abandoned with the replaced engine; the conversation was not changed",
"CtxInspTitle": "Context inspector",
"CtxInspSessionContext": "Session Context",
"CtxInspSystemPrompt": "System Prompt Structure",
+2
View File
@@ -1288,6 +1288,8 @@
"ContextCompactionQueueFull": "No se pudo poner en cola la compactación del contexto porque el motor está ocupado; inténtalo de nuevo cuando termine el turno.",
"ContextCompactionQueueClosed": "La compactación del contexto no está disponible porque el motor ya no está en ejecución.",
"ContextCompactionRouteInvalid": "No se puede compactar porque la ruta del proveedor activo no es válida: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Se detuvo la compactación del contexto; la conversación no cambió",
"ContextPurgeAbandonedOnEngineSwitch": "La limpieza de la sesión se abandonó con el motor reemplazado; la conversación no cambió",
"CtxInspTitle": "Inspector de contexto",
"CtxInspSessionContext": "Contexto de la sesión",
"CtxInspSystemPrompt": "Estructura del prompt del sistema",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "La compression du contexte n’a pas pu être mise en file d’attente car le moteur est occupé ; réessayez une fois le tour terminé.",
"ContextCompactionQueueClosed": "La compression du contexte est indisponible car le moteur ne fonctionne plus.",
"ContextCompactionRouteInvalid": "Impossible de compacter, car la route du fournisseur actif n’est pas valide : {error}",
"ContextCompactionStoppedOnEngineSwitch": "Compression du contexte arrêtée ; la conversation n’a pas été modifiée",
"ContextPurgeAbandonedOnEngineSwitch": "Nettoyage de la session abandonné avec le moteur remplacé ; la conversation n’a pas été modifiée",
"CtxInspTitle": "Inspecteur de contexte",
"CtxInspSessionContext": "Contexte de la session",
"CtxInspSystemPrompt": "Structure du prompt système",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "इंजन व्यस्त होने के कारण संदर्भ संपीड़न को कतार में नहीं लगाया जा सका; टर्न पूरा होने के बाद फिर कोशिश करें।",
"ContextCompactionQueueClosed": "संदर्भ संपीड़न उपलब्ध नहीं है क्योंकि इंजन अब नहीं चल रहा है।",
"ContextCompactionRouteInvalid": "संपीड़ित नहीं किया जा सकता क्योंकि सक्रिय प्रोवाइडर रूट अमान्य है: {error}",
"ContextCompactionStoppedOnEngineSwitch": "संदर्भ संपीड़न रोक दिया गया; बातचीत में कोई बदलाव नहीं हुआ",
"ContextPurgeAbandonedOnEngineSwitch": "बदले गए इंजन के साथ सत्र की सफ़ाई छोड़ दी गई; बातचीत में कोई बदलाव नहीं हुआ",
"CtxInspTitle": "कॉन्टेक्स्ट इंस्पेक्टर",
"CtxInspSessionContext": "सत्र कॉन्टेक्स्ट",
"CtxInspSystemPrompt": "सिस्टम प्रॉम्प्ट संरचना",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "Pemadatan konteks tidak dapat dimasukkan ke antrean karena mesin sedang sibuk; coba lagi setelah giliran selesai.",
"ContextCompactionQueueClosed": "Pemadatan konteks tidak tersedia karena mesin tidak lagi berjalan.",
"ContextCompactionRouteInvalid": "Tidak dapat memadatkan karena rute penyedia aktif tidak valid: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Pemadatan konteks dihentikan; percakapan tidak diubah",
"ContextPurgeAbandonedOnEngineSwitch": "Pembersihan sesi dibatalkan bersama mesin yang diganti; percakapan tidak diubah",
"CtxInspTitle": "Inspektor konteks",
"CtxInspSessionContext": "Konteks Sesi",
"CtxInspSystemPrompt": "Struktur System Prompt",
+2
View File
@@ -1288,6 +1288,8 @@
"ContextCompactionQueueFull": "エンジンがビジーなため、コンテキスト圧縮をキューに追加できませんでした。ターンの完了後にもう一度お試しください。",
"ContextCompactionQueueClosed": "エンジンがすでに停止しているため、コンテキスト圧縮を利用できません。",
"ContextCompactionRouteInvalid": "アクティブなプロバイダールートが無効なため圧縮できません: {error}",
"ContextCompactionStoppedOnEngineSwitch": "コンテキスト圧縮を停止しました。会話は変更されていません",
"ContextPurgeAbandonedOnEngineSwitch": "セッションのクリーンアップは置き換えられたエンジンとともに中止されました。会話は変更されていません",
"CtxInspTitle": "コンテキストインスペクタ",
"CtxInspSessionContext": "セッションコンテキスト",
"CtxInspSystemPrompt": "システムプロンプト構造",
+2
View File
@@ -1290,6 +1290,8 @@
"ContextCompactionQueueFull": "엔진이 사용 중이어서 컨텍스트 압축을 대기열에 추가할 수 없습니다. 턴이 끝난 후 다시 시도하세요.",
"ContextCompactionQueueClosed": "엔진이 더 이상 실행 중이 아니므로 컨텍스트 압축을 사용할 수 없습니다.",
"ContextCompactionRouteInvalid": "현재 프로바이더 경로가 올바르지 않아 압축할 수 없습니다: {error}",
"ContextCompactionStoppedOnEngineSwitch": "컨텍스트 압축을 중지했습니다. 대화는 변경되지 않았습니다",
"ContextPurgeAbandonedOnEngineSwitch": "교체된 엔진과 함께 세션 정리가 중단되었습니다. 대화는 변경되지 않았습니다",
"CtxInspTitle": "컨텍스트 인스펙터",
"CtxInspSessionContext": "세션 컨텍스트",
"CtxInspSystemPrompt": "시스템 프롬프트 구조",
+2
View File
@@ -1288,6 +1288,8 @@
"ContextCompactionQueueFull": "Não foi possível enfileirar a compactação do contexto porque o mecanismo está ocupado; tente novamente após o término do turno.",
"ContextCompactionQueueClosed": "A compactação do contexto está indisponível porque o mecanismo não está mais em execução.",
"ContextCompactionRouteInvalid": "Não é possível compactar porque a rota do provedor ativo é inválida: {error}",
"ContextCompactionStoppedOnEngineSwitch": "A compactação do contexto foi interrompida; a conversa não foi alterada",
"ContextPurgeAbandonedOnEngineSwitch": "A limpeza da sessão foi abandonada com o mecanismo substituído; a conversa não foi alterada",
"CtxInspTitle": "Inspetor de contexto",
"CtxInspSessionContext": "Contexto da sessão",
"CtxInspSystemPrompt": "Estrutura do prompt do sistema",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "Не удалось поставить сжатие контекста в очередь, потому что движок занят; повторите попытку после завершения хода.",
"ContextCompactionQueueClosed": "Сжатие контекста недоступно, потому что движок больше не работает.",
"ContextCompactionRouteInvalid": "Невозможно выполнить сжатие, потому что активный маршрут провайдера недействителен: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Сжатие контекста остановлено; разговор не изменён",
"ContextPurgeAbandonedOnEngineSwitch": "Очистка сессии прервана вместе с заменённым движком; разговор не изменён",
"CtxInspTitle": "Инспектор контекста",
"CtxInspSessionContext": "Контекст сессии",
"CtxInspSystemPrompt": "Структура системного промпта",
+2
View File
@@ -1267,6 +1267,8 @@
"ContextCompactionQueueFull": "Не вдалося поставити стиснення контексту в чергу, оскільки рушій зайнятий; повторіть спробу після завершення ходу.",
"ContextCompactionQueueClosed": "Стиснення контексту недоступне, оскільки рушій більше не працює.",
"ContextCompactionRouteInvalid": "Неможливо виконати стиснення, оскільки активний маршрут провайдера недійсний: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Стиснення контексту зупинено; розмову не змінено",
"ContextPurgeAbandonedOnEngineSwitch": "Очищення сеансу скасовано разом із заміненим рушієм; розмову не змінено",
"CtxInspTitle": "Інспектор контексту",
"CtxInspSessionContext": "Контекст сесії",
"CtxInspSystemPrompt": "Структура системного промпту",
+2
View File
@@ -1288,6 +1288,8 @@
"ContextCompactionQueueFull": "Không thể đưa việc nén ngữ cảnh vào hàng đợi vì bộ máy đang bận; hãy thử lại sau khi lượt này kết thúc.",
"ContextCompactionQueueClosed": "Tính năng nén ngữ cảnh không khả dụng vì bộ máy không còn chạy.",
"ContextCompactionRouteInvalid": "Không thể nén vì tuyến của nhà cung cấp đang hoạt động không hợp lệ: {error}",
"ContextCompactionStoppedOnEngineSwitch": "Đã dừng nén ngữ cảnh; cuộc trò chuyện không bị thay đổi",
"ContextPurgeAbandonedOnEngineSwitch": "Đã bỏ dở việc dọn dẹp phiên cùng bộ máy bị thay thế; cuộc trò chuyện không bị thay đổi",
"CtxInspTitle": "Trình kiểm tra ngữ cảnh",
"CtxInspSessionContext": "Ngữ cảnh phiên",
"CtxInspSystemPrompt": "Cấu trúc lời nhắc hệ thống",
+2
View File
@@ -1290,6 +1290,8 @@
"ContextCompactionQueueFull": "上下文压缩需要等待:引擎正忙。请在本回合结束后重试。",
"ContextCompactionQueueClosed": "无法压缩上下文:引擎已停止。",
"ContextCompactionRouteInvalid": "无法压缩,因为当前提供商路由无效:{error}",
"ContextCompactionStoppedOnEngineSwitch": "已停止压缩上下文;对话未被更改",
"ContextPurgeAbandonedOnEngineSwitch": "会话清理已随被替换的引擎一同放弃;对话未被更改",
"CtxInspTitle": "上下文检查器",
"CtxInspSessionContext": "会话上下文",
"CtxInspSystemPrompt": "系统提示结构",
+2
View File
@@ -1288,6 +1288,8 @@
"ContextCompactionQueueFull": "上下文壓縮需要等待:引擎忙碌中。請在本回合結束後再試一次。",
"ContextCompactionQueueClosed": "無法壓縮上下文:引擎已停止。",
"ContextCompactionRouteInvalid": "無法壓縮,因為目前的供應商路由無效:{error}",
"ContextCompactionStoppedOnEngineSwitch": "已停止壓縮上下文;對話未被變更",
"ContextPurgeAbandonedOnEngineSwitch": "工作階段清理已隨被替換的引擎一併放棄;對話未被變更",
"CtxInspTitle": "上下文檢查器",
"CtxInspSessionContext": "工作階段上下文",
"CtxInspSystemPrompt": "系統提示結構",
+4
View File
@@ -1542,6 +1542,8 @@ pub enum MessageId {
ContextCompactionQueueFull,
ContextCompactionQueueClosed,
ContextCompactionRouteInvalid,
ContextCompactionStoppedOnEngineSwitch,
ContextPurgeAbandonedOnEngineSwitch,
CtxInspTitle,
CtxInspSessionContext,
CtxInspSystemPrompt,
@@ -4172,6 +4174,8 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[
MessageId::ContextCompactionQueueFull,
MessageId::ContextCompactionQueueClosed,
MessageId::ContextCompactionRouteInvalid,
MessageId::ContextCompactionStoppedOnEngineSwitch,
MessageId::ContextPurgeAbandonedOnEngineSwitch,
MessageId::CtxInspTitle,
MessageId::CtxInspSessionContext,
MessageId::CtxInspSystemPrompt,
+13 -12
View File
@@ -37,20 +37,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
tools (scp, rsync, nc, httpie, `aws s3 cp`) and secrets inside an ordinary
file are not detected. Full Access is unchanged (Refs CW-7236).
- Switching provider, model route, profile or workspace, or changing plugins,
while Making room is running or queued no longer leaves the session stuck.
while a `/compact` is running or queued no longer leaves the session stuck.
The pass on the replaced engine is stopped and the transcript says "Making
room stopped; the conversation was not changed". Before, `/new`,
`/new --force`, `/resume` and `/compact` were refused with "context
compaction is running" or "a manual compaction is queued" until Codewhale
was restarted. A `/compact` still waiting for a free engine slot is carried
to the new engine as before. A context purge caught by a switch cannot be
stopped: the replaced engine may still finish and bill its request, and the
transcript now says "Session cleanup was abandoned with the replaced engine;
the conversation was not changed" instead of blocking `/new` with "session
cleanup is running". A turn still running when the engine is replaced is not
covered and can keep `/new` refused. Thanks @luestr for reporting the
refusal in #6981; this is one way to reach it, and the report stays open
until the blocker that 0.10.2 names confirms its cause (Refs #6981).
`/new --force` and `/resume` were refused with "context compaction is
running" or "a manual compaction is queued", and `/compact` answered
"Already making room.", until Codewhale was restarted. A `/compact` still
waiting for a free engine slot is carried to the new engine as before. A
context purge caught by a switch cannot be stopped: the replaced engine may
still finish and bill its request, and the transcript now says "Session
cleanup was abandoned with the replaced engine; the conversation was not
changed" instead of blocking `/new` with "session cleanup is running". A
turn still running when the engine is replaced is not covered and can keep
`/new` refused. Thanks @luestr for reporting the refusal in #6981; this is
one way to reach it, and the report stays open until the blocker that
0.10.2 names confirms its cause (Refs #6981).
## [0.10.2] - 2026-10-13
+8 -8
View File
@@ -527,17 +527,17 @@ async fn retire_tui_engine(
let (id, auto) = active.unwrap_or_else(|| (queued.unwrap_or_default(), false));
app.manual_compaction_queued = false;
app.manual_compaction_id = None;
apply_compaction_cancelled(
app,
&id,
auto,
"Making room stopped; the conversation was not changed".to_string(),
);
let text = app
.tr(MessageId::ContextCompactionStoppedOnEngineSwitch)
.into_owned();
apply_compaction_cancelled(app, &id, auto, text);
}
if std::mem::take(&mut app.is_purging) {
let text = "Session cleanup was abandoned with the replaced engine; the conversation was not changed".to_string();
let text = app
.tr(MessageId::ContextPurgeAbandonedOnEngineSwitch)
.into_owned();
add_compaction_receipt(app, &text);
set_explicit_compaction_status(app, text, StatusToastLevel::Warning, false);
app.push_status_toast(text, StatusToastLevel::Warning, Some(5_000));
}
mcp_handoff
}