7024 Commits

Author SHA1 Message Date
gsxdsm
a014c6d42d FN-5697: retry transient auto-merge failures and fix migration versioning
Treat transient auto-merge/provider abort errors as bounded retries while preserving correct schema migration ordering.

- Add transient merge retry handling with capped exponential backoff, queue re-enqueue, and exhaustion logging before failing tasks.
- Extend task/core types and evaluator evidence plumbing for merge transient retry tracking and MergeTransientRetryExhausted visibility.
- Add regression coverage for transient auto-merge retries and exhaustion behavior in merge error recovery tests.
- Resolve migration collision by promoting workflow_steps.gateMode migration to version 77, shifting subsequent migrations, and bumping schema version to 95.
- Add a changeset and architecture note documenting transient retry behavior.

Files changed:
 .changeset/fn-5697-auto-merge-transient-retry.md   |  5 ++
 docs/architecture.md                               |  1 +
 packages/core/src/db.ts                            | 85 +++++++++++----------
 packages/core/src/eval-types.ts                    |  1 +
 packages/core/src/store.ts                         | 19 +++--
 packages/core/src/types.ts                         |  7 ++
 packages/engine/src/__tests__/evaluator-evidence.test.ts       |  1 +
 packages/engine/src/__tests__/merge-error-recovery.test.ts     | 87 ++++++++++++++++++++++
 packages/engine/src/evaluator-evidence.ts          |  1 +
 packages/engine/src/project-engine.ts              | 68 +++++++++++++++++
 10 files changed, 231 insertions(+), 44 deletions(-)

Fusion-Task-Id: FN-5697

Fusion-Task-Lineage: c8be7374-7cb6-444e-9920-9227e05a43dc
2026-05-29 10:23:59 -07:00
gsxdsm
dbb0804490 FN-5666: exclude base commit from done-task diff ranges
Prevent done-task diff endpoints from counting base-commit-only lineage as task-owned changes.

- add base-boundary handling in done-task merge SHA resolution so `baseCommitSha` is excluded by default and only consulted for boundary checks
- short-circuit `/diff` and `/file-diffs` responses to empty results when resolved done-task SHA is at or below `baseCommitSha`
- export and use an ancestry helper to detect base-boundary cases, while preserving normal and rebase range behavior
- extend done-task diff route tests with FN-5666 cases for no-op merge SHA, lineage association at base commit, normal post-base commits, and rebase ranges
- add a patch changeset for `@runfusion/fusion`

Files changed:
 .changeset/fn-5666-base-commit-exclusive.md        |   5 +
 .../src/__tests__/routes-diff-done-tasks.test.ts   | 217 ++++++++++++++++++++-
 .../src/routes/register-session-diff-routes.ts     |  57 +++++-
 3 files changed, 273 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-5666
Fusion-Task-Lineage: 782f9875-856a-4d31-9505-0bcd638c9c29
2026-05-29 10:14:06 -07:00
gsxdsm
32c877a16a FN-5682: render mission markdown across manager views
Render mission, milestone, slice, and feature text as Markdown in MissionManager.

- add a shared markdown renderer using react-markdown with GFM support
- render mission descriptions, milestone acceptance criteria, slice verification, and feature description/acceptance fields as markdown
- render feature-derived completion criteria and mission list descriptions as markdown
- add MissionManager markdown styling and update mission docs/tests for markdown behavior

Files changed:
 docs/missions.md                                   |  2 +
 .../dashboard/app/components/MissionManager.css    | 45 ++++++++++++
 .../dashboard/app/components/MissionManager.tsx    | 46 ++++++++----
 .../components/__tests__/MissionManager.test.tsx   | 85 ++++++++++++++++++----
 4 files changed, 146 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-5682

Fusion-Task-Lineage: 521193fb-7150-44ab-981f-045c094f32df
2026-05-29 10:11:49 -07:00
gsxdsm
86c98d3593 FN-5680: migrate model selector favorites to shared hooks
Move ModelSelectorTab to shared favorites/model-cache state while keeping selector behavior aligned with shared data flow.

- replace local model/favorites fetching and persistence in ModelSelectorTab with useFavorites and useModelsCache
- delegate provider/model favorite toggles to shared hook handlers and keep existing toast error handling
- update ModelSelectorTab tests to cover shared favorites rendering, shared global-settings toggle calls, and fetch-failure empty-state behavior

Files changed:
 .../dashboard/app/components/ModelSelectorTab.tsx  | 88 ++++------------------
 .../components/__tests__/ModelSelectorTab.test.tsx | 55 ++++++++++++--
 2 files changed, 65 insertions(+), 78 deletions(-)

Fusion-Task-Id: FN-5680

