From 73b38babf0f833538effd41eaef06150bda47ab2 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 5 Jul 2026 10:42:21 -0700 Subject: [PATCH] FN-7578: surface aiUndoTaskWorkflowId picker in Settings General MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Settings → General picker so operators can choose which workflow governs AI-undo (revert) board tasks, instead of it being fixed. - Add aiUndoTaskWorkflowId select to GeneralSection, defaulting to builtin:review-heavy, with an "Inherit project default workflow" empty-string option matching the revert route's blank-is-inherit behavior (FN-7556) - Load full workflow list (including custom workflows, excluding fragments) separately from the builtin-only workflow list used for enable/disable checkboxes - Add FNXC:TaskRevert comment documenting the default/inherit semantics - Add tests for the new picker and update settings-default-descriptions test - Add changeset (minor) and update settings-reference/task-management docs - Add i18n strings across en/es/fr/ko/zh-CN/zh-TW locales Files changed: .changeset/fn-7578-ai-undo-workflow-setting-ui.md | 7 ++ docs/settings-reference.md | 2 +- docs/task-management.md | 2 +- .../settings/sections/GeneralSection.tsx | 42 +++++++ .../GeneralSection.aiUndoWorkflow.test.tsx | 129 +++++++++++++++++++++ .../settings-default-descriptions.test.tsx | 3 +- packages/i18n/locales/en/app.json | 5 +- packages/i18n/locales/es/app.json | 5 +- packages/i18n/locales/fr/app.json | 5 +- packages/i18n/locales/ko/app.json | 5 +- packages/i18n/locales/zh-CN/app.json | 5 +- packages/i18n/locales/zh-TW/app.json | 5 +- 12 files changed, 205 insertions(+), 10 deletions(-) Fusion-Task-Id: FN-7578 Fusion-Task-Lineage: 1d1701ab-ecc7-4bbe-a003-2ce45ac15a25 Co-authored-by: Fusion (runfusion.ai) --- .../fn-7578-ai-undo-workflow-setting-ui.md | 7 + docs/settings-reference.md | 2 +- docs/task-management.md | 2 +- .../settings/sections/GeneralSection.tsx | 42 ++++++ .../GeneralSection.aiUndoWorkflow.test.tsx | 129 ++++++++++++++++++ .../settings-default-descriptions.test.tsx | 3 +- packages/i18n/locales/en/app.json | 5 +- packages/i18n/locales/es/app.json | 5 +- packages/i18n/locales/fr/app.json | 5 +- packages/i18n/locales/ko/app.json | 5 +- packages/i18n/locales/zh-CN/app.json | 5 +- packages/i18n/locales/zh-TW/app.json | 5 +- 12 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 .changeset/fn-7578-ai-undo-workflow-setting-ui.md create mode 100644 packages/dashboard/app/components/settings/sections/__tests__/GeneralSection.aiUndoWorkflow.test.tsx diff --git a/.changeset/fn-7578-ai-undo-workflow-setting-ui.md b/.changeset/fn-7578-ai-undo-workflow-setting-ui.md new file mode 100644 index 0000000000..a57c515d5c --- /dev/null +++ b/.changeset/fn-7578-ai-undo-workflow-setting-ui.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": minor +--- + +summary: Add a Settings → General picker to choose the workflow used for AI-undo (revert) tasks. +category: feature +dev: Surfaces `aiUndoTaskWorkflowId` (default `builtin:review-heavy`) in GeneralSection; empty selection means "inherit project default workflow", matching the revert route's blank-is-inherit behavior from FN-7556. diff --git a/docs/settings-reference.md b/docs/settings-reference.md index ff1f3ceb10..ec706ab760 100644 --- a/docs/settings-reference.md +++ b/docs/settings-reference.md @@ -412,7 +412,7 @@ Security-sensitive file-browser escape hatches are project-only. `allowAbsoluteF | `secretsEnv` | `{ enabled?: boolean; filename?: string; overwritePolicy?: "skip" \| "merge" \| "replace"; keyPrefix?: string; requireGitignored?: boolean }` | `undefined` | Per-project secrets `.env` materialization configuration. When `enabled`, the engine writes `secretsEnv.filename` (default `.env`) into each acquired task worktree from secrets marked `env_exportable=true`. `overwritePolicy` controls merge/skip/replace against an existing file; `requireGitignored` (default `true`) refuses to write a non-gitignored path; `keyPrefix` filters which exported keys are included. See [Secrets](./secrets.md#env-auto-write-into-worktrees). | | `mcpServers` | `McpServersSettings` | `{ enabled: false, servers: [] }` | Project-scoped MCP server settings. Project entries override global entries by `name`; `enabled:false` on a same-named project entry disables the inherited global server. Sensitive env/header/token material must be Fusion secret references only. See [MCP server settings](#mcp-server-settings). | | `owningNodeHandoffPolicy` | `"block" \| "reassign-to-local" \| "reassign-any-healthy"` | `"reassign-to-local"` | Policy for tasks already checked out by an unavailable owning node. `"block"` parks, `"reassign-to-local"` takes over on local node, `"reassign-any-healthy"` makes takeover eligible on healthy peers. | -| `aiUndoTaskWorkflowId` | `string` | `"builtin:review-heavy"` | **FN-7556.** Workflow selected for AI-undo board tasks created by `POST /api/tasks/:id/revert` (`mode: "ai"` and the `auto`/workspace conflict fallbacks) — a stricter review posture since these tasks reverse already-shipped code. Blank/unset means the created task inherits the project default workflow. The route validates the configured id and falls back to inherit on a blank or unknown value, so a misconfigured id never breaks AI-undo task creation. Settings Modal UI for this field is a follow-up; today it is settable only through the settings API. See [Task Management → Reverting Done/Archived tasks](./task-management.md#reverting-donearchived-tasks-git-path--ai-undo-fallback). | +| `aiUndoTaskWorkflowId` | `string` | `"builtin:review-heavy"` | **FN-7556 / FN-7578.** Workflow selected for AI-undo board tasks created by `POST /api/tasks/:id/revert` (`mode: "ai"` and the `auto`/workspace conflict fallbacks) — a stricter review posture since these tasks reverse already-shipped code. Blank/unset means the created task inherits the project default workflow. The route validates the configured id and falls back to inherit on a blank or unknown value, so a misconfigured id never breaks AI-undo task creation. Editable from **Settings → General** ("AI-undo task workflow" picker, next to the workflow-enablement controls); choose "Inherit project default workflow" to store the blank/inherit sentinel. See [Task Management → Reverting Done/Archived tasks](./task-management.md#reverting-donearchived-tasks-git-path--ai-undo-fallback). | | `groupOverlappingFiles` | `boolean` | `true` | Serialize execution when file scopes overlap. | | `pluginTrustPolicy` | `"off" | "warn" | "enforce"` | `"warn"` | Plugin provenance enforcement mode: `off` records verification metadata only, `warn` blocks only `invalid` signatures, `enforce` allows only `verified-trusted` or `trusted-local`. | diff --git a/docs/task-management.md b/docs/task-management.md index 099d216fab..b4f3bc8f47 100644 --- a/docs/task-management.md +++ b/docs/task-management.md @@ -697,7 +697,7 @@ Recovery/backfill guidance: - **Workspace (multi-repo) tasks (FN-7547):** tasks with `workspaceWorktrees` populated (`isWorkspaceTask`) are revertable too — the route dispatches to a dedicated workspace path that reasons about every sub-repo's integration branch as ONE all-or-nothing unit. It resolves each sub-repo's attributable commit(s), dry-run classifies every sub-repo first, and only commits a `revert(FN-xxxx): ...` commit on EACH sub-repo when every sub-repo classifies clean/already-reverted; if any sub-repo conflicts, no sub-repo is committed and every touched sub-repo worktree is rolled back to its pre-call state. Response contract for workspace tasks: `{ mode: "git", clean, workspace: { repos: [{ repo, classification, revertCommitSha?, conflicts?, alreadyReverted? }] }, conflicts?: {repo, file, ...}[] }`. A conflicting workspace result still falls back to the AI-undo task under `"auto"` mode, same as a single-repo conflicting result. - **`autoMerge:false` PR-based revert (FN-7554):** for a single-repo task whose git revert classifies **clean**, `autoMerge:false` no longer dead-ends at `needsHuman`. The route prepares a dedicated `fusion/revert-` branch off the resolved base branch (via the engine's `prepareRevertPrBranch`, which NEVER writes to the base branch itself), pushes it, and opens a GitHub PR through the same owner/repo resolution, `githubRateLimiter` gate, `findPrForBranch` idempotency, and `manual: true` handoff as `POST /tasks/:id/pr/create`. Response: `{ mode: "pr", clean: true, prUrl, prNumber, revertBranch, existingPr? }` — a second call while the PR is still open links the existing PR (`existingPr: true`) instead of re-pushing. GitHub unconfigured or rate-limited still degrades gracefully to `{ mode: "git", needsHuman: true, reason }`, and a conflicting/unsupported/already-reverted classification is unaffected (no PR is opened; `"auto"` mode still falls back to the AI-undo task on conflict/unsupported). Workspace (multi-repo) tasks are not yet covered by this PR path — they keep the existing `needsHuman` result under `autoMerge:false`. - **Dashboard auto-linking (FN-7555):** the AI-undo task's card shows an "Undo of FN-xxxx" chip and its detail view shows a clickable "Created to undo FN-xxxx" link back to the source task. The source task's detail view shows an "Undo task: FN-YYYY" link whenever an OPEN undo task referencing it exists in the loaded tasks (matching `TaskStore.findOpenRevertTaskForSource`'s open-only semantics — a `done`/`archived`/soft-deleted undo task is never surfaced as active). Both directions are derived client-side from `sourceMetadata.revertOf`; no new API. A dedicated Done/Archived card revert-trigger action is still a separate follow-up (see FN-7525). -- **Configurable AI-undo workflow default (FN-7556):** the project setting `aiUndoTaskWorkflowId` (default `builtin:review-heavy`) selects the workflow applied to every AI-undo task created above (`mode:"ai"` and the `auto`/workspace conflict fallbacks all share one creation seam, so all three inherit this default) — a stricter review posture is warranted because these tasks reverse already-shipped code. A blank/unset value means the created task inherits the project default workflow (pre-FN-7556 behavior); the route falls back to inherit (with a logged warning) if the configured id is blank or does not resolve to a real workflow, so a misconfigured id never breaks AI-undo task creation. See [Settings Reference → Project Settings](./settings-reference.md#project-settings). The Settings Modal UI field for this setting is a deliberate follow-up; it is settable today only via the settings API. +- **Configurable AI-undo workflow default (FN-7556, UI: FN-7578):** the project setting `aiUndoTaskWorkflowId` (default `builtin:review-heavy`) selects the workflow applied to every AI-undo task created above (`mode:"ai"` and the `auto`/workspace conflict fallbacks all share one creation seam, so all three inherit this default) — a stricter review posture is warranted because these tasks reverse already-shipped code. A blank/unset value means the created task inherits the project default workflow (pre-FN-7556 behavior); the route falls back to inherit (with a logged warning) if the configured id is blank or does not resolve to a real workflow, so a misconfigured id never breaks AI-undo task creation. Editable from **Settings → General → AI-undo task workflow** (choose "Inherit project default workflow" to store the blank/inherit sentinel). See [Settings Reference → Project Settings](./settings-reference.md#project-settings). ## GitHub Issue Import and PR Creation diff --git a/packages/dashboard/app/components/settings/sections/GeneralSection.tsx b/packages/dashboard/app/components/settings/sections/GeneralSection.tsx index 8cae07c825..f2b9d85eba 100644 --- a/packages/dashboard/app/components/settings/sections/GeneralSection.tsx +++ b/packages/dashboard/app/components/settings/sections/GeneralSection.tsx @@ -38,6 +38,37 @@ export function GeneralSection({ scopeBanner, form, setForm, projectId, addToast cancelled = true; }; }, [projectId]); + /* + FNXC:TaskRevert 2026-07-05-00:00: + AI-undo (revert) board tasks default to the stricter builtin:review-heavy workflow + (FN-7556) so reversals of already-shipped code get extra review scrutiny. This picker + surfaces that choice: the empty-string option means "inherit project default workflow" + (the revert route treats blank/whitespace as inherit), an unset form value displays the + effective builtin:review-heavy default, and any other value is the concrete workflow id + to use for AI-undo tasks. Loaded separately from builtinWorkflows above because this list + includes custom workflows too (builtinWorkflows is deliberately builtin-only, used for the + enable/disable checkboxes). + */ + const [aiUndoWorkflowOptions, setAiUndoWorkflowOptions] = useState([]); + useEffect(() => { + let cancelled = false; + fetchWorkflows(projectId) + .then((workflows) => { + if (!cancelled) { + setAiUndoWorkflowOptions(workflows.filter((workflow) => workflow.kind !== "fragment")); + } + }) + .catch(() => { + if (!cancelled) + setAiUndoWorkflowOptions([]); + }); + return () => { + cancelled = true; + }; + }, [projectId]); + const aiUndoTaskWorkflowValue = form.aiUndoTaskWorkflowId ?? "builtin:review-heavy"; + const aiUndoWorkflowHasStoredValue = aiUndoTaskWorkflowValue === "" || + aiUndoWorkflowOptions.some((workflow) => workflow.id === aiUndoTaskWorkflowValue); const enabledBuiltinWorkflowIds = useMemo(() => { const configured = Array.isArray(form.enabledBuiltinWorkflowIds) ? form.enabledBuiltinWorkflowIds : undefined; return new Set(configured ?? builtinWorkflows.map((workflow) => workflow.id)); @@ -108,6 +139,17 @@ export function GeneralSection({ scopeBanner, form, setForm, projectId, addToast {t("settings.general.disabledFusionWorkflowsAreHiddenFromWorkflow", "Disabled Fusion workflows are hidden from workflow pickers. Existing tasks that already use one continue to resolve. Default: all built-in workflows enabled (unset).")} )} +
+ + + {t("settings.general.aiUndoTaskWorkflowHelp", "Workflow assigned to AI-undo (revert) tasks, which reverse already-shipped code and warrant stricter review. Choose \"Inherit project default workflow\" to leave them on the project default. Default: review-heavy.")} +
diff --git a/packages/dashboard/app/components/settings/sections/__tests__/GeneralSection.aiUndoWorkflow.test.tsx b/packages/dashboard/app/components/settings/sections/__tests__/GeneralSection.aiUndoWorkflow.test.tsx new file mode 100644 index 0000000000..e0321606c2 --- /dev/null +++ b/packages/dashboard/app/components/settings/sections/__tests__/GeneralSection.aiUndoWorkflow.test.tsx @@ -0,0 +1,129 @@ +// @vitest-environment jsdom +/** + * FN-7578: component tests for the "AI-undo task workflow" picker added to + * GeneralSection. Covers the Surface Enumeration data states: unset (shows the + * builtin:review-heavy default), populated (stores the chosen id), explicit + * inherit (stores the "" sentinel, not undefined), and a stale/deleted stored + * id (renders without crashing). + */ +import { useState } from "react"; +import { describe, it, expect, vi, afterEach, beforeEach } from "vitest"; +import { render, screen, fireEvent, cleanup, waitFor } from "@testing-library/react"; +import * as jestDomMatchers from "@testing-library/jest-dom/matchers"; + +import { GeneralSection } from "../GeneralSection"; +import type { SettingsFormState } from "../context"; +import { fetchWorkflows } from "../../../../api"; + +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ + t: (_key: string, fallback?: string) => fallback ?? _key, + }), +})); + +vi.mock("../../../../api", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + fetchWorkflows: vi.fn(), + }; +}); + +expect.extend(jestDomMatchers); + +const WORKFLOWS = [ + { id: "builtin:review-heavy", name: "Review Heavy", ir: {} }, + { id: "builtin:coding", name: "Coding", ir: {} }, + { id: "WF-001", name: "Custom Workflow", ir: {} }, + { id: "WF-002-fragment", name: "Reusable Fragment", ir: {}, kind: "fragment" }, +] as unknown as import("@fusion/core").WorkflowDefinition[]; + +beforeEach(() => { + vi.mocked(fetchWorkflows).mockReset(); + vi.mocked(fetchWorkflows).mockResolvedValue(WORKFLOWS); +}); +afterEach(() => cleanup()); + +function GeneralHost({ initialForm, onSetForm }: { + initialForm: Partial; + onSetForm?: (updater: (f: SettingsFormState) => SettingsFormState) => void; +}) { + const [form, setForm] = useState(initialForm as SettingsFormState); + return ( + { + setForm((prev) => { + const next = (typeof updater === "function" ? (updater as (f: SettingsFormState) => SettingsFormState)(prev) : updater); + onSetForm?.(() => next); + return next; + }); + }} + addToast={vi.fn()} + prefixError={null} + setPrefixError={vi.fn()} + projectTrackingRepoOptions={[]} + projectTrackingRepoLoading={false} + projectTrackingRepoError={null} + /> + ); +} + +describe("GeneralSection - AI-undo task workflow picker", () => { + it("shows builtin:review-heavy as the effective default when unset", async () => { + render(); + + const select = (await screen.findByTestId("ai-undo-workflow-select")) as HTMLSelectElement; + await waitFor(() => expect(select.value).toBe("builtin:review-heavy")); + }); + + it("stores the chosen workflow id when a workflow is selected", async () => { + let latestForm: SettingsFormState | undefined; + render( + { + latestForm = getNext(); + }} + />, + ); + + const select = (await screen.findByTestId("ai-undo-workflow-select")) as HTMLSelectElement; + await waitFor(() => expect(select.querySelectorAll("option").length).toBeGreaterThan(1)); + + fireEvent.change(select, { target: { value: "WF-001" } }); + + await waitFor(() => expect(latestForm?.aiUndoTaskWorkflowId).toBe("WF-001")); + }); + + it("stores the empty-string inherit sentinel when 'Inherit project default workflow' is selected", async () => { + let latestForm: SettingsFormState | undefined; + render( + { + latestForm = getNext(); + }} + />, + ); + + const select = (await screen.findByTestId("ai-undo-workflow-select")) as HTMLSelectElement; + await waitFor(() => expect(select.value).toBe("builtin:coding")); + + fireEvent.change(select, { target: { value: "" } }); + + await waitFor(() => { + expect(latestForm?.aiUndoTaskWorkflowId).toBe(""); + expect(latestForm?.aiUndoTaskWorkflowId).not.toBeUndefined(); + }); + }); + + it("renders a stale/deleted stored workflow id without crashing", async () => { + render(); + + const select = (await screen.findByTestId("ai-undo-workflow-select")) as HTMLSelectElement; + await waitFor(() => expect(select.value).toBe("WF-DELETED")); + expect(screen.getByRole("option", { name: "WF-DELETED" })).toBeInTheDocument(); + }); +}); diff --git a/packages/dashboard/app/components/settings/sections/__tests__/settings-default-descriptions.test.tsx b/packages/dashboard/app/components/settings/sections/__tests__/settings-default-descriptions.test.tsx index 645c1fb262..90f7220152 100644 --- a/packages/dashboard/app/components/settings/sections/__tests__/settings-default-descriptions.test.tsx +++ b/packages/dashboard/app/components/settings/sections/__tests__/settings-default-descriptions.test.tsx @@ -242,6 +242,7 @@ const SETTING_DESCRIPTION_KEYS: Record = { workspaceMode: "general.workspaceModeHint", defaultWorkflowId: "general.newTasksInheritThisCustomWorkflowsStepsOverridable", enabledBuiltinWorkflowIds: "general.disabledFusionWorkflowsAreHiddenFromWorkflow", + aiUndoTaskWorkflowId: "general.aiUndoTaskWorkflowHelp", // ProjectModelsSection autoSelectModelPreset: "projectModels.autoSelectModelPresetHint", autoSummarizeTitles: "projectModels.whenEnabledTasksCreatedWithoutATitleBut", @@ -468,8 +469,6 @@ const NOT_SURFACED_ALLOWLIST: Record = { prerebaseDivergenceThreshold: "internal pre-rebase tuning constant, no UI field", maxSpawnedAgentsPerParent: "internal spawn-limit constant, no UI field", maxSpawnedAgentsGlobal: "internal spawn-limit constant, no UI field", - // FN-7556: AI-undo workflow default — Settings UI is a follow-up task. - aiUndoTaskWorkflowId: "AI-undo workflow default — Settings UI is a follow-up task", }; describe("FN-7505 settings default-value description guard", () => { diff --git a/packages/i18n/locales/en/app.json b/packages/i18n/locales/en/app.json index 10d29e4447..7a99694cf5 100644 --- a/packages/i18n/locales/en/app.json +++ b/packages/i18n/locales/en/app.json @@ -5881,7 +5881,10 @@ "gitLabEnabledHint": "Configure GitLab.com or self-managed GitLab URLs. Blank values inherit global fallbacks and then GitLab.com. No default — unset (unset behaves as enabled until explicitly disabled).", "allowEphemeralAgentsToCreateTasksHint": "When enabled (default), ephemeral task-worker agents can open follow-up tasks via fn_task_create. When disabled, only humans and permanent agents can create tasks; ephemeral callers are rejected.", "quickChatCloseOnOutsideClickHint": "When enabled, clicking outside the Quick Chat window closes it. Disable to keep it open until you close it explicitly. Default: enabled.", - "disabledFusionWorkflowsAreHiddenFromWorkflow": "Disabled Fusion workflows are hidden from workflow pickers. Existing tasks that already use one continue to resolve. Default: all built-in workflows enabled (unset)." + "disabledFusionWorkflowsAreHiddenFromWorkflow": "Disabled Fusion workflows are hidden from workflow pickers. Existing tasks that already use one continue to resolve. Default: all built-in workflows enabled (unset).", + "aiUndoTaskWorkflow": "AI-undo task workflow", + "aiUndoTaskWorkflowInherit": "Inherit project default workflow", + "aiUndoTaskWorkflowHelp": "Workflow assigned to AI-undo (revert) tasks, which reverse already-shipped code and warrant stricter review. Choose \"Inherit project default workflow\" to leave them on the project default. Default: review-heavy." }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": " and shows update notices in the CLI and dashboard. Cadence is governed by the frequency below. Default: enabled. ", diff --git a/packages/i18n/locales/es/app.json b/packages/i18n/locales/es/app.json index f7f44ed940..90e198ea55 100644 --- a/packages/i18n/locales/es/app.json +++ b/packages/i18n/locales/es/app.json @@ -5847,7 +5847,10 @@ "warnOnTheBoardWhenTodoWorkExceeds": "", "whenEnabledDefaultFusionSpawnsShortLived": "", "whenEnabledFusionChecksOpenAndClosedIssues": "", - "workflowsOrChangelogModeWhenContributorsShouldUpdate": "" + "workflowsOrChangelogModeWhenContributorsShouldUpdate": "", + "aiUndoTaskWorkflow": "", + "aiUndoTaskWorkflowInherit": "", + "aiUndoTaskWorkflowHelp": "" }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": "", diff --git a/packages/i18n/locales/fr/app.json b/packages/i18n/locales/fr/app.json index e689a39d2f..b6bc060cc5 100644 --- a/packages/i18n/locales/fr/app.json +++ b/packages/i18n/locales/fr/app.json @@ -5847,7 +5847,10 @@ "warnOnTheBoardWhenTodoWorkExceeds": "", "whenEnabledDefaultFusionSpawnsShortLived": "", "whenEnabledFusionChecksOpenAndClosedIssues": "", - "workflowsOrChangelogModeWhenContributorsShouldUpdate": "" + "workflowsOrChangelogModeWhenContributorsShouldUpdate": "", + "aiUndoTaskWorkflow": "", + "aiUndoTaskWorkflowInherit": "", + "aiUndoTaskWorkflowHelp": "" }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": "", diff --git a/packages/i18n/locales/ko/app.json b/packages/i18n/locales/ko/app.json index 36a8292cd9..b927ec7a21 100644 --- a/packages/i18n/locales/ko/app.json +++ b/packages/i18n/locales/ko/app.json @@ -5847,7 +5847,10 @@ "warnOnTheBoardWhenTodoWorkExceeds": "", "whenEnabledDefaultFusionSpawnsShortLived": "", "whenEnabledFusionChecksOpenAndClosedIssues": "", - "workflowsOrChangelogModeWhenContributorsShouldUpdate": "" + "workflowsOrChangelogModeWhenContributorsShouldUpdate": "", + "aiUndoTaskWorkflow": "", + "aiUndoTaskWorkflowInherit": "", + "aiUndoTaskWorkflowHelp": "" }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": "", diff --git a/packages/i18n/locales/zh-CN/app.json b/packages/i18n/locales/zh-CN/app.json index 27354f327d..9255dcb5d2 100644 --- a/packages/i18n/locales/zh-CN/app.json +++ b/packages/i18n/locales/zh-CN/app.json @@ -5847,7 +5847,10 @@ "warnOnTheBoardWhenTodoWorkExceeds": "", "whenEnabledDefaultFusionSpawnsShortLived": "", "whenEnabledFusionChecksOpenAndClosedIssues": "", - "workflowsOrChangelogModeWhenContributorsShouldUpdate": "" + "workflowsOrChangelogModeWhenContributorsShouldUpdate": "", + "aiUndoTaskWorkflow": "", + "aiUndoTaskWorkflowInherit": "", + "aiUndoTaskWorkflowHelp": "" }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": "", diff --git a/packages/i18n/locales/zh-TW/app.json b/packages/i18n/locales/zh-TW/app.json index 11fc22bfd2..ad97aa9853 100644 --- a/packages/i18n/locales/zh-TW/app.json +++ b/packages/i18n/locales/zh-TW/app.json @@ -5847,7 +5847,10 @@ "warnOnTheBoardWhenTodoWorkExceeds": "", "whenEnabledDefaultFusionSpawnsShortLived": "", "whenEnabledFusionChecksOpenAndClosedIssues": "", - "workflowsOrChangelogModeWhenContributorsShouldUpdate": "" + "workflowsOrChangelogModeWhenContributorsShouldUpdate": "", + "aiUndoTaskWorkflow": "", + "aiUndoTaskWorkflowInherit": "", + "aiUndoTaskWorkflowHelp": "" }, "globalGeneral": { "andShowsUpdateNoticesInTheCLIAnd": "",