Selaa lähdekoodia

r1: current_work_view + direct display_map_for — SaddleService.current_work_view owns the current-task/goal resolution the dashboard's saddle cards and the saddles page duplicated; the goal page's task rows consume TaskService.display_map_for + the batch yeehaw set directly (the GoalTaskDisplay intermediate map and its double list_tasks_for_goal pass die).

clanker 1 kuukausi sitten
vanhempi
sitoutus
40508b0fa9

+ 45 - 0
src/Services/SaddleService.vala

@@ -34,6 +34,19 @@ namespace ClankerSaddle.Services {
         public string token { get; set; default = ""; }
     }
 
+    /**
+     * A saddle's current work as the cards render it: the running
+     * task's title, plus the GOAL it stands for when that task is a
+     * goal agent's internal run.
+     */
+    public class CurrentWork : Object {
+        public int64 task_id { get; set; }
+        public string task_title { get; set; default = ""; }
+        /** Set when the current task is a goal agent's run: the card links the goal. */
+        public int64 goal_id { get; set; }
+        public string goal_title { get; set; default = ""; }
+    }
+
     /**
      * The OpenAI-compatible endpoint every saddle assignment is sent to,
      * read from the environment: `SADDLE_LLM_BASE_URL` (required — dispatch
@@ -324,6 +337,38 @@ namespace ClankerSaddle.Services {
                 .materialise_async();
         }
 
+        /**
+         * The saddle's current work resolved for display — the ONE
+         * lookup the dashboard's saddle cards and the saddles page's
+         * rows share: the current task's title, and the goal it
+         * stands for when it is a goal agent's internal run (runs are
+         * internal — never a task destination at a glance). Null when
+         * the saddle holds no task.
+         */
+        public async CurrentWork? current_work_view(Saddle saddle) throws Error {
+            if (saddle.current_task_id <= 0) {
+                return null;
+            }
+            var work = new CurrentWork() { task_id = saddle.current_task_id };
+            var task = yield db.query<TaskEntity>()
+                .where(expr("id == $0", elem<int64?>(saddle.current_task_id)))
+                .first_async();
+            if (task == null) {
+                return work;
+            }
+            work.task_title = ((!)task).title;
+            if (((!)task).kind == TASK_KIND_GOAL_RUN) {
+                var goal = yield db.query<Goal>()
+                    .where(expr("id == $0", elem<int64?>(((!)task).goal_id)))
+                    .first_async();
+                if (goal != null) {
+                    work.goal_id = ((!)goal).id;
+                    work.goal_title = ((!)goal).title;
+                }
+            }
+            return work;
+        }
+
         /**
          * Lists saddles with status 'busy' (the dispatcher's poll
          * candidates).

+ 12 - 36
src/entrypoints/GoalDetailEntrypoint.vala

@@ -499,12 +499,20 @@ namespace ClankerSaddle {
                     open_sink.add(view);
                 }
             }
-            var display_map = yield task_display_map(tasks, goal.id);
+            var goal_task_rows = new Vector<TaskEntity>();
             foreach (var task in yield tasks.list_tasks_for_goal(goal.id)) {
                 if (task.kind == TASK_KIND_GOAL_RUN) {
                     pub.run_task_id = task.id;
-                    continue;
+                } else {
+                    goal_task_rows.add(task);
                 }
+            }
+            // The rows consume TaskService.display_map_for directly
+            // (the same computed display the queue and the dashboard
+            // read) plus the batch yeehaw presence set.
+            var display_map = yield tasks.display_map_for(goal_task_rows.to_immutable_buffer());
+            var yeehaw_ids = yield tasks.yeehaw_task_ids();
+            foreach (var task in goal_task_rows) {
                 var view = new GoalTaskView() {
                     id = task.id,
                     title = task.title,
@@ -530,8 +538,8 @@ namespace ClankerSaddle {
                 }
                 view.capabilities = task_caps.to_array();
                 var display = display_map.get_or_default(task.id.to_string());
-                view.display = display != null ? ((!)display).display : task.status;
-                view.yeehaw = display != null && ((!)display).yeehaw;
+                view.display = display != null ? ((!)display).status : task.status;
+                view.yeehaw = yeehaw_ids.has(task.id.to_string());
                 goal_tasks.add(view);
                 switch (task.status) {
                     case STATUS_DRAFT:
@@ -759,32 +767,6 @@ namespace ClankerSaddle {
             }
         }
 
-        /**
-         * The goal tasks' display states + yeehaw badges in one map —
-         * the task page's computed display (`display_of_detail`) with
-         * the queue batch lookups.
-         */
-private static async Dictionary<string, GoalTaskDisplay> task_display_map(
-                TaskService tasks, int64 goal_id) throws GLib.Error {
-            var map = new Dictionary<string, GoalTaskDisplay>();
-            var listed = new Vector<TaskEntity>();
-            foreach (var task in yield tasks.list_tasks_for_goal(goal_id)) {
-                if (task.kind != TASK_KIND_GOAL_RUN) {
-                    listed.add(task);
-                }
-            }
-            var display_map = yield tasks.display_map_for(listed.to_immutable_buffer());
-            var yeehaw_ids = yield tasks.yeehaw_task_ids();
-            foreach (var task in listed) {
-                var display = display_map.get_or_default(task.id.to_string());
-                map.set(task.id.to_string(), new GoalTaskDisplay() {
-                    display = display != null ? ((!)display).status : task.status,
-                    yeehaw = yeehaw_ids.has(task.id.to_string())
-                });
-            }
-            return map;
-        }
-
         /** A flattened, clipped activity line (the current-activity display). */
         private static string clip_line(string text, int limit) {
             string flat = text.replace("\n", " ⏎ ").strip();
@@ -792,12 +774,6 @@ private static async Dictionary<string, GoalTaskDisplay> task_display_map(
         }
     }
 
-    /** Display + badge pair for a goal task row. */
-    public class GoalTaskDisplay : Object {
-        public string display { get; set; default = ""; }
-        public bool yeehaw { get; set; }
-    }
-
     /**
      * Entrypoint for /goals: the goals dashboard — every goal (newest
      * first) with lifecycle badges, branch, priority and task counts,

+ 6 - 15
src/entrypoints/HomeEntrypoint.vala

@@ -177,21 +177,12 @@ namespace ClankerSaddle {
                     host = saddle.host,
                     current_task_id = saddle.current_task_id
                 };
-                if (saddle.current_task_id > 0) {
-                    var task = yield db.query<TaskEntity>()
-                        .where(expr("id == $0", elem<int64?>(saddle.current_task_id)))
-                        .first_async();
-                    view.current_task_title = task != null ? ((!)task).title : "";
-                    // A goal agent's run reads as its GOAL here, not as
-                    // the internal run task.
-                    if (task != null && ((!)task).kind == TASK_KIND_GOAL_RUN) {
-                        var goal = yield db.query<Goal>()
-                            .where(expr("id == $0", elem<int64?>(((!)task).goal_id)))
-                            .first_async();
-                        if (goal != null) {
-                            view.current_goal_id = ((!)goal).id;
-                            view.current_goal_title = ((!)goal).title;
-                        }
+                var work = yield saddles.current_work_view(saddle);
+                if (work != null) {
+                    view.current_task_title = ((!)work).task_title;
+                    if (((!)work).goal_id > 0) {
+                        view.current_goal_id = ((!)work).goal_id;
+                        view.current_goal_title = ((!)work).goal_title;
                     }
                 }
                 saddle_rows.add(view);

+ 6 - 15
src/entrypoints/SaddlesEntrypoint.vala

@@ -177,21 +177,12 @@ namespace ClankerSaddle {
                 };
                 string? token = yield saddle_service.token_for_saddle(saddle.id);
                 view.token = token ?? "";
-                if (saddle.current_task_id > 0) {
-                    var task = yield db.query<TaskEntity>()
-                        .where(expr("id == $0", elem<int64?>(saddle.current_task_id)))
-                        .first_async();
-                    view.current_task_title = task != null ? ((!)task).title : "";
-                    // A goal agent's run reads as its GOAL, not as the
-                    // internal run task.
-                    if (task != null && ((!)task).kind == TASK_KIND_GOAL_RUN) {
-                        var goal = yield db.query<Goal>()
-                            .where(expr("id == $0", elem<int64?>(((!)task).goal_id)))
-                            .first_async();
-                        if (goal != null) {
-                            view.current_goal_id = ((!)goal).id;
-                            view.current_goal_title = ((!)goal).title;
-                        }
+                var work = yield saddle_service.current_work_view(saddle);
+                if (work != null) {
+                    view.current_task_title = ((!)work).task_title;
+                    if (((!)work).goal_id > 0) {
+                        view.current_goal_id = ((!)work).goal_id;
+                        view.current_goal_title = ((!)work).goal_title;
                     }
                 }
                 rows.add(view);