Fusion-Task-Lineage: 8df227ce-3dfd-4c60-9212-d0d5078edfc4
2026-05-29 10:02:58 -07:00
gsxdsm
a312da63e4 FN-5674: add per-task auto-merge persistence and resolver
Add per-task auto-merge overrides to the core task model and persist/snapshot them through review transitions.

- add Task.autoMerge typing, storage row mapping, updateTask support, and DB schema migration to persist per-task auto-merge state
- snapshot settings.autoMerge onto tasks when moving into in-review when no explicit task override is set
- export resolveEffectiveAutoMerge to consistently resolve task-level override vs global settings precedence
- expand core tests for migration, persistence, movement, and merge behavior; update roadmap schema-version expectation to match the new schema version

Files changed:
 packages/core/src/__tests__/db-migrate.test.ts     | 10 +++----
 packages/core/src/__tests__/db.test.ts             | 34 +++++++++++-----------
 packages/core/src/__tests__/goals-schema.test.ts   |  2 +-
 packages/core/src/__tests__/insight-store.test.ts  | 10 +++----
 packages/core/src/__tests__/mission-store.test.ts  |  2 +-
 packages/core/src/__tests__/run-audit.test.ts      |  2 +-
 packages/core/src/__tests__/secrets-schema.test.ts |  6 ++--
 .../core/src/__tests__/store-merge-queue.test.ts   |  2 +-
 packages/core/src/__tests__/store-movement.test.ts | 33 +++++++++++++++++++++
 .../core/src/__tests__/store-persistence.test.ts   | 18 ++++++++++++
 packages/core/src/__tests__/task-documents.test.ts |  2 +-
 packages/core/src/__tests__/task-merge.test.ts     | 19 ++++++++++++
 packages/core/src/db.ts                            |  9 +++++-
 packages/core/src/index.ts                         |  1 +
 packages/core/src/store.ts                         | 23 +++++++++++++--
 packages/core/src/task-merge.ts                    | 15 +++++++++-
 packages/core/src/types.ts                         |  7 +++++
 .../src/store/__tests__/roadmap-store.test.ts      |  4 +--
 18 files changed, 157 insertions(+), 42 deletions(-)

Fusion-Task-Id: FN-5674

Fusion-Task-Lineage: 8e1e3988-2e41-4d7a-9653-e88c36ec272c
2026-05-29 09:56:28 -07:00
gsxdsm
4fee2c1324 FN-5671: add branch-strategy selection to new task creation
Add branch-strategy based task branch handling from modal through task creation routes.

- add branch strategy dropdown + validation in New Task modal and TaskForm, including required branch-name handling for existing/custom-new modes
- send structured branchSelection payload from dashboard API client and cover UI/API behavior with new tests
- add server-side branch selection mode parsing, auto-new branch derivation (fusion/<task-id>-<slug>), and response updates when auto branch is generated
- update engine/worktree and dashboard route tests plus dashboard guide documentation
- add a changeset for @runfusion/fusion patch release

Files changed:
 .changeset/fn-5671-branch-strategy-dropdown.md     |  7 ++
 docs/dashboard-guide.md                            | 16 +++++
 packages/dashboard/app/__tests__/api-tasks.test.ts | 21 ++++++
 packages/dashboard/app/api/legacy.ts               |  9 +++
 packages/dashboard/app/components/NewTaskModal.css |  8 +++
 packages/dashboard/app/components/NewTaskModal.tsx | 41 +++++++++---
 packages/dashboard/app/components/TaskForm.tsx     | 30 ++++++++-
 .../app/components/__tests__/NewTaskModal.test.tsx | 77 +++++++++++++++++++---
 .../src/__tests__/branch-selection.test.ts         | 13 ++++
 .../dashboard/src/__tests__/routes-tasks.test.ts   | 72 ++++++++++++++++++++
 packages/dashboard/src/routes/branch-selection.ts  | 45 ++++++++-----
 .../src/routes/register-task-workflow-routes.ts    | 22 +++++--
 .../engine/src/__tests__/worktree-pool.test.ts     | 41 ++++++++++++
 packages/engine/src/worktree-pool.ts               |  2 +-
 14 files changed, 361 insertions(+), 43 deletions(-)

Fusion-Task-Id: FN-5671
Fusion-Task-Lineage: 7f2e7b68-050d-4a2c-af0b-cb895de35576
2026-05-29 09:44:17 -07:00
gsxdsm
16d20063bf FN-5673: keep mobile nav and footer pinned when keyboard opens
Prevent keyboard viewport shifts from displacing mobile bottom bars while preserving iOS hide safeguards.

- Split executor footer keyboard behavior into separate hide and pinning controls
- Add keyboard-open CSS overrides to keep mobile nav/footer bottom at 0 instead of offsetting upward
- Wire App to pass distinct keyboard props and expand component/CSS contract tests for keyboard-open classes and rule ordering

