summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-22 13:17:17 +0000
committerGitHub <noreply@github.com>2026-01-22 13:17:17 +0000
commit265f8cf14fec9d7116d09af49e4b48b357faceda (patch)
treec98ff8be7dd5f01692446e01c7b568279b0635ac
parenta363bfdd7a3e81b75bf230e45d001b80f759ca57 (diff)
downloadsoryu-265f8cf14fec9d7116d09af49e4b48b357faceda.tar.gz
soryu-265f8cf14fec9d7116d09af49e4b48b357faceda.zip
Fix completion actions: default to PR and support remote repos (#21)
* Fix completion actions: default to PR and support remote repos - Change default completion action from 'branch' to 'pr' for tasks using daemon working directory - Allow PR completion action to work without target_repo_path if the worktree already has an origin remote configured (e.g., when cloned from a remote URL) - Update create_pull_request to accept optional target_repo parameter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add dismiss functionality for completed standalone tasks ## Changes ### Backend - Add 'hidden' field to Task model (models.rs) - Add database migration for hidden column (20250122000000_add_task_hidden.sql) - Update task listing queries to include hidden field and filter out hidden tasks - Update update_task_for_owner to handle hidden field ### Frontend - Add hidden field to TaskSummary interface (api.ts) - Add dismissTask API function (api.ts) - Add hideTask function to useTasks hook - Add Dismiss button to TaskList for completed standalone tasks - Wire up onDismiss handler in mesh.tsx route ## Behavior - Completed standalone tasks (tasks without a contract) show a "Dismiss" button - Dismissing a task sets hidden=true and removes it from the task list - Hidden tasks are filtered out by default in all task listing queries 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.tsx38
-rw-r--r--makima/frontend/src/hooks/useTasks.ts17
-rw-r--r--makima/frontend/src/lib/api.ts16
-rw-r--r--makima/frontend/src/routes/mesh.tsx10
-rw-r--r--makima/migrations/20250122000000_add_task_hidden.sql5
-rw-r--r--makima/src/daemon/task/manager.rs31
-rw-r--r--makima/src/daemon/worktree/manager.rs131
-rw-r--r--makima/src/db/models.rs12
-rw-r--r--makima/src/db/repository.rs25
-rw-r--r--makima/src/server/handlers/mesh_chat.rs4
10 files changed, 209 insertions, 80 deletions
diff --git a/makima/frontend/src/components/mesh/TaskList.tsx b/makima/frontend/src/components/mesh/TaskList.tsx
index e3f2862..016fef5 100644
--- a/makima/frontend/src/components/mesh/TaskList.tsx
+++ b/makima/frontend/src/components/mesh/TaskList.tsx
@@ -6,6 +6,7 @@ interface TaskListProps {
loading: boolean;
onSelect: (id: string) => void;
onDelete: (id: string) => void;
+ onDismiss: (id: string) => void;
onCreate: () => void;
}
@@ -88,6 +89,7 @@ export function TaskList({
loading,
onSelect,
onDelete,
+ onDismiss,
onCreate,
}: TaskListProps) {
// Filter state - default to 'active' to show only active contracts
@@ -300,17 +302,31 @@ export function TaskList({
</div>
</button>
{/* Supervisor tasks cannot be deleted directly - they are deleted with the contract */}
- {!task.isSupervisor && (
- <button
- onClick={(e) => {
- e.stopPropagation();
- onDelete(task.id);
- }}
- className="px-2 py-1 font-mono text-[10px] text-red-400 hover:bg-red-400/10 border border-red-400/30 hover:border-red-400/50 transition-colors uppercase"
- >
- Delete
- </button>
- )}
+ <div className="flex gap-2">
+ {/* Show dismiss button for completed standalone tasks (tasks without a contract) */}
+ {!task.contractId && (task.status === "done" || task.status === "failed" || task.status === "merged") && (
+ <button
+ onClick={(e) => {
+ e.stopPropagation();
+ onDismiss(task.id);
+ }}
+ className="px-2 py-1 font-mono text-[10px] text-[#8b949e] hover:bg-[rgba(117,170,252,0.1)] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] transition-colors uppercase"
+ >
+ Dismiss
+ </button>
+ )}
+ {!task.isSupervisor && (
+ <button
+ onClick={(e) => {
+ e.stopPropagation();
+ onDelete(task.id);
+ }}
+ className="px-2 py-1 font-mono text-[10px] text-red-400 hover:bg-red-400/10 border border-red-400/30 hover:border-red-400/50 transition-colors uppercase"
+ >
+ Delete
+ </button>
+ )}
+ </div>
</div>
</div>
))}
diff --git a/makima/frontend/src/hooks/useTasks.ts b/makima/frontend/src/hooks/useTasks.ts
index 6e6c992..4667c4c 100644
--- a/makima/frontend/src/hooks/useTasks.ts
+++ b/makima/frontend/src/hooks/useTasks.ts
@@ -5,6 +5,7 @@ import {
createTask,
updateTask,
deleteTask,
+ dismissTask,
VersionConflictError,
type TaskSummary,
type TaskWithSubtasks,
@@ -110,6 +111,21 @@ export function useTasks() {
[fetchTasks]
);
+ const hideTask = useCallback(
+ async (id: string): Promise<boolean> => {
+ setError(null);
+ try {
+ await dismissTask(id);
+ await fetchTasks(); // Refresh list
+ return true;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Failed to dismiss task");
+ return false;
+ }
+ },
+ [fetchTasks]
+ );
+
// Initial fetch
useEffect(() => {
fetchTasks();
@@ -126,5 +142,6 @@ export function useTasks() {
saveTask,
editTask,
removeTask,
+ hideTask,
};
}
diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts
index aeaa218..76ee4d4 100644
--- a/makima/frontend/src/lib/api.ts
+++ b/makima/frontend/src/lib/api.ts
@@ -543,6 +543,8 @@ export interface TaskSummary {
subtaskCount: number;
/** Whether this is a supervisor task (contract orchestrator) */
isSupervisor: boolean;
+ /** Whether this task is hidden from the UI (user dismissed it) */
+ hidden: boolean;
version: number;
createdAt: string;
updatedAt: string;
@@ -639,6 +641,8 @@ export interface UpdateTaskRequest {
targetRepoPath?: string;
/** Action on completion: "none", "branch", "merge", "pr" */
completionAction?: CompletionAction;
+ /** Whether this task is hidden from the UI (user dismissed it) */
+ hidden?: boolean;
version?: number;
}
@@ -2657,3 +2661,15 @@ export function getSupervisorStatus(
canResume,
};
}
+
+// =============================================================================
+// Task Dismiss (Hide) Functions
+// =============================================================================
+
+/**
+ * Dismiss (hide) a completed standalone task from the UI.
+ * This marks the task as hidden so it won't appear in the task list.
+ */
+export async function dismissTask(taskId: string): Promise<Task> {
+ return updateTask(taskId, { hidden: true });
+}
diff --git a/makima/frontend/src/routes/mesh.tsx b/makima/frontend/src/routes/mesh.tsx
index 425721d..fb366a2 100644
--- a/makima/frontend/src/routes/mesh.tsx
+++ b/makima/frontend/src/routes/mesh.tsx
@@ -81,7 +81,7 @@ export default function MeshPage() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth();
- const { tasks, loading, error, conflict, clearConflict, fetchTask, fetchTasks, editTask, removeTask, saveTask } = useTasks();
+ const { tasks, loading, error, conflict, clearConflict, fetchTask, fetchTasks, editTask, removeTask, hideTask, saveTask } = useTasks();
const { pendingQuestions, submitAnswer } = useSupervisorQuestions();
// Memoize pending question IDs for efficient lookup
@@ -408,6 +408,13 @@ export default function MeshPage() {
[removeTask, id, taskDetail, navigate]
);
+ const handleDismiss = useCallback(
+ async (taskId: string) => {
+ await hideTask(taskId);
+ },
+ [hideTask]
+ );
+
const handleStart = useCallback(
async (taskId: string) => {
try {
@@ -868,6 +875,7 @@ export default function MeshPage() {
loading={loading || creating}
onSelect={handleSelectTask}
onDelete={handleDelete}
+ onDismiss={handleDismiss}
onCreate={handleCreate}
/>
</div>
diff --git a/makima/migrations/20250122000000_add_task_hidden.sql b/makima/migrations/20250122000000_add_task_hidden.sql
new file mode 100644
index 0000000..42eed52
--- /dev/null
+++ b/makima/migrations/20250122000000_add_task_hidden.sql
@@ -0,0 +1,5 @@
+-- Add hidden column to tasks table for dismissing completed standalone tasks
+ALTER TABLE tasks ADD COLUMN hidden BOOLEAN NOT NULL DEFAULT FALSE;
+
+-- Create index for filtering hidden tasks efficiently
+CREATE INDEX IF NOT EXISTS idx_tasks_hidden ON tasks(hidden) WHERE hidden = false;
diff --git a/makima/src/daemon/task/manager.rs b/makima/src/daemon/task/manager.rs
index 95554e9..0cba516 100644
--- a/makima/src/daemon/task/manager.rs
+++ b/makima/src/daemon/task/manager.rs
@@ -4277,16 +4277,25 @@ impl TaskManagerInner {
target_repo_path: Option<&str>,
target_branch: Option<&str>,
) -> Result<Option<String>, String> {
+ // For PR action, we can use the worktree's origin directly if target_repo_path is not set
let target_repo = match target_repo_path {
- Some(path) => crate::daemon::worktree::expand_tilde(path),
+ Some(path) => Some(crate::daemon::worktree::expand_tilde(path)),
None => {
- tracing::warn!(task_id = %task_id, "No target_repo_path configured, skipping completion action");
- return Ok(None);
+ if action == "pr" {
+ // For PR action, check if worktree has an origin remote we can use directly
+ None
+ } else {
+ tracing::warn!(task_id = %task_id, "No target_repo_path configured, skipping completion action");
+ return Ok(None);
+ }
}
};
- if !target_repo.exists() {
- return Err(format!("Target repo not found: {} (expanded from {:?})", target_repo.display(), target_repo_path));
+ // Validate target_repo exists if provided
+ if let Some(ref repo) = target_repo {
+ if !repo.exists() {
+ return Err(format!("Target repo not found: {} (expanded from {:?})", repo.display(), target_repo_path));
+ }
}
// Get the branch name: makima/{task-name-with-dashes}-{short-id}
@@ -4296,13 +4305,14 @@ impl TaskManagerInner {
crate::daemon::worktree::short_uuid(task_id)
);
- // Determine target branch - use provided value or detect default branch of target repo
+ // Determine target branch - use provided value or detect default branch
let target_branch = match target_branch {
Some(branch) => branch.to_string(),
None => {
- // Detect default branch (main, master, develop, etc.)
+ // Detect default branch from target_repo if available, otherwise from worktree
+ let detect_path = target_repo.as_ref().map(|p| p.as_path()).unwrap_or(worktree_path);
self.worktree_manager
- .detect_default_branch(&target_repo)
+ .detect_default_branch(detect_path)
.await
.unwrap_or_else(|_| "master".to_string())
}
@@ -4317,6 +4327,7 @@ impl TaskManagerInner {
match action {
"branch" => {
+ let target_repo = target_repo.ok_or_else(|| "No target_repo_path configured for branch action".to_string())?;
// Just push the branch to target repo
self.worktree_manager
.push_to_target_repo(worktree_path, &target_repo, &branch_name, task_name)
@@ -4332,6 +4343,7 @@ impl TaskManagerInner {
Ok(None)
}
"merge" => {
+ let target_repo = target_repo.ok_or_else(|| "No target_repo_path configured for merge action".to_string())?;
// Push and merge into target branch
let commit_sha = self.worktree_manager
.merge_to_target(worktree_path, &target_repo, &branch_name, &target_branch, task_name)
@@ -4348,6 +4360,7 @@ impl TaskManagerInner {
}
"pr" => {
// Push and create PR
+ // For PR, we can use target_repo if provided, or create PR directly from worktree
let title = task_name.to_string();
let body = format!(
"Automated PR from makima task.\n\nTask ID: `{}`",
@@ -4356,7 +4369,7 @@ impl TaskManagerInner {
let pr_url = self.worktree_manager
.create_pull_request(
worktree_path,
- &target_repo,
+ target_repo.as_deref(),
&branch_name,
&target_branch,
&title,
diff --git a/makima/src/daemon/worktree/manager.rs b/makima/src/daemon/worktree/manager.rs
index d370828..5edd7b1 100644
--- a/makima/src/daemon/worktree/manager.rs
+++ b/makima/src/daemon/worktree/manager.rs
@@ -1470,10 +1470,11 @@ impl WorktreeManager {
/// Create a GitHub pull request using the gh CLI.
///
/// This pushes the branch first, then creates a PR.
+ /// If target_repo is None, uses the worktree's origin remote directly (for repos already cloned from remote).
pub async fn create_pull_request(
&self,
worktree_path: &Path,
- target_repo: &Path,
+ target_repo: Option<&Path>,
source_branch: &str,
target_branch: &str,
title: &str,
@@ -1481,7 +1482,7 @@ impl WorktreeManager {
) -> Result<String, WorktreeError> {
tracing::info!(
worktree = %worktree_path.display(),
- target_repo = %target_repo.display(),
+ target_repo = ?target_repo.map(|p| p.display().to_string()),
source_branch = %source_branch,
target_branch = %target_branch,
title = %title,
@@ -1504,60 +1505,96 @@ impl WorktreeManager {
source_branch.to_string()
};
- // Push to the target repo's origin
- // First, check if target_repo has an origin remote
- let output = Command::new("git")
- .args(["remote", "get-url", "origin"])
- .current_dir(target_repo)
- .output()
- .await?;
+ // Get the origin URL - either from target_repo or from worktree directly
+ let (origin_url, gh_working_dir) = if let Some(target_repo) = target_repo {
+ // Use target_repo's origin
+ let output = Command::new("git")
+ .args(["remote", "get-url", "origin"])
+ .current_dir(target_repo)
+ .output()
+ .await?;
- if !output.status.success() {
- return Err(WorktreeError::GitCommand(
- "Target repository has no origin remote configured".to_string(),
- ));
- }
+ if !output.status.success() {
+ return Err(WorktreeError::GitCommand(
+ "Target repository has no origin remote configured".to_string(),
+ ));
+ }
+
+ let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
+ (url, target_repo.to_path_buf())
+ } else {
+ // Check if worktree has an origin remote directly
+ let output = Command::new("git")
+ .args(["remote", "get-url", "origin"])
+ .current_dir(worktree_path)
+ .output()
+ .await?;
- let origin_url = String::from_utf8_lossy(&output.stdout).trim().to_string();
+ if !output.status.success() {
+ return Err(WorktreeError::GitCommand(
+ "Repository has no origin remote configured. Either set target_repo_path or ensure the worktree was cloned from a remote repository.".to_string(),
+ ));
+ }
+
+ let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
+ (url, worktree_path.to_path_buf())
+ };
// Push the branch from worktree to the remote
- // First add the remote to worktree
- let _ = Command::new("git")
- .args(["remote", "remove", "pr-origin"])
- .current_dir(worktree_path)
- .output()
- .await;
+ // First add the remote to worktree (if not using worktree's origin directly)
+ if target_repo.is_some() {
+ let _ = Command::new("git")
+ .args(["remote", "remove", "pr-origin"])
+ .current_dir(worktree_path)
+ .output()
+ .await;
- let output = Command::new("git")
- .args(["remote", "add", "pr-origin", &origin_url])
- .current_dir(worktree_path)
- .output()
- .await?;
+ let output = Command::new("git")
+ .args(["remote", "add", "pr-origin", &origin_url])
+ .current_dir(worktree_path)
+ .output()
+ .await?;
- if !output.status.success() {
- let stderr = String::from_utf8_lossy(&output.stderr);
- return Err(WorktreeError::GitCommand(format!(
- "Failed to add remote: {}",
- stderr
- )));
- }
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ return Err(WorktreeError::GitCommand(format!(
+ "Failed to add remote: {}",
+ stderr
+ )));
+ }
- // Push to the remote
- let output = Command::new("git")
- .args(["push", "-u", "pr-origin", &format!("{}:{}", current_branch, source_branch)])
- .current_dir(worktree_path)
- .output()
- .await?;
+ // Push to the remote
+ let output = Command::new("git")
+ .args(["push", "-u", "pr-origin", &format!("{}:{}", current_branch, source_branch)])
+ .current_dir(worktree_path)
+ .output()
+ .await?;
- if !output.status.success() {
- let stderr = String::from_utf8_lossy(&output.stderr);
- return Err(WorktreeError::GitCommand(format!(
- "Failed to push branch: {}",
- stderr
- )));
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ return Err(WorktreeError::GitCommand(format!(
+ "Failed to push branch: {}",
+ stderr
+ )));
+ }
+ } else {
+ // Push directly to origin
+ let output = Command::new("git")
+ .args(["push", "-u", "origin", &format!("{}:{}", current_branch, source_branch)])
+ .current_dir(worktree_path)
+ .output()
+ .await?;
+
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ return Err(WorktreeError::GitCommand(format!(
+ "Failed to push branch: {}",
+ stderr
+ )));
+ }
}
- // Create PR using gh CLI in the target repo
+ // Create PR using gh CLI
let output = Command::new("gh")
.args([
"pr",
@@ -1567,7 +1604,7 @@ impl WorktreeManager {
"--head", source_branch,
"--base", target_branch,
])
- .current_dir(target_repo)
+ .current_dir(&gh_working_dir)
.output()
.await?;
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs
index bf95a3a..6ede268 100644
--- a/makima/src/db/models.rs
+++ b/makima/src/db/models.rs
@@ -525,6 +525,12 @@ pub struct Task {
/// Used to track the origin of "what if" explorations.
#[serde(skip_serializing_if = "Option::is_none")]
pub branched_from_task_id: Option<Uuid>,
+
+ // UI visibility
+ /// Whether this task is hidden from the UI (user dismissed it).
+ /// Standalone completed tasks can be dismissed by the user.
+ #[serde(default)]
+ pub hidden: bool,
}
impl Task {
@@ -564,6 +570,9 @@ pub struct TaskSummary {
/// True for contract supervisor tasks
#[serde(default)]
pub is_supervisor: bool,
+ /// Whether this task is hidden from the UI (user dismissed it)
+ #[serde(default)]
+ pub hidden: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
@@ -586,6 +595,7 @@ impl From<Task> for TaskSummary {
subtask_count: 0, // Would need separate query
version: task.version,
is_supervisor: task.is_supervisor,
+ hidden: task.hidden,
created_at: task.created_at,
updated_at: task.updated_at,
}
@@ -670,6 +680,8 @@ pub struct UpdateTaskRequest {
/// Explicitly clear daemon_id (set to NULL)
#[serde(default)]
pub clear_daemon_id: bool,
+ /// Whether this task is hidden from the UI (user dismissed it)
+ pub hidden: Option<bool>,
/// Version for optimistic locking
pub version: Option<i32>,
}
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index 7387735..84afc8d 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -733,6 +733,7 @@ pub async fn get_task(pool: &PgPool, id: Uuid) -> Result<Option<Task>, sqlx::Err
}
/// List all top-level tasks (no parent), ordered by created_at DESC.
+/// Hidden tasks are excluded by default.
pub async fn list_tasks(pool: &PgPool) -> Result<Vec<TaskSummary>, sqlx::Error> {
sqlx::query_as::<_, TaskSummary>(
r#"
@@ -742,10 +743,10 @@ pub async fn list_tasks(pool: &PgPool) -> Result<Vec<TaskSummary>, sqlx::Error>
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
- WHERE t.parent_task_id IS NULL
+ WHERE t.parent_task_id IS NULL AND COALESCE(t.hidden, false) = false
ORDER BY t.priority DESC, t.created_at DESC
"#,
)
@@ -763,7 +764,7 @@ pub async fn list_subtasks(pool: &PgPool, parent_id: Uuid) -> Result<Vec<TaskSum
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.parent_task_id = $1
@@ -1129,6 +1130,7 @@ pub async fn get_task_for_owner(
}
/// List all top-level tasks (no parent) for an owner, ordered by created_at DESC.
+/// Hidden tasks are excluded by default.
pub async fn list_tasks_for_owner(
pool: &PgPool,
owner_id: Uuid,
@@ -1141,10 +1143,10 @@ pub async fn list_tasks_for_owner(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
- WHERE t.owner_id = $1 AND t.parent_task_id IS NULL
+ WHERE t.owner_id = $1 AND t.parent_task_id IS NULL AND COALESCE(t.hidden, false) = false
ORDER BY t.priority DESC, t.created_at DESC
"#,
)
@@ -1167,7 +1169,7 @@ pub async fn list_subtasks_for_owner(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.owner_id = $1 AND t.parent_task_id = $2
@@ -1217,6 +1219,7 @@ pub async fn update_task_for_owner(
let repository_url = req.repository_url.or(existing.repository_url);
let target_repo_path = req.target_repo_path.or(existing.target_repo_path);
let completion_action = req.completion_action.or(existing.completion_action);
+ let hidden = req.hidden.unwrap_or(existing.hidden);
let daemon_id = if req.clear_daemon_id {
None
} else {
@@ -1232,8 +1235,8 @@ pub async fn update_task_for_owner(
progress_summary = $8, last_output = $9, error_message = $10,
merge_mode = $11, pr_url = $12, daemon_id = $13,
target_repo_path = $14, completion_action = $15, repository_url = $16,
- updated_at = NOW()
- WHERE id = $1 AND owner_id = $2 AND version = $17
+ hidden = $17, updated_at = NOW()
+ WHERE id = $1 AND owner_id = $2 AND version = $18
RETURNING *
"#,
)
@@ -1253,6 +1256,7 @@ pub async fn update_task_for_owner(
.bind(&target_repo_path)
.bind(&completion_action)
.bind(&repository_url)
+ .bind(hidden)
.bind(req.version.unwrap())
.fetch_optional(pool)
.await?
@@ -1264,7 +1268,7 @@ pub async fn update_task_for_owner(
progress_summary = $8, last_output = $9, error_message = $10,
merge_mode = $11, pr_url = $12, daemon_id = $13,
target_repo_path = $14, completion_action = $15, repository_url = $16,
- updated_at = NOW()
+ hidden = $17, updated_at = NOW()
WHERE id = $1 AND owner_id = $2
RETURNING *
"#,
@@ -1285,6 +1289,7 @@ pub async fn update_task_for_owner(
.bind(&target_repo_path)
.bind(&completion_action)
.bind(&repository_url)
+ .bind(hidden)
.fetch_optional(pool)
.await?
};
@@ -2685,7 +2690,7 @@ pub async fn list_tasks_in_contract(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.contract_id = $1 AND t.owner_id = $2
diff --git a/makima/src/server/handlers/mesh_chat.rs b/makima/src/server/handlers/mesh_chat.rs
index 0fc5513..8e134bd 100644
--- a/makima/src/server/handlers/mesh_chat.rs
+++ b/makima/src/server/handlers/mesh_chat.rs
@@ -995,8 +995,8 @@ async fn handle_mesh_request(
};
(Some(action), target)
} else if is_daemon_working_dir {
- // No merge_mode but using daemon working dir - default to "branch"
- (Some("branch".to_string()), repository_url.clone())
+ // No merge_mode but using daemon working dir - default to "pr"
+ (Some("pr".to_string()), repository_url.clone())
} else {
(None, None)
};