# Task Management [← Docs index](./README.md) This guide covers task creation, lifecycle behavior, task metadata, and operational workflows. ## Task Creation Options ### 1) Quick Entry (dashboard) Use the inline input on board/list view: - Type description - Press Enter - Task is created in `planning` ### 2) Plan Mode (AI interview) Use the πŸ’‘ button to open planning mode: - AI asks clarifying questions - AI reasoning (thinking output) is preserved and visible throughout the session β€” expand the reasoning toggle to review the model's analysis before answering each question or accepting the summary - Produces summary + key deliverables - Create one task or **Break into Tasks** (multi-task generation with dependencies) - Summary view includes a **Priority** selector (`low`, `normal`, `high`, `urgent`) so single-task creation can set priority before task creation - Break-into-tasks mode includes per-subtask **Priority** selectors (`low`, `normal`, `high`, `urgent`) so each generated task can be prioritized before creation - Break-into-tasks descriptions are structured with subtask-specific guidance first, then a separate larger-plan context section (plus `## Planning Interview Context` when interview history exists) - Final multi-task creation now uses a compact request payload: unchanged generated subtask descriptions stay server-side, while any edits to title, description, size, priority, and dependencies are preserved when tasks are created - Sessions persist when the modal is closed β€” resume from the sidebar list at any time; reasoning context is restored automatically - Back navigation rewinds the server-side planning session to the previous answered question so you can revise earlier answers and continue from the corrected turn - On the summary screen, **Refine Further** continues through the backend planning session (including resumed completed sessions) and waits for a real follow-up question or updated summary; it does not switch to an empty question view ### 3) Todo item β†’ Plan Mode In **Todos** view, each todo item includes a planning action: - Click the planning (πŸ’‘) action on a todo item - Opens Planning Mode with that todo text pre-filled as the initial plan - Starts an AI planning interview (clarification questions + summary) - You can then create one task or break the plan into multiple tasks This action starts a planning session; it does **not** immediately create a task. For full Todo View behavior (enablement, list/item actions, API routes, and storage), see [Todo View](./todo-view.md). ### 4) Subtask Breakdown Dialog Use the 🌳 button: - Generate 2–5 candidate subtasks - Drag to reorder - Add dependencies only on earlier items - Set each subtask's **Priority** (`low`, `normal`, `high`, `urgent`) before create - Create tasks in one action ### 5) Expanded Controls Expand the creation panel (β–Ό) to access additional controls: - **Refine** (✨) β€” Improve the description with AI - **Deps** (πŸ”—) β€” Link existing tasks as dependencies - **Attach** β€” Add image attachments - **Models** (🧠) β€” Set per-task model overrides (executor, validator, planning) - **Priority** (🚩) β€” Set task priority (`low`, `normal`, `high`, `urgent`) before creation; the selected value is applied to the created task (it does not reset to default unless omitted) - **Agent** β€” Assign an agent to the task - **Branch settings** (`branch` / `baseBranch`) remain available in full task forms and task detail editing (not in Quick Entry) - **Review** β€” Set review rigor level (None, Plan Only, Plan and Code, Full) - **Browser Verify** β€” Enable browser verification workflow step ### 6) CLI creation ```bash fn task create "Fix API timeout handling" fn task plan "Implement role-based access control" fn task create "Bug" --attach screenshot.png --depends FN-002 ``` ### 7) Create/Enrich from Research findings From the standalone **Research** view, each finding supports two task actions: - **Create Task** β€” creates a new task with `sourceType: "research"` - **Enrich Task** β€” appends/updates research content on an existing task Research actions persist detailed output in task documents (and optional attachments), not in long task descriptions. ## Task Lifecycle Fusion task columns: 1. **planning** β€” idea intake; AI writes a full plan 2. **todo** β€” ready for scheduling 3. **in-progress** β€” executor active in isolated worktree 4. **in-review** β€” implementation complete; awaiting finalization - If merge/finalization hits a terminal error, tasks can remain in `in-review` with `status: "failed"` for explicit follow-up. This state is intentionally preserved by recovery (not auto-bounced to `todo`). - Retry behavior splits by execution-vs-merge signals: `in-review` tasks with incomplete steps (`pending`/`in-progress`) are treated as execution failures and retried back to `todo` with `preserveProgress: true`; zero-step `in-review` tasks use `mergeRetries` as the tie-breaker (`mergeRetries === 0` or undefined β†’ execution failure path back to `todo`, `mergeRetries > 0` β†’ merge/finalization retry in `in-review` with merge retry state reset); tasks whose steps are all terminal (`done`/`skipped`/`failed`) also stay on the merge/finalization retry path. - Persisted executor session state is resumed only when it still matches the task's current worktree context. If a retry fails with `Refusing to start coding agent in missing worktree: ...` and the persisted session points at stale worktree metadata, recovery clears stale session pointers and retries fresh so review retries do not reopen deleted worktree paths. - Merge-confirmed tasks still respect `getTaskMergeBlocker()` before the final `in-review` β†’ `done` move. If merge is confirmed but a blocker remains (for example, incomplete steps), Fusion parks the task in `in-review` with `status: "failed"` and an explicit blocker error instead of retry-looping auto-finalization. - Self-healing can still auto-finalize retry-exhausted failed review tasks when it can prove their branch content already landed on the merge target, so already-merged work does not deadlock in `in-review`. - Repeated engine merge-queue drops now escalate to an explicit recoverable review failure: if auto-recovery hits `Auto-merge starvation:` in the task `error`, Fusion has already seen three consecutive enqueue attempts rejected by the engine merge queue. Operators can recover by clearing the failed state from the dashboard, which lets the usual unpause/clear flow re-attempt merge once the underlying queue wedge is resolved. - Non-recoverable state-machine errors during finalization (for example `Invalid transition: 'todo' β†’ 'done'`) are treated as terminal review failures: recovery must not re-enqueue these tasks for merge unless task state changes prove they are recoverable. #### In-review stall signal Fusion now derives `task.inReviewStall` for non-paused `in-review` tasks when a known stuck-state shape is detected. This signal is state-based (not log-heuristic) and is computed server-side on task hydration. `InReviewStallCode` values: - `transient-merge-status-no-owner` β€” task is still in `merging`/`merging-pr`/`merging-fix` after the stale-merging age threshold, but no active merger owns it. - `merge-retries-exhausted` β€” `mergeRetries` reached the auto-merge retry cap without `mergeDetails.mergeConfirmed === true`. - `no-worktree-no-merge-confirmed` β€” task has no worktree path and merge is not confirmed (excluding explicit no-op merges). - `merge-blocker` β€” `getTaskMergeBlocker()` reports a merge/finalization blocker. Invariant: `inReviewStall` is **diagnostic-only**. It must never be used as an auto-completion trigger. Self-healing surfaces this diagnosis via task log entries in the form: - `In-review stall surfaced []: ` These entries are rate-limited per `(task, code)` over `taskStuckTimeoutMs`, so unchanged stalls are not spammed every cycle while state transitions can still surface a new code immediately. **Dashboard surface:** In-review, non-paused tasks with `inReviewStall` set show a `Stall` badge on `TaskCard` and a code-specific diagnostic row in `TaskDetailModal` above the PR section. The diagnostic row includes headline/description/action copy, raw reason text, observed timestamp, and a `View activity log` deep-link that switches to Logs β†’ Activity and highlights the most recent matching `In-review stall surfaced []: ` entry. This UI is diagnostic only: neither the badge nor the jump button mutates task state. Auto-completion/finalization remains owned by existing recovery passes: - `recoverStaleMergingStatus` - `finalizeNoOpReviewTasks` - `recoverMergeableReviewTasks` - `recoverAlreadyMergedReviewTasks` 5. **done** β€” merged/finalized 6. **archived** β€” preserved history, optionally cleaned from filesystem Board ordering behavior: - `todo` mirrors scheduler dispatch order: priority first (`urgent` β†’ `low`), then oldest `createdAt` within a priority tier, then task ID as deterministic tie-break. - `triage`, `in-progress`, and `in-review` remain priority-first with task-ID tie-breaks (`in-review` still pins merge-active statuses above non-merging tasks). - The `done` column is recency-ordered by completion time (newest first), using `columnMovedAt` as primary and falling back to `updatedAt` then `createdAt` for legacy tasks. - The dashboard **list view default ordering matches these same per-column semantics** until a user clicks a sortable header (manual list sorting still overrides defaults). ### Lifecycle commands ```bash fn task move FN-001 todo fn task merge FN-001 fn task archive FN-001 fn task unarchive FN-001 ``` ### Lifecycle invariants **Paused-state normalization on reopen:** When a task is moved from `in-progress`, `in-review`, or `done` back to `todo` or `triage` (retry/requeue), Fusion clears `task.paused` and `task.pausedByAgentId` to prevent contradictory `todo + paused` or `in-progress + paused` states. A paused task in `todo` is excluded from scheduler dispatch. **Paused-state normalization on explicit completion:** When an agent calls `fn_task_done` on a paused task, Fusion clears `task.paused` and `task.pausedByAgentId` regardless of the task's column (`in-progress` or `todo`). `task.paused` prevents new work from starting, but does not block an agent from completing in-flight work and transitioning the task to `done`. The scheduler respects `globalPause` independently. **Global pause vs task pause:** `settings.globalPause` gates new scheduler dispatches and is checked by the `fn_task_done` handoff logic. Task-level `task.paused` is a per-task gate that blocks execution start. They are independent β€” a task can be paused individually even when `globalPause` is `false`, and clearing `task.paused` does not affect `globalPause`. **Branch-conflict tripwire:** Executor tracks branch-conflict failures per task in-memory. After more than 5 `BranchConflictError` events for the same task in one executor lifetime, Fusion short-circuits recovery, marks the task `status: "failed"`, sets `paused: true`, and sets `pausedReason: "branch-conflict-tripwire"` to stop further automatic retries and suppress additional "Branch conflict recovery required" emissions for that task. ### Stranded-worktree recovery When Fusion detects uncommitted task-attributable changes in a task worktree during a requeue/release path, it will **not** silently move the task back to `todo`/`triage`. Instead, it parks the task in `status: "failed"` so operators can recover the stranded workspace state. Diagnostics are written to both places: - `task.error` (task detail summary) - task activity log entry (timeline) Each diagnostic includes task ID, absolute worktree path, dirty-file count, and sample dirty paths. Recovery flow: 1. Inspect the worktree: `cd && git status` 2. Rescue changes as needed: `git diff` and/or `git stash push -u` 3. Clear/retry the failed task from the dashboard/CLI so it can re-enter scheduling after the workspace is safe. ### Branch metadata semantics Task cards on the board only surface branch metadata when it is non-default/user-meaningful: they hide the conventional auto-generated working branch (`fusion/` and suffixed variants) and hide the default merge target (`main`), while still showing custom working branches and non-default merge targets. The board header search panel now includes two **board-only** branch filters: - **Working branch** filters by `task.branch` - **Target branch** filters by `task.baseBranch` These filters apply only to board rendering (not list view). Each filter supports concrete branch values plus a **No branch** option that matches tasks where `branch` or `baseBranch` is unset. Persisted filter state remains intentionally deferred to follow-up task FN-3426. Task branch fields are intentionally distinct: - `task.branch` β€” the actual working branch used for the task worktree (for example `fusion/fn-1234` or a conflict-suffixed variant). - `task.baseBranch` β€” the task's configured merge target/base branch intent. - `task.executionStartBranch` β€” internal execution provenance used when scheduler/executor temporarily start from a dependency branch; this is transient and cleared during execution resets/recovery. `PrInfo.baseBranch` is unchanged and continues to represent pull-request target branch metadata. ### Dependency reconciliation guidance When a task was created to resolve a temporary failure state in another task (for example, a preserved `in-review/failed` merge condition), its dependency contract may become stale after recovery. Use supported TaskStore/API paths to reconcile safely: - Remove/replace stale dependencies through task update APIs (do not hand-edit `task.json`/SQLite) - Add a single comment/log entry explaining why the dependency changed - Keep downstream blockers coherent (only tasks that still truly depend on unfinished work should remain blocked) Completion gating treats dependencies as resolved only when the dependency task is in `done`, `in-review`, or `archived`. Auto-merge recovery follow-up creation is deduplicated: Fusion creates at most one active (`not done/archived`) recovery task per unresolved parent failure, and merge-conflict recovery also deduplicates by active branch ownership to prevent parallel duplicate follow-ups on the same conflict branch. ### Landed-task state reconciliation (maintenance) If a task already shipped (`column: done`) but still carries transient failure metadata (`status: failed`, `error`, `worktree`, `blockedBy`, recovery retry fields), reconcile through supported TaskStore/API paths so SQLite and task JSON stay in sync. Recommended pattern: - Audit first (dry-run) for contradictory `done` + transient-failure state. - Apply reconciliation with TaskStore-backed mutations (for example `moveTask(id, "done")` for done-normalization cleanup). - Add one durable reconciliation log entry explaining why stale transient fields were cleared (avoid duplicating historical failure logs). - Re-audit after apply and resolve or explicitly disposition any related stale follow-up tasks. Do **not** patch `.fusion/fusion.db` directly without synchronizing `.fusion/tasks/*/task.json` through a supported store-backed path. ## Branch conflict recovery When the executor tries to allocate the canonical task branch (`fusion/`) and finds that branch already checked out in another live worktree, Fusion now fails loudly by default instead of silently renaming the run onto `fusion/-2`, `-3`, or similar sibling branches. See [CLI Reference β†’ Branch conflict recovery](./cli-reference.md#branch-conflict-recovery) for the command reference and [Settings Reference β†’ executorAllowSiblingBranchRename](./settings-reference.md#executorallowsiblingbranchrename) for the legacy opt-out setting. 1. **When this happens** The executor refuses the branch allocation, moves the task from `in-progress` back to `todo`, sets `status: "failed"`, preserves the branch/worktree recovery metadata, and records the existing tip SHA plus stranded commit subjects in the task lifecycle log and structured agent log. 2. **Inspect candidates** Run the recovery command with no flags to list every matching canonical or sibling branch. The output includes the tip SHA, any attached worktree path, and the stranded commits that are not reachable from the run's start point. ```bash fn task branch-recovery FN-001 ``` 3. **Reclaim** Reclaim points the task back at an existing canonical or sibling branch so the next executor run resumes there instead of allocating a new sibling. No commits are rewritten; Fusion only updates the task metadata. ```bash fn task branch-recovery FN-001 --reclaim fusion/fn-001-2 ``` 4. **Discard** Discard deletes a stranded sibling branch and its worktree when you have confirmed the old work is no longer needed. `--yes` is mandatory because the action is destructive. ```bash fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes ``` 5. **Opt-out / legacy mode** If you must preserve the pre-FN-4068 behavior for a legacy workflow, enable [`executorAllowSiblingBranchRename`](./settings-reference.md#executorallowsiblingbranchrename). That restores silent suffixing onto sibling branches, but it is discouraged because it recreates the same hidden-work / data-loss pattern that motivated loud branch-conflict recovery in the first place. ## Task Execution Modes Each task has an execution mode that controls how the executor agent approaches the task: | Mode | Description | |------|-------------| | `standard` | Full execution with complete review workflow (default) | | `fast` | Expedited execution with minimal overhead for simple tasks | ### Fast Mode Bypassed Gates When `executionMode: "fast"`, the following automated review/validation gates are **bypassed**: | Gate | Standard Mode | Fast Mode | |------|---------------|-----------| | `review_step` tool enforcement | Available to executor agent | **Not injected** | | Pre-merge workflow-step execution | Runs configured steps | **Skipped** | | Workflow revision loop | Enabled (feedback β†’ fix β†’ re-review) | **Disabled** | ### Fast Mode Mandatory Gates The following quality gates **remain enforced** in fast mode: | Gate | Behavior | |------|----------| | `task_done` requirement | Agent must call `task_done()` to complete | | Completion blocker checks | Tests, build, and typecheck from PROMPT.md still enforced | | Post-merge workflow steps | Run as normal (merger-owned) | ### Execution Mode Matrix | Feature | Standard | Fast | |---------|----------|------| | Executor agent session | Full prompt + tools | Full prompt (minus review_step) | | Pre-merge workflow steps | βœ… Run | ❌ Bypassed | | `review_step` tool | βœ… Available | ❌ Not available | | Post-merge workflow steps | βœ… Run | βœ… Run | | Completion blockers (test/build/typecheck) | βœ… Enforced | βœ… Enforced | | `task_done()` requirement | βœ… Required | βœ… Required | ### Setting Execution Mode Execution mode can be set during task creation or editing: - **Via API**: Include `executionMode` field in task create/update payload - **Via dashboard**: Select execution mode in the task creation dialog or task detail modal - **Task detail quick toggle**: In read mode, use the inline lightning-bolt control in task metadata to switch between **Standard** and **Fast** without entering full edit mode - **Values**: `"standard"` (default) or `"fast"` Example API payload: ```json { "description": "Simple fix", "executionMode": "fast" } ``` ## Task provenance and research enrichment Agent-created tasks now show a compact **Created by agent** marker directly on dashboard task cards when creation provenance indicates agent/automation origin (`sourceType: agent_heartbeat` or `sourceType: automation`, with legacy fallback to populated `sourceAgentId`). Where available, displays should prefer `sourceMetadata.agentName` over raw `sourceAgentId`. Research-created tasks show provenance as **Created via Research** in the task detail header and `Source: Research` in `fn task show` output. When `sourceMetadata.findingLabel` is present, the UI/CLI include it as context; otherwise they fall back to `runId` when available. Research enrichment uses a canonical per-run document key: - `research-{sanitizedRunId}` Repeated enrichment from the same run writes new revisions to that same key (no sibling keys for the same run). Optional exported artifacts can also be attached to the task; duplicate attachment records are skipped unless an explicit replacement path is used. Research document content appears in the existing **Documents** tab in Task Detail. Optional artifacts appear in existing task attachments. ## Task Detail Modal (Dashboard) The task detail modal exposes multiple tabs. In read mode, task metadata includes lightweight inline controls: priority can be changed from the priority chip, and execution mode can be toggled with a one-click lightning-bolt fast-mode button (Fast ↔ Standard) without opening full edit mode. These controls are intentionally aligned as a paired row (matched control height, baseline alignment, and mobile-safe wrapping) so frequent priority/mode changes stay quick and visually consistent. Task metadata also shows compact `Created` / `Updated` timestamps: recent values render as relative time (`just now`, `Xm`, `Xh`, `Xd`) and older values switch to short month/day dates; both timestamps stay on one row across desktop and mobile widths for a compact metadata presentation. Task settings edited from the modal now auto-save as you edit (change/blur with debounce for text-like fields). This includes title, description, dependencies, working/base branch (`branch`/`baseBranch`), workflow-step selection, model overrides in the edit form, and source issue metadata. In shared create/edit task forms, the GitHub Tracking controls are placed at the bottom of **More options** after **Workflow Steps**. The footer Save button remains available, but normal field edits no longer depend on a manual save click. The edit footer shows inline autosave state (saving/saved/error), and successful saves propagate the returned task through `onTaskUpdated` so open detail/list state stays fresh. The task detail modal exposes multiple tabs: - **Details** β€” primary metadata and description - **Steps** β€” progress across plan/implementation steps - **Log** β€” task event history - **Changes** β€” merge diff/change summary - **Workflow** β€” workflow step results (pass/fail/skip) - **Review** β€” actionable feedback surface (PR reviews/threads or reviewer-agent findings), manual refresh controls, and same-task revision actions for selected items - **Stats** β€” execution timing + token usage breakdown - `Total execution time` prefers durable wall-clock execution window (`executionStartedAt` β†’ `executionCompletedAt`) - Fallback order for legacy tasks: `timedExecutionMs` when present, otherwise `[timing]` log sum + workflow runtime - Workflow runtime is shown as a separate metric and is not double-counted into totals when `timedExecutionMs` is already available - **Comments** β€” collaboration thread + steering controls - **Model** β€” per-task model overrides and thinking level ## `PROMPT.md` Plan Structure After planning, each task gets a structured `PROMPT.md` with sections like: - Mission - Dependencies - Context to read first - File scope - Steps - Acceptance criteria - Guardrails / Do NOT list - Build/test/typecheck requirements This file is the contract for execution and review. ## Task Comments vs Steering Comments - **Task comments** (`fn task comment`) are general collaboration notes. - **Review tab feedback** is dedicated actionable review input (PR review data in pull-request mode, reviewer-agent findings in direct/non-PR mode) used to request same-task revisions. - Review data is served from task-scoped API endpoints: `GET /api/tasks/:id/review` and `POST /api/tasks/:id/review/refresh`. - Both endpoints return one normalized contract (`TaskReviewData`) with stable per-item `itemId` values and `sourceMode` (`pull-request` or `reviewer-agent`) so Review UI and per-item progress can share one read model. - The Review tab supports **manual refresh** without closing/reopening Task Detail: - Pull-request mode refreshes live GitHub-backed review decision/thread/comment state and updates PR metadata freshness. - Direct/non-PR mode refreshes normalized reviewer-agent feedback from persisted task review artifacts and does not call GitHub. - In direct/non-PR auto-merge mode, the Review tab shows parsed reviewer-agent feedback with explicit loading/error/empty states instead of sending users to raw comments or agent logs. - Review item bodies render markdown by default, and users can switch between **Markdown** and **Plain** modes from the Review tab action bar; the preference persists locally per user. - **Comments remains the general discussion surface**; Review remains the actionable review surface. - **Steering comments** (`fn task steer`) are execution guidance for the running agent. Steering comments can be injected mid-run into active executor sessions. When users select review items and trigger **Request revision** from the Review tab, Fusion starts an in-place same-task AI revision pass (no refinement child task): - Review addressing progress is persisted per selected item in task state, including a durable snapshot and lifecycle timestamps. - Each selected item transitions through `queued` β†’ `in-progress` β†’ `addressed`/`failed`, so Review progress survives refreshes and reloads even if upstream review data changes. - Persisted snapshots are rendered in the Review tab when the original source item is no longer present, while Comments remains dedicated to general discussion. - `in-progress` tasks receive compact steering guidance from the selected review items and continue on the same task/branch/worktree context. - `in-review` tasks are resumed back to `in-progress`, reopen the last completed step, and keep same-task branch/worktree context for the revision pass. - Assigned immediate-response agents are woken on-demand only when there is no active session; otherwise guidance is injected without forcing a new wake. ### User comments and triage re-consideration User comments can trigger **re-triage** for already-planned but non-executing work: - `triage` + `awaiting-approval` β†’ user comment sets `status: "needs-replan"` - `triage` or `todo` with a real (non-bootstrap-stub) `PROMPT.md` β†’ user comment sets `status: "needs-replan"` - `triage` or `todo` with only bootstrap-stub/unplanned prompt content β†’ no re-triage transition Execution ownership is preserved for active work: - User comments on `in-progress` and `in-review` tasks do **not** re-route those tasks back through triage. - Agent/system comments do **not** trigger comment-driven re-triage. This is distinct from steering comments: steering feedback targets the currently running executor session, while comment-driven re-triage requests a fresh specification pass for planned work. ## Refinement Tasks `fn task refine ` creates a new planning task that depends on the original done/in-review task. Example: ```bash fn task refine FN-042 --feedback "Add explicit rollback tests for partial failure" ``` Behavior: - New title format: `Refinement: ` - New task depends on source task - Created in `planning` ## Archive and Restore ### Archive behavior - `fn task archive ` moves done task to `archived` - Cleanup mode can persist compact metadata and remove the task directory - Archived tasks are read-only for task log/document writes: - `logEntry()` throws `Task is archived β€” logging is read-only` - `upsertTaskDocument()` throws `Task is archived β€” documents are read-only` - `fn_task_log` returns `ERROR: Cannot log to archived task β€” this task is read-only` ### Cleanup behavior - Archived entries are persisted as compact archive snapshots (current runtime stores these in SQLite `archivedTasks`; legacy docs may refer to `.fusion/archive.jsonl`) - Task directory (`task.json`, `PROMPT.md`, `agent.log`, attachments) can be removed ### Compact archive entry format Archive entries preserve key metadata needed for restoration, including: - `id`, `title`, `description`, `priority`, `column` - `dependencies`, `steps`, `currentStep` - `size`, `reviewLevel`, `prInfo`, `issueInfo` - `attachments` metadata - task `log` - timestamps (`createdAt`, `updatedAt`, `columnMovedAt`, `archivedAt`) - model override fields (`modelProvider`, `modelId`, `validatorModel*`, `planningModel*`) `agent.log` content is intentionally not preserved in compact archive entries. ### Restore behavior `fn task unarchive `: - Restores archive entry if directory is missing - Rebuilds `PROMPT.md` - Moves task to `done` - Logs β€œTask restored from archive” when recovering from compact archive entry ### Task-ID collision safety and operator recovery - Ordinary task creation, duplicate, and refine flows now fail safely if the chosen task ID already exists in active storage or archive storage. Existing task rows/files always win; the new create attempt must retry with a fresh reservation instead of overwriting data. - A failed create may burn a distributed reservation. Gaps in `FN-*` numbering are expected and are safer than reissuing a possibly-colliding ID. - `config.nextId` is legacy/read-only. The live allocator state is `distributed_task_id_state.nextSequence`, reconciled on store open against live tasks, archived task snapshots, and reservation history. If you suspect **historical overwrites from pre-FN-4044 builds**, inspect surviving evidence in this order: 1. `archive.db` / archived task snapshots for the missing ID 2. `.fusion/tasks//task.json.bak`, `PROMPT.md`, attachments, and any surviving worktree branch named for the task 3. agent run logs / task documents / activity log entries that still mention the original ID 4. git commits whose subject/body references the original task ID but no longer matches the current task metadata Recovery/backfill guidance: - If the original task row still exists in archive storage, unarchive or manually recreate the task from that snapshot. - If only prompt/worktree/git evidence survives, create a replacement task with a new ID and copy over the recovered description, prompt, documents, and attachments manually. - If both the active row and archive snapshot were overwritten, Fusion cannot reconstruct lost attachments/comments automatically; recreate them from git history, branch/worktree contents, screenshots, or external issue trackers. - Record the incident in the replacement task so future audits understand why the task ID and commit history diverge. ## GitHub Issue Import and PR Creation Import issues: - GitHub-imported tasks retain typed source issue metadata (`sourceIssue.provider/repository/externalIssueId/issueNumber/url`), which executor and merger flows use to include `Ref: owner/repo#N` in commit bodies. ```bash fn task import owner/repo --labels bug --limit 20 fn task import owner/repo --interactive ``` Create PR for an `in-review` task: ```bash fn task pr-create FN-120 --title "Fix flaky auth flow" --base main ``` Manual/non-auto-merge behavior: - Task PR branches use `fusion/`. - In the dashboard task detail modal (`in-review`), the existing primary footer action can manually drive PR-first completion when `mergeStrategy: "pull-request"` and `autoMerge: false`: - `Start PR Review` (no PR linked yet) - `Check PR Status` (open PR linked) - `Finish & Close` (PR already merged) - Manual PR creation first checks for an existing PR on that branch and links it when found. - If no PR exists, Fusion pushes the task branch to `origin` before creating the PR. - When buffered actionable PR feedback exists on a PR that is already merged/closed and the task leaves `in-review`, Fusion creates a dependency-linked follow-up task in `triage` so feedback is not stranded. ## GitHub Tracking Issues GitHub tracking issues are optional issues Fusion can create from Fusion tasks. They are **not** the same as imported source issues (`issueInfo` / `sourceIssue`): imported issues represent an existing GitHub issue that created the task, while tracking issues are new GitHub issues opened to track a Fusion task. When task creation runs with tracking enabled, Fusion attempts issue creation during task creation flows (including quick create, planning output, automation `create-task` workflow steps, and subtask creation paths that create tasks). For existing tasks, PATCH first persists any `githubTracking` mutation (enable/disable, repo override, or unlink), then evaluates whether the updated task is **enabled and still unlinked** and should trigger best-effort issue creation (including non-`githubTracking` edits). This keeps retry/create behavior consistent from Task Detail instead of relying on stale pre-patch state. Creation is best-effort and non-blocking: task updates and task creation still succeed even if repo resolution fails or GitHub calls fail. Tracking behavior is controlled per task: - `task.githubTracking.enabled` turns tracking on for that task. - `task.githubTracking.repoOverride` optionally forces a specific target repo (`owner/repo`). - In the dashboard **Task Detail** modal, eligible existing tasks (`triage`, `todo`, `in-progress`, `in-review`) always show a compact GitHub tracking summary row. When tracking is currently disabled and editable, the header exposes a one-click **Enable GitHub tracking** button; linked-issue details and the rest of the tracking controls remain behind the disclosure arrow for disable/retarget flows. - After an engine/dashboard restart, Task Detail preserves the fetched full `githubTracking` payload even when the board opened the modal from a slim task row that intentionally omitted tracking metadata. - When a task is already tracking-enabled but still unlinked, Task Detail exposes a **Create tracking issue** action in the disclosure content (including non-editable columns like `done`) so "Issue not yet created" is not a dead-end state. - Clearing the Task Detail repo override stores `null`, which reverts repo resolution to project/global defaults. - Explicit task-level enablement is honored even when project/global GitHub tracking defaults are unset. If `enabled: true` and the repo resolves at task scope (for example via `repoOverride`), Fusion attempts tracking-issue creation on both create-time and eligible edit-time flows, including tasks imported from GitHub (`sourceType: "github_import"`). - Explicit manual unlink (`githubTracking.issue: null`) does not recreate a tracking issue in that same update request, and disabling tracking does not create new issues. - On board cards, Fusion shows both the imported-source provenance marker and tracking link when they refer to different issues. The tracking chip is hidden only when the linked tracking issue exactly matches the source issue (`owner/repo#number`) to avoid duplicate badges. Repository resolution order: 1. Task override: `task.githubTracking.repoOverride` 2. Project default: `githubTrackingDefaultRepo` 3. Global default: `githubTrackingDefaultRepo` When Fusion creates a tracking issue, it uses: - Title: `[FN-XXXX] Task title` - Body prefix: `Fusion task: FN-XXXX` - Body content: bounded plain-text task summary snippet (not full prompt content) When tracked tasks later move to `in-progress` or `done`, Fusion also posts a short lifecycle comment on the linked tracking issue. The `in-progress` comment stays plain-text and capped, while the `done` comment can include the merge commit SHA/subject, task branch, PR link, file-change stats, and merge timestamp when those fields are available. When a tracked task moves into `done`, Fusion closes the linked GitHub issue with `state_reason: completed`; when it leaves `done` for an active column, Fusion reopens the issue with `state_reason: reopened`; and when the Fusion task is permanently deleted from the dashboard, Fusion now prompts for issue handling (`close`, `delete`, or `leave`). If no explicit choice is provided by API callers, Fusion preserves the legacy default and closes the linked issue with `state_reason: not_planned`. GitHub authentication/settings are configured in [Settings Reference](./settings-reference.md) via `githubAuthMode` (`gh-cli` or `token`) and `githubAuthToken`. ## Completion Modes (`mergeStrategy`) - **`direct`**: local squash-merge flow into target branch - **`pull-request`**: PR-first completion flow via GitHub checks/reviews Configured via settings. ## Per-Task Model Overrides Each task may override: - Executor model (`modelProvider` + `modelId`) - Validator model (`validatorModelProvider` + `validatorModelId`) - Planning model (`planningModelProvider` + `planningModelId`) - Thinking level (`off|minimal|low|medium|high`) Overrides are configured from the task model tab or task creation actions. ## Node Routing Tasks execute on an effective node selected by routing precedence: 1. **Per-task node override** (`Task.nodeId`) 2. **Project default node** (`defaultNodeId` in project settings) 3. **Local execution** (no node configured) At dispatch time, scheduler routing is persisted on the task as: - `effectiveNodeId` - `effectiveNodeSource` (`task-override`, `project-default`, or `local`) ### Create-time routing semantics Cluster-aware task creation separates two routing decisions: - **Transport node**: which node receives the `POST /api/tasks` request (can be local or proxied remote). - **Execution target** (`Task.nodeId`): which node should run the task later. These are intentionally independent. Routing a create request through node A does not force execution on node A unless `Task.nodeId` also points there. ### Per-task node override You can set or clear a task override from: - Task detail modal β†’ **Routing** tab - Quick/create flows that support node selection - Bulk task actions - CLI: - `fn task set-node ` - `fn task clear-node ` - `fn task create "..." --node ` - Pi extension tool `fn_task_update` with `nodeId` ### Active-task blocking Node override changes are blocked while a task is active/in progress. Core validation (`validateNodeOverrideChange`) returns `reason: "task-in-progress"` and users must pause/stop or wait for completion before changing routing. ### Task detail routing summary The Routing tab shows: - Effective node (with health indicator when known) - Routing source (override vs project default vs local) - Unavailable-node policy value (`block` or `fallback-local`) - Lock banner when routing is currently immutable for an active task ### Activity log entries When a task is dispatched, task activity/log records include routing decisions such as: - `Node routing resolved: (source: )` Use `fn task show ` or task logs to inspect current node routing context. ### Examples ```bash # Route one task to a specific remote node fn task set-node FN-204 edge-runner # Remove override and return to project default routing fn task clear-node FN-204 # Create a task with node override immediately fn task create "Reproduce flaky node error" --node edge-runner # Inspect routing summary from CLI fn task show FN-204 ``` See also: [Settings Reference β†’ Node Routing settings](./settings-reference.md#node-routing-settings-project-scope) and [Architecture β†’ Task Routing Architecture](./architecture.md#task-routing-architecture). ## Review Level Review levels control the rigor of the review process for a task: | Level | Name | Description | |-------|------|-------------| | 0 | None | No review | | 1 | Plan Only | Review only the plan | | 2 | Plan and Code | Review both the plan and implementation | | 3 | Full | Full review with all checks | Review level can be set during task creation (in the New Task dialog under More options) or when editing a task (in the task detail modal). The review level affects how the reviewer agent evaluates the task but does not override workflow steps or model presets. ## Model Presets and Auto-Selection by Size Project settings support reusable model presets: - `modelPresets` - `autoSelectModelPreset` - `defaultPresetBySize` (`S`, `M`, `L`) Users can apply presets at task creation; manual model selection can override them. ## AI Title Summarization When `autoSummarizeTitles` is enabled and a task has a long untitled description, Fusion can auto-generate a concise title. This applies to tasks created from the dashboard/API as well as tasks created by agents and tooling flows (`fn_task_create`, delegated tasks, and triage-created child tasks). GitHub tracking also opportunistically uses the title-summarizer lane for untitled tasks before falling back to a deterministic description-derived title. ## Screenshots ### Board/task cards + quick entry ![Task cards and quick entry on board view](./screenshots/dashboard-overview.png) ### Task detail modal ![Task detail modal](./screenshots/task-detail.png) For UI-level details, see [Dashboard Guide](./dashboard-guide.md).