From 94e5604e770d6589f786ea71e51738e21492f301 Mon Sep 17 00:00:00 2001 From: soryu Date: Wed, 21 Jan 2026 17:31:46 +0000 Subject: Add task branching feature (#15) --- makima/frontend/src/components/mesh/TaskDetail.tsx | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'makima/frontend/src/components/mesh/TaskDetail.tsx') diff --git a/makima/frontend/src/components/mesh/TaskDetail.tsx b/makima/frontend/src/components/mesh/TaskDetail.tsx index efe26a8..a74f394 100644 --- a/makima/frontend/src/components/mesh/TaskDetail.tsx +++ b/makima/frontend/src/components/mesh/TaskDetail.tsx @@ -6,6 +6,7 @@ import { OverlayDiffViewer } from "./OverlayDiffViewer"; import { PRPreview } from "./PRPreview"; import { InlineSubtaskEditor } from "./InlineSubtaskEditor"; import { DirectoryInput } from "./DirectoryInput"; +import { BranchTaskModal } from "./BranchTaskModal"; interface TaskDetailProps { task: TaskWithSubtasks; @@ -25,6 +26,8 @@ interface TaskDetailProps { viewingSubtaskId?: string | null; /** Navigate to view the contract */ onViewContract?: (contractId: string) => void; + /** Branch the task to create a new task with same state */ + onBranch?: (taskId: string, message: string, name?: string) => Promise; // Optional advanced features overlayDiff?: string; changedFiles?: string[]; @@ -110,6 +113,7 @@ export function TaskDetail({ onToggleSubtaskOutput, viewingSubtaskId, onViewContract, + onBranch, overlayDiff, changedFiles, onRequestDiff, @@ -142,6 +146,8 @@ export function TaskDetail({ const [isCloning, setIsCloning] = useState(false); const [cloneError, setCloneError] = useState(null); const [cloneTargetDir, setCloneTargetDir] = useState(""); + // Track branch modal state + const [showBranchModal, setShowBranchModal] = useState(false); // Check if task is running const isTaskRunning = task.status === "running" || task.status === "initializing" || task.status === "starting"; @@ -151,6 +157,8 @@ export function TaskDetail({ const isSupervisor = task.isSupervisor === true; // Show continue for supervisors (always) or terminal states for other tasks const canContinue = isSupervisor || isTaskTerminal; + // Show branch button when task has run at least once (not pending) + const canBranch = onBranch && task.status !== "pending"; // Determine which tasks to show: for supervisors, show contractTasks; for regular tasks, show subtasks const displayTasks = useMemo(() => { @@ -380,6 +388,15 @@ export function TaskDetail({ Continue )} + {canBranch && ( + + )}