FN-7578: surface aiUndoTaskWorkflowId picker in Settings General

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) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-05 10:42:21 -07:00
parent e7cb2f1fed
commit 73b38babf0
12 changed files with 205 additions and 10 deletions

View File

@@ -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`. |

View File

@@ -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-<id>` 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