Browse Source

ui: rename every user-visible 'bot' to 'agent' at the source

Comment authors ('bot' -> 'agent'), the from_agent flag, the
.comment.agent style, doc comments and test wording — nothing is
deployed, so stored author strings change at the source.
clanker 1 month ago
parent
commit
8b1c48a785

+ 1 - 1
src/Api/SaddleApi.vala

@@ -87,7 +87,7 @@ namespace ClankerSaddle.Api {
 
                 case "comment":
                     string body_text = get_string_or(data, "body", get_string_or(data, "text", ""));
-                    yield tasks.add_comment(task_id, "bot", body_text);
+                    yield tasks.add_comment(task_id, "agent", body_text);
                     yield tasks.log_session_entry(task_id, "comment", "saddle comment", body_text);
                     break;
 

+ 5 - 5
src/Data/Entities.vala

@@ -51,7 +51,7 @@ namespace ClankerSaddle.Data {
      * TaskService.STATUS_DRAFT}, queued by its creator (human or goal
      * agent), dispatched to a saddle, worked, possibly blocked on
      * questions, and eventually done or failed (completion is
-     * bot-only). The plan-12 shape: goals own the task graph — a task
+     * agent-only). The plan-12 shape: goals own the task graph — a task
      * links its {@link goal_id}, runs as a plain worker or the goal
      * agent itself ({@link kind}), carries a work {@link mode} and its
      * {@link creator}, and human tasks may carry an auto-enqueue
@@ -130,12 +130,12 @@ namespace ClankerSaddle.Data {
         }
     }
 
-    /** A remark on a task, authored either by a human or by the agent ('bot'). */
+    /** A remark on a task, authored either by a human or by the agent ('agent'). */
     public class TaskComment : Object {
 
         public int64 id { get; set; }
         public int64 task_id { get; set; }
-        public string author { get; set; default = "bot"; }
+        public string author { get; set; default = "agent"; }
         public string body { get; set; default = ""; }
         public string? quote { get; set; default = null; }
         public DateTime? created_at { get; set; default = null; }
@@ -556,12 +556,12 @@ namespace ClankerSaddle.Data {
         }
     }
 
-    /** A remark on a goal, authored by a human or by the goal agent ('bot'). */
+    /** A remark on a goal, authored by a human or by the goal agent ('agent'). */
     public class GoalComment : Object {
 
         public int64 id { get; set; }
         public int64 goal_id { get; set; }
-        public string author { get; set; default = "bot"; }
+        public string author { get; set; default = "agent"; }
         public string body { get; set; default = ""; }
         public string? quote { get; set; default = null; }
         public DateTime? created_at { get; set; default = null; }

+ 1 - 1
src/Data/Migrations/M0001_Initial.vala

@@ -208,7 +208,7 @@ namespace ClankerSaddle.Data.Migrations {
             });
 
             // Plan 12: goal-level conversation and review machinery,
