mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(content): add doc_notes column for the documenter's own slot
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
"""Structured content columns + quick_context machine-marker split.
|
||||
|
||||
Adds three nullable columns to ``tasks``:
|
||||
Adds four nullable columns to ``tasks``:
|
||||
|
||||
- ``pr_reviewer_notes`` (TEXT) — the PR reviewer's own rendered note slot, so a
|
||||
review no longer overwrites ``qa_notes`` / ``dev_notes``.
|
||||
- ``doc_notes`` (TEXT) — the documenter's own rendered note slot (doc content
|
||||
used to leak into the human ``quick_context`` blob).
|
||||
- ``notes_structured`` (JSON) — the typed source of truth for every role's
|
||||
structured note (the TEXT note columns become a derived mirror).
|
||||
- ``orchestration_markers`` (JSON) — the machine markers that used to be packed
|
||||
@@ -102,6 +104,7 @@ def _parse_quick_context(blob: str | None) -> tuple[dict, str | None]:
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("tasks", sa.Column("pr_reviewer_notes", sa.Text(), nullable=True))
|
||||
op.add_column("tasks", sa.Column("doc_notes", sa.Text(), nullable=True))
|
||||
op.add_column(
|
||||
"tasks", sa.Column("notes_structured", postgresql.JSON(), nullable=True)
|
||||
)
|
||||
@@ -141,4 +144,5 @@ def downgrade() -> None:
|
||||
# Lossy by design: markers are not re-merged back into quick_context.
|
||||
op.drop_column("tasks", "orchestration_markers")
|
||||
op.drop_column("tasks", "notes_structured")
|
||||
op.drop_column("tasks", "doc_notes")
|
||||
op.drop_column("tasks", "pr_reviewer_notes")
|
||||
|
||||
@@ -236,6 +236,7 @@ class TaskUpdate(BaseModel):
|
||||
qa_notes: str | None = None
|
||||
auditor_notes: str | None = None
|
||||
pr_reviewer_notes: str | None = None
|
||||
doc_notes: str | None = None
|
||||
quick_context: str | None = None
|
||||
|
||||
# Lifecycle override — privileged/admin only. Applied by the route as an
|
||||
@@ -335,6 +336,7 @@ class TaskResponse(BaseModel):
|
||||
qa_notes: str | None
|
||||
auditor_notes: str | None = None
|
||||
pr_reviewer_notes: str | None = None
|
||||
doc_notes: str | None = None
|
||||
quick_context: str | None
|
||||
notes_structured: dict | None = None
|
||||
orchestration_markers: dict | None = None
|
||||
|
||||
@@ -345,6 +345,7 @@ class TaskTable(Base):
|
||||
# quick_context (never human-facing). pr_reviewer_notes is the reviewer's
|
||||
# own slot so a review no longer overwrites qa_notes / dev_notes.
|
||||
pr_reviewer_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
doc_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
notes_structured: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
orchestration_markers: Mapped[dict[str, Any] | None] = mapped_column(
|
||||
JSON, nullable=True
|
||||
|
||||
@@ -251,6 +251,9 @@ class Task(TimestampMixin):
|
||||
pr_reviewer_notes: str | None = Field(
|
||||
default=None, description="PR reviewer's rendered verdict (own slot)"
|
||||
)
|
||||
doc_notes: str | None = Field(
|
||||
default=None, description="Documenter's rendered note (own slot)"
|
||||
)
|
||||
notes_structured: dict | None = Field(
|
||||
default=None,
|
||||
description="Typed structured note payloads — the source of truth",
|
||||
@@ -390,6 +393,7 @@ class TaskUpdate(RobocoBase):
|
||||
auditor_notes: str | None = None
|
||||
quick_context: str | None = None
|
||||
pr_reviewer_notes: str | None = None
|
||||
doc_notes: str | None = None
|
||||
|
||||
# Git fields
|
||||
task_type: TaskType | None = None
|
||||
|
||||
@@ -8,21 +8,28 @@ from roboco.models.task import TaskUpdate as DomainTaskUpdate
|
||||
|
||||
|
||||
def test_api_task_update_accepts_auditor_and_pr_reviewer_notes() -> None:
|
||||
u = ApiTaskUpdate(auditor_notes="audit", pr_reviewer_notes="review")
|
||||
u = ApiTaskUpdate(
|
||||
auditor_notes="audit", pr_reviewer_notes="review", doc_notes="doc"
|
||||
)
|
||||
assert u.auditor_notes == "audit"
|
||||
assert u.pr_reviewer_notes == "review"
|
||||
assert u.doc_notes == "doc"
|
||||
|
||||
|
||||
def test_domain_task_update_accepts_new_notes() -> None:
|
||||
u = DomainTaskUpdate(auditor_notes="audit", pr_reviewer_notes="review")
|
||||
u = DomainTaskUpdate(
|
||||
auditor_notes="audit", pr_reviewer_notes="review", doc_notes="doc"
|
||||
)
|
||||
assert u.auditor_notes == "audit"
|
||||
assert u.pr_reviewer_notes == "review"
|
||||
assert u.doc_notes == "doc"
|
||||
|
||||
|
||||
def test_task_response_exposes_structured_fields() -> None:
|
||||
fields = set(TaskResponse.model_fields)
|
||||
assert {
|
||||
"pr_reviewer_notes",
|
||||
"doc_notes",
|
||||
"notes_structured",
|
||||
"orchestration_markers",
|
||||
} <= fields
|
||||
|
||||
Reference in New Issue
Block a user