Files changed:
 packages/dashboard/app/App.tsx                     |  3 ++-
 packages/dashboard/app/__tests__/mobile-bottom-bars-keyboard-layout.test.ts | 30 ++++++++++++++++++++++
 packages/dashboard/app/components/ExecutorStatusBar.css |  6 +++++
 packages/dashboard/app/components/ExecutorStatusBar.tsx | 14 +++++-----
 packages/dashboard/app/components/MobileNavBar.css |  3 ++-
 packages/dashboard/app/components/__tests__/ExecutorStatusBar.test.tsx | 17 ++++++++++++
 packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx |  6 +++--
 7 files changed, 69 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-5673

Fusion-Task-Lineage: 7c2dc749-214a-48ab-af58-5638ea27ae47
2026-05-29 09:32:22 -07:00
gsxdsm
ab16307750 FN-5669: unify agent model favorites with shared selector state
Use the shared favorites hook so agent model pickers stay in sync with project favorites.

- Switch AgentDetailView config tab model favorites to use useFavorites instead of local settings update logic.
- Switch NewAgentDialog model favorites to the same shared favorites flow and remove duplicated toggle handlers.
- Extend AgentDetailView/NewAgentDialog tests and dropdown test helpers to exercise provider/model favorite toggles through the shared global settings path.

Files changed:
 .../dashboard/app/components/AgentDetailView.tsx   | 44 +++------------------
 .../dashboard/app/components/NewAgentDialog.tsx    | 45 +++-------------------
 .../AgentDetailView.advanced-settings.test.tsx     | 41 ++++++++++++++++++++
 .../__tests__/AgentDetailView.test-helpers.ts      | 25 +++++++++++-
 .../components/__tests__/NewAgentDialog.test.tsx   | 36 +++++++++++++++++
 5 files changed, 111 insertions(+), 80 deletions(-)

Fusion-Task-Id: FN-5669

Fusion-Task-Lineage: 8ace8ea1-1c88-409c-a9ae-6b5deb391f46
2026-05-29 08:45:12 -07:00
gsxdsm
71e2aec5b7 FN-5663: add goal-citation audit trail to agent reasoning
Record goal citation evidence so agent reasoning can be traced end-to-end.

- add core goal citation types, extraction helper, persistence schema, and store APIs for citation create/list workflows
- add CLI support and tests for goal citation flows, including command wiring and regression coverage
- update docs and add a published changeset for @runfusion/fusion describing the new audit-trail capability

Files changed:
 .changeset/fn-5663-goal-citation-audit-trail.md    |  10 +
 docs/agents.md                                     |  15 ++
 docs/cli-reference.md                              |   6 +-
 packages/cli/src/__tests__/bin.test.ts             |   2 +
 .../cli/src/__tests__/goals-citations-cli.test.ts  |  82 ++++++++
 packages/cli/src/bin.ts                            |  19 +-
 packages/cli/src/commands/goals.ts                 |  43 +++++
 packages/core/src/__tests__/db-migrate.test.ts     |  10 +-
 packages/core/src/__tests__/db.test.ts             |  34 ++--
 .../src/__tests__/goal-citation-extractor.test.ts  |  56 ++++++
 .../src/__tests__/goal-citations-store.test.ts     | 175 +++++++++++++++++
 packages/core/src/__tests__/goals-schema.test.ts   |   2 +-
 packages/core/src/__tests__/insight-store.test.ts  |  10 +-
 packages/core/src/__tests__/mission-store.test.ts  |   2 +-
 packages/core/src/__tests__/run-audit.test.ts      |   2 +-
 packages/core/src/__tests__/secrets-schema.test.ts |   6 +-
 .../core/src/__tests__/store-merge-queue.test.ts   |   2 +-
 packages/core/src/__tests__/task-documents.test.ts |   2 +-
 packages/core/src/db.ts                            |  51 ++++-
 packages/core/src/goal-citation-extractor.ts       |  56 ++++++
 packages/core/src/index.ts                         |  13 ++
 packages/core/src/store.ts                         | 210 ++++++++++++++++++++-
 packages/core/src/types.ts                         |  51 ++++-
 .../src/store/__tests__/roadmap-store.test.ts      |   4 +-
 24 files changed, 817 insertions(+), 46 deletions(-)

Fusion-Task-Id: FN-5663

Fusion-Task-Lineage: 720f2c4b-4363-464a-a76f-472ec6aca136
2026-05-29 08:25:38 -07:00
gsxdsm
23e0593cb1 FN-5668: preserve word-boundary wrapping in mobile settings text
Prevent mobile settings prose from splitting words mid-token while keeping long code snippets overflow-safe.

- add a CSS regression test that inspects the mobile media-query rules in SettingsModal.css
- switch mobile backup code wrapping to overflow-wrap:anywhere with normal word-break
- update mobile settings helper text to keep break-word wrapping with normal word-break

