fix(content): keep coordination notes off dev_notes / quick_context

Two agent-authored fields were leaking non-developer content into the
human note columns the panel renders:

- apply_escalation appended '[ESCALATED] From X to Y\nReason: ...' to
  dev_notes (the developer's space). On a re-escalation loop a stuck cell
  PM grew one task's dev_notes to ~8KB across 5 escalations. It now writes
  a structured orchestration_markers['escalation'] record; the target
  still learns the reason from the escalate notification.
- approve_and_start string-packed 'approve_and_start_notes:<text>' into
  quick_context (raw key:value soup). It now writes
  orchestration_markers['approve_and_start_notes'], leaving quick_context
  for the human ResumptionNote only.

Adds typed marker accessors (get/set_escalation, get/set_approve_and_start_notes)
and refactors _record_pr_review under the complexity bound by extracting
_compose_review_body. Documents update_task_with_message as the legacy
A2A-protocol log (dev_notes is intentional there, not pollution).
This commit is contained in:
Renn F
2026-06-21 05:36:50 +02:00
parent 4c85cc6dfa
commit 3ff6967b9d
6 changed files with 98 additions and 20 deletions
@@ -50,6 +50,24 @@ def test_clear_marker_nulls_when_empty() -> None:
assert t.orchestration_markers is None
def test_escalation_roundtrip() -> None:
t = _task()
assert m.get_escalation(t) is None
m.set_escalation(t, from_slug="be-pm", to_slug="main-pm", reason="re-open please")
assert m.get_escalation(t) == {
"from": "be-pm",
"to": "main-pm",
"reason": "re-open please",
}
def test_approve_and_start_notes_roundtrip() -> None:
t = _task()
assert m.get_approve_and_start_notes(t) is None
m.set_approve_and_start_notes(t, "Board approved; build it.")
assert m.get_approve_and_start_notes(t) == "Board approved; build it."
def test_documenter_self_heal_head_supersede() -> None:
t = _task()
m.set_documenter(t, "doc-uuid")