-            // mirroring the task-side shapes (author 'bot' or
+            // mirroring the task-side shapes (author 'agent' or
             // 'user:<name>'; blocks carry question/rfc bodies, plan
             // submissions/revisions and the completion report).
             b.create_table("goal_comments", (t) => {

+ 1 - 1
src/Services/Dispatcher.vala

@@ -16,7 +16,7 @@ namespace ClankerSaddle.Services {
      * work for the next capable sleeping saddle. The staleness pass
      * probes a RUNNING daemon that has pushed neither chunks nor
      * results for the SADDLE_STALE_S window — one exceptional
-     * `GET /status`; a failed probe requeues the task with a bot
+     * `GET /status`; a failed probe requeues the task with an agent
      * comment and marks the saddle offline. Round telemetry arrives as
      * pushes (`/api/saddle/chunks`, `/api/saddle/results`); the
      * dispatcher never polls for output.

+ 1 - 1
src/Services/GoalService.vala

@@ -610,7 +610,7 @@ namespace ClankerSaddle.Services {
         // Comments and events
         // ------------------------------------------------------------------
 
-        /** Appends a goal comment; `author` is 'bot' or 'user:<name>'. */
+        /** Appends a goal comment; `author` is 'agent' or 'user:<name>'. */
         public async GoalComment add_comment(int64 goal_id, string author, string body,
                 string? quote = null) throws Error {
             var comment = new GoalComment() {

+ 10 - 10
src/Services/SaddleService.vala

@@ -547,12 +547,12 @@ namespace ClankerSaddle.Services {
                     throw new Error(Quark.from_string("clanker-saddle"), 45,
                         @"task-update cancel returned HTTP $(status_code)");
                 }
-                yield tasks.add_comment(session.task_id, "bot", @"$(verb); daemon aborted");
+                yield tasks.add_comment(session.task_id, "agent", @"$(verb); daemon aborted");
             } catch (Error e) {
                 warning(@"[ClankerSaddle] Abort for task $(session.task_id) failed: $(e.message); marking saddle '$(((!)saddle).name)' offline");
                 yield mark_saddle_unreachable(((!)saddle).id, tasks,
                     @"abort delivery failed ($(e.message))");
-                yield tasks.add_comment(session.task_id, "bot",
+                yield tasks.add_comment(session.task_id, "agent",
                     @"$(verb); daemon unreachable — saddle marked offline");
             }
         }
@@ -563,7 +563,7 @@ namespace ClankerSaddle.Services {
          * pass they would wait forever for a daemon that will not answer.
          * Only `assigned`/`working` tasks move: parked tasks
          * (blocked/review/suspended) keep their sessions, which the
-         * resume machinery needs. Each move lands a bot comment so the
+         * resume machinery needs. Each move lands a agent comment so the
          * timeline shows why the task restarted.
          */
         public async void requeue_tasks_on_offline_saddles(TaskService tasks) throws Error {
@@ -586,7 +586,7 @@ namespace ClankerSaddle.Services {
                     }
                     print(@"[ClankerSaddle] Task $(task.id) requeued: its saddle went offline\n");
                     yield tasks.requeue_task(task.id);
-                    yield tasks.add_comment(task.id, "bot",
+                    yield tasks.add_comment(task.id, "agent",
                         "saddle went offline; task requeued");
                 }
             }
@@ -626,7 +626,7 @@ namespace ClankerSaddle.Services {
          * Marks a saddle offline when its control server cannot be
          * reached, releasing the task it was holding back to 'queued'
          * and closing that task's open session (outcome 'stopped'). The
-         * requeue lands as a bot comment on the task, so the timeline
+         * requeue lands as a agent comment on the task, so the timeline
          * shows the interruption; combined with the daemon's
          * crash-resume, the next dispatch restores the workspace and
          * reports `resumed` on /status.
@@ -661,7 +661,7 @@ namespace ClankerSaddle.Services {
                         string unreachable_text = reason != null && reason.length > 0
                             ? @"Saddle became unreachable ($(reason)); task requeued"
                             : "Saddle became unreachable; task requeued";
-                        yield tasks.add_comment(task_id, "bot", unreachable_text);
+                        yield tasks.add_comment(task_id, "agent", unreachable_text);
                     }
                 }
 
@@ -1228,7 +1228,7 @@ namespace ClankerSaddle.Services {
 
         /**
          * Projects the agent's conversation-level events onto the task:
-         * `saddle comment` lines become bot comments, `saddle plan`
+         * `saddle comment` lines become agent comments, `saddle plan`
          * lines update the plan, `saddle progress-update` lines append
          * progress, `saddle review` raises the review banner, the
          * `saddle done` entry completes the task with the summary the
@@ -1258,9 +1258,9 @@ namespace ClankerSaddle.Services {
                             body = output;
                         }
                         if (body.length > 0) {
-                            yield tasks.add_comment(task_id, "bot", body);
+                            yield tasks.add_comment(task_id, "agent", body);
                             if (goal_id > 0) {
-                                yield goal_service.add_comment(goal_id, "bot", body);
+                                yield goal_service.add_comment(goal_id, "agent", body);
                                 yield goal_service.record_event(goal_id, "comment",
                                     snippet_text(body));
                             }
@@ -1674,7 +1674,7 @@ namespace ClankerSaddle.Services {
          * window, so ONE exceptional `GET /status` decides its fate —
          * an answer means the daemon is alive (the health snapshot is
          * refreshed and the task keeps running; the silence episode
-         * gets no second probe), a failure requeues the task with a bot
+         * gets no second probe), a failure requeues the task with an agent
          * comment and marks the saddle offline (the normal unreachable
          * bookkeeping). The probe flag was taken by the caller; the
          * next push resets it.

+ 6 - 6
src/Services/TaskService.vala

@@ -783,7 +783,7 @@ namespace ClankerSaddle.Services {
             return ((!)element).try_get_as<DateTime>(out value) ? value : null;
         }
 
-        /** Appends a comment; `author` is 'bot' or 'user:<name>'. */
+        /** Appends a comment; `author` is 'agent' or 'user:<name>'. */
         public async TaskComment add_comment(int64 task_id, string author, string body,
                 string? quote = null) throws Error {
             var comment = new TaskComment() {
@@ -1142,7 +1142,7 @@ namespace ClankerSaddle.Services {
         /**
          * Records a saddle-reported failure: status 'failed' with the
          * daemon's message as summary, the explanation stored again as a
-         * bot comment (so the thread carries it), the open session
+         * agent comment (so the thread carries it), the open session
          * closed with outcome 'failed' and its saddle freed.
          */
         public async void fail_task(int64 task_id, string? summary) throws Error {
@@ -1158,7 +1158,7 @@ namespace ClankerSaddle.Services {
             ((!)task).completed_at = new DateTime.now_local();
             if (summary != null && summary.length > 0) {
                 ((!)task).summary = summary;
-                yield add_comment(task_id, "bot", summary);
+                yield add_comment(task_id, "agent", summary);
             } else if (((!)task).summary == null || ((!)task).summary.length == 0) {
                 ((!)task).summary = "Saddle reported a failure";
             }
@@ -1339,7 +1339,7 @@ namespace ClankerSaddle.Services {
 
         /**
          * Returns a failed task to the queue for another attempt. The
-         * failure summary moves into a bot comment (so the history keeps
+         * failure summary moves into an agent comment (so the history keeps
          * it) before being cleared from the task, `completed_at` is
          * withdrawn, any open session closes and its saddle frees — the
          * same bookkeeping as {@link requeue_task}, plus the audit
@@ -1355,7 +1355,7 @@ namespace ClankerSaddle.Services {
             }
 
             if (((!)task).summary != null && ((!)task).summary.length > 0) {
-                yield add_comment(task_id, "bot", (!)(((!)task).summary));
+                yield add_comment(task_id, "agent", (!)(((!)task).summary));
             }
             ((!)task).status = STATUS_QUEUED;
             ((!)task).summary = null;
@@ -1364,7 +1364,7 @@ namespace ClankerSaddle.Services {
 
             yield close_open_sessions(task_id, "stopped");
             yield free_saddles_running(task_id);
-            yield add_comment(task_id, "bot", "Task retried by user");
+            yield add_comment(task_id, "agent", "Task retried by user");
             yield pulse.bump(task_id, "task retried");
         }
 

+ 3 - 3
src/actions/TaskActions.vala

@@ -123,7 +123,7 @@ namespace ClankerSaddle {
      * lifecycle's edit matrix (see {@link TaskService.edit_task}): in
      * draft every field except status, in non-draft non-terminal
      * states priority only, in terminal states nothing. Status is not
-     * part of the form — Enqueue/Cancel/bot transitions own it.
+     * part of the form — Enqueue/Cancel/agent transitions own it.
      */
     public class UpdateTaskAction : SealedTaskAction {
 
@@ -371,7 +371,7 @@ namespace ClankerSaddle {
      * Cancels a task (status 'failed'); the sealed id comes from the task
      * page's cancel button. Only non-draft non-terminal tasks offer the
      * action — drafts are deleted, terminal tasks are already finished,
-     * and completion itself is bot-only.
+     * and completion itself is agent-only.
      */
     public class CancelTaskAction : SealedTaskAction {
 
@@ -459,7 +459,7 @@ namespace ClankerSaddle {
      * Manually requeues a task stuck working/blocked on a saddle that
      * went offline (the automatic three-strike path may never fire when
      * the saddle row was refreshed to offline first). The same path as
-     * the dispatcher's abandon: requeue + bot comment + saddle offline.
+     * the dispatcher's abandon: requeue + agent comment + saddle offline.
      */
     public class ResumeTaskAction : SealedTaskAction {
 

+ 2 - 2
src/entrypoints/GoalDetailEntrypoint.vala

@@ -46,7 +46,7 @@ namespace ClankerSaddle {
         public string body { get; set; default = ""; }
         public string quote { get; set; default = ""; }
         public string created_display { get; set; default = ""; }
-        public bool from_bot { get; set; default = false; }
+        public bool from_agent { get; set; default = false; }
     }
 
     /** One supervision-narrative event row. */
@@ -403,7 +403,7 @@ namespace ClankerSaddle {
                     body = row.body,
                     quote = row.quote ?? "",
                     created_display = format_stamp(row.created_at),
-                    from_bot = row.author == "bot"
+                    from_agent = row.author == "agent"
                 });
             }
 

+ 2 - 2
src/entrypoints/TaskDetailEntrypoint.vala

@@ -15,7 +15,7 @@ namespace ClankerSaddle {
         public string body { get; set; default = ""; }
         public string quote { get; set; default = ""; }
         public string when_display { get; set; default = ""; }
-        public bool from_bot { get; set; }
+        public bool from_agent { get; set; }
     }
 
     /** One progress line in the task's history. */
@@ -278,7 +278,7 @@ namespace ClankerSaddle {
                     body = comment.body,
                     quote = comment.quote ?? "",
                     when_display = format_time(comment.created_at),
-                    from_bot = comment.author == "bot"
+                    from_agent = comment.author == "agent"
                 });
             }
 

+ 1 - 1
src/pages/app.css

@@ -393,7 +393,7 @@ summary { cursor: pointer; font-weight: 600; }
     padding: var(--grid-1) var(--grid-2);
 }
 
-.comment.bot { border-left-color: var(--accent); }
+.comment.agent { border-left-color: var(--accent); }
 .comment blockquote {
     border-left: 3px solid var(--line);
     color: var(--ink-muted);

+ 1 - 1
src/pages/goal_detail.html

@@ -278,7 +278,7 @@
             <section class="card">
                 <h3>Comments</h3>
                 <div stm-for-comment-in="goal.comments"
-                     stm-attribute.class="'comment' + (comment.from_bot ? ' bot' : '')">
+                     stm-attribute.class="'comment' + (comment.from_agent ? ' agent' : '')">
                     <strong stm-text="comment.author">author</strong>
                     <span class="muted" stm-text="comment.created_display">when</span>
                     <blockquote stm-if="comment.quote.length > 0" stm-text="comment.quote">quote</blockquote>

+ 2 - 2
src/pages/task_detail.html

@@ -286,7 +286,7 @@
                  lifecycle buttons ride the status card (plan 11): new
                  tasks are drafts — Enqueue and Delete in draft (delete
                  guarded by dependents), Cancel in non-draft
-                 non-terminal; completion is bot-only. -->
+                 non-terminal; completion is agent-only. -->
             <div class="grid-2">
                 <section class="card status-head">
                     <h3>Status <span class="badge badge-yeehaw status-corner" stm-if="task.yeehaw"
@@ -506,7 +506,7 @@
             </details>
 
             <h3>Comments</h3>
-            <div stm-for-comment-in="task.comments" stm-attribute.class="'comment' + (comment.from_bot ? ' bot' : '')">
+            <div stm-for-comment-in="task.comments" stm-attribute.class="'comment' + (comment.from_agent ? ' agent' : '')">
                 <strong stm-text="comment.author">author</strong>
                 <span class="muted" stm-text="comment.when_display">when</span>
                 <blockquote stm-if="comment.quote.length > 0" stm-text="comment.quote">quote</blockquote>

+ 7 - 7
test/web_stack_test.py

@@ -54,7 +54,7 @@ Plan 10 phase 2 (telemetry flip):
   session, no wake. A daemon dying with a parked-with-answered task
   never requeues it: the verdict and session survive for the resume
 - staleness: a silent runner gets ONE exceptional GET /status probe —
-  alive keeps it running, dead requeues the task with a bot comment and
+  alive keeps it running, dead requeues the task with an agent comment and
   marks the saddle offline; a recovered daemon's ask flips offline rows
   back to idle
 - the deleted layers are gone: /output, /log and /start 404 on the
@@ -2594,7 +2594,7 @@ def bundle_dispatch(ctx):
     check(detail["status"] == "queued" and (detail.get("summary") or "") == "",
           "retry requeues the task and clears the stale summary")
     check(any("bash -n rejected" in c["body"] for c in detail["comments"]),
-          "failure explanation kept as a bot comment")
+          "failure explanation kept as an agent comment")
     check(any(c["body"] == "Task retried by user" for c in detail["comments"]),
           "retry lands its audit comment")
     check(len(detail["comments"]) >= comments_before + 1,
@@ -3764,7 +3764,7 @@ def bundle_lifecycle(ctx):
     check(status == 200 and "Enqueue task" in page and ">Delete<" in page,
           "the task page shows Enqueue + Delete in draft")
     check("Mark done" not in page,
-          "the user Mark-complete action is gone (bot-only completion)")
+          "the user Mark-complete action is gone (agent-only completion)")
     # Plan 12: the auto-enqueue-after predecessor REPLACES draft
     # dependencies — setting it is allowed while the predecessor is
     # still pending (the enqueue itself succeeds; the DISPATCHER holds
@@ -3928,7 +3928,7 @@ def bundle_lifecycle(ctx):
 
     print("== offline requeues ==")
     # Tasks caught working on a saddle that went offline requeue with a
-    # bot comment each tick.
+    # agent comment each tick.
     task_id_tmp = create_queued(auth, {
         "project_id": "1",
         "title": "Offline saddle task",
@@ -3948,7 +3948,7 @@ def bundle_lifecycle(ctx):
     conn.commit()
     conn.close()
     # The requeue frees the saddle in the same tick, so 'queued' is
-    # transient; the durable evidence is the bot comment (and the task
+    # transient; the durable evidence is the agent comment (and the task
     # completing again on the healthy daemon).
     check(wait_for(lambda: any(c["body"] == "saddle went offline; task requeued"
                                for c in task_state(auth, offline_task).get("comments", []))
@@ -4698,7 +4698,7 @@ def bundle_answers(ctx):
           "the silent thinker completes once output flows again")
 
     # The daemon vanishing mid-task: silence for the window, the
-    # probe fails, the task requeues with a bot comment and the
+    # probe fails, the task requeues with an agent comment and the
     # saddle goes offline.
     task_id_tmp = create_queued(auth, {
         "project_id": "1",
@@ -4716,7 +4716,7 @@ def bundle_answers(ctx):
     check(wait_for(lambda: any("unreachable" in c["body"]
                                for c in task_state(auth, vanish).get("comments", []))
                    or False, timeout=30, what="unreachable comment") is not None,
-          "the affected task gets an unreachable bot comment")
+          "the affected task gets an unreachable agent comment")
     check(task_state(auth, vanish)["status"] == "queued",
           "the task requeues after the daemon death")
     card = saddle_card(auth, "fake-saddle")