Files changed:
 .../app/__tests__/settings-mobile-wrap.test.ts     | 46 ++++++++++++++++++++++
 .../dashboard/app/components/SettingsModal.css     |  5 ++-
 2 files changed, 49 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-5668

Fusion-Task-Lineage: eb66376e-a535-4d07-adfe-4a2d048b93a7
2026-05-29 08:20:28 -07:00
gsxdsm
67c026675b FN-5667: enable scrolling in goals view on mobile
Restore Goals screen scroll behavior by making the main goals container vertically scrollable.

- add full-height, min-height reset, and vertical overflow scrolling to .goals-view
- enable momentum scrolling on iOS via -webkit-overflow-scrolling
- extend GoalsView CSS guardrail test to assert required scroll-related declarations

Files changed:
 packages/dashboard/app/components/GoalsView.css                   | 4 ++++
 packages/dashboard/app/components/__tests__/GoalsView.css.test.ts | 3 +++
 2 files changed, 7 insertions(+)

Fusion-Task-Id: FN-5667

Fusion-Task-Lineage: fed12aa4-ebe0-46aa-a057-375469912acd
2026-05-29 08:11:55 -07:00
gsxdsm
a960bb1031 chore(release): v0.37.0
Version bump via changesets.
2026-05-29 08:09:33 -07:00
gsxdsm
6e30060079 FN-5665: allow editing mission target branch
Enable mission target branch to be viewed and updated from the mission edit form.

- Add `baseBranch` to mission form state and initialize it when opening edit mode.
- Include trimmed `baseBranch` in mission PATCH updates.
- Add target branch input to both MissionManager edit form render paths.
- Add MissionManager tests for pre-filling and saving edited target branch values.

Files changed:
 .../dashboard/app/components/MissionManager.tsx    | 24 ++++++++
 .../components/__tests__/MissionManager.test.tsx   | 66 ++++++++++++++++++++++
 2 files changed, 90 insertions(+)

Fusion-Task-Id: FN-5665
Fusion-Task-Lineage: b25cf171-b681-4dd8-b5f4-70f0e8714774
2026-05-29 08:06:46 -07:00
gsxdsm
52b6e2bb52 FN-5664: prevent mission view pull-to-refresh overscroll
Contain Mission Manager scroll overscroll so mobile pull/swipe gestures no longer refresh or snap the dashboard.

- Add overscroll containment to Mission Manager inline/body/sidebar/detail/event scroll containers.
- Preserve iOS momentum scrolling with -webkit-overflow-scrolling where needed.
- Add CSS regression tests asserting overscroll containment and momentum scrolling coverage.

Files changed:
 packages/dashboard/app/components/MissionManager.css    | 10 ++++++++
 packages/dashboard/app/components/__tests__/MissionManager.mobile-css.test.ts    | 27 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

Fusion-Task-Id: FN-5664

Fusion-Task-Lineage: 4c80b116-5c79-4b76-8764-6262ec81aca7
2026-05-29 08:06:46 -07:00
gsxdsm
46531c6b3b FN-5659: add deterministic goal citation proof test
Add a deterministic mock-runtime proof path that verifies executor output cites injected active goal IDs.

- add a new engine test for goal-citation proof scaffolding and emitted goal ID extraction
- validate positive behavior when ## Active Goals is present in session system prompt
- add a negative control confirming no citation is emitted without injected goal context
- assert the proof runs on mock/scripted runtime for deterministic, model-free coverage

Files changed:
 .../src/__tests__/goal-citation-proof.test.ts      | 142 +++++++++++++++++++++
 1 file changed, 142 insertions(+)

Fusion-Task-Id: FN-5659

Fusion-Task-Lineage: 35f7c1ec-8de3-4813-8f9e-fc5f72096d91
2026-05-29 08:06:46 -07:00
gsxdsm
7ba5ad0781 FN-5649: wire GoalsView to Goals API workflows
Replace mock-only goals behavior with live API-backed create/edit/archive flows in GoalsView.

- load goals from GET /api/goals when initial goals are not injected
- add inline create form that POSTs goals and handles active-goal cap 409 errors
- add per-goal edit form that PATCHes title/description changes
- add archive/unarchive actions wired to archive endpoints with inline error handling
- refresh GoalsView docs and expand component tests for loading, CRUD, cap errors, and status transitions

Files changed:
 docs/dashboard-guide.md                            |  18 +-
 packages/dashboard/app/components/GoalsView.css    |  52 ++-
 packages/dashboard/app/components/GoalsView.tsx    | 402 +++++++++++++++++----
 packages/dashboard/app/components/__tests__/GoalsView.test.tsx    | 250 +++++++++++--
 4 files changed, 600 insertions(+), 122 deletions(-)

