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.
|
"""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
|
- ``pr_reviewer_notes`` (TEXT) — the PR reviewer's own rendered note slot, so a
|
||||||
review no longer overwrites ``qa_notes`` / ``dev_notes``.
|
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
|
- ``notes_structured`` (JSON) — the typed source of truth for every role's
|
||||||
structured note (the TEXT note columns become a derived mirror).
|
structured note (the TEXT note columns become a derived mirror).
|
||||||
- ``orchestration_markers`` (JSON) — the machine markers that used to be packed
|
- ``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:
|
def upgrade() -> None:
|
||||||
op.add_column("tasks", sa.Column("pr_reviewer_notes", sa.Text(), nullable=True))
|
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(
|
op.add_column(
|
||||||
"tasks", sa.Column("notes_structured", postgresql.JSON(), nullable=True)
|
"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.
|
# Lossy by design: markers are not re-merged back into quick_context.
|
||||||
op.drop_column("tasks", "orchestration_markers")
|
op.drop_column("tasks", "orchestration_markers")
|
||||||
op.drop_column("tasks", "notes_structured")
|
op.drop_column("tasks", "notes_structured")
|
||||||
|
op.drop_column("tasks", "doc_notes")
|
||||||
op.drop_column("tasks", "pr_reviewer_notes")
|
op.drop_column("tasks", "pr_reviewer_notes")
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ class TaskUpdate(BaseModel):
|
|||||||
qa_notes: str | None = None
|
qa_notes: str | None = None
|
||||||
auditor_notes: str | None = None
|
auditor_notes: str | None = None
|
||||||
pr_reviewer_notes: str | None = None
|
pr_reviewer_notes: str | None = None
|
||||||
|
doc_notes: str | None = None
|
||||||
quick_context: str | None = None
|
quick_context: str | None = None
|
||||||
|
|
||||||
# Lifecycle override — privileged/admin only. Applied by the route as an
|
# Lifecycle override — privileged/admin only. Applied by the route as an
|
||||||
@@ -335,6 +336,7 @@ class TaskResponse(BaseModel):
|
|||||||
qa_notes: str | None
|
qa_notes: str | None
|
||||||
auditor_notes: str | None = None
|
auditor_notes: str | None = None
|
||||||
pr_reviewer_notes: str | None = None
|
pr_reviewer_notes: str | None = None
|
||||||
|
doc_notes: str | None = None
|
||||||
quick_context: str | None
|
quick_context: str | None
|
||||||
notes_structured: dict | None = None
|
notes_structured: dict | None = None
|
||||||
orchestration_markers: 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
|
# quick_context (never human-facing). pr_reviewer_notes is the reviewer's
|
||||||
# own slot so a review no longer overwrites qa_notes / dev_notes.
|
# own slot so a review no longer overwrites qa_notes / dev_notes.
|
||||||
pr_reviewer_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
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)
|
notes_structured: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||||
orchestration_markers: Mapped[dict[str, Any] | None] = mapped_column(
|
orchestration_markers: Mapped[dict[str, Any] | None] = mapped_column(
|
||||||
JSON, nullable=True
|
JSON, nullable=True
|
||||||
|
|||||||
@@ -251,6 +251,9 @@ class Task(TimestampMixin):
|
|||||||
pr_reviewer_notes: str | None = Field(
|
pr_reviewer_notes: str | None = Field(
|
||||||
default=None, description="PR reviewer's rendered verdict (own slot)"
|
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(
|
notes_structured: dict | None = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="Typed structured note payloads — the source of truth",
|
description="Typed structured note payloads — the source of truth",
|
||||||
@@ -390,6 +393,7 @@ class TaskUpdate(RobocoBase):
|
|||||||
auditor_notes: str | None = None
|
auditor_notes: str | None = None
|
||||||
quick_context: str | None = None
|
quick_context: str | None = None
|
||||||
pr_reviewer_notes: str | None = None
|
pr_reviewer_notes: str | None = None
|
||||||
|
doc_notes: str | None = None
|
||||||
|
|
||||||
# Git fields
|
# Git fields
|
||||||
task_type: TaskType | None = None
|
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:
|
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.auditor_notes == "audit"
|
||||||
assert u.pr_reviewer_notes == "review"
|
assert u.pr_reviewer_notes == "review"
|
||||||
|
assert u.doc_notes == "doc"
|
||||||
|
|
||||||
|
|
||||||
def test_domain_task_update_accepts_new_notes() -> None:
|
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.auditor_notes == "audit"
|
||||||
assert u.pr_reviewer_notes == "review"
|
assert u.pr_reviewer_notes == "review"
|
||||||
|
assert u.doc_notes == "doc"
|
||||||
|
|
||||||
|
|
||||||
def test_task_response_exposes_structured_fields() -> None:
|
def test_task_response_exposes_structured_fields() -> None:
|
||||||
fields = set(TaskResponse.model_fields)
|
fields = set(TaskResponse.model_fields)
|
||||||
assert {
|
assert {
|
||||||
"pr_reviewer_notes",
|
"pr_reviewer_notes",
|
||||||
|
"doc_notes",
|
||||||
"notes_structured",
|
"notes_structured",
|
||||||
"orchestration_markers",
|
"orchestration_markers",
|
||||||
} <= fields
|
} <= fields
|
||||||
|
|||||||
Reference in New Issue
Block a user