- test(FN-2605): complete Step 4 — align tests with planning labels - docs(FN-2605): complete Step 3 — update demo and script terminology - docs(FN-2605): complete Step 2 — update docs terminology - docs(FN-2605): complete Step 1 — update README terminology
6.0 KiB
Contributing
Thanks for contributing to Fusion.
Development Setup
Prerequisites
- Node.js (current LTS recommended)
- pnpm (
packageManageris pnpm) - Git
piruntime/auth configured for AI features
Install dependencies
pnpm install --frozen-lockfile
Build all packages
pnpm build
Workspace Package Overview
| Package | Purpose |
|---|---|
@fusion/core |
Shared domain types, stores, persistence, and core utilities |
@fusion/dashboard |
Express API + React UI (including dashboard TUI in CLI) |
@fusion/engine |
Scheduling, planning, execution, merge orchestration |
@fusion/desktop |
Electron shell around Fusion dashboard/client |
@fusion/mobile |
Capacitor + PWA mobile packaging |
@fusion/plugin-sdk |
Plugin SDK for building Fusion extensions |
@runfusion/fusion |
Published CLI + pi extension (includes merged TUI) |
Development Workflow
pnpm dev # build + run CLI entrypoint in dev mode
pnpm dev:ui # dashboard dev server only
pnpm lint # lint all packages
pnpm test # workspace test suite (clean-worktree compatible)
pnpm build # workspace builds
pnpm verify:workspace # canonical lint -> test -> build verification gate
pnpm typecheck # workspace typechecks
Deterministic workspace verification bootstrap
Fusion codifies workspace verification as a deterministic contract:
- Use
pnpm install --frozen-lockfilefor clean bootstrap and dependency repair paths. pnpm testmust be runnable in a clean worktree without requiring a priorpnpm build.- This includes clean states where
packages/core/dist,packages/engine/dist, andpackages/dashboard/distare absent. pnpm verify:workspaceis the canonical pre-merge gate and runs in strict order:pnpm lintpnpm testpnpm build
CI uses pnpm verify:workspace directly, so changes that reintroduce hidden test pre-build dependencies fail fast.
Quality Gate Checklist
Before submitting changes, verify:
pnpm verify:workspace— canonical lint → test → build gatepnpm typecheck— type checking passes
Testing Requirements
Use real test runs (not manual verification substitutes):
pnpm test
pnpm test:coverage
pnpm test:coverage:core
pnpm test:coverage:engine
pnpm test:coverage:cli
pnpm test:coverage:dashboard
Test File Organization
All test files live in __tests__/ subdirectories alongside the code they test:
- Test for
src/foo.ts→src/__tests__/foo.test.ts - Test for
app/components/Bar.tsx→app/components/__tests__/Bar.test.tsx
When adding new tests, follow this convention. The monorepo has been standardized on __tests__/ organization.
Build Standalone Executables
Fusion supports standalone binary builds through Bun compile scripts in the CLI package.
pnpm build:exe # build host-target executable
pnpm build:exe:all # build multi-target executables
Release Process
Fusion uses Changesets + version PR workflow.
- See RELEASING.md for release flow details.
- For published package behavior changes, include a changeset.
Code Signing
Release binary signing setup is documented here:
Git / Commit Conventions
Use task-ID-scoped conventional commits:
feat(FN-XXX): ...fix(FN-XXX): ...test(FN-XXX): ...docs(FN-XXX): ...(for documentation-only changes)
Project Memory
When enabled, Fusion uses OpenClaw-style memory files:
.fusion/memory/MEMORY.md— long-term project memory.fusion/memory/YYYY-MM-DD.md— daily running notes.fusion/memory/DREAMS.md— dream-processing memory file- The legacy top-level memory file is a deprecated migration fallback (seed/alias behavior) and should not be treated as canonical
Use project memory for reusable patterns, constraints, and pitfalls that should persist across tasks.
Background Memory Summarization
Fusion can automatically extract insights from memory and prune transient content. Enable via insightExtractionEnabled setting:
.fusion/memory/MEMORY.md— Canonical long-term memory source (inside the layered.fusion/memory/workspace) compacted/pruned by extraction jobs.fusion/memory-insights.md— Distilled insights output.fusion/memory-audit.md— Audit report after each extraction (includes pruning outcome)
See Settings Reference for configuration details.
Dashboard CSS Organization
The dashboard's CSS has been modularized:
- Global stylesheet (
packages/dashboard/app/styles.css, ~4,500 lines)- Design tokens, primitives (
.btn,.card,.modal,.form-input), global cross-component rules
- Design tokens, primitives (
- Per-component stylesheets (56+ files in
packages/dashboard/app/components/)- Each component needing CSS has a co-located
ComponentName.css - Each
ComponentName.tsxmust import:import "./ComponentName.css";
- Each component needing CSS has a co-located
Rule: New component CSS goes in the component's .css file, not in styles.css. Only truly global rules belong in the root stylesheet.
CSS Testing
For CSS regression tests, use the helper at packages/dashboard/app/test/cssFixture.ts:
import { loadAllAppCss, loadAllAppCssBaseOnly } from "../test/cssFixture";
// Load all CSS (styles.css + all component .css)
const allCss = await loadAllAppCss();
// Load base rules only (strips @media/@supports)
const baseOnly = await loadAllAppCssBaseOnly();
Never directly readFileSync('../styles.css') — the ESLint rule no-restricted-syntax in eslint.config.mjs blocks this in test files and directs you to cssFixture.ts.
SQLite Test Runner Pitfall
When running engine tests with Vitest and node:sqlite, ensure the engine Vitest config uses thread pool mode:
- ✅
pool: "threads" - ❌
pool: "vmThreads"
node:sqlite fails under Vitest VM contexts; using threads avoids that failure mode.