Commit Graph

9896 Commits

Author SHA1 Message Date
Phil Larson
8cc5fd895e feat(FN-783): add supported overlap blocker repair API 2026-06-25 03:44:23 -07:00
Phil Larson
e2a84d4dd6 feat(FN-783): complete Step 4 — reconcile stale overlap blockers safely
Fusion-Task-Id: FN-783

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-06-25 03:44:22 -07:00
Phil Larson
53825ad0ab fix(core): prefer explicit file scope for duplicate signatures 2026-06-25 03:44:22 -07:00
Phil Larson
41d1d5b74b feat(FN-783): complete Step 3 — shared write-scope classification
Fusion-Task-Id: FN-783

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-06-25 03:44:21 -07:00
Phil Larson
c8be19f9e6 test(FN-783): cover poisoned write-scope metadata
Fusion-Task-Id: FN-783

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-06-25 03:44:21 -07:00
gsxdsm
5cd795a3f2 fix(db): use rollback-journal mode for central DB to stop SIGBUS crashes (#1752)
## Summary

Running more than one fusion process on a host (multiple dashboards/CLIs
across worktrees, all attaching `~/.fusion/fusion-central.db`) could
crash a `node` process at random — instantly, with no JS stack and
nothing in the logs. This happened 3 times in 3 days on one machine.
After this change those processes coexist without crashing.

The crash was an OS-level `SIGBUS` (`EXC_BAD_ACCESS`, `FS pagein error`
/ kernel `cluster_pagein past EOF`) inside SQLite's `walIndexReadHdr`.
In WAL mode every connection coordinates through a memory-mapped `-shm`
wal-index; on macOS/APFS, when one process resizes/rebuilds that file
during a checkpoint while another has it mmap'd, the reader faults on
the now-out-of-bounds page. A hardware memory fault can't be caught by
`node:sqlite` or JS, so the whole process dies.

The fix switches the central DB to `journal_mode = DELETE` (rollback
journal), which uses no `-shm` memory map and coordinates cross-process
access via POSIX byte-range locks instead — removing the faulting
surface entirely while keeping multi-process access. The existing
`busy_timeout` absorbs the writer serialization that DELETE mode trades
for WAL's reader/writer concurrency. Per-project DBs (`db.ts`) are
intentionally left on WAL: they're single-process-per-project and don't
hit this cross-process fault. SQLite migrates the existing WAL database
on first open (checkpoints `-wal` into the main file and removes
`-wal`/`-shm`), so there is no data loss.

## Test plan

- New regression tests in `central-db.test.ts` assert the central DB
reports `journal_mode = delete` (not `wal`) and that **no `-shm`
wal-index file is ever created** even after write traffic — i.e. the
exact faulted surface is gone.
- All 6 central-DB suites pass (221 tests); `@fusion/core` typechecks
clean.

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
![Claude
Code](https://img.shields.io/badge/Opus_4.8_%281M%29-D97757?logo=claude&logoColor=white)


<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1752">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved stability when multiple dashboards or CLIs run on the same
machine.
* Switched the local database to a safer journaling mode to reduce rare
crash issues on macOS/APFS.
* Prevented creation of extra database side files during normal
operation, while keeping data durability and lock-based coordination in
place.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 00:04:43 -07:00
gsxdsm
079c428af9 chore(release): v0.48.0
Version bump via changesets.
2026-06-24 23:56:23 -07:00
gsxdsm
7a00811b4a FN-6987: load mission delete confirmation in modal
Mission delete prompts now open through the shared confirmation modal instead of inline mission panels.

- Route mission list and detail delete buttons through ConfirmDialogProvider.
- Keep inline delete panels reserved for non-mission destructive actions.
- Add desktop, mobile, cancel, success, and failure regression coverage.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-6987-mission-delete-confirm.md       |   7 +
 .../dashboard/app/components/MissionManager.tsx    |  38 +++-
 .../MissionManager.delete-confirm.test.tsx         | 243 +++++++++++++++++++++
 3 files changed, 278 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-6987
Fusion-Task-Lineage: df8a1a05-ff95-4d24-851d-053ecb017353
2026-06-24 23:52:30 -07:00
gsxdsm
e53f50eb38 Address PR review feedback (#1752)
- Verify the WAL->DELETE journal-mode switch instead of discarding exec()'s
  result. During a rolling upgrade a lingering WAL holder blocks the exclusive
  lock the switch needs, so SQLite either throws SQLITE_BUSY or no-ops and
  returns "wal". Capture both outcomes and warn loudly so the residual -shm
  SIGBUS surface is observable, rather than silently swallowed.
- Do not rethrow: the condition is transient and self-healing (the next start
  after the last WAL holder exits migrates cleanly); hard-failing would make the
  central DB unopenable during the very upgrade window it describes.
- Add a migration-path regression test (a WAL holder blocking the switch) that
  the prior fresh-DB-only tests did not cover.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:51:52 -07:00
gsxdsm
ad9b7b9ce3 fix(release): publish binaries — checkout CHANGELOG + externalize @fusion/engine (#1753)
## Problem

The latest release **v0.47.0 published 0 binaries**, and every desktop
build leg has been failing.

Two independent bugs in the release pipeline:

### 1. `github-release` job crashed → no binaries published
The job downloads artifacts but never checks out the repo. A step added
2026-06-24 (`Extract release notes from CHANGELOG`) does
`fs.readFileSync('CHANGELOG.md')`, which threw `ENOENT: no such file or
directory` and failed the whole job — so v0.47.0 shipped **0 assets**
even though every bun build leg succeeded. (v0.45/v0.46 predated this
step and still published 21 assets each.)

### 2. Desktop Windows EXE / macOS DMG legs failing
`packages/desktop/src/local-runtime.ts` dynamically imports
`@fusion/engine`, but engine was missing from the esbuild externals list
(only `@fusion/core` and `@fusion/dashboard` were there). esbuild
followed the import and tried to bundle engine's transitive `node-pty`
native binaries:

```
X [ERROR] No loader is configured for ".node" files:
  .../@homebridge/node-pty-prebuilt-multiarch/build/Release/pty.node
```

## Fix

- **`.github/workflows/release.yml`** — sparse-checkout `CHANGELOG.md`
in the `github-release` job, and harden the notes script to fall back to
a plain `Release vX.Y.Z` body instead of crashing the publish.
- **`packages/desktop/scripts/build.ts`** — externalize `@fusion/engine`
alongside the other workspace packages; it resolves from `node_modules`
at runtime, same as `core`/`dashboard`.

## Verification

- `pnpm build` runs clean locally — `dist/main.js` (623 kB) builds with
no `.node` loader error.
- YAML validated; `pnpm check:changesets` passes.

## Changeset

`"@runfusion/fusion": patch` (category `fix`) — restores
binary/installer publishing.

## Follow-up
These take effect on the next release. To backfill v0.47.0's missing
binaries, after merge delete + re-push the `v0.47.0` tag (the
tag-triggered run uses the workflow file at the tag).

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

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed release publishing so binary and desktop installer artifacts are
published correctly again.
* Improved release note generation to fall back gracefully when
changelog details aren’t available, preventing failed releases.
* Updated desktop app bundling to avoid packaging native dependencies
incorrectly, reducing build and packaging issues.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 23:50:20 -07:00
gsxdsm
a20235be0d chore(changeset): patch for release binary publish fix
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:43:47 -07:00
gsxdsm
50a94714ec fix(db): use rollback-journal mode for central DB to stop SIGBUS crashes
The central DB (~/.fusion/fusion-central.db) is opened concurrently by every
fusion process on a host. In WAL mode those connections coordinate through a
memory-mapped `-shm` wal-index; on macOS/APFS a reader takes a SIGBUS
(walIndexReadHdr / `cluster_pagein past EOF`) when another process resizes it
mid-checkpoint, killing the node process with no JS stack or log. Observed 3x
in 3 days. Switch the central DB to journal_mode=DELETE, which uses no `-shm`
mmap and coordinates cross-process access via POSIX byte-range locks instead;
busy_timeout absorbs the added writer serialization. Per-project DBs keep WAL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:39:35 -07:00
gsxdsm
8b81cceb17 fix(desktop): externalize @fusion/engine so desktop release builds pass
local-runtime.ts dynamically imports @fusion/engine, but it was missing from the
esbuild externals list (only @fusion/core and @fusion/dashboard were there). esbuild
followed the import and tried to bundle engine's transitive node-pty native .node
binaries, failing with "No loader is configured for .node files" — which broke every
desktop Windows EXE and macOS DMG build leg. Externalize @fusion/engine like the other
workspace packages; it resolves from node_modules at runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:38:59 -07:00
gsxdsm
a45cbffa13 fix(release): checkout CHANGELOG in github-release job so binaries publish
The github-release job downloaded artifacts but never checked out the repo,
so the new "Extract release notes from CHANGELOG" step threw ENOENT and failed
the whole job — v0.47.0 published 0 binaries despite every bun build succeeding.
Sparse-checkout CHANGELOG.md and harden the notes script to fall back to a plain
release body instead of crashing the publish.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:37:23 -07:00
gsxdsm
f9816799a0 FN-7000: test unified CLI merge entrypoints
Strengthen CLI merge tests around the unified runAiMerge path.\n\n- Mock runAiMerge separately from deprecated aiMergeTask in CLI task and dashboard tests.\n- Assert task merge uses runAiMerge without falling back to workspace landing or aiMergeTask.\n- Verify dashboard manual merge logging streams through runAiMerge and restores spies safely.\n\nFiles changed:\n .../cli/src/commands/__tests__/dashboard.test.ts   | 51 +++++++++++++---------\n packages/cli/src/commands/__tests__/task.test.ts   | 30 +++++++++----\n 2 files changed, 52 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-7000

Fusion-Task-Lineage: 96080841-c813-4a9e-97bd-a41aba60089f
2026-06-24 23:32:52 -07:00
gsxdsm
bd5a779423 FN-6982: remove task chat guidance copy
Remove the task Chat composer guidance line and rely on placeholders for task state cues.

- Drop the idle/guidance text block above the task Chat entry box.
- Remove obsolete localized guidance strings and generated resource types.
- Update dashboard docs, regression coverage, and release notes for the simplified composer.

Files changed:
 .changeset/fn-6982-task-chat-guidance.md           |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 packages/dashboard/app/components/TaskChatTab.css  |  10 --
 packages/dashboard/app/components/TaskChatTab.tsx  |  83 +----------------
 .../app/components/__tests__/App.test.tsx          |  42 ++++-----
 .../PlanningModeModal.ui-interactions.test.tsx     |   2 +-
 .../app/components/__tests__/TaskChatTab.test.tsx  | 102 +++++++++++----------
 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 -
 packages/i18n/src/resources.d.ts                   |   2 -
 14 files changed, 81 insertions(+), 181 deletions(-)

Fusion-Task-Id: FN-6982

Fusion-Task-Lineage: b880df6c-d84b-4d34-886b-f54c1d568ece
2026-06-24 23:32:52 -07:00
gsxdsm
f918896839 FN-6981: make Git Manager tabs scroll on mobile
Keep Git Manager navigation reachable in narrow mobile and embedded layouts.

- Make Git Manager tab strips non-wrapping horizontal scrollers with touch-friendly panning.
- Constrain repo selector sizing so tabs and Refresh stay reachable on narrow widths.
- Extend modal and CSS coverage for standalone, embedded, and workspace-selector mobile cases.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-6981-git-manager-mobile-tabs.md      |  7 +++
 packages/dashboard/app/components/ScriptsModal.css | 43 ++++++++++++-
 .../components/__tests__/GitManagerModal.test.tsx  | 59 +++++++++++++-----
 .../__tests__/core-modals-mobile.test.tsx          | 70 +++++++++++++++++++++-
 4 files changed, 160 insertions(+), 19 deletions(-)

Fusion-Task-Id: FN-6981

Fusion-Task-Lineage: c8a2910c-3642-4e14-a841-21cc32bc4cdb
2026-06-24 23:32:52 -07:00
gsxdsm
193532bd2b FN-6968: refresh test timing snapshots
Refresh the weekly test velocity baseline with current timing evidence.

- Update the rendered baseline report with the latest capture timestamps and velocity deltas.
- Replace stale slowest-file timing rows with the refreshed snapshot entries.
- Append the latest velocity history sample used by the weekly report.

Files changed:
 docs/test-velocity-baseline.md     |   61 +-
 scripts/test-timings.json          | 1772 +++++++++++++++++++++++++++++-------
 scripts/test-velocity-history.json |  112 +++
 3 files changed, 1580 insertions(+), 365 deletions(-)

Fusion-Task-Id: FN-6968

Fusion-Task-Lineage: 940f3581-3650-4feb-8730-d6dbb760e30c
2026-06-24 23:32:52 -07:00
gsxdsm
5a192ece16 FN-6946: add GitHub reference picker to task dialog
Add a GitHub issue and pull request picker that seeds new task prompts from detected remotes.

- Add remote-aware GitHub issue/PR selection to the New Task modal.
- Generate focused task descriptions for selected issues and pull requests while confirming before replacing user text.
- Style and document the compact picker and cover loading, errors, remote selection, and overwrite behavior in tests.
- Add a changeset for the published Fusion CLI package.

Files changed:
 .changeset/fn-6946-github-reference-picker.md      |   7 +
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/components/NewTaskModal.css |  53 ++++
 packages/dashboard/app/components/NewTaskModal.tsx | 297 ++++++++++++++++++++-
 .../app/components/__tests__/NewTaskModal.test.tsx | 199 +++++++++++++-
 5 files changed, 555 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6946

Fusion-Task-Lineage: e871827c-dfe5-4fc3-a525-c1161639d306
2026-06-24 23:32:52 -07:00
gsxdsm
3ae053e744 FN-6976: keep planning JSON failures retryable
Persist malformed Planning Mode AI responses as retryable errors while improving JSON response selection.

- Preserve failed initial-turn planning sessions with actionable retry errors instead of deleting them.
- Prefer valid planning-shaped JSON candidates over unrelated embedded JSON blobs.
- Cover streaming, non-streaming, retry recovery, and AI merge test mock compatibility.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-6976-planning-json-recovery.md       |   7 +
 .../cli/src/commands/__tests__/dashboard.test.ts   |   1 +
 packages/cli/src/commands/__tests__/task.test.ts   |   9 +-
 .../src/__tests__/session-error-recovery.test.ts   | 144 +++++++++++++++++++++
 packages/dashboard/src/planning.ts                 | 123 ++++++++++--------
 5 files changed, 229 insertions(+), 55 deletions(-)

Fusion-Task-Id: FN-6976

Fusion-Task-Lineage: e1cb59cb-1d7d-4aff-b17f-9633568f823f
2026-06-24 23:32:52 -07:00
gsxdsm
eb3833a542 FN-6971: retire dual-observe cutover gating
Remove stale dual-observe prerequisites from workflow-authoritative readiness while preserving parity-summary safeguards.

- Require the authoritative flag plus clean populated parity summaries for interpreter cutover readiness.
- Keep persisted workflowInterpreterDualObserve values inert in runtime tests and documentation.
- Update cutover, parity, and graph-executor tests to reflect retired shadow observation behavior.
- Add a formatted patch changeset for the operator-facing cutover readiness fix.

Files changed:
 .changeset/fn-6971-workflow-cutover-readiness.md   |  7 ++
 docs/architecture.md                               |  2 +-
 docs/settings-reference.md                         |  4 +-
 docs/workflow-steps.md                             | 19 +++--
 .../core/src/__tests__/workflow-cutover.test.ts    | 19 +++--
 packages/core/src/workflow-cutover.ts              |  9 +--
 .../workflow-interpreter-cutover.test.ts           | 87 +++++++++++++++++++---
 .../workflow-interpreter-dual-observe.test.ts      | 76 ++++++-------------
 .../src/__tests__/stepwise-workflow-parity.test.ts | 25 ++++---
 .../engine/src/workflow-authoritative-driver.ts    | 10 +--
 10 files changed, 152 insertions(+), 106 deletions(-)

Fusion-Task-Id: FN-6971
Fusion-Task-Lineage: 363a441d-62e5-403c-9389-75fcf788352a
2026-06-24 23:32:52 -07:00
gsxdsm
e7021857a9 FN-6999: equalize mobile nav side spacing
Mobile bottom navigation now keeps balanced horizontal spacing without disturbing existing viewport compensation.\n\n- Add tokenized inline padding to the fixed mobile nav bar while preserving ICB and safe-area behavior.\n- Cover symmetric side spacing in mobile nav CSS and component layout tests.\n- Add a patch changeset for the published CLI package.\n\nFiles changed:\n .changeset/fn-6999-mobile-nav-side-spacing.md                  |  7 +++++++\n packages/dashboard/app/__tests__/mobile-nav-bar-css.test.ts    | 10 ++++++++++\n packages/dashboard/app/components/MobileNavBar.css             |  5 +++++\n .../dashboard/app/components/__tests__/MobileNavBar.test.tsx   |  8 ++++++++\n 4 files changed, 30 insertions(+)

Fusion-Task-Id: FN-6999

Fusion-Task-Lineage: 91bd2174-8e5d-4227-a035-ff621e309719
2026-06-24 23:32:52 -07:00
gsxdsm
e473ba68fb FN-6997: widen task changes diff panel
Reclaims task detail padding so inline diffs have more readable width on compact screens.

- Expand the compact Changes file list to consume detail-body padding without page overflow.
- Add mobile breakpoint coverage that matches the detail-body padding contract.
- Add regression tests for the phone-width inline diff surface and CSS rules.
- Add a patch changeset for the published Fusion CLI package.

Files changed:
 .changeset/fn-6997-diff-panel-width.md             |  7 ++
 .../dashboard/app/components/TaskChangesTab.css    | 20 ++++-
 .../components/__tests__/TaskChangesTab.test.tsx   | 98 +++++++++++++++++++++-
 3 files changed, 121 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-6997

Fusion-Task-Lineage: a7f21c0d-89a8-430e-a84c-341a10af4a4a
2026-06-24 23:32:52 -07:00
gsxdsm
29530b5fdb FN-6967: widen tablet agent chat bubbles
Improve tablet Chat readability by widening agent-side response bubbles without expanding user or Quick Chat bubbles.

- Add a ChatView container query that widens assistant, streaming, and failure bubbles on tablet-width containers.
- Cover the targeted bubble classes and CSS width contract in ChatView tests.
- Document the tablet behavior and add a structured patch changeset for the published CLI bundle.

Files changed:
 .changeset/fn-6967-tablet-chat-bubble-width.md     |  7 +++
 docs/dashboard-guide.md                            |  3 +-
 packages/dashboard/app/components/ChatView.css     | 12 +++++
 .../app/components/__tests__/ChatView.test.tsx     | 56 ++++++++++++++++++++++
 4 files changed, 77 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-6967
Fusion-Task-Lineage: 74195885-4ec0-4fc9-b628-0b0510129026
2026-06-24 23:32:52 -07:00
gsxdsm
a554ceb672 FN-6959: align footer launcher typography
Align the Quick Chat and Terminal footer launchers so they read as matching peer controls.

- Inherit the footer font and color contract for the Terminal footer launcher.
- Preserve usable hover, focus, padding, and scripts chevron behavior in the footer variant.
- Document the footer Quick Chat launcher placement and add release notes.
- Expand status bar tests to lock the shared footer launcher styling.

Files changed:
 .changeset/fn-6959-footer-launcher-style.md        |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 .../dashboard/app/components/ExecutorStatusBar.css |   2 +-
 .../dashboard/app/components/TerminalLauncher.css  |  37 +++++++-
 .../__tests__/ExecutorStatusBar.test.tsx           | 105 +++++++++++++++++++--
 5 files changed, 138 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-6959
Fusion-Task-Lineage: 539307cb-dc81-441f-8baf-8823826e2195
2026-06-24 23:32:52 -07:00
gsxdsm
f955606106 FN-6966: flag stale timing metadata in velocity reports
Add stale timing context to the weekly test velocity baseline so W26 regressions are not misattributed.

- Report timing snapshot age and missing slowest-file paths before the slow-file table.
- Persist timing metadata notes in velocity history and regenerate the W26 baseline report.
- Cover stale and missing timing metadata warnings with node:test assertions.

Files changed:
 docs/test-velocity-baseline.md                    |  23 ++-
 scripts/__tests__/test-velocity-baseline.test.mjs |  26 +++
 scripts/test-velocity-baseline.mjs                |  65 +++++-
 scripts/test-velocity-history.json                | 231 ++++++++++++++++++++++
 4 files changed, 330 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-6966

Fusion-Task-Lineage: bccac6c2-11c1-4295-b3af-b77dab1748dc
2026-06-24 23:32:52 -07:00
gsxdsm
8c734fe230 FN-6973: stabilize engine liveness tests
Stabilize engine tests around executor liveness cleanup and scheduler handoff expectations.

- Assert task-move cleanup clears active session registry entries for agent, step, and workflow-step sessions.
- Reset active session registry module state between executor tests alongside executing task locks.
- Relax brittle worktree and scheduler assertions to match current merge-base and handoff behavior.

Files changed:
 .../engine/src/__tests__/executor-pause.test.ts    | 52 +++++++++++++++++++---
 .../engine/src/__tests__/executor-test-helpers.ts  |  8 ++--
 .../engine/src/__tests__/executor-worktree.test.ts |  2 +-
 .../owning-node-unavailable-interactions.test.ts   |  2 +-
 .../src/__tests__/restart.integration.test.ts      |  8 +++-
 5 files changed, 59 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-6973

Fusion-Task-Lineage: 37c7d4b3-7ff5-4339-bd3f-6b10f507883e
2026-06-24 23:32:52 -07:00
gsxdsm
214a60c085 FN-6944: reclaim quick entry textarea width
Quick entry textareas now avoid inheriting refine-button padding that caused right-side dead space.

- Override quick-entry textarea right padding with a selector specific enough to beat the shared description refine rule without !important.
- Add CSS cascade regression coverage confirming quick entry reclaims width while global description textareas retain overlay padding.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-6944-quick-entry-width.md            |   7 ++
 .../dashboard/app/components/QuickEntryBox.css     |   6 +-
 .../components/__tests__/QuickEntryBox.test.tsx    | 114 +++++++++++++++++++++
 3 files changed, 124 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6944

Fusion-Task-Lineage: 2a6c7190-ff87-4da6-9437-8e57a113ce56
2026-06-24 23:32:51 -07:00
gsxdsm
d3593065e4 FN-6960: bound PR metadata generation
Keep Create PR metadata generation responsive and ensure fallback PR content remains editable.

- Race metadata collection, prompt execution, and session creation against abort/timeout signals.
- Return fallback PR metadata from the API route when generation exceeds the route budget.
- Seed the Create PR dialog with editable fallback body content after metadata failures and require a non-empty body before submit.
- Validate non-empty PR bodies in both gh CLI and API-backed PR creation paths.
- Add regression coverage for bounded metadata generation, fallback responses, and PR body validation.

Files changed:
 .changeset/fn-6960-pr-metadata-bounded.md          |  7 ++
 .../dashboard/app/components/PrCreateModal.tsx     | 34 ++++++++-
 .../components/__tests__/PrCreateModal.test.tsx    | 41 +++++++++++
 .../src/__tests__/github-create-pr.test.ts         |  6 +-
 .../src/__tests__/github-forced-mode.test.ts       |  2 +-
 packages/dashboard/src/__tests__/github.test.ts    | 21 ++----
 .../src/__tests__/pr-metadata-generator.test.ts    | 55 ++++++++++----
 .../src/__tests__/pr-routes.contract.test.ts       | 10 +++
 .../register-git-github.pr-errors.test.ts          |  2 +-
 ...it-github.pr-options-preflight-metadata.test.ts | 25 +++++++
 .../dashboard/src/__tests__/routes-auth.test.ts    | 12 +--
 .../dashboard/src/__tests__/routes-github.test.ts  |  2 +-
 packages/dashboard/src/github.ts                   | 20 ++++-
 packages/dashboard/src/pr-metadata-generator.ts    | 86 ++++++++++++++--------
 .../dashboard/src/routes/register-git-github.ts    | 67 +++++++++++++----
 15 files changed, 301 insertions(+), 89 deletions(-)

Fusion-Task-Id: FN-6960
Fusion-Task-Lineage: 1ae72062-7180-4de3-999b-98d131f00792
2026-06-24 23:32:51 -07:00
gsxdsm
d7f3c7093e FN-6941: add graph workflow filtering
Adds a Graph view header workflow dropdown that filters dependency graph tasks by the selected workflow.

- Portal the workflow switcher into the Graph view header and clear selection when unmounted.
- Scope plugin graph task context using workflow assignments and default workflow fallback.
- Cover the header integration, task filtering, portal lifecycle, and disabled workflow mode.
- Document Graph workflow filtering and add the published package changeset.

Files changed:
 .changeset/fn-6941-graph-workflow-dropdown.md      |   7 +
 docs/dashboard-guide.md                            |   1 +
 packages/dashboard/app/App.tsx                     |   4 +
 .../app/__tests__/graph-workflow-header.test.tsx   | 127 +++++++++++++++
 .../app/components/GraphWorkflowSwitcherSlot.tsx   | 110 +++++++++++++
 .../__tests__/GraphWorkflowSwitcherSlot.test.tsx   | 173 +++++++++++++++++++++
 .../app/components/dashboard/MainContent.tsx       |  23 ++-
 .../dashboard/app/components/dashboard/types.ts    |   3 +
 8 files changed, 446 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-6941

Fusion-Task-Lineage: a77bc99e-00fe-42fe-a976-d88ffd803388
2026-06-24 23:32:51 -07:00
gsxdsm
533c8af4bf docs: refresh README media with live captures across all themes incl. Ember (#1737)
## Summary

Re-captured all README showcase GIFs and screenshots from the running
Fusion dashboard, refreshed across every theme including the new Ember
variant.

## What changed

**Media (32 assets: 24 refreshed, 8 new):**
- Dashboard board + Agents roster shots (Tokyo Night + Ember)
- Command Center, Workflows, Agent Chat, Chat Rooms, Agent Mail GIFs
refreshed across Tokyo Night, Shadcn Light, Shadcn Dark Gray, and Ember
- 6 mobile screenshots (board, agents, missions, command center, chat,
chat list)
- All captures use a 1600x1000 viewport (16:10) at deviceScaleFactor 1
to match the original committed media and avoid vertical squashing from
vh-based CSS

**README.md:**
- Added a "board & agent team" showcase section with live dashboard and
agents shots
- Expanded every theme table from 2 columns (Light / Dark Gray) to 3
(Light / Dark Gray / Ember)

**demo/seed.ts:**
- Extended to seed chat messages and agent mail (5 agents, a direct chat
session, a #leads multi-agent room, and 6 mailbox messages covering
triage summaries, approvals, and hand-offs)
- Fixed two pre-existing task-transition bugs so the full seed runs to
completion

## Capture method

Desktop and agent shots were captured read-only from the live Fusion
instance (port 4040). Agent mail was captured from a throwaway seeded
instance — no running Fusion data was modified.


<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1737">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

## Summary by CodeRabbit

* **Documentation**
* Updated feature showcase galleries with expanded theme coverage,
including new Ember theme variants alongside existing Shadcn themes
across all sections.

* **New Features**
* Demo environment enhanced with agent collaboration capabilities
including multi-agent chat rooms, direct messaging, and mailbox
features.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 23:20:48 -07:00
gsxdsm
c34a59edf7 Merge branch 'main' into feature/readme-mobile 2026-06-24 23:20:39 -07:00
gsxdsm
efa97c82e3 refactor(dashboard): break App.tsx into smaller modules (#1740)
## Summary

Behavior-preserving decomposition of the dashboard root
`packages/dashboard/app/App.tsx` — a 2,729-line monolith (~2,350-line
single `AppInner` component) — into focused hooks, a pure-helpers util,
and presentational components. **No functional change.**

**`App.tsx`: 2,729 → 1,636 lines**, now under the 2,000-line file-count
ratchet and graduated off its grandfathered baseline (can never regress
above 2,000).

## What was extracted
- **Pure helpers + constants** → `utils/appLifecycle.ts` (re-exported
from `App` so the 7 unit-tested symbols keep their `from "../../App"`
import contract).
- **12 custom hooks** under `app/hooks/`: `useMailboxUnread`,
`useChatUnreadBadge`, `useStashOrphanCount`, `useApprovalBanner`,
`useBranchTaskFilters`, `useDashboardHealth`, `useAuthTokenRecovery`,
`useScopedDismissFlag`, `useCapacityRiskBanner`,
`useMainPanelTaskDetail`, `useBoardScrollRestore`, `usePoppedOutTasks`.
- **2 presentational components** under `app/components/dashboard/`:
`MainContent` (the 647-line view-switch dispatcher) and
`DashboardBanners`, with typed prop interfaces in `types.ts`.

## Key design decisions
- **KTD4 — single `task:updated` subscriber preserved.** The original
one `/api/events` subscriber (mailbox counts + approval banner +
GitHub-star + awaiting-approval refresh) was split: `useApprovalBanner`
owns `task:updated`/`approval:requested` (banner + star +
`onMailboxRefresh` callback); `useMailboxUnread` owns
`message:*`/`approval:*` count refresh. `subscribeSse` multiplexes onto
one shared `EventSource`, so no extra connections.
- **The 18 lazy view declarations stay in `App.tsx`** (the
`lazy-loaded-views-docs.test.ts` guard regex-scans `App.tsx`) and are
threaded to `MainContent` as `LazyExoticComponent` props.
- **Eager `ChatView.css` import stays at the `App.tsx` top level** (FOUC
prevention).

## Verification
- `pnpm lint` (full repo), `typecheck` (both passes), `pnpm build` — all
clean.
- `App.test.tsx` (the full-render behavior contract) **identical**
pre/post: 123 pass / 5 fail, where the 5 are **pre-existing**
experimental-flag failures verified against unmodified `App.tsx`.
- `lazy-loaded-views-docs.test.ts` passes.
- 30+ new `renderHook` tests, incl. a `sseSplitIntegration` test
co-mounting both SSE hooks to pin the split (no double-fire;
awaiting-approval refresh exactly once).
- `App.tsx` graduated off the line-count ratchet baseline (scoped — only
its entry removed).

## Notes
- `useShellOnboarding` was deferred — the shell region is more
intertwined than planned (onboarding + connection-status + local/remote
redirects).
- The browser/visual smoke wasn't run (requires the server stack);
coverage rests on the green gate + fresh build + `App.test.tsx`
rendering the real `<App/>`.

Plan:
`docs/plans/2026-06-24-001-refactor-dashboard-app-tsx-module-breakup-plan.md`
(status: completed).

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1740">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

* **Refactor**
* Split dashboard main content and banner rendering into dedicated
components and presenter-style logic.
* Moved unread counters, approval/notification banners, dashboard health
refresh, scroll restoration, task detail flow, branch filtering, and
per-project dismissals into dedicated hooks.
* Centralized dashboard lifecycle helpers to keep banner/session
behavior consistent.
* **Documentation**
* Added a plan describing the behavior-preserving dashboard module
breakup.
* **Tests**
* Added/expanded hook and integration coverage for unread badges,
approval banners, scroll restore, branch filtering, dismissals, health
refresh, and main-panel task detail behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 20:43:41 -07:00
gsxdsm
fd63260962 Merge branch 'main' into feature/refactor-apptsx 2026-06-24 20:31:59 -07:00
gsxdsm
2ba81c25b4 chore(release): v0.47.0
Version bump via changesets.
2026-06-24 19:32:59 -07:00
gsxdsm
3630da0658 feat: Better changelog — structured changesets + distilled release notes (#1750)
## Summary

Replaces dense, agent-authored technical changeset paragraphs with a
**structured, concise changeset schema** (end-user summary + category +
optional dev detail), enforced by a linter. Adds a **deterministic
distillation step** at version time that transforms a release's
collected changesets into clean, grouped, end-user-facing release notes.
Unifies both release paths (local `release.mjs` and CI `version.yml` /
`release.yml`) behind a single distilled artifact so the root
`CHANGELOG.md` and GitHub Release both carry the same user-facing notes.

## Changes

### Changeset format (`scripts/lib/changeset-schema.mjs`)
- Each changeset body now uses labeled fields: `summary` (required,
user-facing, max 120 chars), `category` (required:
feature/fix/breaking/security/performance/internal), `dev` (optional
developer detail)
- Legacy freeform changesets are detected and flagged for the transition
period

### Linter (`scripts/check-changeset-format.mjs`)
- Validates structured schema, summary length, category enum, and
frontmatter package scope
- Wired into `test:gate`, `pretest`, `pretest:full`, and `pr-checks.yml`
- Legacy changesets warn (exit 0) during transition; `--strict` flag
fails on them

### Distillation (`scripts/lib/distill-release-notes.mjs`)
- `distillDeterministic` builds grouped, end-user-facing release notes
by category (New, Fixed, Breaking, Security, Performance, Internal)
- `buildDistillationPrompt` and `DISTILLATION_SYSTEM_PROMPT` ready for
AI distillation via `createFnAgent` when model credentials are available
- Graceful fallback: deterministic bullet list when no model is
configured

### Release integration
- **Local path** (`scripts/release.mjs`): captures changeset entries
before `changeset version` deletes them, distills notes post-version,
replaces the version's CHANGELOG section with curated notes
- **CI path** (`scripts/ci-distill-release-notes.mjs`,
`scripts/run-ci-distill.mjs`): chained into `release:version` so both
flows get distilled notes
- **GitHub Release** (`release.yml`): uses curated CHANGELOG notes
instead of `generate_release_notes: true`

### Documentation
- `AGENTS.md`, `RELEASING.md`, `docs/contributing.md` updated with the
structured format guide
- `.changeset/README.md` template for `pnpm changeset` consumers

## Testing

- 54 new unit tests across changeset-schema, check-changeset-format,
distill-release-notes, and extract-version-notes
- `pnpm lint` clean
- `pnpm test:gate` green (371 tests)
- `pnpm check:changesets` passes (13 legacy warnings expected during
transition)

## Plan

Full implementation plan:
`docs/plans/2026-06-24-001-feat-better-changelog-plan.md`

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1750">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

## Summary by CodeRabbit

* **New Features**
* Added structured release-note guidance and validation for changeset
entries.
* Release notes now use curated, grouped changelog content instead of
auto-generated text.
* Added a fallback process to keep release notes consistent when
automated distillation isn’t available.

* **Bug Fixes**
  * Improved handling of legacy changesets and malformed entries.
* Ensured version-specific changelog sections are updated without
affecting older releases.

* **Tests**
* Added coverage for changeset validation, note grouping, and changelog
section replacement.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 19:31:18 -07:00
gsxdsm
2019e5a30f feat(changelog): U6 — docs, agent guidance, and structured changeset
Update AGENTS.md, RELEASING.md, contributing.md with the structured
changeset format guide. Add .changeset/README.md template. Add changeset
for this change. Update distill-release-notes.mjs with final version.
2026-06-24 19:25:51 -07:00
gsxdsm
51d1cc521c feat(changelog): U5 — CI workflow distillation integration
Chain distillation into release:version so both local and CI versioning
flows get distilled notes. Update release.yml to use curated CHANGELOG
notes instead of GitHub's auto-generated release notes.
2026-06-24 19:25:44 -07:00
gsxdsm
901f7124f3 feat(changelog): U4 — wire distillation into local release path
Capture changeset entries before 'changeset version' deletes them,
distill deterministic notes post-version, and replace the version's
section in the root CHANGELOG with curated end-user notes.
2026-06-24 19:25:38 -07:00
gsxdsm
8dfca7ab98 chore: downgrade optional-steps changeset from major to minor
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:23:55 -07:00
gsxdsm
c73dcad911 fix(workspace): suppress spurious 'Not a git repository' toast in Git Manager (#1749)
## Problem
Opening the Git Manager on a multi-repo **workspace** project rendered
the sub-repo dropdown correctly but **also toasted "Not a git
repository"** every time.

## Cause
On open, the section data fetch fires immediately with no `repoPath`
(the `selectedRepo` hasn't resolved yet), so the git status request
targets the **non-git browse-only workspace root** and fails `Not a git
repository`. `fetchWorkspaceRepos` resolves a tick later and the fetch
re-runs against a real sub-repo — but the first failure had already
toasted.

## Fix
Track workspace detection in a ref and suppress that single benign
root-race error: no `repoPath` + `Not a git repository` while detection
is still pending or has confirmed a workspace. A genuinely broken
**non-workspace** project still surfaces the error — once detection
settles as non-workspace, a single *guarded* re-fetch re-surfaces it.
The guard ensures no redundant fetch in the common non-workspace-OK
path, preserving existing call-count expectations.

## Tests
- Added the missing `fetchWorkspaceRepos` api mock — a pre-existing gap
(from the git-manager commit) that had broken the **entire**
GitManagerModal suite at import (130 tests).
- Positive regression: workspace project → no `Not a git repository`
toast.
- Negative control: real non-workspace broken repo → the error still
toasts.

Dashboard typecheck + lint clean; my 2 new tests pass and no
previously-passing test regressed (8 unrelated pre-existing failures
remain, untouched by this change).

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

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1749">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

* **New Features**
* Workspace tasks now return aggregated, repo-prefixed diff results for
both detailed diffs and file-diff listings, including consistent
file/stats aggregation across sub-repositories.
* **Bug Fixes**
* Prevented an initial, harmless “Not a git repository” message from
being shown during early workspace detection; genuine errors still
display the standard error toast.
* Improved workspace detection and retry behavior so the UI loads the
correct repo context after project switching.
* Updated the Task Changes UI to handle workspace tasks without
incorrectly showing the “No worktree available” state.
* **Tests**
* Added/expanded coverage for workspace diff aggregation and
workspace-related UI/error behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 19:18:12 -07:00
gsxdsm
9793ffbf9b Merge branch 'main' into feat/dashboard-workspace-wizard 2026-06-24 19:09:07 -07:00
gsxdsm
e6e096645a fix(workspace): address code-review findings on the workspace diff + Git Manager
From the multi-agent /ce-code-review of PR #1749 (no P0/P1 correctness bugs; these
are perf, race-hardening, and convention fixes):

- P1 (perf/reliability): the workspace diff ran git subprocesses serially per
  sub-repo AND per file — an N×M explosion with no aggregate cap. Add a bounded
  mapWithConcurrency helper (order-preserving) and parallelize the per-file patch
  loop (cap 8) and the per-sub-repo loop (cap 4). Deleted files still fetch their
  patch (skipping it would drop deletes from /file-diffs and zero /diff stats).
- P2 (frontend race): GitManagerModal's workspace-detection could be clobbered by
  a previous project's in-flight fetch on a rapid projectId switch / close-reopen.
  Add a detectionGenerationRef guard — only the latest detection run may mutate
  state; the effect cleanup bumps the generation to abandon superseded runs.
- P2 (DRY): reuse the existing parseStatusCode instead of re-inlining the
  status-code mapping.
- P2 (convention): FNXC-tag the new functions/branches per CLAUDE.md.
- P3: extract DIFF_TIMEOUT_MS/FILE_DIFFS_TIMEOUT_MS constants, drop a dead
  catch-assignment, note the done-fallback oldPath limitation.

Tests: order-preservation after parallelization; rapid-project-switch generation
guard (a stale workspace verdict must not suppress a new project's real error).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:05:11 -07:00
gsxdsm
98fc453f45 feat(workspace): show per-sub-repo changes in the task Changes tab
The Changes / Files-changed tab showed nothing for multi-repo workspace tasks:
the task-diff backend is single-repo throughout, and a workspace task has null
task.worktree/task.branch (its per-repo state lives in workspaceWorktrees), so
every path fell back to git-diff against the non-git workspace root → empty.

Backend (register-session-diff-routes): extract the single-repo per-worktree
detailed-diff into one shared helper (computeWorktreeDetailedFiles) and add a
workspace branch to BOTH /tasks/:id/diff and /tasks/:id/file-diffs that runs
before the single-repo logic: iterate sorted workspaceWorktrees, compute each
sub-repo's diff in its own live worktree against that repo's baseCommitSha (done
tasks fall back to the per-repo landed range in the sub-repo root), and aggregate
with `${repoRel}/`-prefixed paths. Single-repo behavior is byte-for-byte
preserved (renamed→modified fold retained; 58 existing diff-route tests pass).

Frontend: TaskChangesTab takes an isWorkspace prop and no longer shows the
single-repo "No worktree available" empty state for workspace tasks;
TaskDetailModal passes isWorkspace={isWorkspaceTask(workingTask)}.

Tests: backend aggregation (repo-prefixed paths + stats) and frontend rendering
of workspace changes instead of the empty state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 18:29:58 -07:00
gsxdsm
e4a0118579 fix(workspace): suppress spurious "Not a git repository" toast in Git Manager
Opening the Git Manager on a workspace project rendered the sub-repo dropdown
correctly but ALSO toasted "Not a git repository". On open the section fetch
fires immediately with no repoPath (selectedRepo unresolved), hitting the non-git
browse-only workspace root; fetchWorkspaceRepos resolves a tick later and the
fetch re-runs against a real sub-repo. We now track workspace detection in a ref
and suppress that one benign root-race error (no repoPath + "Not a git
repository" while detection is pending or has confirmed a workspace). A genuinely
broken non-workspace project still surfaces the error: once detection settles as
non-workspace, a single guarded re-fetch re-surfaces it (no redundant fetch in
the common non-workspace path, preserving existing call-count expectations).

Tests: add the missing fetchWorkspaceRepos api mock (pre-existing gap that broke
the whole GitManagerModal suite at import), plus a positive (workspace → no
toast) and negative-control (non-workspace broken → toast) regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 18:09:39 -07:00
gsxdsm
de3e84a0cd fix(workspace): remove false reattach banner, silence ai-merge ENOENT prune, skip workspace in rebinder (#1748)
Follow-up polish on the multiworkspace merge flow (after #1747 merged).
Driven by live testing of multi-repo tasks.

## Changes

**1. Remove the "Branch needs reattachment" banner (dashboard)**
The banner fired for any in-review task with a null singular
`task.branch` — which is the **normal, healthy** state for a workspace
task (its attachment is the per-sub-repo worktrees in
`workspaceWorktrees`, not a root branch). So it was a permanent false
positive on every in-review workspace task. Genuine lost bindings
(non-workspace) are already reattached **automatically** by
self-healing's `reconcileInReviewBranchRebind`, which runs event-driven
on move-to-in-review and on the sweep — no manual user action needed.
Removed the banner UI, its handler/state/imports, the obsolete
`rebind-banner` test, and its registry entry.

**2. self-healing: skip workspace tasks in the branch rebinder
(engine)**
`reconcileInReviewBranchRebind` now explicitly skips workspace tasks.
They are never rebind candidates — their `fusion/<id>` branches live
inside each sub-repo, not in the non-git browse-only workspace root, so
a null root branch is healthy. (The slim list select now carries
`workspaceWorktrees` from #1747, so `isWorkspaceTask` is accurate on
slim rows.)

**3. merger-ai: silence ENOENT in the pre-merge prune (engine)**
The AI-merge pre-merge prune `readdirSync`'d `<repo>/.fusion/ai-merge`
and warned on every workspace merge because that clean-room root is
created lazily and is normally absent. ENOENT now means "nothing to
prune" — skipped silently; non-ENOENT failures (and the tmpdir case)
still surface/throw.

**4. test: add `ToggleRight` to the TaskDetailModal lucide mock**
Pre-existing gap from FN-6880 (optional-group node) that broke the
entire TaskDetailModal suite at import; unrelated to this change but
blocking validation.

## Validation
- engine typecheck + build clean; dashboard typecheck clean
- engine rebind + merger-ai suites pass (63); TaskDetailModal suites
pass (117) after the mock fix
- lint clean on changed files

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

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1748">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

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

* **Bug Fixes**
* Removed the “Branch needs reattachment” banner and reattach action
from task details.
* Workspace tasks are skipped during branch rebind checks to avoid
confusing recovery prompts.
  * Temporary AI-merge cleanup now handles missing directories quietly.
* Workspace per-repo landing now continues when dependency
synchronization fails (with degraded dependency availability), while
single-repo landing still fails fast.
* **Tests**
* Updated component test mocks and removed the rebind-banner test
coverage.
* Added coverage for resilient workspace dependency synchronization
behavior and adjusted workspace-merger test fixtures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 17:45:01 -07:00
gsxdsm
9dc228549c fix(workspace): make per-repo land resilient to a sub-repo dependency-sync failure
A workspace land squash-merges each sub-repo via a clean room that first runs the
configured/inferred install (npm/pnpm/yarn). The install hard-fails by design so
merge verification never runs against an uninstalled checkout — but that let ONE
sub-repo with a manifest npm refuses to install (e.g. a corrupt `-@0.0.1`
lockfile entry rejected by npm 11) block landing every other sub-repo.

landWorkspaceTask now passes nonFatalDependencySync to landOneRepo: a clean-room
install failure is caught, logged + audited as a non-fatal degradation, and the
land proceeds (the git squash needs no installed deps; only dep-dependent
verification degrades for that repo). A real abort signal still propagates. The
single-repo land path keeps the documented hard-fail (flag defaults off).

Tests: new workspace-merger-deps-resilient asserts both the resilient workspace
land (all repos land despite install throwing) and the preserved single-repo
hard-fail. Also fix a pre-existing getTask mock gap in workspace-merger.test
(mergeAndReview reads getTask().comments) that broke 3 tests at the land step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 17:15:38 -07:00
gsxdsm
7793e185bc Merge branch 'main' into feat/dashboard-workspace-wizard 2026-06-24 17:12:05 -07:00
gsxdsm
ea67e4424d Merge branch 'main' into feature/refactor-apptsx 2026-06-24 17:07:22 -07:00
gsxdsm
93cfb88e64 fix(workspace): remove false reattach banner, silence ai-merge ENOENT prune
- dashboard: remove the "Branch needs reattachment" banner. It fired for any
  in-review task with a null singular task.branch — the NORMAL state for a
  workspace task (attachment is per-sub-repo worktrees in workspaceWorktrees), so
  it was a permanent false positive. Genuine lost bindings are already reattached
  automatically by self-healing's reconcileInReviewBranchRebind (event-driven on
  move-to-in-review + sweep), so no manual user action is needed. Delete the
  now-obsolete rebind-banner test + its registry entry.
- engine/self-healing: reconcileInReviewBranchRebind now explicitly skips
  workspace tasks (never rebind candidates — their fusion/<id> branches live in
  the sub-repos, not the non-git browse root; null root branch is healthy).
- engine/merger-ai: pre-merge prune treats an absent ai-merge search root (ENOENT)
  as "nothing to prune" instead of warning on every workspace merge.
- test: add ToggleRight to the TaskDetailModal lucide mock (pre-existing gap from
  FN-6880 that broke the whole suite at import).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 16:25:23 -07:00