Fusion-Task-Id: FN-5649

Fusion-Task-Lineage: b787c8e3-64c5-4243-ae84-0f20f12ea09e
2026-05-29 08:06:46 -07:00
gsxdsm
dbfd71373a Merge pull request #1142 from plarson/fix/pending-review-not-failed
fix(engine): do not fail tasks parked for pending review
2026-05-29 08:05:48 -07:00
gsxdsm
b335f3d7c4 FN-5652: add goal retrieval tool for agent execution
Expose goal details to agents during task execution workflows.

- add fn_goal_show tool to the CLI extension with goal lookup, formatted output, and not-found error details
- add focused tests for goal tool registration and execution behavior
- mark fn_goal_show as execution-safe in engine gating classifications and test coverage
- update Fusion skill/reference docs to include the new goal retrieval capability
- add a changeset for @runfusion/fusion patch release

Files changed:
 .changeset/fn-5652-goal-show.md                    |   7 +
 packages/cli/skill/fusion/SKILL.md                 |   2 +-
 .../cli/skill/fusion/references/extension-tools.md |  16 +++
 .../skill/fusion/references/fusion-capabilities.md |   1 +
 .../cli/src/__tests__/extension-goal-tools.test.ts | 148 +++++++++++++++++++++
 packages/cli/src/extension.ts                      |  43 ++++++
 .../src/__tests__/gating-classifications.test.ts   |   7 +
 packages/engine/src/gating-classifications.ts      |   2 +
 8 files changed, 225 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-5652

Fusion-Task-Lineage: 98c2c417-0887-4794-81b1-6b47ab0f708f
2026-05-29 07:13:23 -07:00
gsxdsm
335c49748c FN-5651: add single-seam goal-context injector for system prompts
Introduce a dedicated injector seam that appends active goal context to system prompts.

- add goal-context injector module that builds deterministic system-prompt goal context from active goals
- export injector utilities through engine index for integration and reuse
- add focused tests covering formatting, filtering, ordering, and empty-context behavior

Files changed:
 .../src/__tests__/goal-context-injector.test.ts    | 188 +++++++++++++++++++++
 packages/engine/src/goal-context-injector.ts       | 142 ++++++++++++++++
 packages/engine/src/index.ts                       |   8 +
 3 files changed, 338 insertions(+)

Fusion-Task-Id: FN-5651

Fusion-Task-Lineage: 6fd3a8a0-f33a-48fd-b9f2-9a16c24c48c8
2026-05-29 07:11:00 -07:00
Phil Larson
b5f2f91e87 fix(FN-057): park pending review without failed status 2026-05-29 06:54:45 -07:00
gsxdsm
c89ad28e7b FN-5646: preserve AI body when canonicalizing merge commits
Fusion-Task-Id: FN-5646

Fusion-Task-Lineage: db989a0f-a7d9-4060-9754-84d71f21a8c2
2026-05-29 00:55:17 -07:00
gsxdsm
b8c8642cae FN-5645: fix mission autopilot progression to wait for assertion runs
Fusion-Task-Id: FN-5645

Fusion-Task-Lineage: ed9d2045-2bfe-4070-a7e3-caca010e6cc6
2026-05-28 23:58:47 -07:00
gsxdsm
230efa1cdc FN-5644: default AI merge commit body to summarize changes
Fusion-Task-Id: FN-5644

Fusion-Task-Lineage: 5cf0133b-2a14-4bb4-a1c4-2d5bef5793bc
2026-05-28 23:45:40 -07:00
gsxdsm
6c44ed16e7 chore(release): v0.36.0
Version bump via changesets.
2026-05-28 23:40:25 -07:00
gsxdsm
41ee331429 FN-5648: show in-progress feedback while merging PRs
Fusion-Task-Id: FN-5648

Fusion-Task-Lineage: f056a665-4d52-4472-8495-487a1865aea4
2026-05-28 23:31:03 -07:00
gsxdsm
f5bf7b9b60 FN-5647: remove errant right border on mobile regular chat composer
Fusion-Task-Id: FN-5647

Fusion-Task-Lineage: 278367a7-a3bb-4591-b117-06d17ee71241
2026-05-28 23:27:05 -07:00
gsxdsm
d78fbccacc FN-5643: fix gh api --json flag handling for PR fetches
Fusion-Task-Id: FN-5643

Fusion-Task-Lineage: 2eaba342-1ac7-4ebf-886e-acd22af637ee
2026-05-28 22:59:18 -07:00
gsxdsm
aa7eccbadb FN-5642: add AI-generated merge commit body summaries
Fusion-Task-Id: FN-5642

Fusion-Task-Lineage: 27701749-6107-4ffe-a83e-42873b06473b
2026-05-28 22:23:55 -07:00
gsxdsm
41f40b4669 FN-5641: trigger assertion runs during mission autopilot progression
Fusion-Task-Id: FN-5641

