docs: document CSS extraction, test consolidation, and TUI merge

- AGENTS.md: per-component CSS layout, loadAllAppCss test helper, ESLint
  guardrail, lazy view list + Suspense pattern; __tests__/ convention;
  TUI now invoked via fn (no separate @fusion/tui package).
- docs/contributing.md: Dashboard CSS organization + test layout sections;
  workspace package table reflects fn CLI bundling the TUI.
- docs/architecture.md: CSS architecture subsection; updated CLI/TUI
  references to packages/cli/src/commands/dashboard-tui/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-24 19:43:00 -07:00
parent 60e5899686
commit 9cf24e7c0c
3 changed files with 146 additions and 11 deletions

View File

@@ -23,14 +23,15 @@ At a high level, Fusion is split into:
```text
┌──────────────────────────────┐
│ Human + AI Interactions │
(Dashboard, CLI, Pi tools)
│ (Dashboard SPA, CLI, Pi)
└──────────────┬───────────────┘
┌──────────────────────┼──────────────────────┐
│ │ │
┌─────────▼─────────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐
│ Dashboard (API) │ │ CLI `fn` router │ │ Pi extension tools │
│ + React SPA │ │ (commands/*) │ │ (extension.ts) │
│ + React SPA │ │ + TUI component │ │ (extension.ts) │
│ (lazy-loaded) │ │ (commands/*) │ │ │
└─────────┬─────────┘ └─────────┬─────────┘ └─────────┬─────────┘
└──────────────┬────────┴──────────────┬───────┘
│ │
@@ -422,6 +423,27 @@ Key server capabilities:
- Planning/roadmap/insight UI: `MissionManager.tsx`, `RoadmapsView.tsx`, `InsightsView.tsx`, `DocumentsView.tsx`
- Dev server UI: `DevServerView.tsx` (controls + status/log panel + embedded preview with iframe fallback messaging)
### CSS Architecture
The dashboard's CSS is split between a consolidated global stylesheet and modular per-component files:
- **Global stylesheet** (`packages/dashboard/app/styles.css`, ~4,500 lines)
- Design tokens (spacing, colors, shadows, transitions, fonts)
- Primitive component classes (`.btn`, `.card`, `.modal`, `.form-input`)
- Cross-component `@media` overrides and breakpoint definitions
- **Per-component stylesheets** (56+ files in `packages/dashboard/app/components/`)
- Each component has a co-located `ComponentName.css` file
- Each `ComponentName.tsx` imports its stylesheet: `import "./ComponentName.css";`
- Component-specific CSS rules live in the component's `.css` file, not in the root stylesheet
**Lazy-loaded views** (bundle size optimization):
The following 13 views are lazy-loaded via `React.lazy()` with `<Suspense fallback={null}>`:
- `AgentsView`, `RoadmapsView`, `NodesView`, `ChatView`, `MemoryView`
- `DevServerView`, `InsightsView`, `DocumentsView`, `SkillsView`
- `SetupWizardModal`, `PluginManager`, `PiExtensionsManager`, `AgentDetailView`
A `prefetchLazyViews()` function runs once on mount via `requestIdleCallback` to warm chunks. Do not make these views eager — bundle size is carefully managed.
### Key hooks
- Task + realtime: `useTasks.ts`, `useBadgeWebSocket.ts`, `useAiSessionSync.ts`
- Chat: `useChat.ts`, `useQuickChat.ts`
@@ -468,6 +490,10 @@ Events are tied to specific run IDs for end-to-end traceability.
### Command modules
- `packages/cli/src/commands/*`
- Task operations, settings, git wrappers, backup operations, project/node management
- **TUI component** (`packages/cli/src/commands/dashboard-tui/`)
- Ink-based terminal UI (status panel, logs, cursor visibility, tail-follow)
- Merged from former `@fusion/tui` package
- Invoked as part of the `fn` command (no separate package or `pnpm tui` command)
### Project selection
- `packages/cli/src/project-resolver.ts`
@@ -481,6 +507,7 @@ Events are tied to specific run IDs for end-to-end traceability.
### Binary identity
- Published package defines `fn` binary (`packages/cli/package.json`)
- Running `fn` with no arguments defaults to dashboard (web UI by default)
---

View File

@@ -30,12 +30,12 @@ pnpm build
| Package | Purpose |
|---|---|
| `@fusion/core` | Shared domain types, stores, persistence, and core utilities |
| `@fusion/dashboard` | Express API + React UI |
| `@fusion/dashboard` | Express API + React UI (including dashboard TUI in CLI) |
| `@fusion/engine` | Scheduling, triage, 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 |
| `@runfusion/fusion` | Published CLI + pi extension (includes merged TUI) |
## Development Workflow
@@ -83,6 +83,15 @@ 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.
@@ -135,6 +144,34 @@ Fusion can automatically extract insights from memory and prune transient conten
See [Settings Reference](./settings-reference.md#background-memory-summarization--audit) 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
- **Per-component stylesheets** (56+ files in `packages/dashboard/app/components/`)
- Each component needing CSS has a co-located `ComponentName.css`
- Each `ComponentName.tsx` must import: `import "./ComponentName.css";`
**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`:
```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: