diff options
| author | soryu <soryu@soryu.co> | 2026-01-18 19:55:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-18 19:55:37 +0000 |
| commit | b3eb58d50eea5b235a1c33d5c8787dc81064c46b (patch) | |
| tree | 50e174970ecd42c60d2efc571cad12eb27e43ffc | |
| parent | 9dbc2c3199047609a9f8496fec07ecdb10aee73d (diff) | |
| download | soryu-b3eb58d50eea5b235a1c33d5c8787dc81064c46b.tar.gz soryu-b3eb58d50eea5b235a1c33d5c8787dc81064c46b.zip | |
Clean up mesh page (#6)
* Filter mesh page task list to show only supervisor tasks
- Add `isSupervisor` filter to rootTasks filter in TaskList component
- Only supervisor tasks will appear in the mesh page task list
- Regular tasks are now hidden from the main view
- Update empty state messages to reflect supervisor-only filtering
- When clicking a supervisor task, its detail still shows orchestrated tasks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add supervisor task button to workflow board contract cards
- Add supervisorTaskId field to ContractSummary type in backend and frontend
- Update SQL queries in repository.rs to include supervisor_task_id
- Add navigation button (▶) to WorkflowContractCard that links to /mesh/{supervisorTaskId}
- Button only shows when contract has a supervisorTaskId
- Button has tooltip "Open Supervisor Task" and stops propagation to avoid triggering card click
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add full task page navigation button to TaskTree rows
Add a hover-visible arrow icon (↗) to each task row in the TaskTree
component that links to the full task page (/tasks/{taskId}). The button:
- Appears on hover using opacity transition
- Stops event propagation to avoid triggering parent onSelect
- Matches existing hover styling patterns with the #75aafc color scheme
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
| -rw-r--r-- | makima/frontend/src/components/mesh/TaskList.tsx | 8 | ||||
| -rw-r--r-- | makima/frontend/src/components/mesh/TaskTree.tsx | 10 | ||||
| -rw-r--r-- | makima/frontend/src/components/workflow/WorkflowContractCard.tsx | 26 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 2 | ||||
| -rw-r--r-- | makima/src/db/models.rs | 2 | ||||
| -rw-r--r-- | makima/src/db/repository.rs | 4 | ||||
| -rw-r--r-- | makima/src/server/handlers/contracts.rs | 4 | ||||
| -rw-r--r-- | makima/src/server/handlers/mesh.rs | 1 |
8 files changed, 48 insertions, 9 deletions
diff --git a/makima/frontend/src/components/mesh/TaskList.tsx b/makima/frontend/src/components/mesh/TaskList.tsx index f829b29..80077b6 100644 --- a/makima/frontend/src/components/mesh/TaskList.tsx +++ b/makima/frontend/src/components/mesh/TaskList.tsx @@ -95,8 +95,8 @@ export function TaskList({ // Group tasks by contract and filter by status const groupedTasks = useMemo(() => { - // Separate root tasks (no parent) from subtasks - const rootTasks = tasks.filter((t) => !t.parentTaskId); + // Separate root tasks (no parent) from subtasks, and only show supervisor tasks + const rootTasks = tasks.filter((t) => !t.parentTaskId && t.isSupervisor); // Filter tasks based on contract status const filteredTasks = statusFilter === 'all' @@ -205,8 +205,8 @@ export function TaskList({ {totalTasks === 0 ? ( <div className="text-center text-[#9bc3ff] text-sm font-mono opacity-60 py-8"> {statusFilter === 'all' - ? 'No tasks yet. Create one to start orchestrating Claude Code instances.' - : `No ${statusFilter} tasks found.`} + ? 'No supervisor tasks yet. Create a contract to start orchestrating tasks.' + : `No ${statusFilter} supervisor tasks found.`} </div> ) : ( <div> diff --git a/makima/frontend/src/components/mesh/TaskTree.tsx b/makima/frontend/src/components/mesh/TaskTree.tsx index 46ae78d..296d3c6 100644 --- a/makima/frontend/src/components/mesh/TaskTree.tsx +++ b/makima/frontend/src/components/mesh/TaskTree.tsx @@ -165,6 +165,16 @@ function TreeNode({ task, isSupervisorTask, onSelect, depth, fetchSubtasks }: Tr P{task.priority} </span> )} + + {/* Open in full page button */} + <a + href={`/tasks/${task.id}`} + onClick={(e) => e.stopPropagation()} + className="font-mono text-[10px] text-[#555] opacity-0 group-hover:opacity-100 hover:text-[#75aafc] transition-all" + title="Open task page" + > + ↗ + </a> </div> {/* Children */} diff --git a/makima/frontend/src/components/workflow/WorkflowContractCard.tsx b/makima/frontend/src/components/workflow/WorkflowContractCard.tsx index e6c8a1c..61e6d17 100644 --- a/makima/frontend/src/components/workflow/WorkflowContractCard.tsx +++ b/makima/frontend/src/components/workflow/WorkflowContractCard.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from "react-router"; import type { ContractSummary, ContractStatus } from "../../lib/api"; interface WorkflowContractCardProps { @@ -17,8 +18,16 @@ export function WorkflowContractCard({ onClick, onDragStart, }: WorkflowContractCardProps) { + const navigate = useNavigate(); const status = statusConfig[contract.status] || statusConfig.active; + const handleSupervisorClick = (e: React.MouseEvent) => { + e.stopPropagation(); + if (contract.supervisorTaskId) { + navigate(`/mesh/${contract.supervisorTaskId}`); + } + }; + return ( <div draggable @@ -26,9 +35,20 @@ export function WorkflowContractCard({ onClick={onClick} className="p-3 bg-[rgba(9,13,20,0.8)] border border-[rgba(117,170,252,0.2)] hover:border-[rgba(117,170,252,0.4)] cursor-pointer transition-colors select-none" > - {/* Name */} - <div className="font-mono text-sm text-[#dbe7ff] truncate mb-1"> - {contract.name} + {/* Header row with name and supervisor button */} + <div className="flex items-center justify-between gap-2 mb-1"> + <div className="font-mono text-sm text-[#dbe7ff] truncate flex-1"> + {contract.name} + </div> + {contract.supervisorTaskId && ( + <button + onClick={handleSupervisorClick} + title="Open Supervisor Task" + className="flex-shrink-0 px-1.5 py-0.5 font-mono text-[10px] text-[#75aafc] hover:text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.1)] transition-colors" + > + ▶ + </button> + )} </div> {/* Status and counts row */} diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index abf72b8..daa2b5c 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -1462,6 +1462,8 @@ export interface ContractSummary { contractType: ContractType; phase: ContractPhase; status: ContractStatus; + /** Supervisor task ID for contract orchestration */ + supervisorTaskId: string | null; fileCount: number; taskCount: number; repositoryCount: number; diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index 3e6997f..65f7168 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -1348,6 +1348,8 @@ pub struct ContractSummary { pub contract_type: String, pub phase: String, pub status: String, + /// Supervisor task ID for contract orchestration + pub supervisor_task_id: Option<Uuid>, pub file_count: i64, pub task_count: i64, pub repository_count: i64, diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 36e6bc1..536bc9b 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -2190,7 +2190,7 @@ pub async fn list_contracts_for_owner( r#" SELECT c.id, c.name, c.description, c.contract_type, c.phase, c.status, - c.version, c.created_at, + c.supervisor_task_id, c.version, c.created_at, (SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count, (SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count, (SELECT COUNT(*) FROM contract_repositories WHERE contract_id = c.id) as repository_count @@ -2214,7 +2214,7 @@ pub async fn get_contract_summary_for_owner( r#" SELECT c.id, c.name, c.description, c.contract_type, c.phase, c.status, - c.version, c.created_at, + c.supervisor_task_id, c.version, c.created_at, (SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count, (SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count, (SELECT COUNT(*) FROM contract_repositories WHERE contract_id = c.id) as repository_count diff --git a/makima/src/server/handlers/contracts.rs b/makima/src/server/handlers/contracts.rs index 4f4a94b..4524860 100644 --- a/makima/src/server/handlers/contracts.rs +++ b/makima/src/server/handlers/contracts.rs @@ -371,6 +371,7 @@ pub async fn create_contract( contract_type: contract.contract_type, phase: contract.phase, status: contract.status, + supervisor_task_id: contract.supervisor_task_id, file_count: 0, task_count: 0, repository_count: 0, @@ -391,6 +392,7 @@ pub async fn create_contract( contract_type: contract.contract_type, phase: contract.phase, status: contract.status, + supervisor_task_id: contract.supervisor_task_id, file_count: 0, task_count: 0, repository_count: 0, @@ -518,6 +520,7 @@ pub async fn update_contract( contract_type: contract.contract_type, phase: contract.phase, status: contract.status, + supervisor_task_id: contract.supervisor_task_id, file_count: 0, task_count: 0, repository_count: 0, @@ -1398,6 +1401,7 @@ pub async fn change_phase( contract_type: updated_contract.contract_type, phase: updated_contract.phase, status: updated_contract.status, + supervisor_task_id: updated_contract.supervisor_task_id, file_count: 0, task_count: 0, repository_count: 0, diff --git a/makima/src/server/handlers/mesh.rs b/makima/src/server/handlers/mesh.rs index f710be1..e9a421c 100644 --- a/makima/src/server/handlers/mesh.rs +++ b/makima/src/server/handlers/mesh.rs @@ -3447,6 +3447,7 @@ pub async fn create_adhoc_task( contract_type: contract.contract_type, phase: contract.phase, status: contract.status, + supervisor_task_id: contract.supervisor_task_id, file_count: 0, task_count: 1, repository_count: 0, |
