Commit Graph

11965 Commits

Author SHA1 Message Date
gsxdsm
d393168771 fix(core): accept root-level files in File Scope validation
Root paths with extensions (global.json, Directory.Packages.props, MyApp.slnx)
were rejected because isValidFileScopeEntry required a slash, which failed GitHub
imports whose issue bodies declare those paths and dropped them from effective
write scope. Share one validator between create/update and classification.
2026-07-21 17:50:25 -07:00
gsxdsm
a38524dd54 fix(engine): do not read TaskStore in ProjectEngine constructor
FN-8453 merge-admission registration called getTaskStore() before
runtime.start(), which threw, left the singleton lock held, and made every
later engine start fail with blocked-by-lockfile. Use config.projectId instead.
2026-07-21 17:35:48 -07:00
gsxdsm
4d588ad091 fix(postgres): allow fusion_runtime to write legacy-adoption drained marker
Store-open adoption runs as fusion_runtime, which lacked grants on
public.fusion_schema_migrations, so the drained-marker write failed every
boot. Migration 0032 grants SELECT plus a SECURITY DEFINER helper limited
to the exact marker, and store-open calls that helper instead of raw INSERT.
2026-07-21 17:27:09 -07:00
gsxdsm
396090fc03 fix(startup): bound model registry refresh so dashboard cannot hang
Post-extension modelRegistry.refresh() had no timeout, so a hung remote
catalog fetch left the TUI on "Loading extensions…" forever. Use a shared
15s-bounded refresh across dashboard/serve/daemon and related registration paths.
2026-07-21 17:14:30 -07:00
gsxdsm
515d77cea8 fix(planning): remove extra padding around interview panes
Make the question/plan workspace flush edge-to-edge on desktop with a single column divider, while keeping a compact card inset on mobile.
2026-07-21 17:14:30 -07:00
gsxdsm
4eb532f24e fix(github): dedupe task progress updates
Post at most one in-progress comment per Fusion task while keeping failed deliveries retryable. Persist a durable marker and fall back to the task log when local marker storage fails after GitHub accepts the comment.
2026-07-21 17:14:30 -07:00
flexi767
0e29d9d43c fix(core): restore validating mission recovery (#2372)
Re-lands #2336 directly on current main after its temporary base branch
was merged and deleted.\n\n- allows validating → implementing during
startup recovery\n- shares the transition table across sync and
PostgreSQL mission stores\n- preserves retry-budget enforcement\n-
includes sync and PostgreSQL regressions plus a release
changeset\n\nValidation on current main: focused sync regression 1/1 and
@fusion/core typecheck passed.

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

* **Bug Fixes**
* Improved mission recovery after an engine restart when a feature was
interrupted during validation.
* Features can resume implementation correctly after recovering from
loop-state transitions.
* Synchronous and PostgreSQL mission storage now apply the same
validation-to-implementation recovery behavior.
* **Tests**
* Added integration and unit test coverage for startup recovery and
rejection of unknown persisted loop states.
* **Release**
  * Included in a patch update for `@runfusion/fusion`.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: v <v@v.speedport.ip>
2026-07-21 17:10:25 -07:00
flexi767
c71a9545b0 fix(engine): isolate provider rate-limit pauses (#2339)
## What changed

- Construct one `UsageLimitPauser` per project runtime and wire it into
both executor and triage.
- Replace the project-wide emergency stop for 429/quota failures with
provider-scoped task parking.
- Resolve execution, planning, validator, and merger providers for
active tasks; park only tasks routed through the unavailable provider.
- Preserve the actual reviewer provider on `ReviewerProviderError`, so a
Claude Plan Review 429 does not stop Codex work.
- Record `provider-rate-limit:<provider>` pause provenance without
storing provider response bodies in pause metadata.
- Run one daemon-owned provider-health monitor that probes only
providers with persisted rate-limit parks.
- Resume exact matching provider parks across every project only after
the existing authenticated usage probe succeeds and all reported
capacity windows are usable.
- Probe at five-minute intervals for the first five checks, then back
off independently per provider to 10/20/40/60 minutes with a one-hour
cap.

## Root cause and impact

The runtime refactor left `usageLimitPauser` undefined for
`TriageProcessor`. In the observed FN-922 incident, Claude Plan Review
returned four explicit 429 responses; Fusion backed off for roughly
60/120/240 seconds and then failed the task, but never invoked its pause
coordinator. The older coordinator also used `globalPause`, which would
terminate healthy sessions on every other provider.

After this change, active tasks using the unavailable provider are
parked while work routed exclusively through healthy providers
continues. Recovery is a provider-health state transition: the daemon
checks Claude/Codex authentication and metered capacity independently of
task execution, including after restart, and clears only exact
`provider-rate-limit:<provider>` parks. Logged-out, errored, exhausted,
manually paused, user-paused, and other-provider tasks remain parked.
Explicit global/engine pause controls remain unchanged.

## Surface enumeration

- executor usage-limit catches
- triage planner and Plan Review catches
- reviewer provider-error propagation
- merger usage-limit catches
- per-project runtime construction and wiring
- task model overrides plus project/global execution, planning,
validator, and merger resolution
- daemon startup/listen and shutdown lifecycle
- multi-project provider-probe deduplication
- Claude and Codex authenticated usage/capacity probes
- done/archived/already-paused task exclusions
- manual, user, generic, and other-provider pause provenance

## Symptom verification

**Original symptom:** Anthropic/Claude 429s retried and failed FN-922
without pausing Claude-routed work; a functioning global pauser would
also have stopped Codex, and provider parks had no positive-health
recovery path.

**Exact reproduction:** Raise `ReviewerProviderError("429
overloaded_error", "usage-limit", { provider: "anthropic" })` during
Plan Review with Anthropic and Codex tasks present, then return
logged-out/error/exhausted and finally healthy Claude usage responses
from the daemon probe.

**Assertion it is gone:** Anthropic-routed active tasks receive
`provider-rate-limit:anthropic`; Codex-only tasks are not paused and
`globalPause` is never changed. Unhealthy probes leave the Anthropic
tasks parked; a positive authenticated response with remaining capacity
resumes only exact Anthropic provider parks without executing a model
call as a probe.

## Validation

- `packages/engine/src/__tests__/usage-limit-detector.test.ts`: 49
passed
- `packages/dashboard/src/__tests__/provider-health-monitor.test.ts`: 8
passed
- Engine TypeScript check passed
- Dashboard server and app TypeScript checks passed
- Scoped ESLint passed
- Changeset strict format check passed
- Reapply script passed `bash -n`, two consecutive fixture applications,
and `node --check`


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

## Summary by CodeRabbit

- **New Features**
- Tasks paused due to a provider’s rate limits can now automatically
resume when capacity returns.
- Provider health is monitored in the background, including retry
backoff for unavailable providers.

- **Bug Fixes**
- Rate-limit issues now pause only affected provider-routed tasks
instead of stopping unrelated work.
- Provider failures are handled separately from invalid review results,
improving recovery behavior.
- Healthy providers remain available while another provider is
rate-limited.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: v <v@v.speedport.ip>
2026-07-21 17:08:44 -07:00
flexi767
8f7f52784d Fix merge blockers lost during concurrent rebuilds (#2346)
## What changed

- Preserve blocking merge-review reasons when `main` advances and the
clean-room squash must be rebuilt.
- Recover the latest unresolved blocking reason from task history when a
later merge retry starts.
- Require reviewers to validate prior blockers against the complete
resulting tree, not only a smaller residual diff.
- Add regression coverage for both concurrent-main rebuilds and durable
retry recovery.

## Why

A corrective clean-room squash can be approved and then discarded when
`main` advances before landing. The rebuild previously reset the
reviewer context, allowing a later, smaller squash to be approved and
the task to be finalized as Done without rechecking the original
correctness blocker.

## Impact

Tasks with unresolved blocking review findings can no longer become Done
merely because a concurrent rebuild or later retry loses that review
context.

## Validation

- `pnpm --filter @fusion/engine exec vitest run
src/__tests__/merger-ai.test.ts` — 45 passed
- `pnpm --filter @fusion/engine typecheck`
- ESLint on the changed merger source files
- Changeset format check


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

* **Bug Fixes**
* Merge and review blockers now remain active across rebuilds and retry
attempts.
* Previous blocking reasons are preserved alongside newly identified
issues.
* Empty corrective rebuilds are reviewed before being accepted as
complete.
* Tasks can no longer be finalized solely because a rebuilt diff is
smaller when unresolved blockers remain.

* **Documentation**
  * Updated release notes to describe the improved blocker behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: v <v@v.speedport.ip>
2026-07-21 17:08:17 -07:00
gsxdsm
de2cad7535 fix(workflows): reject missing plan review artifacts (#2390)
## Summary

Workflows could reach Plan Review without an authoritative PROMPT.md,
producing misleading approvals or stranding the task. Planning now
verifies durable prompt persistence before releasing the card, and every
workflow entry/review surface fails closed when its required plan is
absent. Confirmed absence triggers bounded automatic replanning;
TaskStore read outages retry in place; exhausted recovery parks visibly
without consuming review-fix budget or overriding pause, manual-review,
terminal, or merge-confirmed state.

Related: FN-8455

## Validation

- Focused workflow-artifact, graph-recovery, review, writer, and triage
regression suites pass.
- @fusion/engine typecheck passes.
- Repository lint, changeset validation, and diff checks pass.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Plan Review now fails closed when `PROMPT.md` is missing or blank,
returning a revision request with a typed `failureValue`.
* Required workflow artifacts are treated as missing unless they exist
with non-empty content; read failures are handled separately.
* Recovery now deterministically chooses replan vs “park-failed” with
bounded retries, and records a `task:required-artifact-missing` audit
event.

* **Workflow Improvements**
* Triage and approval now persist `PROMPT.md` through the dedicated
prompt-write flow and verify it was stored exactly.
* Optional-group remediation preserves typed required-artifact missing
failures for pre-merge fixes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 17:06:26 -07:00
flexi767
f49f5eb39a fix(dashboard): report Claude CLI login and API billing states (#2338)
## What changed

- Detect the Claude CLI `Not logged in · Run /login` screen and return
an actionable error immediately.
- Detect Claude 2.1.x `API Usage Billing` session-stat output, which has
no subscription quota windows, instead of waiting for the PTY timeout.
- Keep the existing quota-window parser unchanged for authenticated
subscription sessions.

## Root cause and impact

Fusion only recognized the older `/usage` quota view. Newer Claude CLI
builds can render a login prompt or API-billing session statistics after
accepting `/usage`; neither contains quota windows, so Fusion waited 60
seconds and reported a misleading timeout even though it had already
received conclusive output.

Operators now get an immediate instruction to run `claude /login` on the
Fusion host.

## Validation

- `vitest run src/__tests__/usage.test.ts`: 196 passed
- Dashboard TypeScript typecheck passed
- Changeset format check passed


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

* **Bug Fixes**
* Claude usage detection now recognizes authentication-required states
and stops immediately instead of waiting and reporting a misleading
“usage timeout.”
* Enhanced parsing/fallback behavior for Claude “usage” and
billing/session statistics screens, improving reliability when
subscription quota data isn’t available.
* **Tests**
* Added coverage for Claude CLI fallback scenarios after HTTP 429
responses, including validation of correct error messaging and process
termination behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: v <v@v.speedport.ip>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-07-21 16:54:28 -07:00
gsxdsm
eef5eb751e FN-8453: unify concurrency accounting and indicators
Unify live-agent capacity accounting across engine and dashboard.

- Derive Running and Waiting from workflow traits and durable agent liveness.
- Apply unified limits to planner, executor, and merge admission while updating dashboard indicators.
- Remove duplicate concurrency controls and document the unified operator model.

Files changed:
 .changeset/fn-8453-unified-concurrency.md          |   7 +
 docs/agent-tool-surface-full-loop.md               |   4 +-
 docs/architecture.md                               |   2 +-
 docs/dashboard-guide.md                            |   4 +-
 docs/settings-reference.md                         |   4 +-
 .../skill/fusion/references/fusion-capabilities.md |   4 +-
 .../core/src/__tests__/live-agent-count.test.ts    |  91 ++++----
 packages/core/src/index.gate.ts                    |   6 +
 packages/core/src/index.ts                         |   6 +
 packages/core/src/live-agent-count.ts              | 107 ++++++---
 packages/dashboard/app/App.tsx                     |  28 ++-
 packages/dashboard/app/api/board-workflows.ts      |   2 +
 packages/dashboard/app/components/Column.tsx       |   6 +-
 .../dashboard/app/components/EngineControlMenu.tsx |  26 ---
 .../dashboard/app/components/ExecutorStatusBar.tsx |  38 ++-
 .../dashboard/app/components/SettingsModal.tsx     |   1 -
 .../app/components/__tests__/Column.test.tsx       |   6 +-
 .../__tests__/EngineControlMenu.test.tsx           |  10 +-
 .../__tests__/ExecutorStatusBar.test.tsx           |  32 ++-
 .../command-center/CommandCenterControls.tsx       |  26 ---
 .../settings/sections/SchedulingSection.search.ts  |   9 -
 .../settings/sections/SchedulingSection.tsx        |  13 --
 .../app/hooks/__tests__/useExecutorStats.test.ts   |  12 +-
 packages/dashboard/app/hooks/useExecutorStats.ts   |  50 ++--
 .../src/__tests__/project-store-resolver.test.ts   |  11 +-
 packages/dashboard/src/project-store-resolver.ts   |  14 +-
 .../register-config-mcp-pi-settings-routes.ts      |   3 +-
 packages/engine/src/__tests__/concurrency.test.ts  | 123 +++++++++-
 .../engine/src/__tests__/project-engine.test.ts    |  34 +++
 packages/engine/src/__tests__/triage.test.ts       |   7 +-
 packages/engine/src/concurrency.ts                 | 207 ++++++++++++++++-
 packages/engine/src/project-engine.ts              | 151 ++++++++++--
 packages/engine/src/scheduler.ts                   |  82 ++++++-
 packages/engine/src/triage.ts                      | 254 +++++++++++++--------
 .../lib/dashboard-browser-safe-core-modules.json   |   5 +
 35 files changed, 991 insertions(+), 394 deletions(-)

Fusion-Task-Id: FN-8453

Fusion-Task-Lineage: 12cfa5df-675d-4fce-b17e-932376544239

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 15:30:31 -07:00
gsxdsm
0908e75290 FN-8455: add Calm dashboard color theme
Add a persisted Calm theme with slate, sage, and misty light palettes.

- Register Calm across core settings, dashboard selectors, and web/desktop first-paint validators.
- Define Calm theme tokens and selector swatches for dark and light modes.
- Cover persisted selection, previews, and bootstrap validation with tests.
- Document the new theme and add a minor release changeset.

Files changed:
 .changeset/fn-8455-calm-theme.md                   |  7 ++
 docs/dashboard-guide.md                            |  3 +-
 docs/settings-reference.md                         |  2 +-
 packages/core/src/__tests__/global-settings.test.ts|  8 ++
 packages/core/src/types/execution-and-ui.ts        |  2 +
 packages/dashboard/app/__tests__/calm-theme.test.ts| 98 ++++++++++++++++++++++
 packages/dashboard/app/components/ThemeSelector.css| 14 ++++
 packages/dashboard/app/components/__tests__/ThemeDropdown.test.tsx | 22 ++---
 packages/dashboard/app/components/__tests__/ThemeSelector.test.tsx | 2 +-
 packages/dashboard/app/components/command-center/__tests__/CommandCenterControls.test.tsx | 2 +-
 packages/dashboard/app/components/themeOptions.ts  |  1 +
 packages/dashboard/app/hooks/__tests__/useTheme.test.ts | 12 +++
 packages/dashboard/app/index.html                  |  2 +-
 packages/dashboard/app/public/theme-data.css       | 86 ++++++++++++++++++-
 packages/desktop/src/renderer/index.html           |  1 +
 15 files changed, 245 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-8455

Fusion-Task-Lineage: c2c4624e-7012-491d-bd79-d3de570018f7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 15:04:07 -07:00
gsxdsm
dc834e582e fix(workflows): address lifecycle review follow-ups (#2380)
## Summary

- preserve workflow IR hashes in production column-transition audit
metadata
- centralize active workflow-continuation states across release,
runtime, and executor paths
- extract and test actionable planning-continuation selection
- expand Coding (Ideas) remapping/removal coverage and add required
lifecycle decision records

Follow-up to the review body on #2378 after that PR was merged.

## Validation

- `pnpm lint`
- 123 focused core/engine tests
- `pnpm verify:fast`
- `pnpm test:gate` (487 tests)


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

- **Bug Fixes**
- Improved workflow continuation handling by centralizing
“active/continuation-eligible” state selection across executor,
hold/release logic, and in-process runtime.
- Persisted richer task column-transition metadata (including `irHash`)
to preserve workflow provenance.
- Ensured planning continuations exclude paused/missing/invalid tasks
and that task resolution failures surface instead of being ignored.
- Corrected fresh-worktree step execution ordering to return expected
`baselineSha`/`checkpointId` behavior.

- **New Features**
- Added and exposed `ACTIVE_WORKFLOW_WORK_ITEM_STATES` for consistent
work-item “active” semantics.
- Introduced a shared planning-continuation candidate selector to
standardize dispatchable planning work filtering.

- **Documentation**
- Clarified the small coding-ideas workflow preset omits verification
while preserving a continuous executable path.

- **Tests**
- Added coverage for planning continuation filtering and fresh-worktree
ordering behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 13:36:05 -07:00
gsxdsm
527f734ad4 FN-8454: add Aurora dashboard theme
Add the Aurora color theme across dashboard and desktop theme surfaces.

- Register Aurora as a selectable global theme with matching UI styles and metadata
- Load Aurora theme data in dashboard and desktop entry points
- Document the theme and cover selection, token, and settings behavior

Files changed:
 .changeset/fn-8454-aurora-theme.md                 |  7 ++
 docs/dashboard-guide.md                            |  3 +-
 docs/settings-reference.md                         |  2 +-
 .../core/src/__tests__/global-settings.test.ts     |  8 ++
 packages/core/src/types/execution-and-ui.ts        |  2 +
 .../dashboard/app/__tests__/aurora-theme.test.ts   | 98 ++++++++++++++++++++++
 .../dashboard/app/components/ThemeSelector.css     | 14 ++++
 .../components/__tests__/ThemeDropdown.test.tsx    | 51 ++++++++++-
 .../components/__tests__/ThemeSelector.test.tsx    |  2 +-
 .../__tests__/CommandCenterControls.test.tsx       |  2 +-
 packages/dashboard/app/components/themeOptions.ts  |  1 +
 .../dashboard/app/hooks/__tests__/useTheme.test.ts | 12 +++
 packages/dashboard/app/index.html                  |  2 +-
 packages/dashboard/app/public/theme-data.css       | 91 ++++++++++++++++++++
 packages/desktop/src/renderer/index.html           |  1 +
 15 files changed, 290 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8454

Fusion-Task-Lineage: cbae0854-b884-4744-a2fa-f738a71ceb32

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 13:28:24 -07:00
gsxdsm
3b9d508def fix(planning): use back-only session navigation 2026-07-21 13:02:48 -07:00
gsxdsm
83209e64dc fix(workflows): align stages with board columns (#2378)
## Summary

The Coding (Ideas) workflow now behaves like the board it presents:
Ideas stays inert, Todo owns planning and plan review, In progress owns
implementation, and In review owns code review and merge. The restored
preset is intentionally limited to that five-stage path, while the
existing Coding workflow remains unchanged.

Workflow execution now suspends at Todo→In progress instead of running
the implementation node early. A durable, single-owner continuation
records the exact resume node and survives process restarts; the
scheduler remains the only component allowed to admit the task into WIP.
Disabled optional review groups traverse the same boundary without
invoking a reviewer, avoiding the prior stuck-task behavior.

Workflow validation also rejects capacity holds with no reachable WIP
destination, so deterministic lifecycle deadlocks fail at authoring time
rather than after a task is running.

Session-settled decisions carried from planning: columns are execution
invariants, scheduler-owned WIP admission is preserved, the existing
Coding (Ideas) preset is restored and simplified, and invalid release
topology is rejected (user-approved).

## Validation

- `pnpm lint`
- `pnpm verify:fast`
- `pnpm test:gate` (296 engine, 128 PostgreSQL core, and 63 CI-shape
tests)
- Focused workflow lifecycle tests (106 assertions)
- PostgreSQL regression coverage proves atomic continuation replacement
and database rejection of a second active owner


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

* **New Features**
* Added durable, resumable workflow execution across capacity boundaries
(including explicit suspend/resume at the correct node).
* Introduced Todo “plan review” workflow continuations and automated
planning/capacity draining.
* Restored Coding (Ideas) as a selectable built-in and updated its lane
placement; improved optional-step group enablement support.
* **Bug Fixes**
  * User moves back to Todo now cancels active workflow continuations.
* Rejected workflow boundary transitions now surface as errors (instead
of silently continuing).
* Workflows with undriveable capacity-hold configurations are now
rejected.
* **Tests / Data**
* Expanded coverage for workflow suspension, continuations, and
continuation replacement; updated database schema to persist
continuation metadata and enforce single active continuation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 12:17:47 -07:00
gsxdsm
38455359f2 fix(planning): retry interrupted sessions on return
Recover persisted, SSE, and polled stream failures through the existing bounded retry path while preventing stale sessions from taking ownership.
2026-07-21 10:44:51 -07:00
gsxdsm
76cecacddd FN-8451: prevent embedded Postgres double starts
Prevent TaskStore boot collisions when an existing PostgreSQL pid file cannot yet be parsed.

- Read live postmaster pid files asynchronously with bounded retries.
- Fail closed when a present pid file has no readable port.
- Cover join, unreadable pid, and fresh-start lifecycle paths.

Files changed:
 packages/core/src/__tests__/postgres/embedded-lifecycle.test.ts | 119 +++++++++++++++++++++
 packages/core/src/postgres/embedded-lifecycle.ts                |  49 ++++++---
 2 files changed, 155 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-8451

Fusion-Task-Lineage: 823a874d-97ef-4380-97ce-e41981f660ff

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 10:33:28 -07:00
gsxdsm
5f0502e166 FN-8452: reject invalid update flags and announce beta releases
Make update commands fail clearly on invalid arguments while helping stable users discover newer beta releases.

- Parse update and upgrade options strictly, rejecting unknown, duplicate, and malformed flags before running an update
- Show a live-registry beta availability notice for stable human-readable output without affecting JSON or cached results
- Add CLI coverage, beta bootstrap documentation, and a patch changeset

Files changed:
 .changeset/fn-8452-update-unknown-flags.md         |   7 +
 RELEASING.md                                       |   2 +-
 docs/cli-reference.md                              |   4 +
 docs/getting-started.md                            |   2 +
 packages/cli/src/__tests__/bin-update-args.test.ts |  75 ++++++++++
 packages/cli/src/bin.ts                            |  25 +---
 packages/cli/src/commands/__tests__/update.test.ts |  44 ++++++
 packages/cli/src/commands/update.ts                | 162 +++++++++++++++++++--
 8 files changed, 285 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-8452

Fusion-Task-Lineage: b29a1ce5-5a40-40ec-ac18-07107fa18344

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 10:30:19 -07:00
gsxdsm
634295c72f fix(planning): keep questions out of mailbox
Keep planning questions in their dedicated surface while preserving ntfy alerts, and tighten the desktop planning panes without changing compact or shared layouts.
2026-07-21 10:04:19 -07:00
gsxdsm
11c4def87f chore(release): v0.73.0-beta.0
Version bump via changesets.
2026-07-21 01:00:46 -07:00
gsxdsm
e81e3bd687 fix(planning): make refinement actions reliable
Preserve stopped plans as reviewable sessions, replace active generations safely, and submit mobile refinement on the initiating touch.
2026-07-21 00:55:33 -07:00
gsxdsm
36583bc1c7 fix(planning): resume initial generation after stop
Reset the initial-generation guard, ignore stale stream callbacks, and preserve session-specific elapsed time across refreshes.
2026-07-21 00:45:34 -07:00
gsxdsm
b1fa2c77d8 fix(dashboard): show Codex weekly usage 2026-07-21 00:33:57 -07:00
gsxdsm
3c22c133e7 fix(planning): restore stopped generation state
Track elapsed generation time per planning session and return users to the prior editable step when generation is stopped.
2026-07-21 00:32:27 -07:00
gsxdsm
1249086b32 fix(planning): preserve mobile touch actions 2026-07-21 00:15:55 -07:00
gsxdsm
68a7f3f0e8 fix(planning): start and create tasks directly 2026-07-21 00:05:11 -07:00
Drew Donaldson
e74183359a fix(postgres): sanitize NUL bytes in chat/mailbox writes; retry embedded-PG join race (#2366)
## Summary

Chat messages, chat room messages, and agent/user mailbox sends could
crash mid-conversation when the persisted content or metadata contained
a raw U+0000 (NUL) byte — e.g. Windows CLI diagnostic/tool output piped
directly into a message body. PostgreSQL text/jsonb columns reject NUL
outright (`unsupported Unicode escape sequence` / `\u0000 cannot be
converted to text`), which surfaced as an uncaught `PostgresError` that
aborted the write and killed the conversation turn.

A NUL-byte sanitizer already existed for the one-time SQLite →
PostgreSQL first-boot migration (`sqlite-migrator.ts`'s
`stripNulChars`/`deepStripNulChars`), but it was never wired into the
**live** write paths — only into that one-shot migration.

## What changed

- Extracted `stripNulChars`/`deepStripNulChars` into a shared
`packages/core/src/postgres/nul-sanitize.ts` module
(`sqlite-migrator.ts` now imports from it instead of defining its own
copy).
- Wired sanitization into the three live write paths that persist
free-form content/metadata:
  - `async-chat-store.ts`: `addChatMessage`, `addChatRoomMessage`
  - `async-message-store.ts`: `sendMessage`
- Each of these functions now also **returns the sanitized value** —
previously they returned the original, unsanitized input object even
though the sanitized value is what was actually persisted to the
database, which was a latent inconsistency I found while adding test
coverage.

## Bonus fix: embedded-Postgres startup race

While rebuilding and testing this locally via `pnpm smoke:boot`, I hit a
separate, pre-existing, reproducible race: a process joining an existing
embedded-Postgres data dir (via `postmaster.pid`, per the existing
`FNXC:PostgresStartupRace 2026-07-15-20:45` comment in
`embedded-lifecycle.ts`) can race the true owner's TCP listener bind and
get `ECONNREFUSED` on its very first connection attempt.
`bootSchemaBackendOnce` turned this into a hard `startup-factory: failed
to initialize PostgreSQL schema backend` failure with no retry.

I verified this is **not** caused by my NUL-sanitize change — it
reproduces identically on unmodified `main` (confirmed via `git stash`).

Added `JoinedInstanceUnreachableError` and one retry (mirroring the
existing `NonUtf8EmbeddedClusterError` one-retry pattern already in the
same file) instead of failing the whole boot outright.

## Tests

- New unit tests for the shared sanitizer:
`packages/core/src/__tests__/nul-sanitize.test.ts` (10 tests, including
a regression test reproducing the exact production failure signature).
- New PostgreSQL integration test coverage in the existing `.pg.test.ts`
suites, reproducing the exact production failure payload for both
`addChatMessage` and `sendMessage` and asserting both the in-memory
return value and the re-read-from-database value are NUL-free.
- Verified end-to-end against a real, disposable PostgreSQL 16 instance
(outside the vitest harness, since this dev machine lacked a local
`psql`/`pg_dump` client at the time) using a standalone script that
calls the actual patched functions with the production crash payload —
all checks passed before and after the return-value fix was added.
- `pnpm --filter @fusion/core typecheck` clean.

## Changeset

Included (`patch`, category `fix`).


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

* **Bug Fixes**
* Prevented crashes and PostgreSQL insertion failures when chat or
mailbox content/JSON metadata contains raw NUL (`U+0000`) bytes.
* NUL characters are now stripped from message text and deeply from
nested metadata (including JSON object keys) before writes, and
sanitized values are reflected in returned messages.
* Improved embedded PostgreSQL startup reliability by retrying once on
transient joined-instance connection-refused failures.
* **Tests**
* Added unit and PostgreSQL regression coverage for NUL sanitization
across message/chat paths and for the embedded startup retry scenario.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 00:00:08 -07:00
gsxdsm
7b444edc86 fix(planning): complete task creation handoff
Treat active creation claims as transient coordination, keep the created-task handoff visible, and provide direct task and session navigation across desktop and mobile.
2026-07-20 23:35:32 -07:00
gsxdsm
6d6bfdf6c1 FN-8449: collapse planning history AI thinking by default
Keep Planning Mode history focused on questions and answers until operators explicitly expand AI thinking.

- Render planning history without forcing AI thinking open
- Verify thinking starts collapsed and expands through its existing toggle
- Add a patch changeset for the operator-facing fix

Files changed:
 .changeset/fn-8449-planning-history-thinking.md                |  7 +++++++
 packages/dashboard/app/components/PlanningModeModal.tsx        |  3 ++-
 .../__tests__/PlanningModeModal.planning-flow.test.tsx         | 10 ++++++++--
 3 files changed, 17 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-8449

Fusion-Task-Lineage: e318eb85-561b-4d02-8fe8-1b82dcd87cc1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-20 23:33:59 -07:00
gsxdsm
048a2cdd33 FN-8448: fix Back navigation from import detail
Ensure browser Back returns GitHub imports from issue detail to the issue list.

- Preserve navigation history position when More transitions to Import.
- Cover nested detail Back behavior in modal and embedded Import Tasks surfaces.
- Add a patch changeset for the navigation fix.

Files changed:
 .../fn-8448-github-import-back-to-issue-list.md    |  7 +++
 packages/dashboard/app/components/MobileNavBar.tsx | 17 ++++++--
 .../__tests__/GitHubImportModal.test.tsx           | 50 ++++++++++++++++++++++
 .../__tests__/MobileNavBar.swipe-back.test.tsx     | 18 +++++++-
 .../dashboard/app/hooks/useNavigationHistory.ts    | 27 +++++++++---
 5 files changed, 108 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-8448

Fusion-Task-Lineage: ffea2740-861f-464b-839e-030aef06fd34

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-20 23:28:49 -07:00
gsxdsm
d83fae3fea fix(FN-8446): keep Copilot banner dismissed
Preserve the browser dismissal across successful Copilot login events while retaining re-arm behavior for other OAuth providers.
2026-07-20 22:58:22 -07:00
gsxdsm
1861a33534 fix(planning): stabilize refinement and restored sessions
Make refinement freeform-only, tighten responsive Planning controls, and keep restored idle sessions synchronized without reconnecting the stream that caused reopen errors.
2026-07-20 21:57:00 -07:00
gsxdsm
f221d2bc4d fix(planning): complete interactive planning workspace
Keep plan and questions usable across desktop and mobile, add answer and reasoning history, and create tasks directly from validated plans.
2026-07-20 21:20:10 -07:00
gsxdsm
34074e9d04 fix(planning): keep plan visible through sequential questions
Regenerate the Markdown plan after every answer while preserving the
responsive plan-and-question workspace and focused refinement flow.
2026-07-20 20:20:55 -07:00
gsxdsm
f4c24edeba fix(core): allow dependency-ready steps to finalize
Honor explicit workflow dependencies across completion writers, keep the progress cursor aligned with unfinished work, and fail closed when dependency metadata is malformed.
2026-07-20 20:17:27 -07:00
gsxdsm
beae2c673e fix(planning): make refinement session-driven
Open refinement areas on demand with multi-select and custom focus support, then consume synchronous AI responses so restored sessions can continue reliably. Rename the primary review action to Proceed with plan and preserve the responsive Markdown review layout.
2026-07-20 18:40:03 -07:00
gsxdsm
7fe12ae124 test(core): share one golden pg schema template across the gate
The pg-gate rebuilt a full schema baseline (~530ms of DDL) per isolated test
file. Fanned across forks against one Postgres, those baselines and their
CREATE DATABASE calls serialized and pushed per-file beforeAll past the 15s
hookTimeout nondeterministically on high-core machines. Complements the
committed fork cap: apply the baseline ONCE per run into a run-shared,
advisory-lock-coordinated golden template, then copy each test DB directly
from it (concurrent, connection-free copies are safe). Per-module templates
and their lifecycle hooks are retained for the concurrency regression test.
No timeout was changed. pg-gate: ~46s tests / ~17s wall, 6/6 clean runs
(was flaky/364s).

Fusion-Task-Id: automation-slow-test
2026-07-20 18:26:01 -07:00
gsxdsm
caf425eaea test(core): cap pg-gate fork fan-out for DB-bound suite
The test:pg-gate suite runs only *.pg.test.ts files, each building/copying a
per-file schema-template database (heavy CREATE/DROP DATABASE DDL serialized by
the single shared Postgres). Worker count derived from CPU cores over-scales on
high-core machines (6 forks on a 28-core box), oversubscribing the one Postgres
until every beforeAll exceeds the 15s hookTimeout (23/23 hook timeouts). CI's
low-core runners stay near 2 forks and pass, so it only bites high-core locals.

Add a maxCap clamp to computeMaxWorkers and a dedicated vitest.pg.config.ts
(maxCap=4) for the pg-gate, right-sizing concurrency to the actual constraint (a
single shared Postgres) rather than raising the timeout (forbidden appeasement).
Low-core machines keep their smaller CPU-derived count via min(4, cpuCap).

Verified: full test:pg-gate now passes 23 files / 126 tests on a 28-core host.
2026-07-20 18:16:58 -07:00
gsxdsm
2884bf76b1 fix(planning): wait for AI plan before review
Keep seeded fallback summaries out of SSE catch-up while generation is active so Refine and Validate cannot race the initial AI turn.
2026-07-20 18:12:25 -07:00
gsxdsm
0a01cb164d fix(planning): polish markdown plan review
Render the canonical plan as sanitized Markdown and keep responsive review actions reachable outside the scroll owner. Require Markdown-oriented planning output and preserve stable plan.md list round-trips.
2026-07-20 17:35:06 -07:00
gsxdsm
d008d66e01 fix(planning): show all refinement categories
Preserve every valid suggested refinement through prompt generation, server normalization, and desktop/mobile rendering instead of truncating the list to three.
2026-07-20 16:39:07 -07:00
gsxdsm
ba08d90574 fix(core): allow scoped migration health reads
Grant the restricted runtime role read-only access to its own SQLite cutover marker. Repair existing databases with migration 0030 and apply the same row-scoped policy when first-boot migration creates the ledger.
2026-07-20 16:10:46 -07:00
gsxdsm
9ad97317cb fix(FN-1320): block incomplete plans before execution
Require executable steps before recovering stuck planning tasks or advancing the built-in coding workflow. Preserve explicitly authorized no-commit tasks and custom zero-step workflow behavior.
2026-07-20 16:08:00 -07:00
gsxdsm
606c320c52 fix(FN-8442): make planning generation durable and detailed
Generate a reviewable initial plan before clarification, persist generation purpose across refreshes, and surface concrete changes and acceptance criteria with focused refinement choices.
2026-07-20 16:00:11 -07:00
gsxdsm
5dd62fe548 FN-8446: preserve dismissed OAuth re-login banners
Keep OAuth re-login dismissals sticky until the matching provider successfully authenticates.

- Preserve dismissed provider IDs across transient healthy auth-status responses.
- Re-arm only the provider identified by an OAuth re-login success event.
- Add Copilot and multi-provider regression coverage plus operator documentation.
- Add a patch changeset for the banner behavior fix.

Files changed:
 .changeset/fn-8446-oauth-relogin-dismiss-sticky.md |   7 ++
 docs/dashboard-guide.md                            |   2 +
 .../app/components/OAuthReloginBanner.tsx          |  30 +++---
 .../__tests__/OAuthReloginBanner.test.tsx          | 113 +++++++++++++++++++--
 4 files changed, 128 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-8446

Fusion-Task-Lineage: 30574bbc-3efb-4f72-956b-b249d24251c9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-20 15:41:41 -07:00
gsxdsm
4c0dfbcfd6 fix(engine): preserve workflow completion summaries
Keep approved-contract retry instructions scoped to review nodes so advisory and completion-summary agents can produce their intended output.
2026-07-20 15:26:23 -07:00
gsxdsm
36b3180962 FN-8442: redesign planning mode as sequential Q&A
Guide planning through sequential question-and-answer turns before task creation.

- Add plan review, refinement, validation, creation retry, and idempotent task handoff states
- Atomically claim planning-session task creation and reconcile persisted task links
- Replace retired multi-pane planning UI and consolidate focused flow coverage
- Document the sequential planning workflow and mobile behavior

Files changed:
 .changeset/fn-8442-planning-sequential-qa.md       |    7 +
 MOBILE.md                                          |    2 +-
 docs/dashboard-guide.md                            |    9 +-
 packages/core/src/async-ai-session-store.ts        |   82 +-
 packages/core/src/index.ts                         |    4 +
 packages/core/src/types.ts                         |    5 +
 packages/dashboard/app/api/legacy.ts               |    4 +-
 .../dashboard/app/components/PlanningModeModal.css |  178 +-
 .../dashboard/app/components/PlanningModeModal.tsx |  317 +-
 .../__tests__/PlanningModeModal.initial.test.tsx   |  993 +----
 .../PlanningModeModal.planning-flow.test.tsx       | 4377 +-------------------
 .../PlanningModeModal.ui-interactions.test.tsx     | 1276 +-----
 .../__tests__/planning-e2e-plan-creation.test.ts   |   25 +-
 .../dashboard/src/__tests__/planning-infinite-interview.test.ts  |   44 +-
 .../src/__tests__/routes-planning.test.ts          |  119 +-
 packages/dashboard/src/ai-session-store.ts         |   33 +
 packages/dashboard/src/planning.ts                 |  140 +-
 .../src/routes/register-planning-subtask-routes.ts |  132 +-
 18 files changed, 649 insertions(+), 7098 deletions(-)

Fusion-Task-Id: FN-8442

Fusion-Task-Lineage: da2f335f-b1c9-411a-8575-31db20a2b8d5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-20 14:59:22 -07:00
gsxdsm
22db40cba5 FN-8445: pin compact planning switcher above history
Keep compact Planning Mode interview tabs above the answered-question history across responsive layouts.

- Pin the shared compact pane switcher ahead of history in short-shell and tablet flex layouts.
- Cover the visual-order contract and mounted controls across tablet, mobile, and short-landscape panes.
- Add a patch changeset for the Planning Mode fix.

Files changed:
 .changeset/fn-8445-planning-compact-switcher-top.md |  7 +++++++
 .../dashboard/app/components/PlanningModeModal.css  | 19 +++++++++++++++++++
 .../__tests__/PlanningModeModal.css.test.ts         |  9 ++++++++-
 .../PlanningModeModal.planning-flow.test.tsx        | 21 ++++++++++++++-------
 4 files changed, 48 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-8445

Fusion-Task-Lineage: 7aa99bc7-1ad6-46ff-8ff9-4628ccefd705

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-20 14:09:26 -07:00