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:
@@ -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 });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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": "",
|
||||
|
||||
@@ -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": "",
|
||||
|
||||
@@ -5897,7 +5897,12 @@
|
||||
"selectNavItem": "대상 선택",
|
||||
"removeNavItem": "{{item}} 제거",
|
||||
"moveNavItemEarlier": "{{item}} 앞으로 이동",
|
||||
"moveNavItemLater": "{{item}} 뒤로 이동"
|
||||
"moveNavItemLater": "{{item}} 뒤로 이동",
|
||||
"ephemeralAgentTaskCreationPolicy": "임시 에이전트 후속 작업",
|
||||
"ephemeralAgentTaskCreationPolicyHint": "기본값 없음 — 미설정 시 허용으로 폴백합니다. 검증 후는 받은편지함으로 제안을 보내 원클릭 승인합니다. 거부는 후속 작업 생성을 거부합니다.",
|
||||
"ephemeralAgentTaskCreationPolicyAllow": "허용",
|
||||
"ephemeralAgentTaskCreationPolicyUponValidation": "검증 후",
|
||||
"ephemeralAgentTaskCreationPolicyDeny": "거부"
|
||||
},
|
||||
"globalGeneral": {
|
||||
"andShowsUpdateNoticesInTheCLIAnd": "",
|
||||
|
||||
@@ -5897,7 +5897,12 @@
|
||||
"selectNavItem": "选择目标",
|
||||
"removeNavItem": "移除 {{item}}",
|
||||
"moveNavItemEarlier": "将 {{item}} 前移",
|
||||
"moveNavItemLater": "将 {{item}} 后移"
|
||||
"moveNavItemLater": "将 {{item}} 后移",
|
||||
"ephemeralAgentTaskCreationPolicy": "临时代理后续任务",
|
||||
"ephemeralAgentTaskCreationPolicyHint": "无默认值 — 未设置时回退为允许。需验证会将提案发送到邮箱供一键批准;拒绝则禁止创建后续任务。",
|
||||
"ephemeralAgentTaskCreationPolicyAllow": "允许",
|
||||
"ephemeralAgentTaskCreationPolicyUponValidation": "需验证",
|
||||
"ephemeralAgentTaskCreationPolicyDeny": "拒绝"
|
||||
},
|
||||
"globalGeneral": {
|
||||
"andShowsUpdateNoticesInTheCLIAnd": "",
|
||||
|
||||
@@ -5897,7 +5897,12 @@
|
||||
"selectNavItem": "選擇目的地",
|
||||
"removeNavItem": "移除 {{item}}",
|
||||
"moveNavItemEarlier": "將 {{item}} 前移",
|
||||
"moveNavItemLater": "將 {{item}} 後移"
|
||||
"moveNavItemLater": "將 {{item}} 後移",
|
||||
"ephemeralAgentTaskCreationPolicy": "臨時代理後續任務",
|
||||
"ephemeralAgentTaskCreationPolicyHint": "無預設值 — 未設定時回退為允許。需驗證會將提案傳送到信箱供一鍵核准;拒絕則禁止建立後續任務。",
|
||||
"ephemeralAgentTaskCreationPolicyAllow": "允許",
|
||||
"ephemeralAgentTaskCreationPolicyUponValidation": "需驗證",
|
||||
"ephemeralAgentTaskCreationPolicyDeny": "拒絕"
|
||||
},
|
||||
"globalGeneral": {
|
||||
"andShowsUpdateNoticesInTheCLIAnd": "",
|
||||
|
||||
Reference in New Issue
Block a user