Commit Graph

206 Commits

Author SHA1 Message Date
gsxdsm
0863c0fb58 feat(dashboard): auto-translate foreign-language GitHub issues on import (#2141)
## Why

The Import Tasks panel routinely lists issues in languages the operator
cannot read. Translation already shipped in #2128, but deliberately
**opt-in and preview-only** — its header comment read *"Translation is
opt-in (never automatic) so import provenance stays faithful until the
operator asks."*

This reverses that decision **behind a default-off setting**, so
operators who never opt in keep byte-faithful import provenance. The
superseded comment is kept and annotated rather than deleted, so the
reason the rule changed stays in the code.

### The structural gap #2128 left

`POST /github/issues/import` accepts only `{owner, repo, issueNumber}`
and **re-fetches the issue server-side**. A translation held in React
state could never reach the created task, and the in-memory cache died
with the modal. That is why the cache here is server-side rather than in
the hook — it's what makes "imported issues carry the translated
version" actually true.

## What operators get

Auto-translate is **off by default**. When enabled:

- The **50 most recent OPEN** foreign-language issues translate on panel
load — **list titles**, not just the preview, so the list reads in your
language before you click anything.
- Translations show **by default**, with a toggle back to the original
(hover a translated list title to see the original).
- Translations **persist until the issue closes**, so re-opening the
panel neither waits nor re-bills.
- **Both single and batch import** carry the translation, so the created
task reads like the preview you approved.
- A **target language** setting (unset = follow the dashboard language)
and a dedicated **model lane**, so you can pin a cheap/fast model
without dragging the summarization lane onto it.

## Notable decisions

| Decision | Why |
|---|---|
| Detect **before** the model | An issue already in the target language
is never sent. Without this, an English repo with the setting on would
bill every issue to return its input unchanged. |
| Detection moved to `@fusion/core` | The panel and the server must not
disagree about which issues are foreign; two copies of a heuristic
drift. |
| Own rate-limit budget | Translation shared a 10/hour budget with
refine/goal-draft. Fanning out per-issue would fail partway **and**
starve refine for the hour. |
| Cache keyed on a **source hash** | An edited issue misses the cache
and re-translates instead of serving stale prose. |
| Import is **cache-read only** | A miss imports the original. Import
must never block on, or fail because of, translation. |
| `project_id` leads the cache PK + full RLS contract | All projects
share one flat `project` schema. `verification_cache`'s PK predates that
discipline; this table does not copy that mistake. |

## Verification

- ✅ `pnpm lint`, `@fusion/core` + `@fusion/dashboard` typecheck
- ✅ `pnpm verify:fast` — build + scoped typecheck + real boot smoke
(`/api/health`)
- ✅ `pnpm test:gate` — 479 tests
- ✅ 19 new tests covering the billing invariants
(off/closed/same-language ⇒ **no model call**), cache hit/miss-on-edit,
the 50 cap, and per-item fail-soft
- ✅ `schema-applier` real-Postgres suite (46 tests) exercises migration
`0010` and its isolation invariant

**Pre-existing failures NOT touched** (confirmed red on `HEAD` before
this branch): `AppearanceSection`'s task-popup test, and two PG-cutover
keys (`sqliteMigrationNotice`, `postgresMigrationInboxMessageSentAt`)
missing description mappings. I left the latter rather than guess an
allowlist entry that could mask a real coverage gap.

## Reviewer notes

- Short Latin-script prose (a one-line Spanish title) rates only
*medium* confidence and won't auto-translate — the existing heuristic is
deliberately conservative so English issues are never billed. CJK
detects regardless of length. The threshold is the knob if you'd rather
bias toward translating.
- The RLS/isolation contract in migration `0010` is the part most worth
a careful look.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 14:06:42 -07:00
gsxdsm
335b6a4dc2 fix: raise Plan Review replan cap to 8 and explain approval holds
Give planner/reviewer pairs more room to converge before escalating, and surface why a task is parked for plan approval—especially plan-review-replan-cap non-convergence—on cards, detail, and notifications.
2026-07-15 11:14:17 -07:00
gsxdsm
e9f14bf024 perf: speed up local pnpm build and cap stacked verifications (#2134)
## Summary

- Extend the workspace content-hash skip cache to **all** packages (not
just plugins), with `--force` / `--full` flags
- Default local CLI packaging to a **fast mode** (bin/extension +
migrations only); full desktop/plugin/DTS staging runs on CI or `pnpm
build:full`
- Enable TypeScript `incremental` builds for warm recompiles
- Add `maxConcurrentVerifications` (default **1**) so concurrent tasks
cannot stack monorepo typecheck/build and peg CPU

Warm `pnpm build` measured ~**126s → ~0.8s** when nothing changed.

## Test plan

- [x] `node --test scripts/__tests__/build-workspace.test.mjs` (12 pass)
- [x] `pnpm --filter @fusion/engine exec vitest run
src/__tests__/verification-concurrency.test.ts`
- [x] `pnpm --filter @fusion/core exec vitest run
src/__tests__/settings-parity.test.ts`
- [x] Local: first `pnpm build` rebuilds as needed; second warm `pnpm
build` skips all packages (~0.8s)
- [x] Fast CLI packaging logs skip of desktop/plugin staging without
`FUSION_CLI_FULL_PACKAGE`
- [ ] CI: `pnpm build` still full-packages under `CI=true` (plugin
staging / release surfaces)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a Scheduling setting to limit concurrent verification tasks from
1–8, with a default of 1.
* Verification tasks now support cancellation while waiting or running.
  * Added options for forced and full workspace builds.

* **Performance**
* Local builds can skip unchanged packages and use incremental
compilation for faster rebuilds.
* Local CLI packaging is faster by default, while full packaging remains
available when needed.

* **Documentation**
* Updated the settings reference with the new verification concurrency
option.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 08:44:11 -07:00
gsxdsm
bc2d22df6e feat(dashboard): offer AI translation in Import Tasks preview (#2128)
## Summary

Import Tasks can now offer on-demand AI translation when a selected
GitHub or GitLab issue/PR title and body appear to be in a different
language than the active dashboard locale.

- Detect foreign-language content with a conservative client heuristic
(Unicode scripts + Latin stopwords)
- Show an opt-in banner: **Translate**, then **Show original / Show
translation**, plus **Dismiss**
- Call new `POST /api/ai/translate-text` (shared AI-helper rate limit
with refine/draft)
- Translation is **display-only** in the preview; imported task text
stays the original source language

## Why

Operators working in a non-English dashboard (or reading
non-dashboard-language issues) needed a way to understand import
candidates without leaving the preview or changing what gets imported.

## Test plan

- [x] Unit tests for language detection (`detectContentLanguage`)
- [x] Unit tests for translate request validation, response parsing, and
AI agent path
- [x] GitHub import modal: French content shows translate controls;
English content does not
- [x] Dashboard typecheck clean for app + server packages
- [ ] Manual: open Import Tasks with dashboard language English, select
a French/Korean issue, translate and toggle original
- [ ] Manual: confirm Import still creates the task with original
title/body
- [ ] Manual: dismiss banner for a selection and confirm it stays
dismissed for that item

## Notes

- Comments are not translated (title + body only)
- zh-CN / zh-TW share a CJK family so Chinese content does not prompt
translation when the UI is either Chinese locale
- Secondary locale catalogs have empty placeholders for the new
`git.translate*` keys (runtime falls back to English)
2026-07-15 02:18:43 -07:00
gsxdsm
ba1e82381e fix(FN-7952): cut runtime services over to PostgreSQL (#2109)
## Summary

Engine and dashboard traffic now stays on the authoritative PostgreSQL
layer across execution, recovery, project discovery, planning sessions,
analytics, and shutdown. The dashboard no longer presents a migration
notice for a cutover that is already mandatory.

## Design decisions

- Runtime composition requires an async data layer instead of
constructing a hidden SQLite fallback.
- Engine workflow, mission, claim, and self-healing reads await their
PostgreSQL-backed store contracts.
- Project-scoped dashboard stores retain and close their backend owner
exactly once.
- The dashboard test quarantine entry remains paired with its Vitest
exclusion, preserving the repository’s deletion-ratchet policy.

## Validation

- Core, Engine, Dashboard, CLI, and Desktop typechecks pass on the
stacked branch.
- `pnpm test:gate` passes all 478 gate tests.
- This PR changes 62 files.

## Stack

- Depends on #2108.
- CLI/desktop/ops, plugins, and docs/release follow in later PRs.

Related: #2105


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Project discovery now recognizes projects using the
`.fusion/project.json` marker.
* Knowledge indexing and search are more reliable across project-scoped
storage.
* **Bug Fixes**
* Improved session, audit timeline, approval, monitoring, and analytics
data consistency.
* Prevented stale planning-session updates and project-store shutdown
races.
* Ensured chat usage and CLI session status are saved before continuing.
* **UI Changes**
* Removed the storage migration notice banner now that the PostgreSQL
transition is complete.
* **Reliability**
* Improved shutdown handling, workflow execution, and worktree behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 22:16:16 -07:00
gsxdsm
8de0fbcd01 fix: repair full-suite failures after SQLite-to-PostgreSQL cutover (#2086)
## Summary

Fixes all deterministic full-suite (non-blocking) CI failures on `main`
caused by the SQLite-to-PostgreSQL cutover (VAL-REMOVAL-005).

## Changes

### i18n Key Parity (5 locale files)
- Added missing `taskPopupsBoardListOnly` +
`taskPopupsBoardListOnlyHelp` keys (empty strings per convention) to
zh-CN, zh-TW, fr, es, ko `app.json`

### Dashboard Curated-Gate Guard (`scripts/lib/test-quarantine.json`)
- Repaired "mirror drift": 16 dashboard test files were quarantined in
`vitest.config.ts` but never added to the quarantine ledger. Added all
16 with failing run URLs and `quarantinedAt` dates.

### Line-Count Audit CI Cache (`.github/workflows/full-suite.yml`)
- Removed `skip-install: "true"` from `line-count-audit` job —
`setup-node@v5` with `cache: pnpm` failed post-step because no
`node_modules` existed to cache.

### Engine Slow Tier — Full PG Migration
- **CI**: Added PostgreSQL service container to `test-slow` job (same
config as `test-shards`)
- **`_helpers.ts`**: Migrated `makeReliabilityFixture()` from removed
SQLite `Database.init()` to PG-backed `TaskStore`:
  - Added `probeTcpReachable()` (TCP probe, copied from shared harness)
  - Added `hasPg` export (uses TCP probe, not env-var guess)
- Added `adminExecAsync()` (`Promise.withResolvers`, psql via
`PG_TEST_URL_BASE`)
- Added `createPgLayer()` (fresh PG database + schema baseline +
`AsyncDataLayer`)
  - Updated cleanup: `await store.close()`, close layer, drop database
- **Slow test**: Migrated 24 sync SQLite API calls to async PG APIs:
- `store.getRunAuditEvents()` → `await auditEvents(store, ...)` via
exported `queryRunAuditEvents`
- `store.getDatabase().prepare(...)` → Drizzle queries via
`store.getAsyncLayer()!.db`
- **Core exports**: Added `queryRunAuditEvents` from `async-audit.ts`
and `eq as drizzleEq` from `drizzle-orm`
- **22 reliability test files**: Added `hasPg` guards so tests skip
locally when PG is unavailable

### Shard 3 — PG Test Auth Bug (18 postgres test files)
- Replaced `psql -U ${process.env.USER ?? "postgres"}` with `psql
"${PG_TEST_URL_BASE}/postgres"` connection string. On GitHub Actions,
`process.env.USER` is `'runner'`, not `'postgres'`, causing auth
failure.

### Shard 3 — Removed Function Tests (`mesh-task-replication.test.ts`)
- Deleted 3 tests for functions intentionally removed in PostgresCutover
(`buildMeshReplicatedTaskCreatePayload`, `toReplicatedCreateInput`,
`taskMatchesReplicatedCreate`). Kept `buildBootstrapPrompt` test.

### Shard 3 — Store Thinking Levels (`store-thinking-levels.test.ts`)
- Migrated from removed SQLite path to PG-backed
`createTaskStoreForTest` + `pgDescribe`.

## Verification

| Check | Result |
|---|---|
| Merge gate (`pnpm test:gate`) | ✅ 294 + 99 + 63 = 456 passed |
| Engine slow tier (22 tests) | ✅ 22/22 passed |
| i18n parity tests | ✅ 7 passed |
| mesh-task-replication | ✅ 1 passed |
| PG data-layer | ✅ 14 passed |
| PG taskstore-lifecycle | ✅ 16 passed |
| store-thinking-levels | ✅ 1 passed |
| Dashboard curated-gate | ✅ passes |
| Typecheck (engine + core) | ✅ clean |
| Lint | ✅ exit 0 |

## Parked (not in scope)

- **Shards 1/2 timeout**: Engine test suite exceeds CI time budget.
Pre-existing, unrelated to these fixes.
- **2 latent PG files** (`chat-store-content-search-edit`,
`satellite-db-injected-stores`): Surface a separate pre-existing schema
baseline gap. Out of scope.
2026-07-14 00:11:06 -07:00
gsxdsm
c15c78feeb feat: migrate storage from SQLite to PostgreSQL (#1793)
# Migrate storage from SQLite to PostgreSQL — full dashboard cutover

Migrates Fusion's storage layer to the embedded PostgreSQL
`AsyncDataLayer` (the default backend) and **completes the
satellite-store + feature cutover** so every dashboard and Command
Center surface works in PG mode.

## Status — every surface works in embedded-PG mode

Verified live against a running embedded-Postgres dashboard (all
**200**, zero 5xx) and gate-tested (**23 files / 99 tests** on embedded
PG, plus engine-core 294 and ci-shape 63 in the blocking merge gate;
core/engine/cli/dashboard typecheck clean).

| Area | Surfaces | State |
|---|---|---|
| Satellite stores | workflows, todos, insights, research, missions,
goals, mailbox | ✅ |
| Views | artifacts, documents, evals | ✅ |
| Command Center | activity, productivity, team, tokens, tools,
**workflows**, **github**, **signals**, **plugin-activations**, **live**
(all 10) | ✅ |
| Run execution | insight generation, research run execution | ✅
(store-path; AI step needs a provider) |
| Live updates | SSE push for mission/research/insight events | ✅ |
| Workflow editing | create / update / delete / select (+ id counter) |
✅ |
| Engine | mission autopilot, incident-signal ingestion, regression
storm-guard, agent wake-on-message | ✅ |
| Core | tasks, agents, secrets, automations, memory, chat, usage, PRs,
git | ✅ |

## Approach

Each satellite store gets an `Async<Store>` wrapper exposing the sync
store's method names over the existing `async-*-store.ts` helpers;
`get<Store>Store()` returns a `Sync | Async` union; consumers `await`
(harmless on sync), and engine/CLI paths that can't convert use
`instanceof Sync` graceful fallback. Analytics aggregators branch on
`"ping" in dbOrLayer` to run schema-qualified raw SQL over `project.*`
(snake_case) in PG. Executors/orchestrators/autopilot are
await-converted to drive the union store; the async store wrappers
extend `EventEmitter` so SSE live-push fires in both backends.

Not-yet-ported capabilities degrade gracefully (never 500) and are
individually called out in commits.

## Sync with main

The branch is kept continuously merged with `main` (currently through
FN-7845, 2026-07-12); the earlier "final rebase deferred" note no longer
applies. Use **Create a merge commit** (or squash) to land it — GitHub's
rebase-merge cannot replay a merge-maintained branch.

## Residual Review Findings

Multi-agent code review of the PostgreSQL satellite-store ports (U1–U5)
applied 3 safe fixes (see `fix(review): apply autofix feedback`). The
following are **real but gated** — recorded here as follow-up work
rather than auto-applied. All are SQLite→PostgreSQL
**concurrency/atomicity regressions**: the sync stores were immune only
by SQLite's single-writer, single-threaded-handler execution; the async
ports open multi-await read-modify-write windows. **Reachability is low
today** because the execution engines that generate concurrent same-run
mutations (insight run executor, research orchestrator/dispatcher) are
`instanceof`-gated to sync mode in PG. No process-crash class survived
(all engine fallbacks correctly guard the sync store).

- **[P1] Research `appendResearchEvent` dual-write is non-atomic**
(`packages/core/src/async-research-store.ts`, corroborated: adversarial
+ reliability). The `research_run_events` insert (own transaction) and
the `run.events` jsonb update are separate writes — a crash between
them, or two concurrent appends, splits the table count from the jsonb
array. **Fix:** perform the seq-insert and the jsonb update in one
`layer.transactionImmediate`.
- **[P1] Research run terminal-reversion via stale full-row persist**
(`async-research-store.ts` `persistResearchRun`/`updateResearchStatus`).
Concurrent `PATCH /runs/:id/status` + `POST /runs/:id/events` can revert
a terminal run to `running` by overwriting the whole row, bypassing the
transition guard. **Fix:** scoped column `UPDATE`s with a `WHERE status
…` guard, or optimistic version column.
- **[P2] `updateResearchRun`/`updateInsightRun` read-then-write TOCTOU**
— concurrent PATCHes last-writer-wins on the lifecycle merge. **Fix:**
`SELECT … FOR UPDATE` / enclosing transaction.
- **[P2] `upsertRun`/`createRunOrThrowConflict` check-then-create race**
(`async-insight-store.ts`) — two callers can each create an "active"
run. **Fix:** partial unique index on `(projectId, trigger) WHERE status
IN ('pending','running')`.
- **[P3] `createResearchRetryRun` return-value divergence** — sync
returns the pre-update `queued` snapshot; async returns the reloaded
`retry_waiting` run (persisted state is identical). Pick one side for
cross-backend parity.
- **[P2/perf] Mission `getMissionWithHierarchy`/`getMissionHealth` N+1
fan-out** — O(milestones×slices) sequential round-trips hold one pool
slot per request; can starve the pool for large hierarchies. **Fix:**
batched/joined reads.
- **Testing gaps:** no PG-mode concurrency tests (interleaved
status/event mutations), no sync↔async parity assertion for the
lifecycle-error codes, and no mission status/health rollup parity test
vs the sync `MissionStore`.

~~Out of scope (deferred): AI run *execution* (insight/research) +
mission autopilot + live SSE mission events remain sync-gated/degraded
in PG mode.~~ **Since ported** — insight/research run execution, mission
autopilot, and SSE live push all run on the async layer now, which also
makes the concurrency findings above genuinely reachable; they remain
open follow-ups.







---

## Update — 2026-07-12: production-readiness hardening & live acceptance

Everything below landed on this branch since the description above was
written:

**Production blockers from review — fixed**
- `recoverStaleTransitionPending` ported to the async layer (backend
moves write + clear the crash-safe marker; startup/maintenance sweeps no
longer throw).
- Lost-update class fixed: `atomicWriteTaskJson`/`WithAudit` write
changed columns only (full-row upserts silently resurrected stale fields
across concurrent store instances — the "task stuck unplanned forever"
bug).
- First-boot **auto-migration**: booting the PG backend over a project
with a legacy `fusion.db` migrates it automatically (loud failure,
SQLite kept as backup), and the dashboard shows a one-time **"your data
was migrated" banner** with the backup paths and a Need-help Discord
link.
- `pg_dump`/`pg_restore` discovered from common install locations for
embedded-mode backups.
- The PG suite is part of the blocking merge gate (`test:pg-gate`).

**Multi-project isolation (PR #2007, merged into this branch)**
- `project_id` partition key on tasks / archived tasks / config,
`taskProjectScope` threaded through every scan/claim/count, per-project
config rows, layer bound to the project at startup.
- Review P1 follow-up: the shared cold-storage `archive.archived_tasks`
table is also partitioned and all archived-board reads/counts/searches
are scoped.
- Schema drift self-heal generalized to schema-qualified columns so
existing databases upgrade in place.

**Other changes**
- Node settings sync **removed** in PG mode (409
`settings-sync-disabled-postgres`) — nodes share state by connecting to
the same database; auth sync kept (per-machine file).
- Perf (review findings): `listTasks` pushes column filter + ORDER BY +
LIMIT/OFFSET into SQL; `getConversation` capped to the most recent 200
messages.
- Fixed a false "operator action required" pause-abort log fired on
every successfully auto-merged task.

**Live acceptance — PASSED (2026-07-12)**
A sandboxed instance (isolated HOME, embedded PG, real Opus executor)
ran a task through the complete cycle: create → triage (AI spec) →
execute → in-review → AI squash-merge landed on the project's `main` →
done. A write+read sweep of every data surface (settings, comments,
documents, attachments + artifact bridge + artifact edit, chat with real
generation, goals, missions, agent mail, secrets, workflows, memory, CC
analytics) was green on embedded PG.

**Known remaining work**
- The per-project `config` PK re-key has no upgrade path for
pre-isolation embedded-PG databases (needs a real `DROP
CONSTRAINT`/re-key migration; fresh databases are fine).
- `pg_dump`/`pg_restore` binaries are not yet bundled in release
artifacts (PATH/common-location discovery only).
- The satellite-store concurrency findings listed above.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Phil Larson <hello@phillarson.xyz>
Co-authored-by: fusion-merge <fusion-merge@local>
2026-07-13 19:07:58 -07:00
gsxdsm
1ff83a2735 chore(release): v0.60.0
Version bump via changesets.
2026-07-13 10:32:12 -07:00
gsxdsm
7246df22f6 FN-7944: add setting to keep task popups attached to their Board/List view
Adds an opt-in project setting so open task-detail popups stay attached to the Board or List view where they were opened, instead of floating over every main-content view.

- New project setting taskPopupsBoardListOnly (default: off) in settings-schema.ts and ProjectSettings type, with default preserved via settings-defaults tests.
- usePoppedOutTasks now stores each popup's originating TaskView alongside its task snapshot (PoppedOutTaskEntry), keeping legacy tasks output for existing callers.
- App.tsx adds isTaskPopupVisibleForView() gating helper and filters popped-out entries to the current view for rendering/keyboard-close handling, while hidden popups remain mounted in hook state (not cleared) so switching back to the originating view restores them with shared persisted geometry.
- Settings -> Appearance gets a new "Keep task popups on their Board/List view" checkbox (AppearanceSection.tsx) with i18n strings and updated settings search text in SettingsModal.
- Documentation updated in docs/dashboard-guide.md and docs/settings-reference.md to describe the render-only hide/restore behavior.
- New/updated tests: App.taskPopupViewGating.test.tsx, usePoppedOutTasks.test.ts, AppearanceSection.test.tsx, settings-default-descriptions.test.tsx, settings-defaults.test.ts.

Files changed:
 docs/dashboard-guide.md                            |   5 +-
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/settings-defaults.test.ts   |  13 +++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   7 ++
 packages/dashboard/app/App.tsx                     |  49 +++++++--
 .../app/__tests__/App.taskPopupViewGating.test.tsx | 113 +++++++++++++++++++++
 .../dashboard/app/components/SettingsModal.tsx     |   3 +-
 .../settings/sections/AppearanceSection.tsx        |   8 ++
 .../sections/__tests__/AppearanceSection.test.tsx  |  21 ++++
 .../settings-default-descriptions.test.tsx         |   1 +
 .../app/hooks/__tests__/usePoppedOutTasks.test.ts  |  14 +++
 packages/dashboard/app/hooks/useAppSettings.ts     |   4 +
 packages/dashboard/app/hooks/usePoppedOutTasks.ts  |  27 +++--
 packages/i18n/locales/en/app.json                  |   2 +
 15 files changed, 255 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-7944
Fusion-Task-Lineage: 4b8ced0e-1853-429f-8482-163821a35ae6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-13 08:58:51 -07:00
gsxdsm
502c4c132f chore(release): v0.59.0
Version bump via changesets.
2026-07-13 01:23:43 -07:00
gsxdsm
27110ed893 FN-7930: remove terminal footer 'Connected' label and shortcut help text
Declutters the terminal footer by dropping steady-state noise: the redundant 'Connected' status text (the header status dot already conveys connection state) and the persistent zoom/shortcuts/escape help copy.

- Remove .terminal-shortcuts / .terminal-shortcuts--header CSS rules (including responsive breakpoint overrides) as orphaned styling
- Stop rendering the 'Connected' text and the Ctrl++/- zoom / Shortcuts panel / Esc close help span in TerminalModal's footer
- Drop the now-unused terminal.helpText locale key from all 6 locales (en, es, fr, ko, zh-CN, zh-TW) and regenerate resources.d.ts
- Update TerminalModal tests to match the trimmed footer markup and add a regression test asserting the connected-status text and shortcut help are omitted
- Add a patch changeset documenting the fix

Files changed:
 .changeset/remove-terminal-footer-noise.md         |  7 +++++
 .../dashboard/app/components/TerminalModal.css     | 34 ---------------------
 .../dashboard/app/components/TerminalModal.tsx     |  7 +++--
 .../components/__tests__/TerminalModal.test.tsx    | 35 +++++++++++++++++-----
 packages/i18n/locales/en/app.json                  |  1 -
 packages/i18n/locales/es/app.json                  |  1 -
 packages/i18n/locales/fr/app.json                  |  1 -
 packages/i18n/locales/ko/app.json                  |  1 -
 packages/i18n/locales/zh-CN/app.json               |  1 -
 packages/i18n/locales/zh-TW/app.json               |  1 -
 packages/i18n/src/resources.d.ts                   |  1 -
 11 files changed, 40 insertions(+), 50 deletions(-)

Fusion-Task-Id: FN-7930

Fusion-Task-Lineage: 2b8acb5d-c4d4-4766-ba84-b2691a7eb5e8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-13 00:07:21 -07:00
gsxdsm
4ea5dd6739 fix: CLI shouldSuperviseDashboard mock + getCliPackageVersion/isUnresolvedCliPackageVersion + executeRequeueLoopCount + i18n buttonShort (round 9) (#2034)
## Summary

Fixes shard 3 (CLI) + shard 4 (i18n) failures from full-suite run
29223788088.

## Fixes

### CLI (shard 3) — 5 files, ~140 tests
- **`bin.test.ts`** — `bin.ts:851` now imports
`shouldSuperviseDashboard` and `bin.ts:865` imports
`runDashboardSupervised` from `./commands/dashboard.js`. Test mock only
exported `runDashboard`. Missing `shouldSuperviseDashboard` → TypeError
→ caught → `process.exit:1`. Added `shouldSuperviseDashboard: vi.fn(()
=> false)` + `runDashboardSupervised` to mock + `commandMocks`.
- **`daemon/serve/dashboard.test.ts`** — `@fusion/dashboard` barrel
(index.ts:115) re-exports `getCliPackageVersion`,
`isUnresolvedCliPackageVersion`, `resolveCliPackageVersionInfo`. Added
all 3 to each file's `@fusion/dashboard` mock.
- **`task.test.ts`** — `executeRequeueLoopCount: 0` added to
TaskResetField set by recent commit; retry test assertions needed the
new field in both `mockUpdateTask` expectations.

### i18n (shard 4) — 4 locale files
- **`settings.reset.buttonShort`** missing from zh-TW, fr, es, ko (zh-CN
already had it).

### Engine (shards 1+2) — already fixed in PR #2025 (merged on main)
- Run 29223788088 was at commit `b85a6b866` (pre-PR-2025-merge), so
engine + i18n `storageMigrationNotice` failures visible in that run are
already resolved on main.

## Verification
- daemon: 21/21 ✅ | serve: 58/58 ✅ | dashboard: 91/91 ✅ | task retry:
5/5 ✅
- i18n parity + gate-coverage: 7/7 ✅
- Gate (`pnpm test:gate`): exit 0 ✅
- `bin.test.ts`: cannot verify locally (`@agentclientprotocol/sdk` not
installed locally; CI resolves from lockfile). Mock exports verified
against `dashboard.ts` source.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved task retry recovery by correctly resetting execution
counters.

* **Localization**
* Added support for shorter reset-button labels in Spanish, French,
Korean, and Traditional Chinese.

* **Tests**
* Updated command and startup checks to reflect current dashboard and
version-handling behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-12 21:58:12 -07:00
gsxdsm
8835c6cb48 FN-7908: add in-chat model/agent switcher to brain-icon popup
Extend the chat brain-icon popup and its backing session PATCH route so an
active Direct chat's model or agent can be switched mid-conversation instead
of only being set at creation time.

- Add a Model/Agent section to ChatThinkingLevelControl (the brain-icon
  popup) for picking a model provider/model or retargeting to a real agent
  without leaving the chat.
- Extend PATCH /api/chat/sessions/:id to accept modelProvider/modelId (as a
  validated pair via the existing validateModelPair helper) and agentId,
  forwarding only the keys present in the body so omitted fields leave the
  session's stored target untouched.
- Add chat-store updateSession support for the agentId clause alongside the
  existing model/thinkingLevel fields, and a useChat.setSessionModel hook
  for the dashboard to call the new PATCH capability.
- Update i18n locale strings (en/es/fr/ko/zh-CN/zh-TW) and dashboard-guide.md
  docs for the new switcher UI.
- Add unit/integration test coverage across chat-store, chat-manager,
  chat-routes, useChat, ChatThinkingLevelControl, and ChatView for the new
  model/agent switch behavior.
- Add changeset fn-7908-chat-model-agent-switcher.md (minor,
  @runfusion/fusion).

Files changed:
 .changeset/fn-7908-chat-model-agent-switcher.md    |   7 +
 docs/dashboard-guide.md                            |   3 +-
 packages/core/src/__tests__/chat-store.test.ts     |  21 ++
 packages/core/src/chat-store.ts                    |   8 +
 packages/core/src/chat-types.ts                    |   2 +
 packages/dashboard/app/api/legacy.ts               |  11 +-
 .../app/components/ChatThinkingLevelControl.tsx    | 219 ++++++++++++++++++---
 packages/dashboard/app/components/ChatView.css     | 135 ++++++++++++-
 packages/dashboard/app/components/ChatView.tsx     |  23 ++-
 .../__tests__/ChatThinkingLevelControl.test.tsx    | 109 +++++++++-
 .../__tests__/ChatView.thinking-level.test.tsx     |  67 ++++++-
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 166 +++++++++++++++-
 packages/dashboard/app/hooks/useChat.ts            |  56 ++++++
 .../dashboard/src/__tests__/chat-manager.test.ts   |  38 ++++
 .../dashboard/src/__tests__/chat-routes.test.ts    | 117 ++++++++++-
 .../dashboard/src/routes/register-chat-routes.ts   |  48 ++++-
 packages/i18n/locales/en/app.json                  |   8 +-
 packages/i18n/locales/es/app.json                  |   8 +-
 packages/i18n/locales/fr/app.json                  |   8 +-
 packages/i18n/locales/ko/app.json                  |   8 +-
 packages/i18n/locales/zh-CN/app.json               |   8 +-
 packages/i18n/locales/zh-TW/app.json               |   8 +-
 22 files changed, 1007 insertions(+), 71 deletions(-)

Fusion-Task-Id: FN-7908

Fusion-Task-Lineage: b1104865-9b0c-4d77-973e-89152fe245e0

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 21:33:50 -07:00
gsxdsm
03bca1787b FN-7907: Add project chat default (model/agent) setting and New Chat default behavior
Adds a project-scoped Direct-chat default (model pair or durable agent) plus a New Chat behavior toggle (prompt vs. always-use-default), surfaced in Project Models settings using the standard model dropdown.

- Add ProjectSettings fields: chatNewSessionMode, chatDefaultKind, chatDefaultAgentId, chatDefaultModelProvider, chatDefaultModelId, chatDefaultThinkingLevel
- Extend settings-schema validation for the new chat default fields
- Add a "Chat" subsection to ProjectModelsSection with New Chat behavior selector, model/agent target toggle, and the standard CustomModelDropdown for model selection
- Update ChatView.tsx handleNewChat() flow to honor the configured default (prompt vs. immediate session creation)
- Add i18n strings across en/es/fr/ko/zh-CN/zh-TW locales and regenerate resources.d.ts
- Add changeset (@runfusion/fusion minor) and update docs/settings-reference.md and docs/dashboard-guide.md
- Add settings-parity, ChatView new-chat-default, and ProjectModelsSection chatDefault test coverage

Files changed:
 .changeset/fn-7907-chat-default.md                 |   7 +
 docs/dashboard-guide.md                            |   3 +-
 docs/settings-reference.md                         |   8 +
 packages/core/src/__tests__/settings-parity.test.ts     |  20 ++
 packages/core/src/settings-schema.ts               |   6 +
 packages/core/src/types.ts                         |  15 +
 packages/dashboard/app/components/ChatView.tsx     |  93 +++++-
 packages/dashboard/app/components/__tests__/ChatView.new-chat-default.test.tsx   | 357 +++++++++++++++++++++
 packages/dashboard/app/components/settings/sections/ProjectModelsSection.tsx     |  77 +++++
 packages/dashboard/app/components/settings/sections/__tests__/ProjectModelsSection.chatDefault.test.tsx |  193 +++++++++++
 packages/i18n/locales/en/app.json                  |  20 +-
 packages/i18n/locales/es/app.json                  |  20 +-
 packages/i18n/locales/fr/app.json                  |  20 +-
 packages/i18n/locales/ko/app.json                  |  20 +-
 packages/i18n/locales/zh-CN/app.json               |  20 +-
 packages/i18n/locales/zh-TW/app.json               |  20 +-
 packages/i18n/src/resources.d.ts                   |  18 ++
 17 files changed, 899 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-7907

Fusion-Task-Lineage: 86a81b9c-7e0c-4033-9e2a-6f7380810fe9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 20:54:10 -07:00
gsxdsm
23cb061af2 FN-7898: add in-chat thinking-level control next to the attach button
Adds a Brain-icon popover control in the chat composer that lets users change an existing session's reasoning-effort level mid-conversation, extending the existing create-time-only thinking-level picker.

- Add ChatThinkingLevelControl component (Brain-icon trigger + popover) wired into ChatView's direct-session composer, gated to non-CLI model-loop sessions only
- Extend PATCH /api/chat/sessions/:id to accept an optional thinkingLevel field, validated via existing validateThinkingLevel helper; null/empty string explicitly clears back to the inherited default, omitting the key leaves it untouched
- Add useChat().setSessionThinkingLevel hook method to call the new PATCH capability
- Add i18n strings (thinkingLevelButton) across all locales and regenerate packages/i18n/src/resources.d.ts
- Add changeset for @runfusion/fusion (minor) and update docs/dashboard-guide.md

Files changed:
 .changeset/fn-7898-chat-thinking-level-control.md  |   7 +
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/api/legacy.ts               |   4 +-
 .../app/components/ChatThinkingLevelControl.tsx    | 133 +++++++++++
 packages/dashboard/app/components/ChatView.css     |  73 ++++++
 packages/dashboard/app/components/ChatView.tsx     |  20 ++
 .../__tests__/ChatThinkingLevelControl.test.tsx    | 103 ++++++++
 .../__tests__/ChatView.message-edit.test.tsx       |   1 +
 .../components/__tests__/ChatView.test-harness.tsx |   1 +
 .../__tests__/ChatView.thinking-level.test.tsx     | 262 +++++++++++++++++++++
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 108 +++++++++
 packages/dashboard/app/hooks/useChat.ts            |  59 +++++
 .../dashboard/src/__tests__/chat-routes.test.ts    |  83 +++++++
 .../dashboard/src/routes/register-chat-routes.ts   |  35 ++-
 packages/i18n/locales/en/app.json                  |   1 +
 packages/i18n/locales/es/app.json                  |   1 +
 packages/i18n/locales/fr/app.json                  |   1 +
 packages/i18n/locales/ko/app.json                  |   1 +
 packages/i18n/locales/zh-CN/app.json               |   1 +
 packages/i18n/locales/zh-TW/app.json               |   1 +
 packages/i18n/src/resources.d.ts                   |  96 ++++++--
 21 files changed, 970 insertions(+), 23 deletions(-)

Fusion-Task-Id: FN-7898

Fusion-Task-Lineage: a052a6ef-d2d3-45af-9b92-221996780b1b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 20:00:50 -07:00
gsxdsm
56c745240a FN-7880: shorten Reset Settings button to "Reset" on mobile
Shortens the Settings footer's Reset Settings button label to Reset at the mobile breakpoint to preserve footer space, while desktop/tablet keep the full label; confirmation dialog and reset behavior are unchanged.

- Add settings.reset.buttonShort i18n key (en, zh-CN) and typed resources.d.ts entry
- SettingsModal reset button now renders buttonShort ("Reset") when viewportMode === "mobile", otherwise the existing "Reset Settings" label
- Update settings-mobile.test.tsx to assert the compact mobile label and add coverage across modal/embedded x mobile/desktop viewport combinations
- Update docs/dashboard-guide.md to document the mobile-only compact label
- Add changeset (patch) for @runfusion/fusion

Files changed:
 .changeset/fn-7880-reset-mobile-label.md           |  7 ++++
 docs/dashboard-guide.md                            |  6 ++--
 packages/dashboard/app/components/SettingsModal.tsx |  7 +++-
 packages/dashboard/app/components/__tests__/settings-mobile.test.tsx | 37 +++++++++++++++++++++-
 packages/i18n/locales/en/app.json                  |  1 +
 packages/i18n/locales/zh-CN/app.json               |  1 +
 packages/i18n/src/resources.d.ts                   |  1 +
 7 files changed, 56 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7880

Fusion-Task-Lineage: e636e73d-172e-4a6e-bb51-078520fd05ab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 16:48:04 -07:00
gsxdsm
a4dde88ff6 FN-7874: add Discord get-help link and central-DB wording to storage banner
Adds a hardened Discord support link and clarifies that project databases move to the central Fusion database in the storage update notice banner.

- Add a "Get help" button/link to the Fusion Discord (https://discord.gg/ksrfuy7WYR) in StorageMigrationNoticeBanner, with new .storage-migration-notice-banner__actions/__help CSS (desktop + mobile layout)
- Revise the banner body copy to state that project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file
- Add storageMigrationNotice.getHelp/getHelpLabel i18n keys and update en/app.json body copy; sync placeholder keys across es/fr/ko/zh-CN/zh-TW locales and regenerate resources.d.ts
- Extend StorageMigrationNoticeBanner tests to cover the new help link (href/target/rel) and updated body copy, including dismissed/error-path cases
- Add a minor changeset for @runfusion/fusion documenting the banner change

Files changed:
 .changeset/fn-7874-storage-banner-get-help.md      |  7 ++++++
 .../components/StorageMigrationNoticeBanner.css    | 26 ++++++++++++++++++++++
 .../components/StorageMigrationNoticeBanner.tsx    | 16 ++++++++++++-
 .../StorageMigrationNoticeBanner.test.tsx          | 16 +++++++++++--
 packages/i18n/locales/en/app.json                  |  4 +++-
 packages/i18n/locales/es/app.json                  |  7 ++++++
 packages/i18n/locales/fr/app.json                  |  7 ++++++
 packages/i18n/locales/ko/app.json                  |  7 ++++++
 packages/i18n/locales/zh-CN/app.json                |  7 ++++++
 packages/i18n/locales/zh-TW/app.json                |  7 ++++++
 packages/i18n/src/resources.d.ts                    |  7 ++++++
 11 files changed, 107 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7874
Fusion-Task-Lineage: baa88812-18ca-4910-a641-8d6e23f602a6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 13:17:47 -07:00
gsxdsm
bb86844f8d FN-7869: add hide done toggle to Todo list view
Adds a per-project Hide done / Show done toggle to the Todo list items header so operators can declutter long selected lists while completion counts still reflect all items.
- Add hideDone state persisted per project via localStorage (kb-dashboard-todo-hide-done key registered in projectStorage)
- Filter rendered todo items to hide completed ones when the toggle is active, while keeping list stats/progress counts based on all items
- Adjust up/down item reordering to operate correctly against the visible (filtered) list while still reordering the underlying full item list
- Add an empty-state message when all items are hidden by the toggle, with Eye/EyeOff icon + i18n strings (todo.hideDone, todo.showDone, todo.allDoneHidden)
- Add regression tests covering the toggle, persistence, filtering, and empty state
- Document the Hide done / Show done control in the dashboard guide

Files changed:
 docs/dashboard-guide.md                            |  3 +
 packages/dashboard/app/components/TodoView.css     | 45 ++++++++++
 packages/dashboard/app/components/TodoView.tsx     | 66 +++++++++++++--
 .../app/components/__tests__/TodoView.test.tsx     | 99 ++++++++++++++++++++++
 packages/dashboard/app/utils/projectStorage.ts     |  1 +
 packages/i18n/locales/en/app.json                  |  3 +
 6 files changed, 210 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7869

Fusion-Task-Lineage: 9c334aba-e802-43b8-963c-0f2daf727583

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:52:30 -07:00
gsxdsm
06ec0e606e FN-7866: add auto-save toggle for the workspace file editor (default on)
Adds a shared, persisted auto-save preference for workspace text-file editing, defaulted to on, surfaced as a toolbar toggle in both the Files modal and right-dock Files view.

- Add useAutoSavePreference hook: persists the fn-file-editor-auto-save localStorage preference, broadcasts same-window changes via a custom event (storage events only reach other documents), and defaults to true.
- Extend useWorkspaceFileEditor with an autoSave flag that debounces (800ms) and triggers save() for a loaded, editable file with real pending changes, keyed by workspace+file+content to avoid re-firing on failed writes.
- Add an Auto-save toggle button to FileEditor's toolbar (autoSaveEnabled/onToggleAutoSave/canToggleAutoSave props), hidden for read-only/preview/binary files.
- Wire the shared preference into FileBrowserModal and DockFilesView, disabling auto-save for binary files in the modal.
- Add fileEditor.autoSave / fileEditor.toggleAutoSave i18n strings and document the new default behavior in docs/dashboard-guide.md.
- Add/extend tests covering the new hook, debounced auto-save behavior, and toolbar toggle wiring across FileEditor, FileBrowserModal, and DockFilesView.

Files changed:
 docs/dashboard-guide.md                            |   3 +
 .../dashboard/app/components/DockFilesView.tsx     |   6 +-
 .../dashboard/app/components/FileBrowserModal.tsx  |  20 ++--
 packages/dashboard/app/components/FileEditor.tsx   |  17 +++-
 .../components/__tests__/DockFilesView.test.tsx    |  37 ++++++-
 .../components/__tests__/FileBrowserModal.test.tsx |  86 +++++++++++++---
 .../app/components/__tests__/FileEditor.test.tsx   |  56 +++++++++++
 .../hooks/__tests__/useAutoSavePreference.test.ts  |  66 +++++++++++++
 .../hooks/__tests__/useWorkspaceFileEditor.test.ts | 108 +++++++++++++++++++++
 .../dashboard/app/hooks/useAutoSavePreference.ts   |  79 +++++++++++++++
 .../dashboard/app/hooks/useWorkspaceFileEditor.ts  |  47 ++++++++-
 packages/i18n/locales/en/app.json                  |   2 +
 12 files changed, 500 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7866

Fusion-Task-Lineage: 0604de18-666d-4872-abce-2a3886c9ea55

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:49:37 -07:00
gsxdsm
fb3e843bc2 test(i18n): add storageMigrationNotice keys to all non-en locales 2026-07-12 12:44:05 -07:00
gsxdsm
9bb74595c2 FN-7852: add one-time SQLite→embedded Postgres storage notice banner
Adds a dismissible, one-time dashboard banner announcing the upcoming SQLite→embedded-Postgres storage backend change.

- New self-contained StorageMigrationNoticeBanner component with title/body copy and a dismiss control that persists via localStorage key fusion:storage-migration-notice-dismissed
- Wire the banner into DashboardBanners alongside the CLI binary install banner for project-scoped views
- Add en locale strings (storageMigrationNotice.title/body/dismissLabel) in app.json
- Add component test coverage for render/dismiss/persistence behavior
- Document the notice in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7852-storage-migration-notice.md     |  7 ++
 docs/dashboard-guide.md                            |  2 +
 .../components/StorageMigrationNoticeBanner.css    | 73 +++++++++++++++++++
 .../components/StorageMigrationNoticeBanner.tsx    | 65 +++++++++++++++++
 .../StorageMigrationNoticeBanner.test.tsx          | 82 ++++++++++++++++++++++
 .../app/components/dashboard/DashboardBanners.tsx  | 11 ++-
 packages/i18n/locales/en/app.json                  |  5 ++
 7 files changed, 242 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7852

Fusion-Task-Lineage: e3235cce-9ca3-4830-8733-a2ec46c53246

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:19:52 -07:00
gsxdsm
f82a3d2840 chore(release): v0.58.0
Version bump via changesets.
2026-07-11 23:50:00 -07:00
gsxdsm
4397cafb94 fix: wire push-after-merge into the unified runAiMerge path with remote/branch dropdown settings
pushAfterMerge was only implemented in the soft-deprecated legacy aiMergeTask
pipeline, so after master-plan U0 made runAiMerge the sole merge path the
setting silently did nothing and origin fell permanently behind local main.

- runAiMerge now runs a post-finalize push step: working-tree-independent
  ref-to-ref push fast path; on remote divergence a detached clean-room
  pull --rebase (with AI conflict resolution) pushes HEAD and CAS-advances
  the local integration ref (explicit non-FF opt-in, push path only), then
  runs merge-advance auto-sync and refreshes mergeDetails.commitSha.
- Push failures stay non-fatal (task finalizes done) with push:origin
  run-audit events and PushToRemoteFailed task-log entries.
- Merge settings: Push Remote free-text replaced by remote + target-branch
  dropdowns (Custom… escape, free-text fallback when no remotes), persisting
  to the same pushRemote setting string. New GET /api/git/remotes/:name/branches
  endpoint lists remote-tracking branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:16:48 -07:00
gsxdsm
937650472a FN-7820: add Cost tab to task detail and optional card cost badge
Adds a shared cost-derivation utility and surfaces token/cost info in a new Cost tab on the task detail modal, plus an opt-in per-card cost badge on the board.

- Extract token-cost calculation into a shared taskTokenCost helper (read-time costFor derivation) reused by the Summary tab, new Cost tab, and card badge
- Add TaskDetailModal Cost tab (TaskCostTab.tsx/.css) showing cost breakdown for a task
- Simplify TaskSummaryTab by delegating cost math to the shared helper
- Add default-off project setting showCostBadgeOnCards (settings-schema.ts, types.ts) with a SettingsModal/AppearanceSection toggle
- Add CostBadgeContext to thread the setting into TaskCard without prop drilling
- Show an optional cost badge on TaskCard when the setting is enabled
- Update i18n strings across en/es/fr/ko/zh-CN/zh-TW locales
- Update docs (dashboard-guide.md, settings-reference.md) and add changeset fn-7820-cost-tab-and-card-badge.md

Files changed:
 .changeset/fn-7820-cost-tab-and-card-badge.md      |   7 ++
 docs/dashboard-guide.md                            |   4 +
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/settings-defaults.test.ts   |  13 ++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   5 +
 packages/dashboard/app/App.tsx                     |   5 +
 .../dashboard/app/components/SettingsModal.tsx     |   6 +
 packages/dashboard/app/components/TaskCard.css     |   7 +-
 packages/dashboard/app/components/TaskCard.tsx     |  27 +++-
 packages/dashboard/app/components/TaskCostTab.css  |  51 ++++++++
 packages/dashboard/app/components/TaskCostTab.tsx  |  91 ++++++++++++++
 .../dashboard/app/components/TaskDetailModal.tsx   |  14 ++-
 .../dashboard/app/components/TaskSummaryTab.tsx    | 123 +-----------------
 .../app/components/__tests__/TaskCard.test.tsx     |  81 +++++++++++-
 .../app/components/__tests__/TaskCostTab.test.tsx  |  55 ++++++++
 .../TaskDetailModal.attachments-and-tabs.test.tsx  |  11 +-
 .../settings/sections/AppearanceSection.tsx        |   8 ++
 .../sections/__tests__/AppearanceSection.test.tsx  |  20 +++
 .../settings-default-descriptions.test.tsx         |   1 +
 .../dashboard/app/context/CostBadgeContext.tsx     |  19 +++
 packages/dashboard/app/hooks/useAppSettings.ts     |  15 +++
 .../app/utils/__tests__/taskTokenCost.test.ts      |  62 +++++++++
 packages/dashboard/app/utils/taskTokenCost.ts      | 139 +++++++++++++++++++++
 packages/i18n/locales/en/app.json                  |  29 ++++-
 packages/i18n/locales/es/app.json                  |  30 ++++-
 packages/i18n/locales/fr/app.json                  |  27 +++-
 packages/i18n/locales/ko/app.json                  |  30 ++++-
 packages/i18n/locales/zh-CN/app.json               |  30 ++++-
 packages/i18n/locales/zh-TW/app.json               |  30 ++++-
 30 files changed, 789 insertions(+), 157 deletions(-)

Fusion-Task-Id: FN-7820

Fusion-Task-Lineage: d33c5678-a68c-4b29-9db1-8ff0369dfd72

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
51d5f9a28f test: fix executor artifact-register assertion (FN-7790) + i18n versionShort parity 2026-07-11 18:06:45 -07:00
gsxdsm
f6806f06cb feat: live lifecycle warning analysis with one-click Fix / Fix all
Lifecycle warnings now recompute client-side from the live graph for
editable workflows, so the banner reflects edits immediately instead of
waiting for a save round-trip. The two deterministically fixable codes gain
one-click fixes in the banner (all view modes):
- missing-merge-region inserts a Merge boundary in front of end;
- missing-completion-summary inserts the canonical completion-summary node
  (config from @fusion/core's completionSummaryNode) upstream of the merge
  region when one exists, else in front of end.
"Fix all" on the collapsed summary line applies both in order, producing
start → summary → merge → end on a fresh workflow in one click. The other
three codes are structural judgment calls and stay manual.

analyzeWorkflowLifecycle + completionSummaryNode are pure and now re-export
through core's browser-safe types.ts alias entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
d79e2d62af Address PR review feedback + compact lifecycle warnings banner (#2006)
- fix: edge-targeted fragment and "insert as optional group" picks from the
  add-step dialog now splice the inserted subgraph into the targeted edge
  (entries inherit the original routing condition, exits feed the old
  target, subgraph moves into the source's column band) instead of dropping
  disconnected fixed-position nodes (Greptile P1).
- feat: the lifecycle warnings banner is now a one-line collapsible
  disclosure (count summary, details on expand) so it no longer dominates
  the editor header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
bcbd97cc1c feat: simplified workflow editor view with Simple/Advanced/List modes
Adds a simplified graphical node editor as the workflow editor's default
view: a modern vertical auto-laid-out React Flow canvas with insert-on-edge
"+" affordances and a searchable, categorized add-step dialog (node kinds +
fragments + step templates). A segmented Simple/Advanced/List switch
(persisted in localStorage) keeps the full advanced canvas untouched and
retains the old compact row editor as the List fallback. Mobile's graph tab
gains the touch-friendly simplified canvas with the row list as fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
6317fcddb5 FN-7813: add embedded worktree-rooted multi-tab Terminal to Task Detail
Add an interactive, worktree-rooted, multi-tab Terminal tab to the Task Detail
view, distinct from the pre-existing CLI-agent Session tab.

- TaskDetailModal gains a new embedded Terminal tab (single non-workspace
  task with one recorded worktree) that mounts TerminalModal in a new
  `embedded` render mode, rooted at the task's worktree
- Rename the existing agent-session tab label to "Session" to disambiguate
  it from the new Terminal tab
- useTerminalSessions gains task-scoped session storage and a `defaultCwd`
  option so embedded terminal tabs persist separately from footer/global
  project terminal tabs and start in the task worktree
- TerminalModal/CSS updated to support the embedded layout mode
- Update lazy-loaded-views docs test and AGENTS.md exclusion list to cover
  the new `LazyTerminalModal` task-detail-internal surface
- Document the new Session/Terminal tab split in docs/dashboard-guide.md
- Add i18n strings for the new Terminal tab across all locales
- Add a changeset (minor) for @runfusion/fusion

Files changed:
 .changeset/FN-7813-worktree-terminal-tab.md        |   7 +
 AGENTS.md                                          |   2 +-
 docs/dashboard-guide.md                            |   3 +
 .../app/__tests__/lazy-loaded-views-docs.test.ts   |   4 +-
 .../dashboard/app/components/TaskDetailModal.css   |  17 +++
 .../dashboard/app/components/TaskDetailModal.tsx   |  41 +++++-
 .../dashboard/app/components/TerminalModal.css     |  51 +++++++
 .../dashboard/app/components/TerminalModal.tsx     |  71 +++++++---
 .../__tests__/TaskDetailModal.test-helpers.ts      |   3 +
 .../TaskDetailModal.worktree-terminal.test.tsx     | 139 ++++++++++++++++++
 .../components/__tests__/TerminalModal.test.tsx    |  29 ++++
 .../hooks/__tests__/useTerminalSessions.test.ts    | 157 +++++++++++++++++++++
 .../dashboard/app/hooks/useTerminalSessions.ts     |  63 ++++++---
 packages/i18n/locales/en/app.json                  |   3 +-
 packages/i18n/locales/es/app.json                  |   3 +-
 packages/i18n/locales/fr/app.json                  |   3 +-
 packages/i18n/locales/ko/app.json                  |   3 +-
 packages/i18n/locales/zh-CN/app.json               |   3 +-
 packages/i18n/locales/zh-TW/app.json               |   3 +-
 19 files changed, 550 insertions(+), 55 deletions(-)

Fusion-Task-Id: FN-7813

Fusion-Task-Lineage: 4ef86a15-347a-4862-b01c-5063d8004cb8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 00:01:10 -07:00
gsxdsm
367f5915bf FN-7804: show compact version label in mobile Settings footer
Mobile Settings footer now shows a compact "vX.Y.Z" version label instead of the full "Version X.Y.Z" wording, freeing horizontal space on small viewports while desktop/tablet keep the full label.

- SettingsModal renders settings.footer.versionShort ("v{{version}}") when viewportMode === "mobile", falling back to the existing settings.footer.version label otherwise
- Added settings.footer.versionShort translation key to en and fr locale files
- Updated settings-mobile tests: renamed/adjusted the mobile version test to assert the compact label and added a new test asserting the full label is kept outside the mobile viewport
- Added a patch changeset documenting the fix

Files changed:
 .changeset/fn-7804-mobile-settings-version.md          |  7 +++++++
 packages/dashboard/app/components/SettingsModal.tsx    | 10 +++++++++-
 .../app/components/__tests__/settings-mobile.test.tsx  | 18 +++++++++++++++---
 packages/i18n/locales/en/app.json                      |  1 +
 packages/i18n/locales/fr/app.json                      |  1 +
 5 files changed, 33 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7804

Fusion-Task-Lineage: 3ff5af53-3242-44b8-b8d8-6b81f416a333

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 22:25:21 -07:00
gsxdsm
c73094ec7f fix(dashboard): fix Memory view dead space, unlabeled toolbar, and toggle-row alignment
- Working/Insights/Engines tabs now render a centered 960px content
  column instead of leaving the right half of wide viewports empty.
- The file editor's collapsed chevron-only toolbar (an unlabeled mystery
  control) now always shows its labeled actions in MemoryView.
- 'Process dreams' / 'Auto-summarize memory' rows share one aligned
  layout, sentence case, and a tooltip explaining dream processing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:13:48 -07:00
gsxdsm
f628095205 fix(dashboard): make selection Add-comment trigger clickable and label read-only previews
The global .btn:active press-feedback transform (scale 0.97) overrode
the selection-comment trigger's positioning translate, teleporting the
fixed-position button mid-press so the click never landed and the
composer silently never opened. The :active state now restates the
translate alongside the scale on desktop and mobile offsets. Document
previews also gain a subtle Read-only badge explaining select-to-comment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:09:58 -07:00
gsxdsm
2cfeb74407 fix(dashboard): polish first-run setup wizard (AI step, GitHub step, project step)
- AI Setup: connected providers now render first; 'Skip for now' hides
  once a provider is connected; footer buttons share one size.
- GitHub step: state-driven (no install/pitch content when connected),
  one type scale, real <code> literals, per-OS gh instructions behind a
  disclosure, single skip affordance; gh/OAuth status revalidates on
  window focus and OAuth relogin so later steps stop showing stale
  'not connected'.
- Project step: onboarding-driven opens keep 'Step 3 of 5' context;
  runtime-node picker no longer lists 'Local node' and 'local (local)'
  duplicates and hides itself when only the local node exists;
  isolation-mode cards no longer render a stretched native radio or
  uppercased descriptions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:20:17 -07:00
gsxdsm
70330bcffb FN-7779: render No message placeholder for empty assistant chat replies
Empty final assistant chat messages (e.g. Grok CLI runs that finish with no text) now show a muted "No message" placeholder instead of a blank bubble, in both Chat and Planner Chat via the shared StandardChatSurface component.

- Add isEmptyAssistantMessage check in StandardChatMessageItem: only applies to final persisted assistant messages with no content, tool calls, thinking output, attachments, or failure info
- Render a new .chat-message-content--empty block with the "No message" i18n string when the check matches
- Add shared CSS rule combining --waiting and --empty muted/italic styling, switching to var(--font-size-sm)
- Add "chat.noMessage" translation key to en/app.json and regenerate resources.d.ts
- Document the new behavior in docs/dashboard-guide.md
- Add a patch changeset for @runfusion/fusion
- Add StandardChatSurface.empty-message.test.tsx covering empty/whitespace content, populated content, tool calls, thinking output, attachments, failure info, non-assistant roles, and streaming waiting/thinking states

Files changed:
$(cat /tmp/diffstat_fn7779.txt)

Fusion-Task-Id: FN-7779

Fusion-Task-Lineage: d3ae068e-acba-4b4c-85d6-a788aa24a53b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 07:40:22 -07:00
gsxdsm
5f14a58d3b FN-7770: add per-lane thinking-level overrides for project & global model settings
Adds an optional thinking-effort/reasoning override per model lane in Settings (project and global), resolved with precedence task > lane > global default, and reconciles this work with the already-landed FN-7768 inline thinking-level control on CustomModelDropdown (kept the shared shouldShowThinking/thinkingBadgeLabel implementation to avoid duplicating the selector/badge UI).

- Add lane thinking-level settings schema fields and runtime precedence (task > lane > global default) in @fusion/core
- Wire per-lane thinking selectors into GlobalModelsSection and ProjectModelsSection via CustomModelDropdown's existing showThinkingLevel/thinkingLevel/onThinkingLevelChange/defaultThinkingLevel props
- Resolve merger thinking level from the default lane rather than the title-summarizer lane in engine session helpers/executor/merger/triage
- Update settings-reference docs and add a minor changeset for the new lane thinking overrides
- Add/expand test coverage: settings-parity, store-settings, settings-sections, agent-session-helpers
- Add new i18n key models.options.defaultWithLevel across locales

Files changed:
 .changeset/fn-7770-lane-thinking.md                |   7 ++
 docs/settings-reference.md                         |   8 ++
 .../core/src/__tests__/settings-parity.test.ts     |  17 ++++
 packages/core/src/__tests__/store-settings.test.ts |  42 +++++++++
 packages/core/src/settings-schema.ts               |  14 +++
 packages/core/src/types.ts                         |  16 ++++
 .../app/__tests__/settings-sections.test.tsx       | 100 ++++++++++++++++++---
 .../app/components/CustomModelDropdown.css         |   1 +
 .../dashboard/app/components/SettingsModal.tsx     |  37 ++++++++
 .../settings/sections/GlobalModelsSection.tsx      |   9 +-
 .../settings/sections/ProjectModelsSection.tsx     |  12 ++-
 .../app/components/settings/sections/context.ts    |   2 +
 .../src/__tests__/agent-session-helpers.test.ts    |  36 ++++++++
 packages/engine/src/agent-session-helpers.ts       |  60 +++++++++++++
 packages/engine/src/executor.ts                    |  14 +--
 packages/engine/src/merger-ai.ts                   |  12 ++-
 packages/engine/src/merger.ts                      |  12 +--
 packages/engine/src/pr-response-run-ops.ts         |   4 +-
 packages/engine/src/step-session-executor.ts       |   3 +-
 packages/engine/src/triage.ts                      |   5 +-
 packages/i18n/locales/en/app.json                  |   3 +-
 packages/i18n/locales/es/app.json                  |   3 +-
 packages/i18n/locales/fr/app.json                  |   3 +-
 packages/i18n/locales/ko/app.json                  |   3 +-
 packages/i18n/locales/zh-CN/app.json               |   3 +-
 packages/i18n/locales/zh-TW/app.json               |   3 +-
 packages/i18n/src/resources.d.ts                   |   3 +
 27 files changed, 390 insertions(+), 42 deletions(-)

Fusion-Task-Id: FN-7770
Fusion-Task-Lineage: 3418c621-ac99-4cd4-a435-9348da03972f
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 01:15:40 -07:00
gsxdsm
6a13ad175e FN-7732: remove dangling release-authorization UI/i18n/docs scaffolding
Narrative: The triage release-authorization gate itself was already removed in b5b0458; this cleans up the leftover scaffolding it left behind — an unemitted activity type, a dead TaskCard badge/label/CSS, orphaned i18n keys across all 6 locales, and a stale solutions doc — so the codebase no longer references a gate that no longer exists.

- Drop the unused `task:release-authorization-required` ActivityEventType and its label/rendering in ActivityFeed.tsx and ActivityLogModal.tsx
- Remove the dead `isReleaseAuthorizationHold` badge logic and `.awaiting-release-authorization` CSS class from TaskCard.tsx/TaskCard.css
- Simplify TaskDetailModal.tsx comments/logic now that legacy release-authorization holds render as ordinary manual plan-approval holds
- Delete orphaned i18n keys `tasks.awaitingReleaseAuthorization` and `taskDetail.plan.releaseAuthorizationHold` across en/es/fr/ko/zh-CN/zh-TW locales and resources.d.ts
- Delete the stale docs/solutions/architecture-patterns/release-triage-requires-user-authorization.md doc
- Update docs/workflow-steps.md and docs/settings-reference.md to describe the gate as removed (superseded by FN-7732) instead of documenting still-active behavior
- Add changeset for @runfusion/fusion (patch/internal)

Files changed:
 .changeset/fn-7732-remove-release-authorization-block.md |  7 +++++
 docs/settings-reference.md                                |  2 +-
 docs/solutions/architecture-patterns/release-triage-requires-user-authorization.md | 33 ----------------------
 docs/workflow-steps.md                                    |  6 ++--
 packages/core/src/types.ts                                 |  8 ++++--
 packages/dashboard/app/components/ActivityFeed.tsx         |  5 ----
 packages/dashboard/app/components/ActivityLogModal.tsx     |  6 ----
 packages/dashboard/app/components/TaskCard.css             | 11 --------
 packages/dashboard/app/components/TaskCard.tsx              | 13 +++------
 packages/dashboard/app/components/TaskDetailModal.tsx       | 14 +++------
 packages/i18n/locales/en/app.json                           |  3 --
 packages/i18n/locales/es/app.json                           |  5 +---
 packages/i18n/locales/fr/app.json                           |  5 +---
 packages/i18n/locales/ko/app.json                           |  5 +---
 packages/i18n/locales/zh-CN/app.json                        |  5 +---
 packages/i18n/locales/zh-TW/app.json                        |  5 +---
 packages/i18n/src/resources.d.ts                            |  3 --
 17 files changed, 30 insertions(+), 106 deletions(-)

Fusion-Task-Id: FN-7732

Fusion-Task-Lineage: d4137bd8-9056-4062-9f2a-c6f5d47295f4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 19:58:07 -07:00
gsxdsm
2c4052c76b FN-7746: Add thinking level selector to model pickers
Adds a thinking-level (reasoning-effort) selector to the quick-create model pickers, matching the levels already available in the full task pickers.

- ModelSelectionModal: adds optional thinking-level <select> (off/minimal/low/medium/high/xhigh) with a status badge, rendered only when onThinkingLevelChange is supplied
- QuickEntryBox: wires thinking-level state through to ModelSelectionModal and persists the override with quick-created tasks
- InlineCreateCard: same thinking-level wiring for the inline task creation card
- Adds i18n strings for the new thinking-level labels across en/es/fr/ko/zh-CN/zh-TW locale files
- Adds test coverage in InlineCreateCard.test.tsx, ModelSelectionModal.test.tsx, and QuickEntryBox.test.tsx for the new selector

Files changed:
 .../dashboard/app/components/InlineCreateCard.tsx  | 16 ++++-
 .../app/components/ModelSelectionModal.tsx         | 47 +++++++++++++-
 .../dashboard/app/components/QuickEntryBox.tsx     | 67 ++++++++++++++++++-
 .../components/__tests__/InlineCreateCard.test.tsx | 70 ++++++++++++++++++++
 .../__tests__/ModelSelectionModal.test.tsx         | 69 ++++++++++++++++++++
 .../components/__tests__/QuickEntryBox.test.tsx    | 75 ++++++++++++++++++++++
 packages/i18n/locales/en/app.json                  |  2 +
 packages/i18n/locales/es/app.json                  |  2 +
 packages/i18n/locales/fr/app.json                  |  2 +
 packages/i18n/locales/ko/app.json                  |  2 +
 packages/i18n/locales/zh-CN/app.json               |  2 +
 packages/i18n/locales/zh-TW/app.json               |  2 +
 12 files changed, 351 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7746

Fusion-Task-Lineage: 4a221203-0222-47d6-93f8-632638bcfbfe

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 19:58:07 -07:00
gsxdsm
0e90578122 FN-7737: Add file_scope agent permission category with default allow disposition
Introduces a new file_scope sensitive-action category to the agent permission policy model so file-scope-related FN tools are classified and gated distinctly from other categories, defaulting to allowed under the grant-all preset.

- Add file_scope to AGENT_PERMISSION_POLICY_ACTION_CATEGORIES in @fusion/core types
- Classify FILE_SCOPE_FN_TOOLS in both agent-action-gate and permanent-agent-gating with a uniform preset disposition (no review_gate_bypass-style override)
- Update AgentDetailView and AgentPermissionPolicyEditor to surface the new category in the dashboard UI
- Add/extend unit tests across core, engine, and dashboard packages covering the new category's resolution, gating, and UI rendering
- Update docs/agents.md and docs/settings-reference.md to document the new permission category
- Regenerate i18n locale strings (en/es/fr/ko/zh-CN/zh-TW) and resources.d.ts for the new category labels
- Add changeset for @runfusion/fusion (minor) describing the new File Scope permission category

Files changed:
 .../fn-7737-file-scope-permission-category.md      |   7 +
 docs/agents.md                                     |  10 +-
 docs/settings-reference.md                         |   8 +-
 .../agent-permission-policy-resolution.test.ts     |  13 +
 .../src/__tests__/agent-permission-policy.test.ts  |  45 +++
 packages/core/src/types.ts                         |   7 +
 .../dashboard/app/components/AgentDetailView.tsx   |   2 +
 .../app/components/AgentPermissionPolicyEditor.tsx |   8 +
 .../__tests__/AgentPermissionPolicyEditor.test.tsx |  37 +++
 .../engine/src/__tests__/agent-action-gate.test.ts |  46 +++
 .../src/__tests__/gating-classifications.test.ts   |  67 +++++
 .../src/__tests__/permanent-agent-gating.test.ts   |  41 +++
 packages/engine/src/agent-action-gate.ts           |   7 +
 packages/engine/src/gating-classifications.ts      |   6 +
 packages/engine/src/permanent-agent-gating.ts      |   6 +
 packages/i18n/locales/en/app.json                  |   4 +
 packages/i18n/locales/es/app.json                  |   4 +
 packages/i18n/locales/fr/app.json                  |   4 +
 packages/i18n/locales/ko/app.json                  |   4 +
 packages/i18n/locales/zh-CN/app.json               |   4 +
 packages/i18n/locales/zh-TW/app.json               |   4 +
 packages/i18n/src/resources.d.ts                   | 310 +++++++++++++++------
 22 files changed, 550 insertions(+), 94 deletions(-)

Fusion-Task-Id: FN-7737

Fusion-Task-Lineage: 7b161fb3-7dd9-4860-aa4d-0cb35f38ea5b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 19:58:07 -07:00
gsxdsm
626e00288c FN-7720: add operator review-lane bypass for stranded pre-merge review failures
Add a policy-gated review-lane bypass primitive so operators can unstick cards stranded by a failed pre-merge review step (e.g. the no-feedback review-engine defect), without exposing it to agent-driven lanes.

- Add `store.bypassFailedPreMergeReviewStep(id, { reason, actor })` in @fusion/core plus `getLatestFailedPreMergeReviewStep` in task-merge.ts, and new `bypassedBy`/`bypassedAt`/`bypassReason`/`bypassedFromStatus`/`bypassedFromVerdict` fields on `WorkflowStepResult`
- Add operator-only `fn_task_bypass_review` CLI/pi-extension tool; explicitly withheld from executor/reviewer/triage agent tool lists
- Add `POST /tasks/:id/bypass-review` dashboard API route and wire it through `register-task-workflow-routes.ts` and legacy API compatibility layer
- Add dashboard UI affordance (context menu action + task detail modal + right-dock controller wiring) to trigger the bypass with a reason
- Add i18n strings for the bypass action/labels across en/es/fr/ko/zh-CN/zh-TW locales
- Update `gating-classifications.ts` to recognize the bypassed state
- Add unit tests: `store-bypass-review.test.ts`, `task-merge-bypass.test.ts`, extension test coverage, and `useTasks` hook test coverage
- Update docs (`docs/workflow-steps.md`, `docs/dashboard-guide.md`, AGENTS.md, fusion skill references) to describe the new bypass tool/route
- Add changeset `.changeset/fn-7720-review-lane-bypass-primitive.md` (minor)

Files changed:
$(git diff --cached --stat)

Fusion-Task-Id: FN-7720

Fusion-Task-Lineage: 590b020a-ae02-4b51-8189-df8f54bf3044

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 19:58:04 -07:00
gsxdsm
400f04530c chore(release): v0.57.0
Version bump via changesets.
2026-07-08 16:27:10 -07:00
gsxdsm
681113b095 fix: restore full-suite green — i18n parity (FN-7658 keys) + chat core mock (FN-7675) 2026-07-08 15:17:45 -07:00
gsxdsm
7cf70b3c59 FN-7665: rename Command Center SDLC funnel intake stage label to Planning
Rename the Command Center SDLC funnel's intake stage display text from "Triage" to "Planning" to match the renamed board column, updating English locale copy and tests; the underlying aggregator/i18n key names stay "triage".

- SdlcFunnel.tsx: stage label fallback, enteredInRange, and completionRateAria copy changed to Planning/Entered planning/in-range planning entrants; added FNXC comment explaining the key-vs-label distinction
- packages/i18n/locales/en/app.json: synced English strings for the same three keys
- SdlcFunnel.test.tsx: updated assertions to match new Planning copy
- Added changeset (patch) documenting the label rename

Files changed:
 .changeset/fn-7665-funnel-planning-label.md              |  7 +++++++
 .../app/components/command-center/SdlcFunnel.tsx         | 16 ++++++++++++----
 .../command-center/__tests__/SdlcFunnel.test.tsx         |  6 +++---
 packages/i18n/locales/en/app.json                        |  6 +++---
 4 files changed, 25 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-7665

Fusion-Task-Lineage: d8aec609-6b8b-4f36-bb43-61d7c7c421f9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-08 00:50:11 -07:00
gsxdsm
97e46674f4 FN-7660: rename remaining board-column "Triage" labels to "Planning"
Rename remaining "Triage" board-column label references to "Planning" across dashboard editors, locale strings, and docs.

- Fixed BUILTIN_WORKFLOW_COLUMN_LABELS.triage in board-workflows.ts (was still "Triage", clobbering FN-7599's IR rename); column id "triage" stays unchanged
- Updated dashboard components (AgentDetailView, RoutineEditor, ScheduleForm, ScheduleStepsEditor) to use the "Planning" label
- Updated en/app.json locale strings (board.triage, schedule.columnTriage/taskColumnTriage/triageColumn) to "Planning"
- Updated board-workflows tests to assert the new label
- Updated docs/dashboard-guide.md Triage/Planning column references to "Planning", preserving the FN-7653 intake-only gating correction
- Added a patch changeset documenting the label-consistency fix

Files changed:
 .changeset/fn-7660-planning-label-consistency.md               |  7 +++++++
 docs/dashboard-guide.md                                        |  9 +++++----
 packages/dashboard/app/components/AgentDetailView.tsx          |  2 +-
 packages/dashboard/app/components/RoutineEditor.tsx            |  2 +-
 packages/dashboard/app/components/ScheduleForm.tsx             |  2 +-
 packages/dashboard/app/components/ScheduleStepsEditor.tsx      |  2 +-
 .../dashboard/src/routes/__tests__/board-workflows.test.ts     |  7 ++++++-
 packages/dashboard/src/routes/board-workflows.ts               | 10 +++++++++-
 packages/i18n/locales/en/app.json                              |  8 ++++----
 9 files changed, 35 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-7660

Fusion-Task-Lineage: fc6c94d6-9876-4c0e-80b1-a5518903952e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-08 00:27:52 -07:00
gsxdsm
f7d9509294 FN-7658: gate same-agent duplicate auto-archiving behind opt-in setting
Duplicate tasks created by the same agent are no longer auto-archived by default; they are flagged for review instead, controlled by a new opt-in project setting.

- Add project setting `autoArchiveDuplicateTasksEnabled` (default false) gating the FN-4892 same-agent duplicate intake path
- Add `flagSameAgentDuplicate` path and `nearDuplicateOf` metadata used when auto-archive is disabled; tombstone-resurrection blocking is unchanged
- Wire the setting through core settings schema/types/store, dashboard SchedulingSection UI, and i18n strings
- Update docs (settings-reference.md, task-management.md) to describe the new default-off behavior
- Add a changeset for the @runfusion/fusion minor release
- Extend duplicate-intake, tombstone-window, store-parent-task-dedup, and reliability-interaction tests to cover both flag states

Files changed:
$(cat /tmp/fn7658_stat.txt)

Fusion-Task-Id: FN-7658

Fusion-Task-Lineage: 7d0d1074-1020-48a8-b96f-186154c2c408

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-08 00:23:32 -07:00
gsxdsm
efabdd6f04 FN-7651: remove chat "Search in title only" toggle
Simplifies chat search UX by always matching both title and message content, removing the now-unneeded title-only toggle button and state.

- Removed the "Search in title only" toggle button and its CSS from ChatView
- Dropped searchInTitleOnly/setSearchInTitleOnly state and logic from useChat; content-search query params are now always-on
- Updated ChatView tests to drop title-only toggle interactions and assertions
- Removed the title-only-search i18n string across all locales
- Updated dashboard-guide.md docs to reflect the simplified search behavior
- Added a patch changeset documenting the removal

Files changed:
 .../fn-7651-remove-chat-title-only-toggle.md       |  7 +++
 docs/dashboard-guide.md                            |  4 +-
 packages/dashboard/app/components/ChatView.css     | 18 --------
 packages/dashboard/app/components/ChatView.tsx     | 26 +++--------
 .../__tests__/ChatView.autosize.test.tsx           |  2 -
 .../__tests__/ChatView.content-search.test.tsx     | 51 ++++++----------------
 .../components/__tests__/ChatView.draft.test.tsx   |  2 -
 .../__tests__/ChatView.hash-mention.test.tsx       |  2 -
 .../__tests__/ChatView.mobile-render.test.tsx      |  2 -
 .../components/__tests__/ChatView.rooms.test.tsx   |  2 -
 .../__tests__/ChatView.scroll-to-top.test.tsx      |  2 -
 .../components/__tests__/ChatView.test-harness.tsx |  2 -
 packages/dashboard/app/hooks/useChat.ts            | 39 ++++++++---------
 packages/i18n/locales/en/app.json                  |  1 -
 packages/i18n/locales/es/app.json                  |  1 -
 packages/i18n/locales/zh-CN/app.json               |  1 -
 packages/i18n/locales/zh-TW/app.json               |  1 -
 packages/i18n/locales/ko/app.json                  |  1 -
 packages/i18n/locales/fr/app.json                  |  1 -
 19 files changed, 47 insertions(+), 118 deletions(-)

Fusion-Task-Id: FN-7651

Fusion-Task-Lineage: 5a31825c-8e6e-441f-800d-6053f5f844ba

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-07 23:15:53 -07:00
gsxdsm
6777eea5d2 FN-7631: add content search to Chat sidebar with title-only toggle
Chat sidebar search now matches message content by default, not just the conversation title/agent, with an opt-out toggle to restore title-only filtering.

- Add ChatStore.searchSessionsByMessageContent (parameterized LIKE ... ESCAPE) for server-side content search across sessions
- GET /chat/sessions route (register-chat-routes.ts, legacy.ts) gains q/titleOnly query params, debounced server-side content lookup merged with local title/agent matches
- useChat hook exposes searchInTitleOnly state and wires debounced content search into session list results
- ChatView renders a "Search in title only" toggle beside the search box (desktop + mobile) and shows a "Matched: ..." preview snippet on content-matched rows
- Task-planner sessions remain excluded from content matches via the same common-feed visibility guard used for the normal session list
- Add unit/integration tests: chat-store content-search, chat-routes API test, ChatView content-search test
- Update docs/dashboard-guide.md to document the new content search behavior and toggle
- Add changeset fn-7631-chat-content-search.md (@runfusion/fusion minor)

Files changed:
 .changeset/fn-7631-chat-content-search.md          |   7 +
 docs/dashboard-guide.md                            |   2 +
 .../__tests__/chat-store.content-search.test.ts    | 157 +++++++++++++++++++++
 packages/core/src/chat-store.ts                    |  64 +++++++++
 packages/core/src/chat-types.ts                    |   8 ++
 packages/dashboard/app/api/legacy.ts               |  23 ++-
 packages/dashboard/app/components/ChatView.css     |  30 ++++
 packages/dashboard/app/components/ChatView.tsx     |  26 ++++
 .../__tests__/ChatView.autosize.test.tsx           |   2 +
 .../__tests__/ChatView.content-search.test.tsx     | 114 +++++++++++++++
 .../components/__tests__/ChatView.draft.test.tsx   |   2 +
 .../__tests__/ChatView.hash-mention.test.tsx       |   2 +
 .../__tests__/ChatView.mobile-render.test.tsx      |   2 +
 .../components/__tests__/ChatView.rooms.test.tsx   |   2 +
 .../__tests__/ChatView.scroll-to-top.test.tsx      |   2 +
 .../components/__tests__/ChatView.test-harness.tsx |   2 +
 packages/dashboard/app/hooks/useChat.ts            | 105 ++++++++++++--
 .../dashboard/src/__tests__/chat-routes.test.ts    |  78 ++++++++++
 .../dashboard/src/routes/register-chat-routes.ts   |  39 ++++-
 packages/i18n/locales/en/app.json                  |   2 +
 packages/i18n/locales/es/app.json                  |   2 +
 packages/i18n/locales/fr/app.json                  |   2 +
 packages/i18n/locales/ko/app.json                  |   2 +
 packages/i18n/locales/zh-CN/app.json               |   2 +
 packages/i18n/locales/zh-TW/app.json               |   2 +
 25 files changed, 667 insertions(+), 12 deletions(-)

Fusion-Task-Id: FN-7631

Fusion-Task-Lineage: bc68b489-26a7-453e-901b-bda816af364e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-07 22:06:17 -07:00
gsxdsm
0f2bfa546c FN-7629: add enable/disable control for built-in runtime plugins
Adds a durable Plugin Manager toggle to enable/disable built-in runtime plugins (Hermes, Paperclip, OpenClaw, Droid) that persists across restarts, replacing the dead-end "Built-in metadata only" CTA.

- renderBuiltinPluginSection now renders an enable/disable toggle for runtime built-ins regardless of installed status
- Disabling a not-yet-installed built-in first installs it (mirroring CLI's ensureBundledPluginInstalled) then immediately disables it, so a plugin_installs row + disabled project state exists with no new persistence primitive needed
- HermesRuntimeCard/OpenClawRuntimeCard/PaperclipRuntimeCard now show "Disabled in Plugin Manager" instead of a stale detected/connected status when disabled
- Added i18n strings across all locales and updated docs
- Added changeset for @runfusion/fusion (minor)
- Expanded plugin-loader and PluginManager test coverage for the new disable/enable flows

Files changed:
 .changeset/fn-7629-builtin-runtime-disable.md      |   7 +
 docs/dashboard-guide.md                            |   1 +
 docs/plugin-management.md                          |   4 +
 packages/core/src/__tests__/plugin-loader.test.ts  |  46 ++++++
 .../dashboard/app/components/HermesRuntimeCard.tsx |  40 ++++-
 .../app/components/OpenClawRuntimeCard.tsx         |  32 +++-
 .../app/components/PaperclipRuntimeCard.tsx        |  32 +++-
 .../dashboard/app/components/PluginManager.css     |  34 +++++
 .../dashboard/app/components/PluginManager.tsx     | 167 +++++++++++++++------
 .../components/__tests__/PluginManager.test.tsx    |  12 +-
 .../__tests__/PluginManager.toggle.test.tsx        | 104 ++++++++++++-
 packages/i18n/locales/en/app.json                  |   4 +
 packages/i18n/locales/es/app.json                  |   4 +
 packages/i18n/locales/fr/app.json                  |   4 +
 packages/i18n/locales/ko/app.json                  |   4 +
 packages/i18n/locales/zh-CN/app.json               |   4 +
 packages/i18n/locales/zh-TW/app.json               |   4 +
 packages/i18n/src/resources.d.ts                   |   4 +
 18 files changed, 440 insertions(+), 67 deletions(-)

Fusion-Task-Id: FN-7629
Fusion-Task-Lineage: 2a25bb1f-3f73-4273-8769-af05c61778f9
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-07 22:04:53 -07:00
gsxdsm
5631c88d54 FN-7614: replace planning-mode banner with yellow nav badge for needs-input state
Planning Mode's "waiting for input" indicator moves from a top banner (whose button did not redirect correctly) to a yellow status-dot badge on the Planning nav destination, matching the existing chat unread-badge pattern.

- Add a `planningNeedsInput` flag in app lifecycle utils to detect awaiting_input planning sessions
- Exclude planning awaiting_input sessions from SessionNotificationBanner so the banner no longer shows for this case
- Add a status-dot--pending badge to the Planning entry in LeftSidebarNav and to the Planning item/tab in MobileNavBar
- Add/extend tests covering appLifecycle, LeftSidebarNav, MobileNavBar, and SessionNotificationBanner behavior
- Add changeset (patch) documenting the fix
- Update dashboard-guide.md docs

Files changed:
 .changeset/fn-7614-planning-badge.md               |  7 +++
 docs/dashboard-guide.md                            |  4 ++
 packages/dashboard/app/App.tsx                     | 13 +++-
 .../dashboard/app/components/LeftSidebarNav.tsx    | 10 +++
 packages/dashboard/app/components/MobileNavBar.css | 20 ++++++
 packages/dashboard/app/components/MobileNavBar.tsx | 19 +++++-
 .../components/__tests__/LeftSidebarNav.test.tsx   | 28 +++++++++
 .../app/components/__tests__/MobileNavBar.test.tsx | 41 ++++++++++++
 .../__tests__/SessionNotificationBanner.test.tsx   | 44 +++++++++++++
 .../app/utils/__tests__/appLifecycle.test.ts       | 73 +++++++++++++++++++++-
 packages/dashboard/app/utils/appLifecycle.ts       | 12 ++++
 packages/i18n/locales/en/app.json                  |  1 +
 packages/i18n/locales/es/app.json                  |  1 +
 packages/i18n/locales/fr/app.json                  |  1 +
 packages/i18n/locales/ko/app.json                  |  1 +
 packages/i18n/locales/zh-CN/app.json               |  1 +
 packages/i18n/locales/zh-TW/app.json               |  1 +
 packages/i18n/src/resources.d.ts                   |  1 +
 18 files changed, 275 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7614

Fusion-Task-Lineage: 249e6ee8-149c-4d51-85b6-561dfc30c769

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-06 19:03:06 -07:00
gsxdsm
eb86555797 chore(release): v0.56.1
Version bump via changesets.
2026-07-05 19:57:09 -07:00
gsxdsm
2025f9d56d chore(release): v0.56.0
Version bump via changesets.
2026-07-05 17:13:36 -07:00