mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(content): obligate role note sections like journals
Completes the note(scope='handoff') write-path (WIP 23e6ee57): every role
with a dedicated note section is now obligated to populate it, the same way
journals are obligated.
Obligations (foundation.policy.tracing):
- DEV_NOTES / PR_REVIEWER_NOTES / QUICK_CONTEXT_MIN_CHARS requirements +
checkers, wired onto i_am_done (dev_notes), delegate (quick_context), and
pr_pass / pr_fail / post_pr_review (pr_reviewer_notes).
- Fixes a latent bug: the docs-notes checker read dev_notes instead of
doc_notes (the documenter's section); the i_documented shim now feeds
doc_notes to match.
Auditor: a session-scoped note obligation on i_am_idle — the auditor owns no
delivery task and has no delivery verb, so it must have recorded an
observation within the window before going idle (JournalService.has_recent_entry).
Write-then-gate: persisted sections (dev_notes / quick_context) are
pre-written by the agent's note(scope='handoff') before the gated verb;
argument-borne sections (doc_notes / pr_reviewer_notes) are checked through a
SimpleNamespace shim, the same pattern qa_notes already uses.
Config: dev/pr_reviewer/quick_context min-chars (40/40/30), panel-tunable.
Plus per-gap remediation hints and full coverage (write-path routing,
ownership, validation->remediation, each obligation, the doc_notes fix).
Full make-quality green: 9777 passed, 95.6% coverage.
This commit is contained in:
@@ -31,6 +31,9 @@ def test_requirement_enum_has_canonical_values() -> None:
|
||||
"self_verified",
|
||||
"notes>=min",
|
||||
"subtasks_terminal",
|
||||
"dev_notes>=min",
|
||||
"pr_reviewer_notes>=min",
|
||||
"quick_context>=min",
|
||||
}
|
||||
actual = {r.value for r in tracing.Requirement}
|
||||
assert actual == expected, f"Requirement drift: {actual ^ expected}"
|
||||
@@ -52,6 +55,51 @@ def test_gate_result_has_passed_and_missing() -> None:
|
||||
assert result.missing == []
|
||||
|
||||
|
||||
def test_docs_notes_checker_reads_doc_notes_not_dev_notes() -> None:
|
||||
"""Regression: _check_docs_notes_min_chars must read ``doc_notes`` (the
|
||||
documenter's section), not ``dev_notes`` (the developer's)."""
|
||||
ctx = tracing.GateContext(docs_notes_min_chars=20)
|
||||
# A long dev_notes must NOT satisfy the docs requirement.
|
||||
only_dev = SimpleNamespace(dev_notes="x" * 50, doc_notes="")
|
||||
assert tracing._check_docs_notes_min_chars(only_dev, ctx) == ["docs_notes>=min"]
|
||||
# A long doc_notes satisfies it.
|
||||
has_doc = SimpleNamespace(dev_notes="", doc_notes="y" * 25)
|
||||
assert tracing._check_docs_notes_min_chars(has_doc, ctx) == []
|
||||
|
||||
|
||||
def test_note_section_checkers_read_their_own_fields() -> None:
|
||||
ctx = tracing.GateContext() # defaults: dev 40, pr_reviewer 40, quick_context 30
|
||||
assert (
|
||||
tracing._check_dev_notes_min_chars(SimpleNamespace(dev_notes="z" * 40), ctx)
|
||||
== []
|
||||
)
|
||||
assert tracing._check_dev_notes_min_chars(
|
||||
SimpleNamespace(dev_notes="z" * 39), ctx
|
||||
) == ["dev_notes>=min"]
|
||||
assert (
|
||||
tracing._check_pr_reviewer_notes_min_chars(
|
||||
SimpleNamespace(pr_reviewer_notes="z" * 40), ctx
|
||||
)
|
||||
== []
|
||||
)
|
||||
assert tracing._check_quick_context_min_chars(
|
||||
SimpleNamespace(quick_context="z" * 29), ctx
|
||||
) == ["quick_context>=min"]
|
||||
|
||||
|
||||
def test_note_section_obligations_wired_to_verbs() -> None:
|
||||
assert tracing.Requirement.DEV_NOTES_MIN_CHARS in tracing.requirements_for(
|
||||
"i_am_done"
|
||||
)
|
||||
assert tracing.Requirement.QUICK_CONTEXT_MIN_CHARS in tracing.requirements_for(
|
||||
"delegate"
|
||||
)
|
||||
for verb in ("pr_pass", "pr_fail", "post_pr_review"):
|
||||
assert tracing.Requirement.PR_REVIEWER_NOTES_MIN_CHARS in (
|
||||
tracing.requirements_for(verb)
|
||||
)
|
||||
|
||||
|
||||
def test_check_requirements_passes_when_all_satisfied() -> None:
|
||||
task = SimpleNamespace(
|
||||
plan={"x": 1},
|
||||
|
||||
Reference in New Issue
Block a user