mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(api): serialize pr_reviewer_notes/doc_notes/notes_structured in the task response
task_to_response (the builder behind the task list + detail endpoints the panel reads) set dev_notes/qa_notes/quick_context but dropped pr_reviewer_notes, doc_notes, and notes_structured, and TaskResponse didn't declare notes_structured at all — so the PR-reviewer notes, documenter notes, and the structured PR-review verdict were always blank in the panel regardless of what agents persisted. The structured-content write-path + obligation gates were fine; the data just wasn't serialized. Now returns every note section + the structured source of truth. Regression test asserts all three round-trip.
This commit is contained in:
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Task notes were invisible in the panel — the API response dropped them.** The `task_to_response` serializer (used by the task list and detail endpoints the panel reads) set `dev_notes` / `qa_notes` / `quick_context` but **omitted `pr_reviewer_notes`, `doc_notes`, and `notes_structured`**, and `TaskResponse` didn't even declare `notes_structured` — so the PR-reviewer's notes, the documenter's notes, and the structured PR-review verdict were always blank in the UI no matter what the agents wrote to the DB (the structured-content write-path and obligation gates work; the data simply wasn't being serialized). The builder now returns all note sections plus the structured source of truth. (`dev_notes`/`qa_notes` on an in-flight task are still legitimately empty until the developer submits / QA reviews.)
|
||||
|
||||
## [0.9.0] - 2026-06-23
|
||||
|
||||
### Added
|
||||
|
||||
@@ -238,6 +238,10 @@ class TaskUpdate(BaseModel):
|
||||
pr_reviewer_notes: str | None = None
|
||||
doc_notes: str | None = None
|
||||
quick_context: str | None = None
|
||||
# The structured source of truth (panel renders the verdict pill + sections
|
||||
# from this). Must be serialized or the PR-review verdict + any structured
|
||||
# rendering are blank even when the DB has them.
|
||||
notes_structured: dict | None = None
|
||||
|
||||
# Lifecycle override — privileged/admin only. Applied by the route as an
|
||||
# audited force-transition (so an operator can recover a task wedged in a
|
||||
@@ -705,7 +709,10 @@ def task_to_response(task: "TaskTable") -> TaskResponse:
|
||||
dev_notes=task.dev_notes,
|
||||
qa_notes=task.qa_notes,
|
||||
auditor_notes=task.auditor_notes,
|
||||
pr_reviewer_notes=task.pr_reviewer_notes,
|
||||
doc_notes=task.doc_notes,
|
||||
quick_context=task.quick_context,
|
||||
notes_structured=task.notes_structured,
|
||||
self_verified=task.self_verified,
|
||||
qa_verified=task.qa_verified,
|
||||
branch_name=getattr(task, "branch_name", None),
|
||||
|
||||
@@ -300,7 +300,10 @@ def _stub_task(*, with_project: bool = False) -> SimpleNamespace:
|
||||
dev_notes=None,
|
||||
qa_notes=None,
|
||||
auditor_notes=None,
|
||||
pr_reviewer_notes=None,
|
||||
doc_notes=None,
|
||||
quick_context=None,
|
||||
notes_structured=None,
|
||||
self_verified=False,
|
||||
qa_verified=None,
|
||||
branch_name=None,
|
||||
@@ -327,6 +330,23 @@ def test_task_to_response_includes_slug_when_project_loaded() -> None:
|
||||
assert resp.project_slug == "proj-1"
|
||||
|
||||
|
||||
def test_task_to_response_serializes_all_note_sections() -> None:
|
||||
"""Regression: pr_reviewer_notes / doc_notes / notes_structured MUST be in the
|
||||
response. The builder previously omitted them, so the panel showed them blank
|
||||
even when the DB had them (the recurring "notes invisible" bug)."""
|
||||
stub = _stub_task()
|
||||
stub.pr_reviewer_notes = "## Findings\n- looks good"
|
||||
stub.doc_notes = "Updated the README"
|
||||
stub.notes_structured = {"pr_review": {"verdict": "passed"}}
|
||||
fake_inspector = MagicMock()
|
||||
fake_inspector.unloaded = {"project"}
|
||||
with patch("roboco.api.schemas.tasks.sa_inspect", return_value=fake_inspector):
|
||||
resp = task_to_response(stub) # type: ignore[arg-type]
|
||||
assert resp.pr_reviewer_notes == "## Findings\n- looks good"
|
||||
assert resp.doc_notes == "Updated the README"
|
||||
assert resp.notes_structured == {"pr_review": {"verdict": "passed"}}
|
||||
|
||||
|
||||
def test_task_list_to_response_returns_list() -> None:
|
||||
stubs = [_stub_task(), _stub_task()]
|
||||
fake_inspector = MagicMock()
|
||||
|
||||
Reference in New Issue
Block a user