Document why PluginSkillContribution.skillFiles silently fails to load bundled skills in live sessions (resolver only filters disk-discovered skills) and the physical-install + additionalSkillPaths-forwarding fix, as a searchable docs/solutions/ learning. Surface docs/solutions/ in AGENTS.md so agents discover it.
18 KiB
Project Guidelines
Essential rules
STANDING DIRECTIVE: Buttons Are Frozen (2026-05-13)
Do not file, plan, or implement tasks that adjust button mobile-responsiveness, touch-target sizing, or mobile reflow of header/action button rows anywhere in the dashboard (TaskCard, SettingsModal, ChatView, MissionManager, AgentsView, FAB, etc.). Keep buttons as they are.
This supersedes earlier guidance about mobile touch targets, primary/secondary control sizing on mobile, and .touch-target minimums for buttons. The Frontend UX Design workflow step (WS-006) is disabled and must stay disabled.
If you find yourself opening SettingsModal.css, TaskCard.css, ChatView.css, etc. inside an @media (max-width: 768px) block to touch a .btn, .modal-close, .settings-header-actions, or .card-* button — stop. Confirm with the user in chat before proceeding.
Exception: explicit named user request in chat that overrides this directive.
Spec Generation Hygiene
- Do not cite
.fusion/tasks/<id>/<file>paths in Context/Steps/File Scope unless the file already exists, is explicitly created as a(new)Artifact, or is siblingPROMPT.md/task.json/attachments/*. - Dangling task-local file references are a blocking spec REVISE.
- Save planning scratch and interim notes via
fn_task_document_writeinstead of inventing on-disk task-local files.
External-integration evidence
Any task integrating a third-party tool (CLI, daemon, downloadable binary, installer-managed dependency) must cite, in PROMPT.md:
- Canonical upstream repo URL.
- Docs/homepage URL.
- Release/download URL.
- Binary/CLI name in backticks.
- Checksum or
upstream-pending-verificationmarker.
Missing evidence is a blocking REVISE. Never invent release URLs, binary names, or hashes.
Finalizing Changes
When a change affects published @runfusion/fusion, add a changeset (example: .changeset/<name>.md with "@runfusion/fusion": patch).
Bump types:
- patch — bug fixes/internal
- minor — new features/CLI/tools
- major — breaking changes
Do NOT create changesets for AGENTS.md/README/internal docs, CI config, or behavior-preserving refactors. @fusion/core, @fusion/dashboard, and @fusion/engine are private.
Releasing
Use only:
pnpm release --yes
scripts/release.mjs is the source of truth. Do not substitute with manual changeset version, pnpm publish, or git tags.
Package Structure
@fusion/core— domain model/task store (private)@fusion/dashboard— web UI + API server (private)@fusion/engine— triage/executor/reviewer/merger/scheduler (private)@runfusion/fusion— CLI + pi extension (published)
Only @runfusion/fusion is published; @fusion/* packages are bundled into it.
Importing across @fusion/* packages
@fusion/* imports must be statically analyzable. Anti-pattern:
const engineModule = "@fusion/engine";
const engine = await import(/* @vite-ignore */ engineModule);
Rules:
- Default to static imports.
@fusion/coreuses DI (setCreateFnAgent) instead of dynamicimport("@fusion/engine")due to circularity.- Never reintroduce the
engineModule = "@fusion/engine"trick. vi.mock("@fusion/engine", ...)remains valid.
Testing commands
Tests are required. Typechecks/manual checks are not substitutes.
pnpm test
pnpm test:full
pnpm lint
pnpm build
pnpm verify:workspace
Standing Rule: Do Not Add Slow Tests (FN-5048)
- Prefer narrow seams, in-memory fakes, shared harnesses, and targeted assertions.
- Prefer fake timers over real polling/time waits.
- Do not mask slowness by raising worker/concurrency knobs.
- Do not add new real-network calls, real polling loops, or mock-the-world shells when a narrower seam exists.
- Use the testing taxonomy in
docs/testing.mdwhen deciding trim vs keep.
Standing Rule: Fix the Invariant, Not the Repro (FN-5893)
- When fixing a bug, the regression test must assert the general invariant across ALL known surfaces — not only the single reported reproduction.
- Enumerate the surfaces before filing or closing the fix: every provider/bridge for streaming and agent paths, both desktop and mobile breakpoints for UI behavior, and empty/undefined/populated data states.
- Motivating incidents: streamed-response spacing was fixed three times before the invariant was fully covered (FN-5787, FN-5789, FN-5803), and the auto-merge blank-dashboard fix re-opened after desktop-only coverage missed mobile Android (FN-5751).
- If a regression test only proves the exact reported case, it is incomplete; extend it until the invariant holds across all known surfaces.
Port 4040 is Reserved
Never kill processes on port 4040 and never start test servers on 4040. Use --port 0 or another free port.
Engine Process Rules
Never use execSync for user-configured commands
Run user-configured commands (test/build/workflow scripts) via async exec with timeout. execSync is only acceptable for short deterministic git plumbing.
Move-Task contract
User moveTask(in-progress → todo) is a hard cancel: abort active sessions/subprocesses and park task in todo with user-paused semantics. Engine rebounds must not set userPaused.
Process supervision
Use superviseSpawn(...) from @fusion/core for managed child processes; do not use raw detached spawn/nohup patterns unless explicitly allowlisted. eslint.config.mjs + scripts/check-no-nohup.mjs enforce this.
Git Conventions
- Commit prefixes:
feat(FN-XXX):,fix(FN-XXX):,test(FN-XXX): - One commit per step boundary
- Include task ID prefix
- Fusion task-worktree commits should carry
Fusion-Task-Id: FN-NNNNtrailers
Merging Branches Into Main
- Drop duplicate commits before merging. Rebase away duplicates already on main.
- Squash is now the project default; history-preserving merge paths require opt-in. New projects default
directMergeCommitStrategy="always-squash". To preserve multi-commit history, explicitly set projectdirectMergeCommitStrategyto"auto"or"always-rebase", or set a per-task**Direct Merge Commit Strategy:** ...override inPROMPT.md. - Empty cherry-picks are no-ops. Do not create empty commits.
- Already-on-main classifier applies. Allow finalize/self-healing recovery when lineage is landed.
- Contamination auto-recovery is bounded. First pass can auto-drop upstream foreign commits; repeated/ambiguous cases escalate.
- Run post-squash audit policy. Respect
postMergeAuditMode(warn/block/off) and auto-recovery stages. - Enforce pre-commit diff-volume gate. Block suspicious shrinkage before squash commit.
- Smart-prefer-main overlap guard. Recent overlapping main commits can flip to prefer-branch.
- Layer-3 scope partition. Out-of-scope conflicts resolve to main before AI arbitration unless
task.scopeOverride=true. - Auto-prerebase on divergence/hot files. Fail-soft and continue normal conflict stack.
Gitignored-path guard on squash merges
Never force-add ignored artifacts (for example git add -f .fusion/...). Use task documents for findings/notes.
File-Scope invariant on squash merges
Every squash commit must overlap task ## File Scope (unless scope is empty). Violations must fail with FileScopeViolationError and reset pre-squash state.
Per-task opt-out exists: task.scopeOverride = true (log the reason).
autoMerge: false callout (FN-5147)
When settings.autoMerge: false, in-review is terminal-until-merged by a human. Lifecycle-mutating self-healing must not move these tasks backward, pause/fail them, or re-enqueue them for execution.
Scoped exception (FN-5819): shared-branch-group members (branchContext.assignmentMode === "shared") still run the member→shared-branch local integration step while auto-merge is off. This exception is only for assembling branch_groups.branchName; shared-branch → default-branch promotion remains gated by group/global auto-merge.
Mock provider (test mode)
testMode?: boolean is now available in both project and global settings. If project testMode === true (or the resolved default provider is "mock" at any tier), every AI lane is forced to mock/scripted, overriding per-task and per-lane model selections. The dashboard exposes this via the Settings Modal "Enable test mode" toggle and a persistent "Test mode — no real AI calls" banner.
Run Audit
- FN-5419: git run-audit now includes
pull:fast-forwardandstash:pop-conflict; dashboard git surfaces now include the extendedPOST /api/git/pullintegration-worktree path plus companionPOST /api/git/stash-resolve,POST /api/git/stash-drop, andPOST /api/git/stash-applyroutes.
Reliability Mechanism Coverage
- FN-5432 backstop:
packages/engine/src/__tests__/reliability-interactions/dependency-cycle-reconcile.test.tsextends FN-5256 coverage with long-cycle ambiguous sweep, write-boundary/sweep race, self-defeating+cycle non-contradiction across one maintenance flow, and audit-event shape regression; core regression cases (long cycle, self-loop via update, incremental-update closes a loop, moveTask seam invariant, DependencyCycleError shape) live inpackages/core/src/__tests__/store-dependency-cycle.test.ts. User-facing pull/stash audit event behavior (pull:fast-forward,stash:pop-conflict) is documented indocs/dashboard-guide.mdunder Merge Advance Notice / Smart Pull. - FN-5403 backstop:
packages/engine/src/__tests__/reliability-interactions/engine-stop-aborts-execution.test.tslocks stop-ordering behavior so engine shutdown aborts executor AI sessions before drain wait and preserves task-row lifecycle semantics. - FN-5704 backstop:
packages/engine/src/__tests__/reliability-interactions/reclaim-self-owned-resume-limbo-escalation.test.tsguards reclaim/unpause no-progress oscillation recovery by capping repeated no-progress resumes, escalating to preserve-worktodorebound, and emittingtask:resume-limbo-escalatedaudit metadata while exempting progress/user-paused/autoMerge-off cases. - FN-5715 backstop:
packages/engine/src/__tests__/reliability-interactions/mission-validation-trigger-gap.test.tsguards mission validation trigger continuity so done task completion and startup recovery both route assertion-linked features through validator runs before completion. - FN-5738 backstop:
packages/engine/src/__tests__/reliability-interactions/mission-validation-trigger-gap.test.tsextends mission-loop coverage so zero-assertion auto-pass deterministically advances toloopState="passed"and emitsvalidation_auto_passed_no_assertionswithout duplicate recovery re-fire. - FN-5741 backstop:
packages/engine/src/__tests__/reliability-interactions/merge-request-shadow-handoff.test.tsguards Phase-1 write-only-shadow merge-request record + handoff-accepted marker seam (flag OFF = no-op, ON = shadow-only non-authoritative). - FN-5742 backstop:
packages/engine/src/__tests__/reliability-interactions/dual-observe-merge-seam.test.tsguards Phase-2 dual-observe parity (dependency + lease diffs, shadow dequeue parity, manual-required shadow skip) while legacy behavior remains authoritative. - FN-5743 backstop:
packages/engine/src/__tests__/reliability-interactions/merge-request-cancel-on-hard-cancel.test.tspluspackages/core/src/__tests__/merge-request-record.test.tsguard Phase-3 cutover semantics (merge-request retry state transitions, authoritative user hard-cancel tombstone, and non-user rebound no-op cancel semantics). - FN-5754 backstop:
packages/engine/src/__tests__/reliability-interactions/mission-stranded-feature-retriage.test.tsguards startup/maintenance stranded-feature re-triage for active autopilot slices, including link-first dedupe, non-defined skip safety, non-autopilot no-op, idempotency, andmission:stranded-feature-triagedaudit shape. - FN-5755 backstop:
packages/engine/src/__tests__/reliability-interactions/mission-validation-trigger-gap.test.tsextends mission validation coverage so bounded periodic maintenance replaysrecoverActiveMissionsfor strandedimplementingfeatures and remains idempotent on repeated passes. - FN-5783 backstop:
packages/engine/src/__tests__/reliability-interactions/branch-group-automerge-precedence.test.tsguards grouped merge precedence so per-taskautoMergeremains member→integration only, groupautoMergegates promotion eligibility, and promotion-gate audit events capture pause/automerge override reasons. - FN-5788 backstop:
packages/engine/src/__tests__/reliability-interactions/branch-group-promotion-gate.test.tsguards merger-side promotion-gate telemetry on shared member landings, including pause/settings/group autoMerge reason mapping and no default-branch auto-promotion side effects. - FN-5830 backstop:
packages/engine/src/__tests__/reliability-interactions/branch-group-promotion.test.tsguards branch-group completion-gate + promotion lifecycle so completion detection drives exactly one shared→default promotion, re-calls stay idempotent, and gated paths emit promotion-gated telemetry without promoting. - FN-5820 backstop:
packages/engine/src/__tests__/reliability-interactions/shared-branch-group-lifecycle.test.tsguards the full shared-branch-group lifecycle—concurrent distinct-worktree execution, member→shared-branch accumulation, single shared→main completion-gate promotion with idempotent re-evaluation, gate-disabled integration-without-promotion, and per-task-derived/ungrouped no-regression. - FN-5866 backstop:
packages/engine/src/__tests__/reliability-interactions/post-done-continuation-no-wedge.test.tsguards the post-done non-continuable-session seam so completed executor work stays cleanly inin-reviewwhile incomplete tasks still fail normally. - FN-5888 backstop:
packages/engine/src/__tests__/reliability-interactions/post-done-continuation-no-wedge.test.tsalso covers the incomplete-task non-continuable-session fresh-session retry path, ensuring within-budget failures clearsessionFileand requeue totodowith preserved resume state while exhausted budgets still fall through to terminal failure. - FN-5889 backstop:
packages/engine/src/__tests__/reliability-interactions/post-done-continuation-no-wedge.test.tsextends the seam to the step-session post-done continuation path and therecoverPostDoneNonContinuableWedgeself-heal, so completed work never wedges toin-review+status="failed"and already-wedged rows are cleared before stall surfacing. - FN-5891 backstop:
packages/engine/src/__tests__/mission-execution-loop.test.tsguards mission validation session model resolution (assigned-agent runtime, validator lane settings, test mode) and infrastructure-error surfacing so validator session failures emitvalidation_errorinstead of silently entering fix-feature retries. - FN-5901 backstop:
packages/engine/src/__tests__/reliability-interactions/mission-validator-run-reaper.test.tsguards stale mission-validator-run recovery across manual and automatic trigger types, verifiesmission:validator-run-reapedaudit metadata, preserves complete/archived parent feature state during reap, and proves reaped active features resume validation instead of staying wedged behind abandonedrunningrows. - FN-5874 backstop:
packages/engine/src/__tests__/reliability-interactions/ai-merge-ff-landed-files.test.tsguards AI-merge fast-forward finalizer persistence ofmergeDetails.commitSha,landedFiles, andmodifiedFiles, verifies no-op landings do not fabricate metadata, and confirms normal squash landings do not set FN-5103 attribution-restriction flags; companion coverage inpackages/engine/src/__tests__/self-healing.test.tsextendsrecoverDoneTaskMergeMetadataso done tasks with emptymergeDetailsbut a recordedbaseCommitShaare backfilled via owned-commit discovery while FN-5103 skip guards still prevent overwrite.
Reference docs (deeper detail)
./docs/architecture.md— lifecycle invariants, self-healing rules, reliability interaction backstops, run-audit internals../docs/testing.md— full testing lanes, worker fanout guidance, test taxonomy, and file organization../docs/dashboard-guide.md— dashboard behavior and Styling Guide details. User-facing docs for Merge Advance Notice and Smart Pull live here../docs/agents.md— pi extension scope, coordination tools, checkout leasing, runtime config../docs/settings-reference.md— model-selection hierarchy, mock provider mode, token budget precedence, presets../docs/storage.md— hybrid storage model details../docs/multi-project.md— central/per-project DB and isolation modes../docs/missions.md— mission/milestone/slice/feature model../docs/workflow-steps.md— prompt/script gates and merge-blocking behavior../docs/secrets.md— secrets policy and tooling behavior../docs/diagnostics.md— engine diagnostic logging conventions../docs/task-management.md— archive cleanup and restore semantics../docs/soft-delete-verification-matrix.md— mandatory soft-delete verification matrix../docs/cli-reference.md— CLI and terminal UI reference../docs/contributing.md— contributing conventions and release-adjacent context../docs/solutions/— documented solutions to past problems (bugs, best practices, workflow patterns), organized by category with YAML frontmatter (module,tags,problem_type). Relevant when implementing or debugging in a documented area.
Lazy-Loaded Heavy Views
These 19 views are lazy-loaded via React.lazy() with <Suspense fallback={null}>.
Keep this AGENTS inventory in sync with App lazy imports and packages/dashboard/app/__tests__/lazy-loaded-views-docs.test.ts.
AgentsViewNodesViewChatViewMemoryViewDevServerViewSecretsViewInsightsViewDocumentsViewSkillsViewResearchViewReliabilityViewEvalsViewTodoViewGoalsViewStashRecoveryViewSetupWizardModalPluginManagerPiExtensionsManagerAgentDetailView