Reverts the FN-4316 todo aging indicator feature, removing the `TodoAgingSummary` component and its CSS, the `todoAging` utility, all associated tests, and the corresponding documentation. The revert is accompanied by a changeset confirming the patch-level reversal. Fusion-Task-Id: FN-4415
40 KiB
Task Management
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 Contextwhen 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.
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
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:
- planning — idea intake; AI writes a full plan
- todo — ready for scheduling
- in-progress — executor active in isolated worktree
- in-review — implementation complete; awaiting finalization
- If merge/finalization hits a terminal error, tasks can remain in
in-reviewwithstatus: "failed"for explicit follow-up. This state is intentionally preserved by recovery (not auto-bounced totodo). - Retry behavior splits by execution-vs-merge signals:
in-reviewtasks with incomplete steps (pending/in-progress) are treated as execution failures and retried back totodowithpreserveProgress: true; zero-stepin-reviewtasks usemergeRetriesas the tie-breaker (mergeRetries === 0or undefined → execution failure path back totodo,mergeRetries > 0→ merge/finalization retry inin-reviewwith 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 finalin-review→donemove. If merge is confirmed but a blocker remains (for example, incomplete steps), Fusion parks the task inin-reviewwithstatus: "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 taskerror, 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.
- If merge/finalization hits a terminal error, tasks can remain in
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 inmerging/merging-pr/merging-fixafter the stale-merging age threshold, but no active merger owns it.merge-retries-exhausted—mergeRetriesreached the auto-merge retry cap withoutmergeDetails.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 [<code>]: <reason>
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 [<code>]: <reason> 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:
recoverStaleMergingStatusfinalizeNoOpReviewTasksrecoverMergeableReviewTasksrecoverAlreadyMergedReviewTasks
- done — merged/finalized
- archived — preserved history, optionally cleaned from filesystem
Board ordering behavior:
todomirrors scheduler dispatch order: priority first (urgent→low), then oldestcreatedAtwithin a priority tier, then task ID as deterministic tie-break.triage,in-progress, andin-reviewremain priority-first with task-ID tie-breaks (in-reviewstill pins merge-active statuses above non-merging tasks).- The
donecolumn is recency-ordered by completion time (newest first), usingcolumnMovedAtas primary and falling back toupdatedAtthencreatedAtfor 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
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:
- Inspect the worktree:
cd <worktreePath> && git status - Rescue changes as needed:
git diffand/orgit stash push -u - 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/<task-id> 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 examplefusion/fn-1234or 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/<task-id>) 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/<task-id>-2, -3, or similar sibling branches. See CLI Reference → Branch conflict recovery for the command reference and Settings Reference → executorAllowSiblingBranchRename for the legacy opt-out setting.
-
When this happens
The executor refuses the branch allocation, moves the task from
in-progressback totodo, setsstatus: "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. -
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.
fn task branch-recovery FN-001 -
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.
fn task branch-recovery FN-001 --reclaim fusion/fn-001-2 -
Discard
Discard deletes a stranded sibling branch and its worktree when you have confirmed the old work is no longer needed.
--yesis mandatory because the action is destructive.fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes -
Opt-out / legacy mode
If you must preserve the pre-FN-4068 behavior for a legacy workflow, enable
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
executionModefield 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:
{
"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 timeprefers durable wall-clock execution window (executionStartedAt→executionCompletedAt)- Fallback order for legacy tasks:
timedExecutionMswhen present, otherwise[timing]log sum + workflow runtime - Workflow runtime is shown as a separate metric and is not double-counted into totals when
timedExecutionMsis 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/reviewandPOST /api/tasks/:id/review/refresh. - Both endpoints return one normalized contract (
TaskReviewData) with stable per-itemitemIdvalues andsourceMode(pull-requestorreviewer-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-progresstasks receive compact steering guidance from the selected review items and continue on the same task/branch/worktree context. -
in-reviewtasks are resumed back toin-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 setsstatus: "needs-replan"triageortodowith a real (non-bootstrap-stub)PROMPT.md→ user comment setsstatus: "needs-replan"triageortodowith only bootstrap-stub/unplanned prompt content → no re-triage transition
Execution ownership is preserved for active work:
- User comments on
in-progressandin-reviewtasks 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 <id> creates a new planning task that depends on the original done/in-review task.
Example:
fn task refine FN-042 --feedback "Add explicit rollback tests for partial failure"
Behavior:
- New title format:
Refinement: <source label> - New task depends on source task
- Created in
planning
Archive and Restore
Archive behavior
fn task archive <id>moves done task toarchived- Cleanup mode can persist compact metadata and remove the task directory
- Archived tasks are read-only for task log/document writes:
logEntry()throwsTask <id> is archived — logging is read-onlyupsertTaskDocument()throwsTask <id> is archived — documents are read-onlyfn_task_logreturnsERROR: 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,columndependencies,steps,currentStepsize,reviewLevel,prInfo,issueInfoattachmentsmetadata- 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 <id>:
- 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.nextIdis legacy/read-only. The live allocator state isdistributed_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:
archive.db/ archived task snapshots for the missing ID.fusion/tasks/<id>/task.json.bak,PROMPT.md, attachments, and any surviving worktree branch named for the task- agent run logs / task documents / activity log entries that still mention the original ID
- 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 includeRef: owner/repo#Nin commit bodies.
fn task import owner/repo --labels bug --limit 20
fn task import owner/repo --interactive
Create PR for an in-review task:
fn task pr-create FN-120 --title "Fix flaky auth flow" --base main
Manual/non-auto-merge behavior:
- Task PR branches use
fusion/<task-id-lower>. - In the dashboard task detail modal (
in-review), the existing primary footer action can manually drive PR-first completion whenmergeStrategy: "pull-request"andautoMerge: 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
originbefore 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 intriageso 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.enabledturns tracking on for that task.task.githubTracking.repoOverrideoptionally 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
githubTrackingpayload 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: trueand the repo resolves at task scope (for example viarepoOverride), 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:
- Task override:
task.githubTracking.repoOverride - Project default:
githubTrackingDefaultRepo - 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 via githubAuthMode (gh-cli or token) and githubAuthToken.
Completion Modes (mergeStrategy)
direct: local squash-merge flow into target branchpull-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:
- Per-task node override (
Task.nodeId) - Project default node (
defaultNodeIdin project settings) - Local execution (no node configured)
At dispatch time, scheduler routing is persisted on the task as:
effectiveNodeIdeffectiveNodeSource(task-override,project-default, orlocal)
Create-time routing semantics
Cluster-aware task creation separates two routing decisions:
- Transport node: which node receives the
POST /api/tasksrequest (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 <task-id> <node-name-or-id>fn task clear-node <task-id>fn task create "..." --node <node-name-or-id>
- Pi extension tool
fn_task_updatewithnodeId
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 (
blockorfallback-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: <node-or-local> (source: <source>)
Use fn task show <id> or task logs to inspect current node routing context.
Examples
# 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 and Architecture → 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:
modelPresetsautoSelectModelPresetdefaultPresetBySize(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 detail modal
For UI-level details, see Dashboard Guide.

