feat(FN-3498): add self-healing and ownership-aware done-task merge reconci

The merge completes FN-3498 across three steps: adds ownership-aware done-task reconciliation to the merger, prevents branch-missing head SHA pollution during merge operations, and restores workspace typecheck compatibility. Core changes touch the merger (103 lines) and self-healing module (67 lines

Fusion-Task-Id: FN-3498
This commit is contained in:
Fusion
2026-05-05 13:42:39 -07:00
committed by gsxdsm
parent 57c67b6bbd
commit 36493eca0f
11 changed files with 277 additions and 73 deletions

View File

@@ -36,7 +36,7 @@ import { useCurrentProject } from "./hooks/useCurrentProject";
import { ToastProvider, useToast } from "./hooks/useToast";
import { ConfirmDialogProvider } from "./hooks/useConfirm";
import { useTheme } from "./hooks/useTheme";
import { useModalManager, type DetailTaskOrigin } from "./hooks/useModalManager";
import { useModalManager, type DetailTaskOrigin, type DetailTaskTab } from "./hooks/useModalManager";
import { useAppSettings } from "./hooks/useAppSettings";
import { useDeepLink } from "./hooks/useDeepLink";
import { useFavorites } from "./hooks/useFavorites";
@@ -879,10 +879,8 @@ function AppInner() {
tasks: isRemote && remoteData.tasks.length > 0 ? remoteData.tasks : tasks,
workflowSteps,
openTaskDetail: isMobile
? (task: Task | TaskDetail, initialTab?: Parameters<typeof modalManager.openDetailTask>[1]) =>
openDetailTaskWithHistory(task, initialTab)
: (task: Task | TaskDetail, initialTab?: Parameters<typeof modalManager.openDetailTask>[1]) =>
modalManager.openDetailTask(task, initialTab),
? (task: Task | TaskDetail, initialTab?: DetailTaskTab) => openDetailTaskWithHistory(task, initialTab)
: (task: Task | TaskDetail, initialTab?: DetailTaskTab) => modalManager.openDetailTask(task, initialTab),
renderTaskCard: (task: Task | TaskDetail) => (
<TaskCard
task={task}

View File

@@ -1172,7 +1172,7 @@ describe("PlanningModeModal", () => {
await waitFor(() => {
expect(screen.getByText("What are the key requirements?")).toBeDefined();
});
}, { timeout: 5000 });
expect(screen.getByTestId("conversation-history")).toBeDefined();
expect(screen.getByText("What is the scope?")).toBeDefined();

View File

@@ -5,7 +5,7 @@ import "./pluginViewRegistry.css";
export type PluginTaskView = `plugin:${string}:${string}`;
type PluginViewComponent = LazyExoticComponent<() => ReactNode>;
type PluginViewComponent = LazyExoticComponent<() => ReactElement>;
const registry = new Map<string, PluginViewComponent>();