fix: i18n ephemeral policy keys + planning loading race (#2298)

## Summary
- Full Suite
[29642536622](https://github.com/Runfusion/Fusion/actions/runs/29642536622)
after #2297: shards 1–2 green; shard 4 i18n parity + shard 3
PlanningMode loading.
- Add `settings.general.ephemeralAgentTaskCreationPolicy*` to
zh-CN/zh-TW/fr/es/ko (FN-8265 keys were en-only).
- Gate the follow-up SSE question in the PlanningMode loading test so
`.planning-loading` is assertable before the next question arrives (CI
race).

## Test plan
- [x] `@fusion/i18n` parity + gate-coverage tests
- [x] PlanningModeModal loading-after-response test
- [ ] Full Suite all 4 shards green on main

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added localized settings text for configuring ephemeral agent
follow-up task creation policies in Spanish, French, Korean, Simplified
Chinese, and Traditional Chinese.
* Added options to allow, require validation, or deny follow-up task
creation.

* **Tests**
* Improved planning mode loading-state test reliability with
deterministic synchronization.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
gsxdsm
2026-07-18 04:54:34 -07:00
committed by GitHub
parent b3904f6405
commit ec99f17478
6 changed files with 48 additions and 9 deletions

View File

@@ -517,6 +517,12 @@ describe("PlanningModeModal", () => {
});
it("shows loading state with appropriate text after submitting a response", async () => {
/*
FNXC:DashboardTests 2026-07-18-11:45:
Full Suite shard 3 failed when a 50ms setTimeout second-question race skipped the
loading paint under CI load. Gate the next SSE question on an explicit release so
`.planning-loading` is assertable before the follow-up question arrives.
*/
const secondQuestion: PlanningQuestion = {
id: "q-requirements",
type: "text",
@@ -525,6 +531,10 @@ describe("PlanningModeModal", () => {
};
let streamHandlers: any = null;
let releaseSecondQuestion: (() => void) | null = null;
const secondQuestionGate = new Promise<void>((resolve) => {
releaseSecondQuestion = resolve;
});
mockConnectPlanningStream.mockImplementation((_sessionId: string, _projectId: string | undefined, handlers: any) => {
streamHandlers = handlers;
@@ -540,12 +550,12 @@ describe("PlanningModeModal", () => {
});
mockRespondToPlanning.mockImplementation(async () => {
// Simulate server broadcasting second question via the existing SSE connection
setTimeout(() => {
// Hold the follow-up question until the loading UI has been observed.
void secondQuestionGate.then(() => {
if (streamHandlers) {
streamHandlers.onQuestion?.(secondQuestion);
}
}, 50);
});
return { sessionId: "session-123", currentQuestion: null, summary: null };
});
@@ -581,10 +591,14 @@ describe("PlanningModeModal", () => {
// Verify thinking container is visible during loading
expect(container.querySelector(".planning-thinking-container")).not.toBeNull();
await act(async () => {
releaseSecondQuestion?.();
});
// Wait for second question to appear
await waitFor(() => {
expect(screen.getByText("What are the key requirements?")).toBeDefined();
}, { timeout: 3000 });
});
});
});

View File

@@ -5897,7 +5897,12 @@
"selectNavItem": "Elegir un destino",
"removeNavItem": "Quitar {{item}}",
"moveNavItemEarlier": "Mover {{item}} antes",
"moveNavItemLater": "Mover {{item}} después"
"moveNavItemLater": "Mover {{item}} después",
"ephemeralAgentTaskCreationPolicy": "Tareas de seguimiento de agentes efímeros",
"ephemeralAgentTaskCreationPolicyHint": "Sin valor predeterminado — si no se define, se usa Permitir. «Tras validación» envía una propuesta a tu buzón para aprobar con un clic; Denegar rechaza la creación de tareas de seguimiento.",
"ephemeralAgentTaskCreationPolicyAllow": "Permitir",
"ephemeralAgentTaskCreationPolicyUponValidation": "Tras validación",
"ephemeralAgentTaskCreationPolicyDeny": "Denegar"
},
"globalGeneral": {
"andShowsUpdateNoticesInTheCLIAnd": "",

View File

@@ -5897,7 +5897,12 @@
"selectNavItem": "Choisir une destination",
"removeNavItem": "Retirer {{item}}",
"moveNavItemEarlier": "Déplacer {{item}} plus tôt",
"moveNavItemLater": "Déplacer {{item}} plus tard"
"moveNavItemLater": "Déplacer {{item}} plus tard",
"ephemeralAgentTaskCreationPolicy": "Tâches de suivi des agents éphémères",
"ephemeralAgentTaskCreationPolicyHint": "Pas de valeur par défaut — non défini revient à Autoriser. « Sur validation » envoie une proposition à votre boîte pour une approbation en un clic ; Refuser bloque la création de tâches de suivi.",
"ephemeralAgentTaskCreationPolicyAllow": "Autoriser",
"ephemeralAgentTaskCreationPolicyUponValidation": "Sur validation",
"ephemeralAgentTaskCreationPolicyDeny": "Refuser"
},
"globalGeneral": {
"andShowsUpdateNoticesInTheCLIAnd": "",

View File

@@ -5897,7 +5897,12 @@
"selectNavItem": "대상 선택",
"removeNavItem": "{{item}} 제거",
"moveNavItemEarlier": "{{item}} 앞으로 이동",
"moveNavItemLater": "{{item}} 뒤로 이동"
"moveNavItemLater": "{{item}} 뒤로 이동",
"ephemeralAgentTaskCreationPolicy": "임시 에이전트 후속 작업",
"ephemeralAgentTaskCreationPolicyHint": "기본값 없음 — 미설정 시 허용으로 폴백합니다. 검증 후는 받은편지함으로 제안을 보내 원클릭 승인합니다. 거부는 후속 작업 생성을 거부합니다.",
"ephemeralAgentTaskCreationPolicyAllow": "허용",
"ephemeralAgentTaskCreationPolicyUponValidation": "검증 후",
"ephemeralAgentTaskCreationPolicyDeny": "거부"
},
"globalGeneral": {
"andShowsUpdateNoticesInTheCLIAnd": "",

View File

@@ -5897,7 +5897,12 @@
"selectNavItem": "选择目标",
"removeNavItem": "移除 {{item}}",
"moveNavItemEarlier": "将 {{item}} 前移",
"moveNavItemLater": "将 {{item}} 后移"
"moveNavItemLater": "将 {{item}} 后移",
"ephemeralAgentTaskCreationPolicy": "临时代理后续任务",
"ephemeralAgentTaskCreationPolicyHint": "无默认值 — 未设置时回退为允许。需验证会将提案发送到邮箱供一键批准;拒绝则禁止创建后续任务。",
"ephemeralAgentTaskCreationPolicyAllow": "允许",
"ephemeralAgentTaskCreationPolicyUponValidation": "需验证",
"ephemeralAgentTaskCreationPolicyDeny": "拒绝"
},
"globalGeneral": {
"andShowsUpdateNoticesInTheCLIAnd": "",

View File

@@ -5897,7 +5897,12 @@
"selectNavItem": "選擇目的地",
"removeNavItem": "移除 {{item}}",
"moveNavItemEarlier": "將 {{item}} 前移",
"moveNavItemLater": "將 {{item}} 後移"
"moveNavItemLater": "將 {{item}} 後移",
"ephemeralAgentTaskCreationPolicy": "臨時代理後續任務",
"ephemeralAgentTaskCreationPolicyHint": "無預設值 — 未設定時回退為允許。需驗證會將提案傳送到信箱供一鍵核准;拒絕則禁止建立後續任務。",
"ephemeralAgentTaskCreationPolicyAllow": "允許",
"ephemeralAgentTaskCreationPolicyUponValidation": "需驗證",
"ephemeralAgentTaskCreationPolicyDeny": "拒絕"
},
"globalGeneral": {
"andShowsUpdateNoticesInTheCLIAnd": "",