Fusion-Task-Lineage: ba5befe3-cee5-4dc5-9dbe-b718df8ea4fa
2026-05-28 22:07:54 -07:00
gsxdsm
1df1b479dd FN-5640: refresh PR status from Check PR Status footer action
Fusion-Task-Id: FN-5640

Fusion-Task-Lineage: 80074933-2486-4aa6-b23d-1d0e049808cb
2026-05-28 21:40:01 -07:00
gsxdsm
f5cf974504 FN-5639: fix PR panel merge button disabled state
Fusion-Task-Id: FN-5639

Fusion-Task-Lineage: 12a37f9b-895e-4116-b8e1-33315785a42a
2026-05-28 21:32:54 -07:00
gsxdsm
cec191eac3 FN-5638: migrate pi-ai and pi-coding-agent packages to @earendil-works scope
Fusion-Task-Id: FN-5638

Fusion-Task-Lineage: 6e99c156-5f6c-42e6-bd26-618e08ffd05f
2026-05-28 21:23:48 -07:00
gsxdsm
f258a75162 FN-5634: fix ntfy JSON publish priority mapping
Fusion-Task-Id: FN-5634

Fusion-Task-Lineage: 20868ce3-fe31-4638-87f6-83577f46caab
2026-05-28 21:17:02 -07:00
gsxdsm
c21b907211 feat(FN-5633): reviewer also grades the commit message (retry-to-fix)
Add a 4th reviewer axis: the squash commit subject must concisely and
accurately summarize the actual changes. A poor/inaccurate message is an
ADVISORY-severity concern, so it drives a corrective re-merge (which rewrites
the message) up to maxReviewPasses, then lands — it never hard-blocks the merge
over a message nit. Structural correctness (task-id prefix + Fusion-Task-Id /
lineage trailers) remains deterministically guaranteed by
ensureCommitTaskMetadata regardless.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 20:21:06 -07:00
gsxdsm
7f536eb619 fix(FN-5633): guarantee the squash subject starts with the task id
ensureCommitTaskMetadata (was ensureTaskTrailersOnHead) now also prefixes the
commit subject with `<taskId>: ` when includeTaskIdInCommit is on, in addition
to ensuring the Fusion-Task-Id / lineage trailers — so the landed commit both
starts with the task id and carries the board-association trailers even if the
AI agent omits them. Single idempotent amend.

Test: asserts the landed subject matches /^FN-1: / when the agent committed
without a prefix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 20:18:41 -07:00
gsxdsm
c1d558c765 feat(FN-5633): AI merge commit summary + task trailers, verify-and-fix, editable prompt
- Commit message: the merge agent writes a concise change-summary subject (not
  just the task title), and every landed squash carries board-association
  trailers — `Fusion-Task-Id: <taskId>` plus the canonical lineage trailer when
  the task has a lineageId — guaranteed via an idempotent amend
  (ensureTaskTrailersOnHead) even if the agent omits them.
- Verify-and-fix: the merge prompt instructs the agent to run the project's
  tests / type-check / lint after resolving the merge and fix any NEW failure
  the merge introduced (not pre-existing breakage) before committing.
- Editable prompt: the AI merge agent's base persona is the editable "merger"
  role prompt (Settings -> Prompts); the clean-room / verification / trailer
  rules are always appended so a custom prompt can't drop them.
- Reviewer model: reviewer uses the project reviewer/validator model lane
  (resolveValidatorSettingsModel); the bespoke merger.reviewerModel setting is
  removed.

Changeset updated to cover all AI merger changes.

