Kaynağa Gözat

Task create form: branch fields

The task detail page's edit form already carried task_branch and
branch_from; the /tasks create form did not. Add two optional rows to
the tasks.create form, between Mandate and Priority (mirroring the
goal form's ordering): 'Task branch name' with a muted hint that
leaving it empty lets the system name the branch (goal worker tasks
auto-name task/<goal-id>-<task-id>), and 'Branch from' hinting at the
project's default branch.

No backend change: CreateTaskAction already posts both fields through
Forms.optional into TaskService.create_task, which nulls empty values,
prefills branch_from from the project default for project_id > 0
(standalone tasks get no prefill, so the always-rendered fields stay
inert there), and overrides both fields after insert for goal worker
tasks so human-supplied values never clobber the ephemeral naming.

Tests: pages bundle B6b pins the rendering of both inputs, the posted
values landing on the task row, and the empty-post fallback (null
task_branch, branch_from prefilled from the project default).
Full suite: 1149 passed, 0 failed across all 18 shards.
saddle-Clanker-Saddle 1 ay önce
ebeveyn
işleme
c153a4e3fd
2 değiştirilmiş dosya ile 44 ekleme ve 0 silme
  1. 8 0
      src/pages/tasks.html
  2. 36 0
      test/bundles/pages.py

+ 8 - 0
src/pages/tasks.html

@@ -113,6 +113,14 @@
                 <div class="form-row"><label for="task-description">Mandate</label>
                     <textarea id="task-description" name="description" rows="4"
                               placeholder="What the agent must accomplish (the mandate)"></textarea></div>
+                <div class="form-row"><label for="task-branch">Task branch name
+                        <span class="muted">(optional — empty lets the system name the branch; goal worker tasks auto-name task/&lt;goal-id&gt;-&lt;task-id&gt;)</span></label>
+                    <input type="text" id="task-branch" name="task_branch"
+                           placeholder="task/&lt;id&gt;-&lt;slug&gt;"></div>
+                <div class="form-row"><label for="task-branch-from">Branch from
+                        <span class="muted">(default: the project's default branch)</span></label>
+                    <input type="text" id="task-branch-from" name="branch_from"
+                           placeholder="main"></div>
                 <div class="form-row"><label for="task-priority">Priority</label>
                     <select id="task-priority" name="priority">
                         <option value="1">1 — highest</option>

+ 36 - 0
test/bundles/pages.py

@@ -182,6 +182,42 @@ def run(ctx):
     check(detail.get("draft") is True and detail.get("enqueue") is not None
           and detail.get("delete") is not None,
           "draft tasks expose the enqueue + delete actions")
+
+    print("== B6b: create-form branch fields (goal 16) ==")
+    # The queue form carries both branch rows; they post through
+    # tasks.create into the stored task (empty optional -> null,
+    # branch_from prefill from the project's default branch).
+    tasks_page = http_get_page(auth, "/tasks")
+    check('name="task_branch"' in tasks_page and "Task branch name" in tasks_page,
+          "the create form renders the Task branch name input")
+    check('name="branch_from"' in tasks_page and "Branch from" in tasks_page,
+          "the create form renders the Branch from input")
+    check("default: the project's default branch" in tasks_page,
+          "the Branch from label hints at the project default")
+    act(auth, slot_public(auth, "/tasks", "tasks")["create"], {
+        "project_id": "1",
+        "title": "Branch fields task",
+        "priority": "5",
+        "task_branch": "task/999-branch-fields",
+        "branch_from": "release/2026",
+    })
+    detail = task_state(auth, task_id_of("Branch fields task"))
+    check(detail["task_branch"] == "task/999-branch-fields"
+          and detail["branch_from"] == "release/2026",
+          "posted branch fields store on the created task")
+    # Both optional: empty posts leave task_branch null and prefill
+    # branch_from from the project's default branch (demo -> main).
+    act(auth, slot_public(auth, "/tasks", "tasks")["create"], {
+        "project_id": "1",
+        "title": "Default branch fields task",
+        "priority": "5",
+    })
+    detail = task_state(auth, task_id_of("Default branch fields task"))
+    check((detail.get("task_branch") is None
+           or detail.get("task_branch") == "")
+          and detail.get("branch_from") == "main",
+          "empty posts leave task_branch null and prefill branch_from"
+          " from the project default")
     check(quiet_window(quiet_seconds(),
                        lambda: task_state(auth, draft_display)["status"] == "draft",
                        "draft task never dispatches"),