Adds validatorThinkingLevel and planningThinkingLevel task fields so the Reviewer and Planning AI lanes can override reasoning effort independently of the shared task thinkingLevel, with dashboard UI, storage, and runtime fallback wiring.
- Add validatorThinkingLevel and planningThinkingLevel to Task/TaskCreateInput types (packages/core/src/types.ts)
- Persist the new fields in the SQLite schema and store read/write/replication paths (packages/core/src/db.ts, store.ts, mesh-task-replication.ts)
- Wire executor and triage lanes to fall back per-lane thinking level -> task.thinkingLevel -> existing settings/lane fallback (packages/engine/src/executor.ts, triage.ts)
- Add per-lane thinking-level selectors to the ModelSelectorTab UI, alongside the existing thinking-level control (packages/dashboard/app/components/ModelSelectorTab.tsx)
- Expose the new fields through the legacy task API and task-workflow routes (packages/dashboard/app/api/legacy.ts, packages/dashboard/src/routes/register-task-workflow-routes.ts)
- Document the new settings in dashboard-guide.md and settings-reference.md
- Add a minor changeset and unit/integration test coverage for store persistence, routes, UI, and agent-session helpers
Files changed:
.changeset/per-lane-task-thinking.md | 7 ++
docs/dashboard-guide.md | 2 +
docs/settings-reference.md | 2 +-
.../src/__tests__/store-thinking-levels.test.ts | 43 +++++++
packages/core/src/db.ts | 15 ++-
packages/core/src/mesh-task-replication.ts | 4 +
packages/core/src/store.ts | 24 +++-
packages/core/src/types.ts | 12 ++
packages/dashboard/app/api/legacy.ts | 2 +
.../dashboard/app/components/ModelSelectorTab.tsx | 126 ++++++++++++++++++++-
.../components/__tests__/ModelSelectorTab.test.tsx | 50 +++++++-
.../src/__tests__/routes-tasks-ops.test.ts | 74 ++++++++++++
.../src/routes/register-task-workflow-routes.ts | 19 +++-
.../src/__tests__/agent-session-helpers.test.ts | 15 +++
packages/engine/src/executor.ts | 16 ++-
packages/engine/src/triage.ts | 8 +-
16 files changed, 395 insertions(+), 24 deletions(-)
Fusion-Task-Id: FN-7932
Fusion-Task-Lineage: 4202f774-aab9-41d2-86a0-f5277dd0f848
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Many loading states rendered bare "Loading…" text with no spinner
element, and a couple rendered an unstyled `loading-spinner` div with no
matching CSS (invisible). The global spin animation was never broken —
it rotates in Chromium and WebKit — so prior transform-box edits chased
a non-bug, validated only by a string-matching CSS test.
Add a shared <LoadingSpinner> (self-contained animated SVG, no
lucide-react import so it survives partial test mocks) and adopt it
across ~47 loading placeholders so every loading state shows a
consistent animated spinner. Includes a component test that asserts the
svg carries the animate-spin utility.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migration (multi-agent sweep over 216 files, 60 batches):
- Every user-visible dashboard + TUI string moved to t() with the exact
English inline default (en rendering byte-identical)
- Catalogs merged from per-batch fragments: en/zh-CN/zh-TW/fr/es now
carry ~5,930 keys each across common/app/errors/cli namespaces;
CLI bundles regenerated (6 locales incl. ko)
Integration fixes:
- 18 type errors: reserved {{count}} interpolations renamed, malformed
plural call, hand-rolled t-param types replaced with TFunction<"app">
- 23 lint errors: superseded label constants/helpers removed
- ExecutorStatusBar hook-order violation (keyboard-open early return
moved below hooks)
- TUI tests wrapped in I18nextProvider (uninitialized fallback renders
literal {{placeholders}}); dashboard vitest.setup boots a minimal en
i18next instance for the same reason
Known WIP (next commits): ~457 residual strings across 50 batches,
Korean drafts for swept keys, and a dashboard test-suite pass that is
still being stabilized (~283 failures under investigation — fake-timer
waitFor interaction, likely stale node_modules vs merged lockfile).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split app/styles.css from ~40k lines down to ~4.5k. Created 56 co-located
component CSS files in app/components/, each imported by its owning .tsx.
The remainder of styles.css holds genuinely global rules (design tokens,
.btn/.card/.modal/.form-input primitives, cross-component @media overrides).
- Lazy-load 13 heavy views (AgentsView, RoadmapsView, NodesView, etc.) via
React.lazy + Suspense; prefetch all chunks on idle so first navigation is
instant. Initial JS bundle: 1.58 MB → 1.16 MB (-26%). Initial CSS bundle:
635 kB → 471 kB (-26%); the rest splits into 13 per-view chunks.
- Add app/test/cssFixture.ts exposing loadAllAppCss() + loadAllAppCssBaseOnly()
so CSS regression tests load the full per-component bundle (mirroring Vite
source order). Migrate 30+ tests off direct readFileSync('../styles.css').
- Enable test.css: { include: [/.+/] } in vitest.config.ts so component CSS
imports actually inject styles in jsdom (fixes getComputedStyle assertions).
- Add ESLint rule (no-restricted-syntax) banning direct styles.css reads in
dashboard test files; points at loadAllAppCss() instead.
- Restore lost utility classes (.text-muted, .text-secondary, .text-dim,
.form-input) and rescue dropped chat tool-call rules into QuickChatFAB.css.
- Mobile fixes along the way: scroll containment for view containers
(min-height:0 + -webkit-overflow-scrolling), QuickChatFAB full-screen on
mobile (with safe-area-inset for iOS home bar), AgentsView single-row
header layout, ActivityLogModal close button on right, model-combobox
z-index above the mobile quick-chat panel.
- Bug fix: SkillsView toggle was display:none which hid the input from the
accessibility tree; replaced with the visually-hidden pattern so screen
readers + getByRole still find the checkbox.
- Bug fix: standalone Delete button in TaskDetailModal for triage-column
tasks (Actions dropdown is hidden in triage state, so previously no way
to delete a freshly-created task without status change first).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parallel subagent pass: four typescript-pro agents on non-overlapping scopes.
Patterns applied:
- catch (err: any) { ... err.message ... } → catch (err) { ... getErrorMessage(err) ... }
using the new @fusion/core helper. Bare catch {} where the error was unused.
- SQLite row types: defined typed XxxRow interfaces per table and cast
.all()/.get() results via `as unknown as XxxRow[]` (the double cast is
required because better-sqlite3 returns Record<string, SQLOutputValue>).
- rowToX(row: any) converters: typed argument with the matching row interface.
- Dynamic settings key writes: (settings as Record<string, unknown>)[key].
- React event handlers and setState callbacks: inferred types or concrete
React.{Mouse,Change,Form}Event<...> where needed.
- pi-claude-cli: local PiMessage / PiContext duck types to avoid re-typing
pi-ai concrete shapes; typed Claude stream event message fields.
72 files changed, ~400 anys eliminated. Typecheck passes across the workspace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clears the remaining no-unused-vars warnings across the dashboard app and
server, desktop main, and engine sources. Dead React state destructures are
collapsed to setter-only, unused props are underscore-prefixed to preserve
API shape, and unreferenced catch bindings are dropped. No behaviour change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Fix thinking level selector to default to 'off' when no global default is configured
- Add 'Using default' badge when thinking level falls back to global setting
- Show explicit thinking level badge only when a non-default value is selected
- Add comprehensive tests for thinking level selector behavior
- Add tests for resolved model display with global settings fallback
- Show resolved default executor, validator, and planning models in the task Model tab
- Pass merged settings into the Model tab from TaskDetailModal so default badges reflect effective runtime resolution
- Hot-swap active single-session executor models when task overrides change, including fallback to project defaults when overrides are cleared
- Add dashboard and executor tests for default model display, hot-swap behavior, fallback logic, and failure logging
- Document hot-swap behavior and limitations in AGENTS.md and add a patch changeset for @gsxdsm/fusion
- Pass TaskDetailModal's onTaskUpdated callback into ModelSelectorTab
- Propagate server-returned task updates after model and thinking-level saves so edit mode uses fresh values
- Add regression tests for ModelSelectorTab update callbacks and TaskDetailModal model-sync flow
- Add a patch changeset for @gsxdsm/fusion covering the model edit sync fix
- Add thinkingLevel field to createTask and updateTask in core store
- Accept thinkingLevel and planningModel fields in dashboard task routes
- Send thinkingLevel and planningModel in frontend API calls from task forms
- Add ThinkingLevel selector to ModelSelectorTab component with tests
- Wire up planning model and thinking level in QuickEntryBox, TaskForm, and NewTaskModal
- Add unit tests for store, routes, and ModelSelectorTab coverage
- Add changeset and update AGENTS.md documentation
- Add planningModelProvider and planningModelId fields to core Task type
- Update backend API validation to accept planning model fields on create/update
- Update frontend API client and TaskForm to handle planning model
- Add planning model selector row to ModelSelectorTab component
- Wire up planning model in TaskDetailModal edit mode with save support
- Update AGENTS.md with planning model override documentation
- Add comprehensive tests for ModelSelectorTab and API routes
- Bump schema version from 10 to 11
- Rename @kb/core, @kb/dashboard, @kb/engine to @fusion/* namespace
- Update all import statements across 143+ files to use new package names
- Update workspace dependencies and root package.json references
- Fix bundler configurations (tsup, vite) for new package names
- Update test files and fix typecheck issues
- Add changeset file documenting the package rename
- Auto-save executor and validator model selections immediately from the model selector tab
- Send explicit null override fields when users switch a task back to default models
- Keep saved badges stable while requests are pending and restore the previous selection on save failures
- Expand ModelSelectorTab tests to cover auto-save requests, status feedback, success toasts, and clear-to-default flows
- Create ProviderIcon component with provider-to-icon mappings (OpenAI, Anthropic, Google, etc.)
- Build CustomModelDropdown with icon display, filtering, and keyboard navigation
- Integrate custom dropdown into ModelSelectorTab replacing native select element
- Add CSS styles for provider icons in dropdown items and model badges
- Add comprehensive tests for ProviderIcon, CustomModelDropdown, and ModelSelectorTab
- Create new combobox component for model/provider selection
- Refactor ModelSelectorTab to use combined dropdown UI
- Add scrollIntoView null check for test environment compatibility
- Add changeset for combined model dropdown feature
- Clean up obsolete changeset and subtask-related code
- Add search input with clear button and results count to ModelSelectorTab
- Extract filterModels utility for shared filtering logic across components
- Apply filtering to SettingsModal model section
- Add CSS styles for filter UI components
- Add comprehensive tests for ModelSelectorTab and SettingsModal filtering
- Add section expansion state management with localStorage persistence
- Update section headers with chevron toggle controls
- Implement conditional task row rendering based on section state
- Add Expand All / Collapse All toolbar controls
- Add CSS styles for chevron rotation animation and section headers
- Add comprehensive tests for collapsible section behavior