- Add GET /api/git/workspace-repos endpoint returning sub-repo list
- Add resolveGitDir() helper: resolves repoPath query param to sub-repo dir
- Update all 34 git endpoints to use resolveGitDir for workspace targeting
- Add repoPath param to 30+ frontend git API functions
- GitManagerModal: auto-detect workspace repos on mount, show repo selector
dropdown at top of sidebar, pass selected repo to all git API calls
- Auto-select first repo when workspace mode is detected
- Repo change triggers data refetch via gitRepoPath dependency
- Add POST /api/projects/detect-workspace endpoint for sub-repo scanning
- Modify POST /api/projects to accept workspaceMode + taskPrefix params
- SetupWizardModal: auto-detect sub-repos when path is entered, show
workspace mode checkbox with detected repo count, add task prefix field
auto-derived from project name
- Wire workspaceMode and taskPrefix through registration API call
- Close first TaskStore before creating second in interactive registration (P1)
- Revert defaultWorkflowId default to undefined; set explicitly in onboarding only (P1)
- Add alpha-only filter + 2-char min to interactive prefix input (P2)
- Move suggestTaskPrefix to @fusion/core, share between CLI and dashboard (P2)
- Fix suggestTaskPrefix JSDoc to match implementation (P2)
- Fix workspace detection: change workspaceMode default from false to
undefined so isWorkspaceModeExplicitlyDisabled no longer blocks
auto-detection on fresh projects (config.json was being written with
workspaceMode:false during store.init(), causing the guard to skip
detection before it ever ran)
- Derive task prefix from project name (first 2-4 chars) instead of
hardcoded 'FN' as the suggested default
- Default workflow is now builtin:coding instead of undefined
- CLI registerProjectInteractive: onboarding prompt for task prefix
confirmation after project name
- Dashboard POST /api/projects: auto-derive prefix and set default
workflow for new registrations
Let ntfy test notifications use the current Settings form values before they are saved.
- Send unsaved ntfy enabled/topic/server/token values from all Settings ntfy test buttons.
- Resolve request-scoped ntfy config on the backend for general, message, and room test notifications.
- Publish message and room ntfy tests directly with the resolved config instead of the active persisted notification service.
- Cover unsaved ntfy test behavior across Settings UI and API routes.
Files changed:
.changeset/fn-6953-ntfy-test-unsaved-config.md | 5 +
.../dashboard/app/components/SettingsModal.css | 5 +-
.../dashboard/app/components/SettingsModal.tsx | 21 +-
.../components/__tests__/SettingsModal.test.tsx | 60 +++-
.../src/__tests__/routes-settings.test.ts | 181 ++++++++---
.../src/routes/register-settings-memory-routes.ts | 355 +++++++++------------
6 files changed, 380 insertions(+), 247 deletions(-)
Fusion-Task-Id: FN-6953
Fusion-Task-Lineage: 90557168-3b11-4ab4-b5c1-4261225600ba
gh pr/issue view --json comments returns only author.login (no type), and app-bot logins (coderabbitai, greptileai) lack the [bot] suffix — so every app bot was classified human. Fetch comments via gh api graphql with author{ __typename login avatarUrl } so authorIsBot = __typename === 'Bot' (any app bot by type, no hardcoded names); REST token-fallback already used user.type/[bot]. Output shape + avatars preserved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SKILL.md now renders via MailboxMessageContent (markdown + sanitized HTML + mermaid) instead of raw <pre>. Files strip is compact and lists all files; clicking a file loads its content in the detail pane (markdown via MailboxMessageContent, other text via <pre>, binary/oversized notice) with a Back-to-SKILL.md affordance. New GET /api/skills/:id/file endpoint (readSkillFileContent: path-traversal-guarded, 2MB ceiling, binary detection) + fetchSkillFileContent client fn.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment shape gains authorAvatarUrl + authorIsBot (gh GraphQL Bot/__typename or REST user.type==Bot or [bot] login; avatar from API or github.com/{login}.png, suppressed for bots). New shared CommentsThread (PR + issue) shows author avatar (lucide Bot/User fallback), readable localized timestamp (ISO title), a Human/Bot badge + data-comment-author-type, prev/next chevron nav that scrolls+highlights, and an All/Human/Bot filter defaulting to All.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirrors the PR detail pattern for issues: GitHubClient.getIssueDetail (gh issue view --json comments, REST fallback) + closeIssue (gh issue close, REST PATCH fallback); new POST /api/github/issues/detail + /issues/close routes. The Issues preview fetches comments on selection (cached, non-blocking) and renders them below the body; a Close-issue button in the preview header (open issues only) closes via the API, toasts, and reflects the closed state without dismissing the view.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New POST /api/github/pulls/detail endpoint + GitHubClient.getPullRequestDetail (gh pr view --json comments,statusCheckRollup, REST fallback). On PR select, the preview fetches detail (cached per PR, body never blocked) and renders below the body: a Checks section (each check name + status pill success/failure/pending/neutral, linked to detailsUrl) and a Comments section (chronological, markdown via MailboxMessageContent). Issues tab unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- GitHub import preview shows the full issue/PR body (markdown) + metadata (list already returned full bodies; removed client truncation).
- Task-detail main view: constrain width (no right cutoff); move 'Back to board' into the gray header far right.
- Dock pop-out: smoother touch drag (touch-action:none + captured-element listeners); popping out closes the dock but keeps the floating modal; modal survives dock dismiss.
- Remove duplicate inner headers in Git Manager / Activity Log / Dev Server / Secrets (dock + pop-out chrome already titles them); keep the title on mobile narrow; relocate gm Refresh into the section tab strip.
- Git Manager tabs: one scrollable row of compact icon-only tabs (max visible, scroll if needed).
- List quick entry is single-line (not tall) via singleLine prop; Board unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the Command Center pricing contract for maintainers and users.
- Explain that estimated token costs are derived at read time from the maintained pricing table and are not persisted billing truth.\n- Document pricingAsOf, stale low-confidence, unknown-model unavailable, and provider coverage maintenance expectations.\n- Add a documentation contract test to keep the dashboard and architecture guides aligned.
Files changed:\n docs/architecture.md | 2 ++\n docs/dashboard-guide.md | 3 +-\n .../__tests__/command-center-pricing-docs.test.ts | 35 ++++++++++++++++++++++\n 3 files changed, 39 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-6874
Fusion-Task-Lineage: 04606ae1-4870-479a-afb6-8a24675fe66b
- Stop reconciliation/startAll/onProjectAccessed from warning every tick for
externally-owned engines: swallow EngineAlreadyRunningError in the outer
catches (it's expected and already logged once in createAndStart)
- Add FNXC:DashboardHealth requirement-trace comments on the externalEngines
field and the dashboard hasRunningEngine health check
- Add regression test: reconciliation stays quiet across ticks for an
externally-owned engine (inner refusal logged once, outer failure suppressed)
- Add regression test: hasDashboardEngine legacy fallback to getAllEngines when
hasRunningEngine is unavailable on the manager
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The dashboard's engine-availability health check only counted engines
this process started. A second launch (e.g. `pnpm dev dashboard`
alongside an already-running `fusion`) is correctly refused the
per-machine engine singleton lock, so its engine map stays empty and
the dashboard showed a false "engine not running" banner even though an
engine was live on the machine.
ProjectEngineManager now records projects whose singleton lock is held
by another process (via EngineAlreadyRunningError) and exposes
hasRunningEngine(), which the health endpoint consults so the banner
reflects machine-level truth. Reconciliation still retries so this
process takes over if the other exits, and the "refusing to start" log
fires once per project instead of on every 30s reconciliation tick.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Plugin skills now respect project-settings enable/disable toggles
(discoverSkills consults getSkillSettingState, falling back to the
plugin's declared default) so toggleExecutionSkill writes persist
- readSkillContent returns synthesized content for plugin-contributed
skills (name + description + provenance) instead of a silent blank
panel, since their path is a virtual runtime-materialized path
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve conflicts from main's analytics schema additions (plugin
activations, per-model token buckets) against the PR's contract-assertion
type column:
- db.ts: renumber behavioral-verification migration 124 -> 126, bump
SCHEMA_VERSION to 126 so it follows main's migrations 124/125
- core/roadmap tests: adopt main's SCHEMA_VERSION-constant assertions
instead of stale literal 124
- test-quarantine.json: keep all four quarantine entries from both sides
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The dashboard's discovered-skills catalog was built only from the
disk-scanning package manager, so plugin-contributed skills (e.g.
compound-engineering ce-*) — which the engine materializes for executor
sessions separately — never appeared in the editor. Built-in workflow
nodes that reference them (builtin:compound-engineering) showed
"— select skill —" / unresolved.
- skills-adapter: merge plugin skill contributions into the discovered
list (deduped by bare name) via an optional getPluginSkills thunk;
add shared bareSkillName normalizer.
- wire getPluginSkills into all three server entry points: serve,
daemon, and dashboard (the UI-serving command — verified via live
end-to-end that omitting it left the editor catalog empty).
- node-summary + WorkflowNodeEditor: resolve namespaced skillNames
(compound-engineering:ce-work) against the catalog's two-segment
names (ce-work/SKILL.md) so nodes display and select the right skill.
Verified: dashboard + CLI typecheck, 136 dashboard tests, and a live
dashboard E2E (discovered skills 0→11; Plan node resolves to "ce-plan"
in both the canvas label and the inspector dropdown).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three failures in the non-blocking Full Suite:
- CommandCenter mobile-scroll / tablet-layout regression tests rendered with
productivity fixtures missing the `hoursSaved` field added in FN-6721. That
made ProductivityArea throw on `data.hoursSaved.unavailable`, an uncaught
exception that crashed the CommandCenter render (no `command-center` testid)
and polluted the shared worker, causing collateral QuickEntryBox failures.
Add `hoursSaved` to both fixtures.
- github-tracking-delete route test failed intermittently with
`ENOTEMPTY: ... rmdir '.../.fusion'` because the fire-and-forget delete
handler can write into `.fusion` while afterEach removes the temp dir. Make
rm tolerant via maxRetries/retryDelay.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a live Team area to Command Center with per-agent analytics and supporting API data.\n\n- Add read-only core aggregation for agent tokens, cost, changed files, and task status counts.\n- Expose the team metrics through the Command Center API and render a responsive Team dashboard with charts and tables.\n- Cover aggregation, route, desktop, and mobile Command Center behavior with tests.\n- Document the Team area and add a patch changeset for the published CLI bundle.\n\nFiles changed:\n .changeset/fn-6655-command-center-team-view.md | 5 +\n docs/dashboard-guide.md | 2 +\n packages/core/src/__tests__/team-analytics.test.ts | 315 +++++++++++++++++++++\n packages/core/src/index.ts | 7 +\n packages/core/src/team-analytics.ts | 315 +++++++++++++++++++++\n .../components/command-center/CommandCenter.tsx | 9 +\n .../__tests__/CommandCenter.mobile-scroll.test.tsx | 22 ++\n .../__tests__/CommandCenter.test.tsx | 148 +++++++++-\n .../components/command-center/areas/TeamArea.tsx | 265 +++++++++++++++++\n .../app/components/command-center/areas/areas.css | 89 ++++++\n .../register-command-center-routes.auth.test.ts | 1 +\n .../register-command-center-routes.test.ts | 69 +++++\n .../src/routes/register-command-center-routes.ts | 24 ++\n 13 files changed, 1269 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-6655
Fusion-Task-Lineage: 366170f4-a250-49ce-8ca6-aea865ab0b84