Tests: trailer present on landed commit (+ lineage when set), editable-prompt
incorporation, new-breakage verification wording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 20:14:13 -07:00
gsxdsm
1153b0932e Gitignore .fusion and stray fusion.db files on fn init 2026-05-28 19:55:52 -07:00
gsxdsm
0e5ca34c61 refactor(FN-5633): AI merge reviewer uses the project reviewer/validator model
Drop the bespoke `merger.reviewerModel` setting. The AI merge reviewer now
resolves its model via `resolveValidatorSettingsModel` — the same
reviewer/validator lane used elsewhere (project validator → global validator →
project default) — falling back to the merger model only if that lane is empty.
Removes the setting from the type, schema default, and the Settings UI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 19:53:11 -07:00
gsxdsm
730cee8d61 Remove errant vertical gray line on regular chat input box 2026-05-28 19:52:16 -07:00
gsxdsm
fb27ead6b3 Recovery: re-land PR tab spacing tokens onto main 2026-05-28 19:50:53 -07:00
gsxdsm
b2dce7d852 Recovery: Re-land (Close source-imported GitHub issues on ta 2026-05-28 19:49:31 -07:00
gsxdsm
c722451a1c Recovery: re-land onto main 2026-05-28 19:48:41 -07:00
gsxdsm
2c4683a298 Recovery: re-land tablet TaskDetailModal width onto main 2026-05-28 19:45:27 -07:00
gsxdsm
009d569bdd Recovery: re-land fn goals CLI + pi tools onto main 2026-05-28 19:44:15 -07:00
gsxdsm
be0be507b3 fix(FN-5633): fail loudly when an executed, never-merged task has no branch
The AI merge path treated a missing task branch as a benign no-op. That's
correct when the task was never executed or already merged (branch cleaned up
on a re-process), but if the task WAS executed (a baseCommitSha was recorded)
and has no recorded merge, the branch should still exist — its work appears
lost. Now that case throws instead of silently marking the task done; the
benign cases still finalize as a no-op (reason "already-merged" / "no-branch").

Tests: executed+never-merged → throws; already-merged → no-op done;
never-executed → no-op done.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 19:28:57 -07:00
gsxdsm
29ac58f8d0 feat(FN-5633): standalone AI merge path (clean-room merge + AI reviewer)
New default merge path (merger.mode="ai"), self-contained in merger-ai.ts and
dispatched from ProjectEngine.onMerge instead of the legacy aiMergeTask pipeline
(kept for merger.mode="deterministic").

Flow: clean-room detached worktree at the target branch tip → AI agent merges
the task branch + squashes (resolving conflicts) → fresh read-only AI reviewer
audits with corrective retries (blocking vs advisory; advisory lands, unfixable
correctness hard-fails via AiMergeBlockedError; fail-safe verdict parsing) →
land via `git merge --ff-only` when the checkout is on the target (else
update-ref CAS) → sync the local checkout (stash → ff → restore; AI reconciles
a conflicting restore and keeps the original edits in a backup stash;
un-stashable dirt advances the ref + warns) → finalize (delete task branch —
never the integration branch — task→done, remove temp worktree).

- Per-task target branch honored (falls back to the default integration
  branch); local checkout synced only when on that target.
- Structurally immune to the dirty-clobber and stale-base/non-FF bug classes of
  the legacy path (clean room + FF-by-construction).
- Progress surfaced on the task status pill + task log stream.
- Clear error when the target branch has no local ref.

Settings: merger.mode / merger.reviewerModel / merger.maxReviewPasses, surfaced
in Settings → Merge; legacy merge-mechanics settings hidden when AI mode is on.

Tests: merger-ai.test.ts (verdict parser, clean merge, blocking hard-fail,
advisory land, empty no-op, target-branch isolation, missing-target error,
landSquash clean/other-branch/dirty-restore/AI-resolved). Legacy
merge-orchestration tests pinned to deterministic mode.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 18:50:23 -07:00
gsxdsm
e75c4dae28 fix(FN-5627): suppress ntfy notifications for transient merge failures the engine auto-recovers
Even with FN-5627's merger TOCTOU fix + transient-failure self-healing
sweep + safety-fallback auto-prerebase landed, the merger can still hit
transient failure classes (lease handoff races, brief same-SHA non-FF
advances) for tasks whose branches are particularly out-of-sync. The
self-healing sweep auto-recovers them within bounded budget \u2014 but each
individual failure cycle was firing a ntfy alarm before the recovery
cleared the failed state, producing user-facing alarm spam for tasks
that were never actually stuck.

Two layers of fix:

1. NotificationService.handleTaskUpdated now classifies task.error via
   the new shared classifyTransientMergeError helper before scheduling
   the deferred failure notification. Transient classes
   (lease-handoff-target-not-queued, spurious-concurrent-advance-same-sha)
   get logged as suppressed and never schedule a ntfy timer.

2. Defense-in-depth: fireDeferredFailureNotification re-classifies the
   error at dispatch time, so a failure scheduled before the suppression
   landed on a newer cycle still suppresses if the error matches a
   transient class.

The classifier itself moved from self-healing.ts to a new logger-free
transient-merge-error-classifier.ts module so consumers in
NotificationService don't pull createLogger through the import chain and
break test mocks of ../logger.js (per project-memory rule about new
modules using createLogger). self-healing.ts re-exports the symbol for
backward compatibility.

Log prefix for the recovery actions also changed from
'[FN-5627] Auto-recovering...' to 'Auto-recovered:' so that
NotificationService.maybeSuppressTransientFailedNotification's existing
/^Auto-recovered:/ log-prefix check cancels any already-scheduled failure
notification when the sweep runs mid-grace-window.

Tests (3 new):
- transient lease-handoff-target-not-queued failure NOT notified
- transient spurious-concurrent-advance-same-sha failure NOT notified
- genuine different-SHAs concurrent-advance still notifies (control)

Engine suite: 6166 tests pass.

Fusion-Task-Id: FN-5627
2026-05-28 15:39:23 -07:00
gsxdsm
694970b2f1 fix(FN-5627): always rebase behind branches before squash (safety fallback)
The FN-5627 default-threshold fix changed the prerebase threshold default
from 0 (never fire on commit-count) to 1 (fire on any divergence). But
that only affected projects WITHOUT an explicit threshold. Projects with
user-set values like 'prerebaseDivergenceThreshold: 50' continued to
skip prerebase for small divergences (e.g., 4 commits behind), so the
squash built against stale base and update-ref refused non-FF \u2014
producing the same-SHA spurious-concurrent-advance signature that
stranded FN-5626/FN-5628/FN-5633.

Root distinction missed earlier:
- prerebaseDivergenceThreshold is for USER-VISIBLE SEVERITY REPORTING
  (this branch is N commits behind, warn me).
- Engine correctness requires a SAFETY INVARIANT (any branch behind main
  MUST be rebased before squash or update-ref will fail).

These are independent concerns. The safety invariant must not be gated
on the user's threshold.

decideAutoPrerebase() now returns fire=true with reason
'safety-fallback-any-divergence' whenever commitsBehind > 0, after the
hot-file and threshold checks. The threshold path still wins the reason
label when its condition trips, so user-visible severity reporting is
unchanged for non-pathological cases.

Full opt-out remains prerebaseAutoEnabled=false (skips the safety
fallback; user accepts behind-branch merges will fail).
prerebaseDivergenceThreshold=0 is no longer a complete opt-out from the
commit-count gate \u2014 it only suppresses the threshold-based reason label.

Tests (4 updated/new):
- safety-fallback-any-divergence reason added to AutoPrerebaseDecision
- 4 commits behind with threshold=50 fires via safety fallback
- prerebaseAutoEnabled=false respects full opt-out
- threshold trip still wins reason label
- commitsBehind=0 returns no-divergence (unchanged)

Engine suite: 6163 tests pass.

In-flight: FN-5626, FN-5628, FN-5633 manually SQL-reset to mergeRetries=0,
status=null, error=null, transientRecoveryCount=0 so the next merger tick
(after engine restart picks up this code) auto-prerebases via safety
fallback and lands the work. Future occurrences self-heal automatically.

Fusion-Task-Id: FN-5627
2026-05-28 15:04:41 -07:00
gsxdsm
b96b0bc79a feat(FN-5632): add collision retry logic to fn update command
Adds collision retry logic to the `fn update` CLI command to handle binary path conflicts, including test coverage and a getting-started guide update.

Fusion-Task-Id: FN-5632

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5632
2026-05-28 14:50:15 -07:00
gsxdsm
6b27ab5aab fix(FN-5627): default auto-prerebase to fire when branch >=1 commit behind
decideAutoPrerebase() previously defaulted prerebaseDivergenceThreshold
to 0, which meant the threshold path NEVER fired unless the user
explicitly set a positive value. Only hot-file matches could trigger
prerebase.

The result: tasks whose branch was started against an older main tip
(because other tasks landed concurrently) skipped prerebase, built their
squash commit against the stale base, and then failed at git update-ref
because the squash didn't descend from current main. The merger correctly
detected this as non-fast-forward and threw
IntegrationBranchConcurrentAdvanceError, but with both 'expected' and
'observed' SHAs set to current main tip \u2014 because observedCurrentSha was
captured from the pre-update rev-parse, not post-failure. This produced
the misleading 'expected X, observed X' same-SHA error signature that
stranded FN-5632 stuck at mergeRetries=3 after the FN-5627 merger fix
and engine restart.

New default: prerebaseDivergenceThreshold = 1. Any branch behind by at
least 1 commit auto-rebases before squash. Users who want the legacy
never-fire behavior can explicitly set prerebaseDivergenceThreshold = 0.
Threshold comparison also changed from > to >= so an explicit threshold
of N rebases at N+ commits behind instead of N+1+.

The self-healing classifier comment for spurious-concurrent-advance-same-sha
is updated to note the signature can come from either pre-FN-5627
misclassification OR the legitimate post-FN-5627 non-FF path; the
auto-recovery sweep is unchanged because both cases self-heal cleanly
once prerebase fires on the retry.

Tests (3 new):
- Default threshold (undefined) fires at 1 commit behind
- Explicit threshold = 0 stays as opt-out (never fire on commit-count)
- Default threshold doesn't fire when branch is up-to-date

Engine suite: 6160 tests pass.

In-flight: FN-5632 manually SQL-reset to mergeRetries=0 / status=null
once more so the next merger tick (after engine restart picks up this
code) auto-prerebases and lands the work. Future occurrences self-recover.

Fusion-Task-Id: FN-5627
2026-05-28 14:21:38 -07:00