mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(prompter): board-review → redraft loop for MegaTask batches (#411)
Batch parity with the single-draft keep-alive redraft loop. A first board-route confirm-batch parks the intake session against the umbrella (instead of the unconditional reap), so the existing board-completion injection reaches the still-live chat — now with a batch-aware brief (compose_batch_redraft_message: live root-subtask snapshots + board notes + a one-propose_batch re-proposal instruction). The re-confirm carries BatchConfirmRequest.task_id and routes to the new PrompterService.update_live_batch: in-place umbrella + root-subtask update (positional patch of live children, cancel+recreate on scope change, create/cancel on count change, dependency edges rewired to the fresh wave plan) gated by the same _validate_batch_scope as create. Readers use the CANCELLED-excluding get_live_subtasks view so multi-round redrafts survive earlier cancels. Cold path: re-interview now handles a branchless umbrella by recovering its multi-repo scope from live children (distinct_projects_for_batch) and returning project_ids — fixes the live 400 behind the task-detail redraft button on umbrellas. Panel: confirmBatch board branch keeps the chat open, threads batchRedraftTaskIdRef (persisted) into the re-confirm, treats a redraft re-confirm as terminal on both routes, and surfaces the server's real validation message on confirm failure. Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -12,6 +12,7 @@ from roboco.models.base import TaskNature, TaskStatus, TaskType
|
||||
from roboco.services.base import NotFoundError
|
||||
from roboco.services.prompter import (
|
||||
PrompterService,
|
||||
compose_batch_redraft_message,
|
||||
compose_redraft_message,
|
||||
format_board_briefing,
|
||||
)
|
||||
@@ -63,6 +64,60 @@ def test_compose_redraft_message_includes_draft_and_brief() -> None:
|
||||
assert "z" in msg
|
||||
|
||||
|
||||
def test_compose_batch_redraft_message_includes_every_child_and_brief() -> None:
|
||||
umbrella = SimpleNamespace(
|
||||
title="MegaTask: Ship the thing",
|
||||
description="Coordinate 2 sequenced tasks as one MegaTask.",
|
||||
)
|
||||
children = [
|
||||
SimpleNamespace(
|
||||
title="Backend piece",
|
||||
description="Backend description.",
|
||||
acceptance_criteria=["backend ac"],
|
||||
project=SimpleNamespace(name="roboco-api"),
|
||||
cell_projects=[],
|
||||
),
|
||||
SimpleNamespace(
|
||||
title="Frontend piece",
|
||||
description="Frontend description.",
|
||||
acceptance_criteria=["frontend ac"],
|
||||
project=None,
|
||||
cell_projects=[
|
||||
SimpleNamespace(
|
||||
team=Team.FRONTEND, project=SimpleNamespace(name="panel-repo")
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
entries = [
|
||||
{
|
||||
"author_role": "product_owner",
|
||||
"author": "po",
|
||||
"title": "PO",
|
||||
"content": "board feedback",
|
||||
}
|
||||
]
|
||||
msg = compose_batch_redraft_message(
|
||||
cast("TaskTable", umbrella), cast("list[TaskTable]", children), entries
|
||||
)
|
||||
assert "Ship the thing" in msg
|
||||
assert "Backend piece" in msg
|
||||
assert "roboco-api" in msg
|
||||
assert "backend ac" in msg
|
||||
assert "Frontend piece" in msg
|
||||
assert "panel-repo" in msg
|
||||
assert "Product Owner" in msg
|
||||
assert "board feedback" in msg
|
||||
assert "propose_batch" in msg
|
||||
|
||||
|
||||
def test_compose_batch_redraft_message_no_children_is_still_valid() -> None:
|
||||
umbrella = SimpleNamespace(title="MegaTask: Empty", description="Nothing yet.")
|
||||
msg = compose_batch_redraft_message(cast("TaskTable", umbrella), [], [])
|
||||
assert "Empty" in msg
|
||||
assert "propose_batch" in msg
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# update_live_draft (DB)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
Reference in New Issue
Block a user