Commit Graph

3374 Commits

Author SHA1 Message Date
gsxdsm
f5c9dc6f91 fix: prevent stuck-kill from stranding approved plans as unplanned (#2326)
## Summary

Fixes a race where a stuck-kill during Plan Review could leave an
approved task stranded in `todo` as **unplanned**, so the scheduler
refused release to `in-progress` for several minutes (observed on
FN-1312: ~6m39s idle after Plan Review APPROVE).

### What went wrong

1. Finalize clears `status` early, then runs Plan Review.
2. Stuck-kill disposes the main triage session near the 30m processing
threshold.
3. Stale eviction only treated the main session as live, so the card
left `processing` while Plan Review / finalize was still running.
4. A second planner claimed `status: "planning"` and rewrote
`PROMPT.md`.
5. The first finalize moved `triage → todo` without clearing planning
statuses.
6. Hold-release saw planning/`needs-replan` and blocked: *“card is
unplanned and cannot enter processing column in-progress”*.

### Fix

In `packages/engine/src/triage.ts`:

- Track **finalizing** handoffs and **live Plan Review subagents** as
live planning work.
- Keep them in `getProcessingTaskIds`, refuse concurrent `specifyTask`,
and skip stale-processing eviction while they are live.
- **Defer** stuck-abort requeue during finalize (bump kill count only;
do not force `needs-replan`).
- Recover approved drafts with `status: null` (post early-clear), not
only `status: "planning"`.
- Re-assert `status: null` after the successful release move to todo.

### Tests

Regression coverage in `triage.test.ts` for eviction retention,
processing-id inclusion, null-status recovery, needs-replan
non-recovery, and deferred stuck-abort during finalize.

## Test plan

- [x] `pnpm --filter @fusion/engine exec vitest run
src/__tests__/triage.test.ts -t "evictStaleProcessing|specified triage
recovery|stuck|recoverApproved|markStuckAborted|defers stuck-abort"`
(related cases green)
- [ ] CI gate on this PR
- [ ] Optional: reproduce stuck-kill mid–Plan Review and confirm todo
releases without a second full replan

## Notes

Secondary report (stuck-kill immediately after all implementation steps
complete, then 16s auto-recovery) is **out of scope** here; existing
recovery already continued by skipping completed steps.


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

* **Bug Fixes**
* Improved recovery for approved tasks when Plan Review has completed,
including correct handling of `null`-status drafts.
* Avoided recovering unplanned seed drafts and tasks that should enter a
replanning flow.
* Refined stuck-abort requeue/cleanup to respect in-progress Plan Review
and finalize handoffs.
* Prevented stale-processing eviction from removing tasks while Plan
Review/subagent finalization is still active.
* Blocked new triage discovery and task specification when finalize/Plan
Review work is ongoing, preventing handoff disruption.
* Preserved durable task state during handoff completion
(approval/failure/replan outcomes).
* **Tests**
* Added expanded triage recovery and stuck-abort/stale-eviction
regression coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 17:11:55 -07:00
gsxdsm
a8e1393e3c fix: serialize Anthropic OAuth token refresh
Prevent concurrent Fusion sessions and processes from consuming the same rotating refresh token. Share one refresh lock across legacy and subscription Anthropic credential aliases.
2026-07-18 17:08:35 -07:00
gsxdsm
3ebac72345 fix(ci): research promote tool inventory + 0023 upgrade seed bookkeeping (#2329)
## Summary
- Heartbeat customTools inventory includes `fn_research_promote_finding`
(64 tools).
- Schema-applier bookkeeping for migration `0023` research feature
provenance.
- Seed upgrade fixtures include `mission_features.slice_id` for the
unique index.

## Evidence
- Full greens earlier this session: **29662309385** (#2323),
**29663526777** (#2325), **29664692957** (#2327).
- Tip red after FN-8297: heartbeat 63→64 + schema upgrade seed.

## Test plan
- [x] heartbeat expected-tools + schema upgrade tests green locally
- [ ] Full Suite all shards green on tip after merge
2026-07-18 16:44:58 -07:00
gsxdsm
c95e08ea21 FN-8297: add research finding promotion to mission features
Bridge completed research findings into durable mission roadmap features.

- Persist stable finding and citation provenance on mission features
- Add idempotent promotion APIs, dashboard controls, and agent tooling
- Document the promotion flow and cover finding identity and feature synchronization

Files changed:
 .changeset/fn-8297-research-mission-bridge.md      |  7 ++++
 docs/missions.md                                   |  4 +++
 docs/research.md                                   |  4 +++
 .../__tests__/research-finding-identity.test.ts    | 15 +++++++++
 packages/core/src/async-mission-store-queries.ts   | 26 +++++++++++++++
 packages/core/src/async-mission-store.ts           | 16 +++++++++
 packages/core/src/index.gate.ts                    |  3 ++
 packages/core/src/index.ts                         |  3 ++
 packages/core/src/mission-types.ts                 | 13 ++++++++
 .../core/src/postgres/migrations/0000_initial.sql  |  4 +++
 .../0023_research_feature_provenance.sql           |  8 +++++
 packages/core/src/postgres/schema-applier.ts       | 13 +++++++-
 packages/core/src/postgres/schema/project.ts       |  5 +++
 packages/core/src/research-feature-promotion.ts    | 38 ++++++++++++++++++++++
 packages/core/src/research-types.ts                | 21 ++++++++++++
 packages/core/src/types.ts                         |  1 +
 packages/dashboard/app/api/legacy.ts               | 21 ++++++++++++
 packages/dashboard/app/components/ResearchView.tsx | 19 ++++++-----
 packages/dashboard/app/hooks/useResearch.ts        |  3 ++
 packages/dashboard/src/chat.ts                     |  4 +--
 packages/dashboard/src/research-routes.ts          | 37 +++++++++++++++++----
 .../src/__tests__/agent-mission-tools.test.ts      | 14 +++++++-
 .../src/__tests__/mission-feature-sync.test.ts     | 20 ++++++++++++
 packages/engine/src/agent-tools.ts                 | 26 +++++++++++++++
 packages/engine/src/mission-feature-sync.ts        |  1 +
 25 files changed, 308 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-8297

Fusion-Task-Lineage: ffef4d26-1372-466a-8d3d-2b9b5cc9a53b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 16:18:15 -07:00
gsxdsm
de2669fd17 fix(ci): mock createAgentTask for route tests; quarantine merge-reuse slow flake (#2327)
## Summary
- Default `createAgentTask` in dashboard `@fusion/engine` mock so
planning/subtask create routes return 201 (FN-8277).
- Mock `findRecentTasksBySourceParentTaskId` on github/planning route
stores.
- Quarantine `merge-reuse-task-worktree.slow.test.ts` (engine-slow load
flake, run 29663725381).

## Evidence
- Prior full green: Full Suite run **29663526777** on #2325.
- Tip red class: routes-github/planning 500 + engine-slow lease
residual.

## Test plan
- [x] routes subtask create-tasks / shared branch groups tests green
locally
- [ ] Full Suite all 4 shards + engine-slow green on main tip after
merge

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved task and subtask creation test coverage to correctly handle
parent-scoped duplicate checks.
  * Updated test behavior to return reliable task creation results.

* **Tests**
* Quarantined a flaky integration test from the slow test suite to
improve test run reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 16:08:14 -07:00
gsxdsm
4a4f231ef4 fix(FN-8277): preserve planning task lineage (#2324)
## Summary

Planning breakdowns now preserve their creating task as durable lineage
and reuse only siblings from that same parent. Identical wording under a
different parent creates a distinct child instead of silently linking
the wrong lineage.

The dashboard planning path now uses the same duplicate-safe creation
contract as agent tools, leaves reused canonical tasks untouched, and
exposes API-created parent links in task details.

Related: FN-8277

## Validation

- Core duplicate guard: 12 tests passed
- Engine task creation: 32 tests passed
- Dashboard planning routes: 4 focused tests passed
- Dashboard task detail provenance: 2 focused tests passed
- Core, engine, dashboard, and CLI typechecks passed
- Lint and strict changeset validation passed


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

## Summary by CodeRabbit

- **New Features**
- Preserved parent-task lineage for subtasks created through planning
breakdowns and API workflows.
- Improved duplicate detection so identical tasks from different parent
tasks can coexist safely.
  - Added parent-task links to API-created task provenance details.
  - Reused existing duplicates only within the same parent-task context.

- **Bug Fixes**
- Prevented duplicate handling from incorrectly archiving or skipping
tasks belonging to other parents.
  - Improved dependency handling when creating planned subtasks.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 15:35:26 -07:00
gsxdsm
cf1a5991aa fix: stop processing before returning tasks to Todo (#2322)
## Summary

Moving an active task back to Todo could update the board before its
agent and subprocesses had stopped, leaving a Todo card that was still
processing. User-initiated in-progress-to-Todo moves now wait for every
executor cancellation surface before the new column is persisted or
returned to the dashboard. Cancellation is fail-closed and bounded: a
wedged shutdown leaves the task in Progress, releases its lock for
recovery, and fences late cleanup from replacement execution
generations. Engine-driven recovery moves and other transitions retain
their existing behavior.

## Validation

- Confirmed with PostgreSQL-backed symptom tests that the durable row
stays in Progress while cancellation is pending and that a timeout
releases the task lock without publishing Todo.
- Verified multi-executor ownership and replacement-generation fencing
across focused core and engine tests: 18 tests passed.
- Core build, engine typecheck, targeted lint, and strict changeset
validation passed.

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
2026-07-18 14:54:54 -07:00
gsxdsm
6268433d37 fix(ci): parent-task uniqueness mocks, roadmap search index, flake quarantine (#2323)
## Summary
- FN-8277 parent-scoped uniqueness: mock
`findRecentTasksBySourceParentTaskId` in heartbeat/triage/split suites.
- FN-8326: index `reportRoadmapDedup` in Settings search.
- Quarantine re-flaked `dev-server-process` under full-suite API load
(run 29661202279).

## Test plan
- [x] Targeted createTask / search-index tests green locally
- [ ] Full Suite all 4 shards green on main after merge
2026-07-18 14:49:24 -07:00
gsxdsm
ca7bc3e46e refactor: package code organization wave 9 (#2274)
## Summary

Wave 9 of package code organization (plan:
`docs/plans/2026-07-14-001-refactor-package-code-organization-plan.md`),
after #2252.

### Peels
| New module | Parent |
|---|---|
| `app/api/global-and-pi-settings.ts` | `legacy.ts` |
| `app/api/task-content.ts` | `legacy.ts`
(attachments/logs/comments/docs/artifacts) |
| `types/messages.ts` | `types.ts` |
| `merger-diff-volume-gate` helpers | `merger.ts` |

Public paths stay stable via re-exports.

### LOC
- `legacy.ts` ~10561 → ~10269
- `types.ts` ~6998 → ~6937
- `merger.ts` ~11223 → ~11208

## Test plan
- [x] core/engine/dashboard typecheck (app)
- [x] eslint on peeled modules
- [x] api-tasks + memory/agent-log focused tests
- [ ] CI merge gate

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

* **New Features**
* Added dashboard API endpoints for global and project-scoped settings,
PI configuration, notification testing, and PI package
install/reinstall.
* Added task content APIs covering attachments, agent logs, session
files, task comments, task documents, artifacts, and project markdown
files.
* Added structured messaging contracts and participant/message
normalization.
* Added diff-volume gate settings resolution and formatted findings
output.
* **Refactor**
* Organized messaging and dashboard API surface into dedicated modules
via re-exports.
  * Removed a deprecated verification-output alias.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 14:42:59 -07:00
gsxdsm
9bc0eb6943 fix(FN-8277): prevent replayed duplicate follow-up tasks (#2319)
## Summary

Repeated review and executor sessions could replay a follow-up creation
step and produce another live task whenever the wording changed. In the
incident behind this fix, 21 creation calls for three intended
follow-ups left 18 duplicate tasks.

Agent-created tasks now retain their parent and agent provenance across
step sessions, heartbeats, and the published CLI surface. Same-parent
paraphrases converge on the existing task through a serialized pre-check
and a database-backed intent claim, while distinct sibling actions
remain separate. Candidate lookup is parent-indexed, uniqueness failures
abort creation, and canonical reuse no longer emits misleading creation
audit events or workflow claims.

Related: FN-8277

## Validation

- Core duplicate guard and intake: 24 tests passed
- Engine task creation and heartbeat: 154 tests passed
- CLI extension: 66 tests passed, 95 skipped
- Core, engine, and CLI typechecks passed
- Core, engine, and CLI builds passed before rebase; the rebase was
conflict-free
- Scoped lint, strict changeset validation, and diff checks passed


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

* **Bug Fixes**
* Prevented retried agent steps from creating duplicate follow-up tasks.
* Improved parent-scoped deduplication for paraphrased follow-ups while
preserving distinct sibling actions.
  * Preserved parent-task and agent context for created follow-ups.
* Concurrent follow-up requests are now serialized/deduplicated so
duplicates link to the existing task instead of showing as newly
created.
* Updated agent follow-up/heartbeat activity so reused follow-ups no
longer appear in run results as fresh creations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 14:18:25 -07:00
gsxdsm
89b42ed1d6 fix(ci): ideation heartbeat tools, review-artifact i18n, tab-persist quarantine (#2321)
## Summary
- Heartbeat customTools inventory includes FN-8295 ideation tools (63
total).
- Non-en i18n parity for FN-8286 `reviewArtifacts` Command Center +
settings keys.
- Quarantine `TaskDetailModal.tab-persistence.test.tsx` (CI load flake;
green focused thrice).

## Test plan
- [x] heartbeat expected-tools case green
- [x] i18n-gate-coverage + parity green
- [ ] Full Suite all 4 shards green on main after merge
2026-07-18 14:13:28 -07:00
gsxdsm
bcdad279d7 FN-8289: add feature-video review artifacts
Add gated local feature-video capture to completed user-facing deliverables.

- Capture loopback scenario WebM recordings through the existing artifact registry.
- Keep recording failures non-blocking and cover gated, unsafe, and failed capture paths.
- Document the scenario contract and package the Playwright runtime dependency.

Files changed:
 .changeset/fn-8289-feature-video.md                |   7 +
 docs/workflow-steps.md                             |   8 +
 packages/cli/package.json                          |   3 +-
 packages/cli/tsup.config.ts                        |   7 +
 packages/engine/package.json                       |   3 +-
 .../__tests__/executor-review-artifacts.test.ts    |  44 ++++
 packages/engine/src/executor.ts                    |  33 +++
 .../src/review-artifacts/feature-video.test.ts     |  75 +++++++
 .../engine/src/review-artifacts/feature-video.ts   | 226 +++++++++++++++++++++
 packages/engine/src/review-artifacts/index.ts      |  10 +
 pnpm-lock.yaml                                     |   6 +
 11 files changed, 420 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-8289

Fusion-Task-Lineage: 8a34675a-2417-4669-a14a-b74c4aa99331

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 13:53:58 -07:00
gsxdsm
d51ce46db5 FN-8295: add persisted ideation mission handoffs
Persist bounded ideation sessions through agent tools, the Command Center, and atomic Mission convergence.

- Store ideation sessions and divergent candidates in PostgreSQL with async APIs and migration support.
- Expose gated ideation tools, chat routes, and agent lifecycle integration.
- Add the Ideation panel, documentation, release metadata, and regression coverage.

Files changed:
 .changeset/fn-8295-ideation-diverge-converge.md    |   7 ++
 docs/ideation/persisted-diverge-converge.md        |  22 ++++
 docs/missions.md                                   |   4 +
 .../__tests__/postgres/ideation-store.pg.test.ts   |  57 +++++++++
 packages/core/src/async-ideation-store-queries.ts  | 117 +++++++++++++++++
 packages/core/src/async-ideation-store.ts          | 138 +++++++++++++++++++++
 packages/core/src/async-mission-store.ts           |  27 ++--
 packages/core/src/ideation-types.ts                |  69 +++++++++++
 packages/core/src/index.ts                         |   3 +
 .../core/src/postgres/migrations/0022_ideation.sql |  67 ++++++++++
 packages/core/src/postgres/schema-applier.ts       |  18 ++-
 packages/core/src/postgres/schema/project.ts       |  49 +++++++-
 packages/core/src/store.ts                         |   8 +-
 packages/core/src/task-store/remaining-ops-8.ts    |  14 +++
 .../components/command-center/CommandCenter.tsx    |   7 +-
 .../components/command-center/IdeationPanel.css    |  18 +++
 .../components/command-center/IdeationPanel.tsx    |  58 +++++++++
 .../__tests__/CommandCenter.test.tsx               |   6 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   |   1 +
 packages/dashboard/src/__tests__/chat.test.ts      |   1 +
 .../__tests__/ideation-tool-route-parity.test.ts   |  29 +++++
 packages/dashboard/src/chat.ts                     |   4 +
 packages/dashboard/src/ideation-routes.ts          |  50 ++++++++
 .../src/routes/register-integrated-routers.ts      |   2 +
 .../src/__tests__/agent-ideation-tools.test.ts     |  40 ++++++
 .../src/__tests__/gating-classifications.test.ts   |  16 +++
 .../src/__tests__/permanent-agent-gating.test.ts   |   2 +
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 |  67 ++++++++++
 packages/engine/src/executor.ts                    |   2 +
 packages/engine/src/gating-classifications.ts      |   8 ++
 packages/engine/src/index.ts                       |   1 +
 packages/engine/src/triage.ts                      |   2 +
 33 files changed, 897 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-8295

Fusion-Task-Lineage: 1b8b0752-22bd-4b2f-aebd-4305c63abcf9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 13:18:08 -07:00
gsxdsm
13f936eb7b FN-8286: add review artifact controls and galleries
Add configurable review-deliverable policies and surface eligible artifacts in review workflows.

- Add project and PROMPT.md review-artifact modes with task eligibility enforcement.
- Display video and live-demo deliverables in Task Review and Command Center galleries.
- Document, localize, and test the new review-artifact controls.

Files changed:
 .changeset/fn-8286-review-artifacts.md             |  7 ++
 docs/settings-reference.md                         |  1 +
 .../core/src/__tests__/review-artifacts.test.ts    | 53 +++++++++++++++
 .../core/src/__tests__/settings-parity.test.ts     |  5 ++
 packages/core/src/index.ts                         |  4 +-
 packages/core/src/settings-schema.ts               |  1 +
 packages/core/src/types.ts                         | 75 ++++++++++++++++++++++
 packages/core/src/types/execution-and-ui.ts        |  8 +++
 .../dashboard/app/components/TaskReviewTab.tsx     | 28 +++++++-
 .../__tests__/SettingsModal.general.test.tsx       |  8 +++
 .../components/__tests__/TaskReviewTab.test.tsx    | 27 ++++++++
 .../components/command-center/CommandCenter.tsx    |  5 ++
 .../command-center/areas/ReviewArtifactsArea.tsx   | 59 +++++++++++++++++
 .../areas/__tests__/ReviewArtifactsArea.test.tsx   | 39 +++++++++++
 .../app/components/settings/section-keys.ts        |  1 +
 .../settings/sections/GeneralSection.tsx           | 20 ++++++
 .../settings-default-descriptions.test.tsx         |  1 +
 .../src/__tests__/agent-artifact-tools.test.ts     | 19 +++++-
 packages/engine/src/agent-tools.ts                 | 26 ++++++++
 packages/i18n/locales/en/app.json                  |  7 ++
 packages/i18n/src/resources.d.ts                   |  7 ++
 21 files changed, 397 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-8286
Fusion-Task-Lineage: 357ccbe3-510d-4ffd-ba7c-6bf79fe40a09
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 13:09:38 -07:00
gsxdsm
17ee1a8040 fix(ci): restore Full Suite bookkeeping after concurrent main landings (#2316)
## Summary
- Align heartbeat `customTools` expectations with FN-8294 mission
hierarchy tools (43→58).
- Refresh `COORDINATION_EXEMPT_TOOLS` snapshot for `fn_mission_list` /
`fn_mission_show`.
- Backfill `commandCenter.portability.*` for non-en locales and map
`reportMode` / `reportModeByAction` / `embeddedPostgresMaxConnections`
into settings default-description inventory with i18n help text.
- Realign FN-8064 skip-narration unit test with store-owned proactive
chat (no tool-side `appendAgentLog`).
- Quarantine load-sensitive `async-quality-store.pg.test.ts` (5s timeout
+ leftover psql under full-suite shard load; run 29657633544).

## Test plan
- [x] `pnpm --filter @fusion/engine exec vitest run`
gating-classifications + executor-prompt + heartbeat expected-tools case
- [x] `pnpm --filter @fusion/i18n exec vitest run` i18n-gate-coverage +
parity
- [x] `pnpm --filter @fusion/dashboard exec vitest run`
settings-default-descriptions
- [ ] Full Suite all 4 shards green on main after merge

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

## Summary by CodeRabbit

* **Settings**
* Added clearer, localized help text for report modes and per-action
overrides, including inheritance behavior.
* Added advanced embedded database connection-limit settings and
validation guidance.

* **Localization**
* Expanded translations for report settings, database tuning, and
organization configuration import/export workflows across supported
languages.

* **Tests & Maintenance**
* Updated test coverage and expectations for expanded tools and
reporting behavior.
  * Quarantined a flaky database-related test.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 12:48:13 -07:00
gsxdsm
d593d87686 feat(FN-8064): make proactive task chat optional
Fusion-Task-Id: FN-8064
2026-07-18 12:21:08 -07:00
gsxdsm
b533b918fe fix(FN-8064): narrate all task step transitions
Fusion-Task-Id: FN-8064
2026-07-18 12:21:08 -07:00
gsxdsm
bcb1256d6b FN-8282: add configuration revision history and rollback
Record configuration revisions so prior settings can be restored safely.

- Add revision storage interfaces, PostgreSQL schema, migration, and pruning.
- Capture changes to global settings, routines, automations, and async task settings.
- Expose revision listing and restore operations with coverage and storage documentation.

Files changed:
 .changeset/fn-8282-config-versioning.md            |   7 +
 docs/storage.md                                    |   6 +
 .../__tests__/configuration-revision-store.test.ts |  26 +++
 .../src/__tests__/postgres/schema-applier.test.ts  |  15 +-
 .../core/src/async-configuration-revision-store.ts | 192 +++++++++++++++++++++
 packages/core/src/automation-store.ts              |  88 +++++++++-
 packages/core/src/configuration-revision-store.ts  |  33 ++++
 packages/core/src/global-settings.ts               | 172 +++++++++++++++++-
 packages/core/src/index.gate.ts                    |   3 +
 packages/core/src/index.ts                         |   3 +
 .../migrations/0021_configuration_revisions.sql    |  40 +++++
 packages/core/src/postgres/schema-applier.ts       |  19 +-
 packages/core/src/postgres/schema/project.ts       |  27 +++
 packages/core/src/routine-store.ts                 | 103 ++++++++++-
 packages/core/src/store.ts                         |  21 ++-
 packages/core/src/task-store/async-settings.ts     |  14 +-
 packages/core/src/task-store/remaining-ops-2.ts    |  86 ++++++++-
 packages/core/src/task-store/settings-ops.ts       | 104 +++++++----
 packages/core/src/types.ts                         |  36 ++++
 packages/engine/src/agent-tools.ts                 |   7 +-
 20 files changed, 928 insertions(+), 74 deletions(-)

Fusion-Task-Id: FN-8282

Fusion-Task-Lineage: fd681798-10b0-47ce-b96b-6f33eecdf70a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 11:34:42 -07:00
gsxdsm
8d1620ea23 FN-8294: expose action-gated Mission hierarchy tools
Expose project-scoped Mission hierarchy operations to engine agents and eligible dashboard chat sessions.

- Add Mission, milestone, slice, and feature tool definitions backed by MissionStore
- Classify hierarchy mutations for action and permanent-agent approval gates
- Wire gated tool access through triage, executor, heartbeat, CLI, and chat lanes
- Cover tool availability, mutation gating, and chat integration with tests and documentation

Files changed:
 .changeset/fn-8294-mission-engine-tools.md         |   7 ++
 docs/missions.md                                   |   8 ++
 packages/cli/src/extension.ts                      |   2 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   |  48 +++++++++
 packages/dashboard/src/__tests__/chat.test.ts      |   1 +
 packages/dashboard/src/chat.ts                     | 113 ++++++++++++++++++++-
 .../src/__tests__/agent-mission-tools.test.ts      |  43 ++++++++
 packages/engine/src/__tests__/triage.test.ts       |  34 ++++++-
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 |  64 ++++++++++++
 packages/engine/src/executor.ts                    |   2 +
 packages/engine/src/gating-classifications.ts      |  11 ++
 packages/engine/src/index.ts                       |  17 ++++
 packages/engine/src/triage.ts                      | 111 ++++++++++++++++++++
 14 files changed, 457 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-8294

Fusion-Task-Lineage: ab0f248b-8a38-40e3-b297-79f9dbe18075

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 10:31:59 -07:00
gsxdsm
2b455672c6 FN-8275: clarify mission merge behavior
Clarify mission merge choices and surface shared branch status in mission detail.

- Explain auto-merge and single-pull-request behavior in mission forms
- Show mission-owned shared branch member and PR status
- Cover UI behavior and PostgreSQL triage auto-merge cascading

Files changed:
 .changeset/fn-8275-mission-merge-summary.md        |  7 ++
 docs/missions.md                                   |  2 +-
 .../dashboard/app/components/MissionManager.tsx    | 75 ++++++++++++++++++++++
 .../__tests__/MissionManager.auto-merge.test.tsx   | 64 ++++++++++++++++++
 .../mission-auto-merge-cascade.pg.test.ts          | 58 +++++++++++++++++
 5 files changed, 205 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8275

Fusion-Task-Lineage: cd259293-b68e-4bc5-803e-40d2287d8438

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 09:41:25 -07:00
gsxdsm
afb2ed0650 FN-8271: restore quarantined CLI tests under shard load
Restore affected CLI and engine tests by removing load-amplifying fixture work and synchronizing fake-timer recovery.

- Replace the dist-barrel PostgreSQL fixture with an injected in-memory task store.
- Move mission and goal tool coverage to the shared PostgreSQL harness and complete plugin-store mocks.
- Return rescued CLI and heartbeat tests to default lanes and clear their quarantine records.

Files changed:
 .../src/__tests__/extension-dist-barrel.test.ts    | 90 ++++++++--------------
 .../__tests__/extension-mission-goal-tools.test.ts | 27 ++++---
 packages/cli/src/commands/__tests__/plugin.test.ts | 11 +++
 packages/cli/vitest.config.ts                      | 21 +----
 .../src/__tests__/heartbeat-error-recovery.test.ts | 33 ++++----
 packages/engine/vitest.config.ts                   |  7 +-
 scripts/lib/test-quarantine.json                   | 78 +------------------
 7 files changed, 84 insertions(+), 183 deletions(-)

Fusion-Task-Id: FN-8271

Fusion-Task-Lineage: 212a3ec7-db6b-4e80-97c3-1c704822cf60

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 07:48:45 -07:00
gsxdsm
e436635abd FN-8270: restore PostgreSQL migration quarantine tests
Restore seven PostgreSQL-compatible engine suites to the active test runs.

- Model asynchronous insight and goal-store collaborators in reporter and diagnostics tests.
- Await PostgreSQL audit reads in merger reliability tests.
- Remove the restored suites from Vitest exclusions and the quarantine ledger.

Files changed:
 .../__tests__/backlog-pressure-reporter.test.ts    | 19 +++++++----
 .../dependency-blocked-todo-reporter.test.ts       | 15 ++++++---
 .../goal-injection-diagnostics-wiring.test.ts      | 15 ++++++---
 .../__tests__/merger-cwd-fallback-removed.test.ts  | 13 +++++---
 .../integration-worktree-state.test.ts             | 13 +++++---
 .../merge-runner-spawn-enoent-prevention.test.ts   | 15 +++++---
 .../meta-chain-auto-close.test.ts                  |  9 ++++--
 packages/engine/vitest.config.ts                   | 20 ++----------
 scripts/lib/test-quarantine.json                   | 37 +---------------------
 9 files changed, 73 insertions(+), 83 deletions(-)

Fusion-Task-Id: FN-8270
Fusion-Task-Lineage: 65be82ef-f4d4-4a8a-b3cc-63486ee0823a
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 04:40:18 -07:00
gsxdsm
7c23771433 FN-8265: add task follow-up proposal creation
Enable configured ephemeral workers to propose and create follow-up tasks from mailbox messages.

- Add persisted task-proposal claim state, migrations, and async messaging APIs.
- Register task-proposal creation routes, SSE events, agent tool support, and CLI integration.
- Add mailbox creation controls, settings, documentation, localization, and regression coverage.

Files changed:
 .changeset/fn-8265-task-follow-up-policy.md        |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 docs/settings-reference.md                         |  12 ++-
 packages/cli/src/extension.ts                      |  34 ++++---
 .../src/__tests__/postgres/sqlite-migrator.test.ts |  14 ++-
 .../postgres/task-proposal-claim.pg.test.ts        |  51 +++++++++++
 packages/core/src/async-message-store.ts           |  39 ++++++++
 packages/core/src/index.gate.ts                    |   4 +-
 packages/core/src/index.ts                         |   4 +-
 packages/core/src/message-store.ts                 |  46 ++++++++++
 .../core/src/postgres/migrations/0000_initial.sql  |   2 +
 .../migrations/0020_task_proposal_claim.sql        |   4 +
 packages/core/src/postgres/schema-applier.ts       |  13 ++-
 packages/core/src/postgres/schema/project.ts       |   3 +
 packages/core/src/settings-schema.ts               |  19 +++-
 packages/core/src/task-store/async-persistence.ts  |   2 +-
 packages/core/src/task-store/persistence.ts        |   4 +-
 packages/core/src/task-store/serialization.ts      |   1 +
 packages/core/src/task-store/task-creation.ts      |  51 +++++++++++
 packages/core/src/task-store/task-row-mappers.ts   |   2 +-
 packages/core/src/types.ts                         |  56 +++++++++++-
 packages/dashboard/app/api/legacy.ts               |   5 +
 packages/dashboard/app/components/MailboxModal.tsx |   4 +
 .../app/components/MailboxTaskProposal.css         |   3 +
 .../app/components/MailboxTaskProposal.tsx         |  33 +++++++
 packages/dashboard/app/components/MailboxView.tsx  |   4 +
 .../__tests__/MailboxTaskProposal.test.tsx         |  43 +++++++++
 .../app/components/settings/section-keys.ts        |   2 +-
 .../settings/sections/GeneralSection.search.ts     |  13 ++-
 .../settings/sections/GeneralSection.tsx           |  22 +++--
 .../settings-default-descriptions.test.tsx         |   4 +-
 .../routes/__tests__/task-proposal-routes.test.ts  |  99 ++++++++++++++++++++
 .../src/routes/register-messaging-scripts.ts       | 101 +++++++++++++++++++++
 packages/dashboard/src/sse.ts                      |   7 ++
 packages/engine/src/agent-tools.ts                 |  30 ++++--
 packages/engine/src/executor.ts                    |   9 +-
 packages/engine/src/step-session-executor.ts       |   8 +-
 packages/i18n/locales/en/app.json                  |   5 +
 38 files changed, 696 insertions(+), 66 deletions(-)

Fusion-Task-Id: FN-8265

Fusion-Task-Lineage: 4e864a2f-3485-4a54-8be7-1699b5479a94

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 03:48:38 -07:00
gsxdsm
e18c3b4584 FN-8262: route OMP models through ACP runtime
Route omp-cli model selections to the bundled OMP ACP runtime instead of pi registry resolution.

- Derive and validate OMP runtime routing for primary and fallback model selections.
- Preserve mock and test-mode short-circuits and provide actionable plugin remediation.
- Add OMP routing regression coverage and a patch changeset.

Files changed:
 .changeset/fn-8262-omp-model-routing.md            |   7 +
 .../agent-session-helpers-omp-routing.test.ts      | 218 +++++++++++++++++++++
 packages/engine/src/agent-session-helpers.ts       |  87 +++++++-
 3 files changed, 306 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8262

Fusion-Task-Lineage: 7a77031f-8703-484e-9e53-a2ef097ec17e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 01:47:52 -07:00
gsxdsm
377cb9c90a FN-8258: complete PostgreSQL quarantine rescues
Complete PostgreSQL-backed rescue coverage while retaining archived shared-branch landing proof.

- Preserve merge details when archiving and restoring tasks for branch-group promotion.
- Migrate remaining quarantine tests and mocks to PostgreSQL-aware boundaries.
- Remove rescued tests from the engine quarantine configuration and ledger.

Files changed:
 .changeset/fn-8258-pg-quarantine.md                |  7 +++
 .../core/src/task-store/archive-lifecycle-2.ts     |  1 +
 packages/core/src/task-store/remaining-ops-6.ts    |  8 ++-
 packages/core/src/task-store/serialization.ts      |  1 +
 .../__tests__/agent-tools-intake-column.test.ts    | 26 ++++------
 .../agent-workflow-tools-exposure.test.ts          | 18 +++----
 .../engine/src/__tests__/executor-task-done-invariant.test.ts | 33 ++++++------
 .../engine/src/__tests__/executor-test-helpers.ts  |  7 +++
 .../src/__tests__/group-merge-coordinator.test.ts  | 43 ++++++++++------
 .../hybrid-executor-multi-node-routing.test.ts     |  5 ++
 .../mission-factory-parity.integration.test.ts     |  2 +-
 .../engine/src/__tests__/routine-runner.test.ts    | 56 +++++++++++++--------
 .../self-healing-meta-archive-guards.test.ts       | 28 +++++------
 .../src/__tests__/triage-token-usage.test.ts       | 58 +++++-----------------
 .../__tests__/workflow-graph-task-runner.test.ts   | 16 +++---
 packages/engine/src/hybrid-executor-gate.ts        |  8 ++-
 packages/engine/vitest.config.ts                   | 12 +----
 scripts/lib/test-quarantine.json                   | 52 +------------------
 18 files changed, 165 insertions(+), 216 deletions(-)

Fusion-Task-Id: FN-8258

Fusion-Task-Lineage: 121c2b52-ad50-4475-b925-7a36ecfaf28b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 01:23:31 -07:00
gsxdsm
2ab0413c07 fix: make OMP process lifecycle tests full-suite safe (#2290)
## Summary
After #2289, Full Suite shard 4 still failed on the **OMP** twin of the
Grok process-lifecycle stress test (`import("../index.js")` × 15 under
shard transform load → 5s timeout).

Apply the same fix class as grok-runtime:
- Symbol.for exit reaper on `process-manager`
- Stress test reimports that module
- 15s timeout for cold transform

## Test plan
- [x] Local OMP process-lifecycle green
- [ ] PR gate
- [ ] Post-merge Full Suite

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

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved cleanup of OMP ACP processes when the application exits.
- Prevented duplicate exit handlers and excess listener growth during
runtime reloads.
- Preserved reliable process lifecycle behavior under repeated module
loading.

- **Tests**
  - Added lifecycle coverage for repeated process-manager reloads.
- Optimized the stress test to complete more efficiently while retaining
cleanup assertions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 01:19:14 -07:00
gsxdsm
57120f3d29 test: preserve default getTask mock for DUPLICATE recovery (#2283)
## Summary
Follow-up to #2275 review feedback: `getTask` mocks for DUPLICATE
recovery tests now return a default current-task fixture for
non-canonical IDs instead of `undefined`.

## Context
CodeRabbit on #2275 noted that returning `undefined` for every id except
the canonical task could break recovery if the subject task is
re-fetched mid-path.

## Test plan
- [x] `triage-split-into-subtasks-delete.test.ts`
- [x] `triage-finalize-duplicate-lineage.test.ts`

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

## Summary by CodeRabbit

* **Tests**
* Improved duplicate-resolution test coverage by preserving task data
during recovery and re-fetch scenarios.
* Added validation for non-canonical task handling to prevent errors
when duplicate tasks are resolved or split.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-18 00:57:06 -07:00
gsxdsm
5c7ed8b26f chore(release): v0.72.0
Version bump via changesets.
2026-07-18 00:52:59 -07:00
gsxdsm
38c6fdc60d fix: green full-suite after mock and stacking drift (#2287)
## Summary
Restacks onto latest main after #2285 and clears the remaining Full
Suite red classes from run
[29633869887](https://github.com/Runfusion/Fusion/actions/runs/29633869887)
(post-#2285):

- **Shard 1:** `agent-skills-flow` vitest TDZ — hoist `mockFiles` via
`vi.hoisted` (same class as skill-resolver in #2285)
- **Shard 2/3:** incomplete mocks after product drift
- `isFullScreenSheetViewport` / `isShortViewport` on viewport mocks
(without overriding dynamic mobile helpers)
  - `fetchCodebaseMetrics` on Command Center `api/legacy` mocks
  - `fetchSettings` on `agent-modals-mobile` api mock
- **Shard 3:** PlanningMode `ui-interactions` race — sync-settle
`fetchGlobalSettings` (FN-8245 pattern from planning-flow)
- **Shard 3:** settings search drift guard — inventory
`SettingsFieldRow` `htmlFor` keys (`mobileNavPrimaryItems`)
- **Shard 2:** FloatingWindow shared-stack product bug — only reclaim
z-index on hidden→visible (not every mount effect), so last-mounted
utility stays on top
- **Shard 4:** grok process-lifecycle timeout under shard load — prove
bound with 5 reimports instead of 15

## Test plan
- [x] `agent-skills-flow.test.ts` green
- [x] `process-lifecycle.test.ts` green
- [x] FileBrowserModal, FloatingWindowStack.cross-type,
agent-modals-mobile, settings-search-index, SystemControlsArea,
PlanningModeModal.ui-interactions + planning-flow (210 tests) green
- [ ] PR merge gate (Lint/Typecheck/Build/Gate)
- [ ] Post-merge Full Suite on `main` green

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved floating-window stacking so reopened or interacted windows
appear in the correct order.
* Restored consistent layering between floating windows and expanded
dock modals.
* **Tests**
* Updated automated coverage for viewport behavior, codebase metrics,
settings search indexing, and process lifecycle scenarios.
* Improved test reliability and consistency across responsive layouts
and modal interactions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 23:53:50 -07:00
gsxdsm
1afce9532a fix: green full-suite after product and CI PG drift (#2285)
## Summary
Main Full Suite was red again after release/desktop workflow drift,
engine mock gaps, mission landed-SHA gating, and compound-engineering PG
admin auth on GHA (`USER=runner`).

## Fixes
| Area | Failure | Fix |
|------|---------|-----|
| desktop `release-workflow` | expected old `find artifacts -type f` |
assert pruned collect + `release-files/*` |
| `step-session-executor` | missing
`resolveExecutorFallbackThinkingLevel` | mock export |
| tool-availability tests | empty tools (cascade from above) | fixed by
mock |
| `skill-resolver` | TDZ on `mockFiles` during import | `vi.hoisted`
filesystem state |
| `merge-error-recovery` | enqueue no-op when not started | set
`started=true` |
| mission behavioral posture | `blocked` (no landed SHA / git probe) |
`mergeDetails.commitSha` + staleness stub |
| GraphTaskNode | missing `useOptionalToast` | mock both toast exports |
| CE `pipeline-store.pg` | psql as `runner` | admin via
`FUSION_PG_TEST_URL_BASE` |

## Test plan
- [x] step-session-executor, skill-resolver, merge-error-recovery,
mission-validator-behavioral-posture (203)
- [x] release-workflow (10)
- [x] `pnpm --filter @fusion/engine test:core` (294)
- [ ] Full Suite (non-blocking) after merge

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

- **Bug Fixes**
- Improved desktop release artifact collection by pruning nested
`runtime` and `migrations` directories and consistently staging release
uploads via a dedicated `release-files` mapping.

- **Tests**
- Enhanced engine merge error-recovery coverage and mission validator
behavioral posture setup.
- Improved test reliability by synchronizing mocked filesystem state,
executor fallbacks, and toast hook variants.
- Updated Postgres test harness/admin commands to use a configurable
base URL; refined related Windows changeset description.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 23:22:04 -07:00
gsxdsm
7dda1aa3f5 chore(release): v0.71.0
Version bump via changesets.
2026-07-17 20:13:12 -07:00
gsxdsm
e31223c25f chore(release): v0.70.2
Version bump via changesets.
2026-07-17 19:17:17 -07:00
gsxdsm
eccb115c7e chore(release): v0.70.1
Version bump via changesets.
2026-07-17 18:17:15 -07:00
gsxdsm
e24f765495 FN-8252: rescue quarantined engine tests
Restore non-mechanical engine coverage with PostgreSQL-safe test fixtures and awaited overseer audit writes.

- migrate eligible engine tests to shared PostgreSQL harnesses and restore their Vitest coverage
- harden mission and advisory reporting paths for async persistence and observable failures
- await the production planner-overseer audit callback and verify the start() wiring preserves persistence

Files changed:
 .../__tests__/mission-autopilot-end-to-end.test.ts |  27 ++--
 .../engine/src/__tests__/mission-autopilot.test.ts |   4 +-
 .../planner-overseer-intervention-wiring.test.ts   |  39 +++---
 .../engine/src/__tests__/project-engine.test.ts    | 138 ++++++++++++++++-----
 .../unlinked-missions-advisory-reporter.pg.test.ts |  51 ++++++++
 .../unlinked-missions-advisory-reporter.test.ts    |  20 ++-
 packages/engine/src/mission-execution-loop.ts      |  27 ++--
 packages/engine/src/project-engine.ts              |  41 +++---
 .../src/unlinked-missions-advisory-reporter.ts     |  23 ++--
 packages/engine/vitest.config.ts                   |   6 +-
 scripts/lib/test-quarantine.json                   |  27 +---
 11 files changed, 260 insertions(+), 143 deletions(-)

Fusion-Task-Id: FN-8252
Fusion-Task-Lineage: 4f86ce7e-11a2-4704-a5d1-00e0a8c1448e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 17:28:36 -07:00
Victor Canô
9cafa045df fix(pr-merge): resolve repo from the project checkout, not process.cwd(), in PR-mode auto-merge (#2281)
## Summary

In a centrally-installed, multi-project Fusion server (one process
serving several repos, `process.cwd()` = the install dir, not any repo),
every task under `mergeStrategy: "pull-request"` fails at the auto-merge
stage with:

```
Could not determine repository. Specify owner/repo in params or run from a git repository with a GitHub remote.
```

PR creation from the dashboard and status polling work; only the
engine's automatic PR path fails. This is the **non-workspace sibling of
#1924** (FN-7610 routed workspace-mode tasks to direct merge but does
not cover regular multi-project tasks) and the completion of
#1797/FN-7133 (which fixed only the `getPrMergeStatus` arguments).

## Root cause

`GitHubClient.resolveRepo()` (`packages/dashboard/src/github.ts`) falls
back to a cwd-less `getCurrentRepo()` — i.e. `git remote get-url origin`
in `process.cwd()` — whenever a PR method is called without explicit
`owner`/`repo`. The engine merge path already resolves the correct repo
from the per-project cwd (`prRepo = getCurrentRepo(cwd)`, FN-7133) but
only threaded it into `getPrMergeStatus`. Every other GitHub call
omitted it:

- `processPullRequestMergeTask`: `findPrForBranch` / `createPr` /
`mergePr` on both the per-task and shared-branch-group paths
- `createGroupPrCallback` (group-PR promotion): `findPrForBranch` /
`createPr`
- `createPrNodeGithubOps` (`pr-create`/`pr-merge` workflow nodes):
cwd-less `getCurrentRepo()` persisted `entity.repo` as `""` (poisoning
the downstream `splitRepoSlug` consumers), and the git
push/`createPr`/`mergePr` ran against `process.cwd()`
- the engine's review-response run (`buildRespondCallback`):
`respondOps.getCwd` collapses to `process.cwd()` because no CLI
composition site wires `getTaskWorktree`, so its git ops and response
agent ran outside the project repo

In a central install the fallback throws; worse, if `process.cwd()`
happens to be inside some *other* git repo, it silently targets the
**wrong repository**.

## What changed

- `fix(pr-merge): thread repo identity into PR auto-merge GitHub calls`
— widens the CLI-local `GitHubOperations` interface (optional
`owner`/`repo`, already accepted by `GitHubClient`'s
`FindPrParams`/`CreatePrParams`/`MergePrParams`) and passes `prRepo` at
all six call sites in `processPullRequestMergeTask`.
- `fix(pr-merge): resolve group-PR repo from project cwd in
createGroupPrCallback` — resolves via `getCurrentRepo(cwd)` from the
callback input (same T4 pattern as `syncGroupPrCallback`) with a loud
failure instead of a silent wrong-repo fallback.
- `fix(pr-merge): resolve PR-node repo from task worktree instead of
process cwd` — `resolvePrSource` resolves from `task.worktree`, git ops
run in `getTaskWorktree(...) ?? task.worktree ?? process.cwd()`, and
`createPr`/`mergePr` pass `owner`/`repo` parsed from `entity.repo`.
- `fix(pr-merge): resolve review-response run cwd from the task
worktree` — the engine owns the store, so `buildRespondCallback` prefers
the task's recorded `worktree` for the response run's git ops + agent,
keeping `ops.getCwd` as the single-project fallback (defensive against
structural `PrNodeStore`s without `getTask`).
- Changeset (`@runfusion/fusion` patch, structured body) included.

Deliberately **not** done: a constructor-scoped default repo on
`GitHubClient` — one client instance is shared across all projects in a
central install (`serve.ts`/`daemon.ts`/`dashboard.ts`), so per-call
`owner`/`repo` is the only correct scope.

## Testing

- New regression tests simulate the central-install topology
(`getCurrentRepo` mocked as `(cwd?) => cwd ? repo : null`, exactly the
failing environment) and drive the merge flow end-to-end on the per-task
path, the shared-branch-group path, `createGroupPrCallback`, and all
three `createPrNodeGithubOps` ops, asserting every GitHub call carries
explicit `owner`/`repo` (45 tests in
`packages/cli/src/commands/__tests__/task-lifecycle.test.ts`, all
green).
- `packages/engine/src/__tests__/pr-respond-cwd-resolution.test.ts`
covers the respond-run cwd: worktree preferred, `ops.getCwd` fallback
when the task has no worktree, when the lookup fails, and when a
structural store has no `getTask`.
- Existing exact-argument assertions were extended to the new call
contract (no assertions weakened or removed).
- `pnpm lint`, `pnpm typecheck`, and `pnpm build` green locally; `pnpm
test:gate`'s engine-core suite green (294/294) — its PostgreSQL-backend
lane needs local PG credentials this environment lacks, so that lane
defers to CI. `pnpm verify:fast` (scoped typecheck/build + CLI build +
boot smoke) also passes.

## Repro

1. Install the CLI centrally; run the server from a dir that is not a
git repo, serving ≥1 project with a GitHub `origin` and `mergeStrategy:
"pull-request"`.
2. Run a task to completion and let it reach the merge stage.
3. Before this fix: the auto-merger throws `Could not determine
repository …` (tasks with a persisted PR poll fine but never merge).
Merging the same task from the Pull Requests tab succeeds, because the
dashboard route resolves the repo explicitly (`parseBadgeUrl(...) ??
getCurrentRepo(rootDir)`).

Full analysis: https://github.com/Tchori-Labs/Fusion/issues/4

---

Developed with Claude (co-authored on all commits).

https://claude.ai/code/session_01ChEa8SHFYNAzjCdFbwFMfh


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

- **Bug Fixes**
- Resolved pull request auto-merge failures in centrally installed,
multi-project deployments.
- Ensured explicit repository context (`owner/repo`) is used for pull
request lookup, creation, and merging throughout the merge workflow.
- Improved pull request response handling to prefer the task worktree
for working-directory resolution, with safe error behavior when task
details are unavailable.
- **Tests**
- Expanded coverage for multi-repository merge workflows and
worktree-based repository/cwd resolution in PR response handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-17 17:28:09 -07:00
gsxdsm
3fcab9fc1d fix: green full-suite after main product drift (#2275)
## Summary
Follow-up after #2266: full suite on latest `main` still failed on i18n
parity and engine product-drift tests (duplicate flagging, mission
validator signature, worktree path reservation, pi ModelRuntime,
assigned-agent PG layer).

## Changes
- **i18n**: add `listView/tasks.statusReplan` and mobile-nav settings
keys to es/fr/ko/zh-CN/zh-TW
- **triage**: opt-in `triageDuplicateResolution: "delete"` coverage +
default prompt/flag path; stub `recordActivity`
- **MCP PR response**: stub `getTask` for merger model resolution
- **pi-layers**: mock `ModelRuntime.create` (FN-8142)
- **assigned-agent**: stub `getAsyncLayer` for authoritative AgentStore
fallback
- **mission validation**: `startValidatorRun(..., taskId)` +
`runValidation` `{ result, inspection }` shape
- **worktree acquisition**: real temp roots for path reservation;
probe-aware worktrunk failure fixture
- **useBlockerFanout**: read `MAX_AUTO_MERGE_RETRIES` from
`self-healing-constants.ts` (wave-8 peel)

## Test plan
- [x] Targeted engine suites above (48 tests)
- [x] i18n parity + gate coverage
- [x] useBlockerFanout
- [x] `pnpm test:gate`
- [ ] Full Suite (non-blocking) on PR

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

* **Localization**
* Added “Replan”/replanning status labels across Spanish, French,
Korean, Simplified Chinese, and Traditional Chinese.
* Completed settings mobile navigation translations, including primary
items controls and reordering options.

* **Tests**
* Expanded coverage for validation recovery and task forwarding
behavior.
* Improved duplicate-resolution scenarios (including activity recording
and lineage deletion behavior).
* Increased test reliability for worktree acquisition by using temporary
filesystem roots.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 17:27:04 -07:00
gsxdsm
f5538e6253 chore(release): v0.70.0
Version bump via changesets.
2026-07-17 17:12:42 -07:00
gsxdsm
703488f0f3 fix(FN-8142): restore Anthropic OAuth refresh
Use the Claude OAuth client identity issued by the login flow and lock the request contract down with a regression assertion.
2026-07-17 16:26:20 -07:00
gsxdsm
62f121e0c9 FN-8247: stop session advisor with oversight
Stop now persists session-advisor disablement and reflects inherited advisor state in task details.

- Persist an explicit advisor-off override and clear its live runtime when stopping oversight.
- Resolve workflow-level advisor defaults for task-detail icons and toggle behavior.
- Cover stop cleanup and desktop/mobile oversight state transitions with regression tests.
- Document the combined stop contract and add a patch changeset.

Files changed:
 .changeset/fn-8247-session-advisor-stop-and-icon.md       |   7 ++
 docs/dashboard-guide.md                            |   6 +-
 packages/dashboard/app/components/TaskDetailModal.tsx   |  86 +++++++++++------
 packages/dashboard/app/components/__tests__/TaskDetailModal.oversight-controls.test.tsx    | 104 +++++++++++++++++++++
 packages/dashboard/app/components/__tests__/TaskDetailModal.oversight-mobile.test.tsx      |  62 ++++++++++++
 packages/engine/src/__tests__/project-engine-stop-overseer-session-advisor.test.ts |  62 ++++++++++++
 packages/engine/src/project-engine.ts              |  13 ++-
 7 files changed, 310 insertions(+), 30 deletions(-)

Fusion-Task-Id: FN-8247

Fusion-Task-Lineage: dcb67af7-9a36-4b25-bafa-84722fe158a0

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 16:20:10 -07:00
gsxdsm
600e9c9ecc FN-8242: fix triage duplicate-finalization test mock
Make triage duplicate-finalization tests provide the activity recorder used by the implementation.

- Add an awaited recordActivity mock to the shared TaskStore fixture.
- Select delete resolution in the reviewer-outage retry scenario so it reaches deleteTask.

Files changed:
 packages/engine/src/__tests__/triage.test.ts | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8242

Fusion-Task-Lineage: 8f9fd4b6-8071-47f3-8091-747884762ec9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 14:40:48 -07:00
gsxdsm
0b6957a1b2 FN-8241: log Plan Review revisions distinctly
Classify requested Plan Review changes as normal specification revision activity rather than workflow failures.

- Replace failure log actions for deterministic and reviewer-requested revisions
- Preserve failed workflow-result state for replan and recovery processing
- Cover revision logging across deterministic, reviewer, and retry paths

Files changed:
 .../triage-review-spec-external-integration.test.ts        |  5 ++++-
 packages/engine/src/__tests__/triage.test.ts               | 11 +++++++++++
 packages/engine/src/triage.ts                              | 14 ++++++++++++--
 3 files changed, 27 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-8241

Fusion-Task-Lineage: 316370ac-36c2-45b5-944f-602375167cdd

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 14:19:28 -07:00
gsxdsm
5d2c3be6a0 FN-8221: clear inactive planner overseer state
Clear retained planner overseer state when effective oversight is disabled.

- Remove monitor, recovery, advisor, and dedup runtime for oversight-off tasks.
- Suppress stale oversight-off Eye badges in task cards.
- Cover cleanup and badge behavior with regression tests.
- Document the runtime snapshot invariant and add a patch changeset.

Files changed:
 .changeset/fn-8221-overseer-badge-oversight-off.md |   7 ++
 docs/architecture.md                               |   4 +
 packages/dashboard/app/components/TaskCard.tsx     |   9 +-
 .../app/components/__tests__/TaskCard.test.tsx     |  20 ++++
 .../__tests__/planner-overseer-off-cleanup.test.ts | 119 +++++++++++++++++++++
 packages/engine/src/project-engine.ts              |  12 +++
 6 files changed, 170 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8221

Fusion-Task-Lineage: 01c9d838-fbe4-4d34-8eb5-d735cf35e581

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:27:44 -07:00
gsxdsm
5acea6c0cf fix(pg): route residual SQLite-stub store paths through the async data layer (#2273)
## Summary

An audit of the SQLite→PostgreSQL store migration found data-store paths
still reaching the removed SQLite stub in backend (PG) mode. In backend
mode `store.db`/`getDatabase()` throw the removed-SQLite error, so each
of these either threw on every run or — worse — had the throw swallowed
into a silent wrong result. This PR routes all of them through the
`AsyncDataLayer` (and removes one dead primitive).

## The 6 live bugs fixed

| Fix | Was |
|-----|-----|
| `executor.ts` authoritative assigned-agent fallback now inherits the
TaskStore `asyncLayer` | silently returned `null` → model drift to the
pi built-in (the exact thing its comment guards) |
| `pruneAgentLogFilesAsync` replaces the sync self-healing prune call |
threw `SQLite Database is not available` every maintenance sweep →
agent-log pruning never ran |
| `cleanupOrphanedMaterializedSteps` deletes PG `workflow_steps` rows on
a failed create | swallowed the throw → leaked rows |
| `deleteTaskBackendImpl` now runs the async mission feature/task-link
unlink | PG hard delete left orphaned mission links |
| `getWorkflowSettingsProjectId` returns `rootDir` in backend mode
without touching the stub | swallowed throw for unscoped backend stores
|
| `fn plugin` unregistered-project fallback bootstraps a `CentralCore`
`AsyncDataLayer` | layerless `PluginStore` threw in PG |

## The 4 latent traps, fixed properly

- **`cleanupArchivedTasks`** — real async port (enumerate archived
soft-deleted rows, guarantee cold snapshot, hard-delete project row +
purge selection rows + rm dir).
- **`deleteWorkflowStep`** — real async port (delete `workflow_steps`
via the layer with `.returning()` to preserve the not-found contract).
- **`applyTaskPatch`** — **removed** (zero-caller SQLite column-patch
primitive with no backend analogue; impl + facade + import deleted).
- **`AgentStore.importLegacyFileRuns`** — clean backend no-op (no legacy
SQLite run-files exist in a PG deployment; its only `init()` caller
early-returns in backend mode).

## Symptom Verification

New PG regression suite
`packages/core/src/__tests__/postgres/store-sqlite-residue-fixes.pg.test.ts`
reproduces the original failures against real embedded Postgres and
asserts they're gone:
- orphaned `workflow_steps` are actually deleted (no swallowed throw)
- `pruneAgentLogFilesAsync` resolves and prunes inactive-task log files
- hard delete unlinks the mission feature from the task
- `deleteWorkflowStep` removes the row / reports not-found
- `cleanupArchivedTasks` hard-deletes the project row while retaining
the cold snapshot

## Verification

- `@fusion/core`, `@fusion/engine`, `@runfusion/fusion` typecheck clean
- ~50 existing + 5 new PG tests pass; lint clean; changeset validates

🤖 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**
* Prevented PostgreSQL backend maintenance from hitting removed legacy
SQLite code paths, avoiding datastore failures and residue cleanup
issues.
* Fixed workflow-step deletion and “not found” behavior in backend mode.
* Ensured backend hard-deletes correctly unlink related mission
feature/task links and clean orphaned materialized steps.
* Prevented legacy file-run imports from incorrectly reporting success
in backend mode.
* **New Features**
* Added async agent-log pruning for inactive tasks and updated
maintenance to use it.
* **Tests**
* Added PostgreSQL regression coverage for residue fixes and
archive/workflow cleanup.
* **Refactor**
* Removed an unused task patch operation and updated task-store cleanup
methods to be async where needed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:22:21 -07:00
gsxdsm
a7ab3ccb49 fix(heartbeat): stop zombie-timer audit churning live-but-skipping timers (#2271)
## Problem

Permanent (durable) agent heartbeats went silent while the rest of the
engine kept running. Investigation of the live DB showed **every**
permanent agent's `heartbeatTimerRepair` metadata carrying
`nonAdvancingEscalated: true` with **3–63 consecutive** zombie re-arms —
the audit re-arming a timer every 60s for hours while emitting
`heartbeat-rearm-nonadvancing-escalated` warnings that never recovered
anything.

## Root cause

The heartbeat trigger audit classified a "zombie" (dead) timer **solely
from a stale `lastHeartbeatAt`**. But that column advances *only* on a
successful `"ok"` delivery (`agent-store.ts` `recordHeartbeat`). It
stays frozen whenever a heartbeat is intentionally skipped or no-op'd:

- agent over budget / over budget threshold
- `globalPause` / `enginePaused`
- `skipHeartbeatWhenIdle` on an idle agent
- idle "org" agents whose runs complete as `no_assignment_identity_run`

In all of these the interval keeps firing perfectly — the timer is
alive, delivery is just (correctly) skipped. Keying zombie detection off
`lastHeartbeatAt` misread those healthy timers as dead, re-armed them
every 60s, and escalated forever. Re-arming a live timer is a no-op, so
the loop could never recover — it only produced churn and phantom
warnings.

## Fix (the invariant)

Key zombie detection off **whether the interval physically fired**, not
whether delivery advanced.

- New `lastTimerFireAtMs` map, stamped at the top of `onTimerTick`
**before any gate** — a fired-but-skipped tick still counts as proof of
liveness.
- In the audit: a present + stale timer that fired within its stale
window is **left untouched** (no re-arm, no escalation, non-advancing
counter reset). Only a timer with **no recent fire** (a genuinely dead
interval) falls through to the existing re-arm/escalation path.
- Map cleaned up in `unregisterAgent()` / `stop()`.

This preserves the FN-7645 zombie repair (a timer that stops firing goes
stale in lockstep on both clocks and is still re-armed) and the FN-7939
watchdog, while eliminating the phantom churn for live-but-skipping
timers.

Why not "force a heartbeat" or "park the agent": forcing delivery would
bypass budget/pause governance, and parking a healthy idle agent would
be wrong. The correct action for a live-but-skipping timer is to leave
it alone — its next real tick delivers once the skip condition clears.

## Tests

- Rewrote the old `skipHeartbeatWhenIdle` test that codified the buggy
escalation → now asserts a **live** idle-skipping timer is left
untouched (no zombie re-arm, no escalation).
- Added a budget/no-assignment surface: a live timer that dispatches but
leaves `lastHeartbeatAt` frozen must not be misclassified.

`heartbeat-scheduler.test.ts` 120/120; broader heartbeat + concurrency
suites 349/349; `@fusion/engine` typecheck 0 errors.

## Review

Self-reviewed at medium effort. Two acknowledged, bounded trade-offs
(kept intentionally): a genuinely-dead-but-recently-fired timer's repair
latency is bounded at ~2× interval (same as the original FN-7645
latency), and the escalation warning is suppressed for live timers (it
only ever fired because of the churn this removes; per-tick error logs +
a new "left live-but-skipping timer" log retain visibility). One trivial
cleanup applied (single `Date.now()` sample).

## Notes

- Engine is a private package → no changeset.
- Complementary to a separate in-flight fix for the
agentStore/scheduler-not-constructed bug (why heartbeats stopped
*entirely*); this PR ensures that once the scheduler runs again, the
audit stops the phantom churn/escalation.

🤖 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**
* Improved heartbeat timer monitoring to distinguish healthy timers from
genuinely stopped timers.
* Prevented unnecessary timer re-registration and warning escalation
when heartbeats are intentionally skipped due to idle, paused,
budget-limited, or unassigned states.
* Improved recovery when a replacement timer stops firing, ensuring it
is detected and repaired reliably.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:15:41 -07:00
gsxdsm
eb7d223a03 FN-8207: add task reassignment for delegated work
Correct delegation routing for duplicate tasks and enable explicit task owner reassignment.

- Preserve requested assignee and todo routing on duplicate canonical tasks
- Add governed fn_task_assign to engine, heartbeat, triage, workflow, and chat sessions
- Cover assignment validation, truthful delegation responses, and tool availability

Files changed:
 .changeset/fn-8207-delegate-assign.md              |   7 ++
 docs/agents.md                                     |   6 ++
 packages/core/src/types.ts                         |   1 +
 packages/core/src/usage-events.ts                  |   2 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   |   2 +
 packages/dashboard/src/__tests__/chat.test.ts      |   2 +
 packages/dashboard/src/chat.ts                     |   2 +
 .../engine/src/__tests__/agent-action-gate.test.ts |   2 +
 .../src/__tests__/agent-tools-delegation.test.ts   |  99 ++++++++++++++++++-
 .../src/__tests__/agent-tools-task-assign.test.ts  |  75 +++++++++++++++
 .../src/__tests__/gating-classifications.test.ts   |   1 +
 .../src/__tests__/heartbeat-executor.test.ts       |   8 +-
 .../src/__tests__/permanent-agent-gating.test.ts   |   2 +
 .../src/__tests__/step-session-executor.test.ts    |   4 +-
 packages/engine/src/__tests__/triage.test.ts       |   5 +-
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 | 105 ++++++++++++++++++++-
 packages/engine/src/executor.ts                    |   3 +
 packages/engine/src/gating-classifications.ts      |   1 +
 packages/engine/src/index.ts                       |   2 +
 packages/engine/src/step-session-executor.ts       |   2 +
 packages/engine/src/triage.ts                      |   2 +
 22 files changed, 324 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-8207

Fusion-Task-Lineage: db6f3876-bdc8-4279-b726-29344d9acdb9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:53:19 -07:00
gsxdsm
7a50232916 FN-8208: validate agent message recipients before delivery
Prevent false-success agent messages by validating recipients before delivery.

- Wire AgentStore into every send-message tool registration.
- Reject missing or unvalidated agent recipients before persistence or wake-up.
- Add recipient validation coverage and a patch changeset.

Files changed:
 .../fn-8208-send-message-recipient-validation.md   |   7 ++
 .../chat-send-message-agentstore-wiring.test.ts    |  11 ++
 packages/dashboard/src/chat.ts                     |   2 +-
 ...tools-send-message-recipient-validation.test.ts | 116 +++++++++++++++++++++
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 |  24 ++++-
 packages/engine/src/executor.ts                    |   2 +-
 packages/engine/src/step-session-executor.ts       |   2 +-
 8 files changed, 162 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8208
Fusion-Task-Lineage: 84752bb8-c9f7-42bd-87c1-9681ac442789
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:07:24 -07:00
gsxdsm
28878d8125 FN-8206: validate landed merge checkout
Validate mission assertions against the delivered merge revision rather than an ambient working branch.

- Materialize and dispose a detached checkout at mergeDetails.commitSha for validator sessions.
- Defer failed validation when landed-code ancestry cannot be proven, preventing spurious fix features.
- Link validator runs to their board tasks and document the inspection behavior.

Files changed:
 .changeset/fn-8206-mission-validator-inspection-root.md   |   7 +
 docs/missions.md                                          |   2 +
 packages/engine/src/__tests__/mission-execution-loop.test.ts | 278 +++++++++++++--------
 packages/engine/src/mission-execution-loop.ts             | 160 ++++++++----
 4 files changed, 298 insertions(+), 149 deletions(-)

Fusion-Task-Id: FN-8206

Fusion-Task-Lineage: dfd1eb21-fcdf-4722-acb8-416750f4f40b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:00:18 -07:00
gsxdsm
7fc4b439ee FN-8205: fix shared auth credential lock retries
Serialize shared auth credential writes and await durable persistence under contention.

- Replace synchronous auth-file locking with queued asynchronous retries.
- Propagate asynchronous credential mutations through CLI, dashboard, and provider wrappers.
- Cover held-lock persistence, queue recovery, and awaited caller behavior.

Files changed:
 .changeset/fn-8205-auth-lock-retry.md              |   7 ++
 .../cli/src/commands/__tests__/onboard.test.ts     |  17 +++
 .../src/commands/__tests__/provider-auth.test.ts   |  78 ++++++------
 packages/cli/src/commands/onboard.ts               |   2 +-
 packages/dashboard/src/routes.ts                   |   6 +-
 .../dashboard/src/routes/register-auth-routes.ts   |  10 +-
 .../dashboard/src/routes/register-mesh-routes.ts   |   4 +-
 .../register-settings-sync-inbound-routes.ts       |   4 +-
 .../src/routes/register-settings-sync-routes.ts    |   4 +-
 .../src/__tests__/auth-storage-concurrency.test.ts |  84 ++++++++++---
 packages/engine/src/__tests__/auth-storage.test.ts |  48 ++++----
 packages/engine/src/auth-storage.ts                | 137 +++++++++++++--------
 packages/engine/src/provider-auth.ts               |  56 ++++-----
 13 files changed, 284 insertions(+), 173 deletions(-)

Fusion-Task-Id: FN-8205

Fusion-Task-Lineage: b932b9ce-9aee-4f0a-9155-63b026c6bde4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:47:40 -07:00
gsxdsm
e445b3e367 FN-8201: pin pi dependency versions
Pin the pi runtime packages to a single exact version so global npm installs resolve a compatible set.

- Pin pi-ai and pi-coding-agent declarations across workspace manifests
- Add a guard and tests that reject ranged or mismatched pi versions
- Document the source-install fallback and add a patch changeset

Files changed:
 .changeset/fn-8201-pin-pi-versions.md              |   7 ++
 docs/getting-started.md                            |   3 +
 package.json                                       |   6 +-
 packages/cli/package.json                          |   4 +-
 packages/cli/src/__tests__/package-config.test.ts  |  18 +++-
 packages/core/package.json                         |   2 +-
 packages/dashboard/package.json                    |   2 +-
 packages/engine/package.json                       |   4 +-
 packages/pi-claude-cli/package.json                |   8 +-
 .../__tests__/check-pi-versions-pinned.test.mjs    |  45 ++++++++
 scripts/check-pi-versions-pinned.mjs               | 120 +++++++++++++++++++++
 11 files changed, 205 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-8201

Fusion-Task-Lineage: bf0ac363-df5f-4445-835b-cfd2d4909659

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:12:01 -07:00
gsxdsm
6ca7e48f87 fix(FN-7965): surface duplicate decisions
Show a clear operator-decision badge and deliver an idempotent mailbox prompt for triage duplicate markers.

Fusion-Task-Id: FN-7965
2026-07-17 08:53:44 -07:00