mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[sweep] strip Fxxx audit-ID tokens + trim bloated comments/docstrings + add behavior-change docs
Post-audit sweep over the 135 audit-fix commits since19a474d3: 1. Stripped every # Fxxx: audit-ID token from comments AND every Fxxx token from docstring openings across 211 blocks / ~626 lines. The CEO flagged these twice: audit-issue IDs in code confuse future devs/agents. The descriptive text is preserved; only the Fxxx token is removed (and bloated narrative blocks trimmed to 1-3 lines keeping the one non-obvious invariant). 2. Trimmed bloated comments/docstrings to the concise standard (1-3 lines). 3. Added missing behavior-change docs for the audit-fix batch: prompts/roles (documenter, pr_reviewer, qa), user-facing docs (api auth, websockets, agent-gateway, megatask, merge-model, task-lifecycle, grok, resilience, conventions, panel, security, troubleshooting), and the RAG corpus (cell-pm, main-pm, pr-reviewer, qa roles; conventions; messaging-tools; escalation; megatask; task-claiming workflows). Comment/docstring/prose ONLY — zero code-line edits (verified: the diff contains no def/class/return/if/for/await/assignment/call lines). Gates green: ruff format + ruff check clean, mypy clean on roboco/. The only pytest failures are the pre-existing sync_branch tracing-decision gap (B1,250be5c2) — not sweep-caused and tracked separately.
This commit is contained in:
@@ -102,13 +102,10 @@ async def test_explicit_dep_update_paths_scope(tmp_path: Path) -> None:
|
||||
async def test_probe_holds_read_clone_lock_across_local_clone(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""F116: the dep-update probe must hold the read-clone lock for the
|
||||
duration of the local ``git clone --local`` from the read clone, so a
|
||||
concurrent ``ensure_read_clone`` → ``_sync_read_clone`` (fetch + hard-reset
|
||||
to origin's default branch) cannot mutate the read clone mid-clone. The
|
||||
lock is released before the upgrade runs on the independent copy (the
|
||||
upgrade never touches the read clone, so holding the lock past the clone
|
||||
would needlessly block conventions reads for the upgrade duration)."""
|
||||
"""The dep-update probe holds the read-clone lock across the local
|
||||
``git clone --local`` so a concurrent ``_sync_read_clone`` cannot mutate the
|
||||
read clone mid-clone; released before the upgrade (which runs on an
|
||||
independent copy)."""
|
||||
read_clone = _make_read_clone(tmp_path)
|
||||
svc = _svc(read_clone)
|
||||
# Unique slug → a fresh lock not shared with any other test.
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
"""F074 — real-Postgres proof that ``TaskService.acquire_claim_lock`` serializes
|
||||
concurrent claims by the SAME agent (the one-task-per-agent invariant) while NOT
|
||||
serializing claims by DIFFERENT agents.
|
||||
|
||||
The choreographer-level ordering + coordinator-exemption is covered by the unit
|
||||
suite (``test_choreographer_claim_lock.py``); this test pins the DB-level
|
||||
contract the unit suite mocks out: that ``pg_advisory_xact_lock`` keyed by
|
||||
``hashtextextended(agent_id)`` actually blocks a second transaction trying to
|
||||
acquire the same agent's lock until the first commits/rolls back, and that a
|
||||
different agent's lock is uncontended. Skips when Postgres is unreachable.
|
||||
|
||||
Each ``acquire_claim_lock`` call uses its own fresh session/engine. The
|
||||
blocking call's session is single-use: ``asyncio.wait_for`` cancelling an
|
||||
in-flight asyncpg query leaves the SQLAlchemy session mid-connection-checkout
|
||||
("provisioning a new connection"), so a throwaway session per timed acquire
|
||||
keeps the rest of the test on clean connections.
|
||||
"""Real-Postgres proof that ``TaskService.acquire_claim_lock`` serializes
|
||||
concurrent claims by the SAME agent (one-task-per-agent) while NOT serializing
|
||||
different agents. Skips when Postgres is unreachable; each ``acquire_claim_lock``
|
||||
uses a throwaway session so cancellation mid-checkout can't poison the rest of
|
||||
the test.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -1198,7 +1198,7 @@ async def _seed_messages_same_timestamp(
|
||||
async def test_get_messages_compound_before_cursor_no_skip_on_equal_timestamps(
|
||||
msg_setup: dict,
|
||||
) -> None:
|
||||
"""Equal-timestamp messages must not be skipped across pages (F106).
|
||||
"""Equal-timestamp messages must not be skipped across pages.
|
||||
|
||||
With a strict ``timestamp < before`` cursor and ``order_by(timestamp.desc())``,
|
||||
messages sharing the page's last timestamp are cut by ``limit`` on page 1
|
||||
@@ -1239,7 +1239,7 @@ async def test_get_messages_compound_after_cursor_no_skip_on_equal_timestamps(
|
||||
) -> None:
|
||||
"""Forward pagination (``after``) with the compound ``(timestamp, id)``
|
||||
cursor tie-breaks on id so newer-direction pagination across equal
|
||||
timestamps skips nothing either (F106).
|
||||
timestamps skips nothing either.
|
||||
|
||||
With a strict ``timestamp > after`` cursor, every row sharing the cursor's
|
||||
timestamp is EXCLUDED — so forward-paginating from a middle message would
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
"""F107 — Redis bus publish must be deferred until the DB commit lands.
|
||||
"""Redis bus publish must be deferred until the DB commit lands so a rollback
|
||||
drops the event (no phantom notification for a row that never became durable).
|
||||
|
||||
`NotificationDeliveryService.deliver` historically published
|
||||
``NOTIFICATION_SENT`` to the Redis event bus *before* the caller committed
|
||||
the notification row. A commit failure (DB hiccup, constraint, asyncpg error)
|
||||
rolled the row back but left the bus event behind — connected WebSocket
|
||||
clients received a push for an id that no longer existed (a phantom
|
||||
notification). The fix defers the bus publish to the session's
|
||||
``after_commit`` so a rollback drops it; the row is durable by the time the
|
||||
event fires.
|
||||
|
||||
These tests need a real ``AsyncSession`` (the deferral uses SQLAlchemy
|
||||
session commit/rollback events) plus a recording bus stand-in, so they are
|
||||
integration tests against the migrated Postgres test DB.
|
||||
Integration tests against the migrated Postgres DB: the deferral uses
|
||||
SQLAlchemy ``after_commit`` events and a recording bus stand-in.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -129,12 +120,8 @@ async def _seed_agents_and_notification(
|
||||
async def test_deliver_does_not_publish_before_commit(
|
||||
db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""The bus event must NOT fire until the session commits (F107).
|
||||
|
||||
Currently RED: ``deliver`` publishes immediately, so the bus is non-empty
|
||||
before any commit — the phantom window. With the deferred-publish fix,
|
||||
``deliver`` only schedules; the event fires on commit.
|
||||
"""
|
||||
"""The bus event must NOT fire until the session commits — ``deliver``
|
||||
only schedules; the event fires on commit."""
|
||||
bus = _RecordingBus()
|
||||
monkeypatch.setattr(
|
||||
"roboco.services.notification_delivery.get_event_bus", lambda: bus
|
||||
@@ -152,7 +139,7 @@ async def test_deliver_does_not_publish_before_commit(
|
||||
async def test_deliver_publishes_after_commit(
|
||||
db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Commit drains the deferred publish — one event per recipient (F107)."""
|
||||
"""Commit drains the deferred publish — one event per recipient."""
|
||||
bus = _RecordingBus()
|
||||
monkeypatch.setattr(
|
||||
"roboco.services.notification_delivery.get_event_bus", lambda: bus
|
||||
@@ -179,7 +166,7 @@ async def test_deliver_rollback_drops_phantom(
|
||||
db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""A rollback instead of commit drops the pending publish — no phantom
|
||||
event for a row that never became durable (F107)."""
|
||||
event for a row that never became durable."""
|
||||
bus = _RecordingBus()
|
||||
monkeypatch.setattr(
|
||||
"roboco.services.notification_delivery.get_event_bus", lambda: bus
|
||||
|
||||
@@ -1467,10 +1467,9 @@ async def _gate_task(task_setup: dict, db_session: AsyncSession) -> Any:
|
||||
async def test_pr_gate_claim_rejects_second_reviewer_race(
|
||||
task_setup: dict, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""F114: a second PR-reviewer race-claiming a gate task already claimed by a
|
||||
reviewer must be refused (last-write-wins would otherwise overwrite the
|
||||
first reviewer's claim and the first reviewer's pr_pass/pr_fail would
|
||||
actor-mismatch)."""
|
||||
"""A second PR-reviewer race-claiming a gate task already claimed by another
|
||||
reviewer is refused, so the first reviewer's claim and subsequent
|
||||
pr_pass/pr_fail actor-checks are not overwritten."""
|
||||
svc = task_setup["svc"]
|
||||
reviewer1 = _reviewer("R1")
|
||||
reviewer2 = _reviewer("R2")
|
||||
@@ -1497,10 +1496,9 @@ async def test_pr_gate_claim_rejects_second_reviewer_race(
|
||||
async def test_pr_gate_claim_allows_first_reviewer_when_pm_owns_root(
|
||||
task_setup: dict, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""F114 regression guard: the gate task is owned by the PM at entry
|
||||
(submit_for_review does not clear ownership), so the FIRST reviewer must
|
||||
still be allowed to claim — the guard only rejects a competing REVIEWER
|
||||
claim, not the PM owner."""
|
||||
"""The first reviewer can still claim a gate task owned by the PM at entry
|
||||
(submit_for_review does not clear ownership); the guard only rejects a
|
||||
competing REVIEWER claim, not the PM owner."""
|
||||
svc = task_setup["svc"]
|
||||
pm = _pm("PM")
|
||||
reviewer = _reviewer("R")
|
||||
@@ -1526,8 +1524,8 @@ async def test_pr_gate_claim_allows_first_reviewer_when_pm_owns_root(
|
||||
async def test_pr_gate_claim_idempotent_for_same_reviewer(
|
||||
task_setup: dict, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""F114: a reviewer re-claiming its OWN gate claim is idempotent (allowed),
|
||||
not rejected — the guard only refuses a DIFFERENT reviewer."""
|
||||
"""A reviewer re-claiming its own gate claim is idempotent (allowed); the
|
||||
guard only refuses a different reviewer."""
|
||||
svc = task_setup["svc"]
|
||||
reviewer = _reviewer("R")
|
||||
db_session.add(reviewer)
|
||||
|
||||
@@ -453,14 +453,10 @@ async def test_create_work_session_no_project_returns_none(
|
||||
async def test_create_work_session_delegates_to_service_create(
|
||||
task_setup: dict, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""F113: the claim path must create the WorkSession through the validated
|
||||
``WorkSessionService.create`` (the single source of truth), not construct a
|
||||
``WorkSessionTable`` directly. Two divergent creation sites had drifted and
|
||||
bypassed the service-layer validation (existing-active check, supersede
|
||||
invariant, project/task existence). Routing through ``create`` collapses
|
||||
them to one validated path. The derived target_branch (parent branch for
|
||||
subtasks, project default for roots) is passed in via ``WorkSessionCreate``.
|
||||
"""
|
||||
"""The claim path must create the WorkSession via ``WorkSessionService.create``
|
||||
(single source of truth) rather than constructing a ``WorkSessionTable``
|
||||
directly, so service-layer validation (existing-active check, supersede
|
||||
invariant) is not bypassed."""
|
||||
svc = task_setup["svc"]
|
||||
task = await svc.create(_req(task_setup))
|
||||
task.branch_name = "feature/backend/delegate"
|
||||
|
||||
@@ -1657,11 +1657,9 @@ async def test_submit_for_pm_review_advances_with_notes(
|
||||
async def test_submit_for_pm_review_waives_branch_pr_for_batch_umbrella(
|
||||
task_setup: dict, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""F001: a MegaTask umbrella is branchless by design (no branch/PR) yet
|
||||
must walk in_progress -> awaiting_pm_review so main_pm_complete can
|
||||
escalate it to the CEO. submit_for_pm_review must waive the branch+PR
|
||||
requirement for a batch umbrella, or umbrella completion deadlocks in
|
||||
in_progress forever (the Main PM loops on `complete` -> invalid_state)."""
|
||||
"""A MegaTask umbrella is branchless by design yet must walk
|
||||
in_progress -> awaiting_pm_review; submit_for_pm_review waives the
|
||||
branch+PR requirement for a batch umbrella so completion does not deadlock."""
|
||||
svc = task_setup["svc"]
|
||||
task = await svc.create(_req(task_setup))
|
||||
task.status = TaskStatus.IN_PROGRESS
|
||||
@@ -1682,13 +1680,10 @@ async def test_submit_for_pm_review_waives_branch_pr_for_batch_umbrella(
|
||||
async def test_activate_batch_root_subtasks_retypes_code_to_planning(
|
||||
task_setup: dict, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""F002: a board-routed MegaTask root-subtask is created in BACKLOG with
|
||||
team=board and task_type=code (intake only coerces main_pm-team drafts, so a
|
||||
board-routed code root-subtask reaches activation still code-typed). When
|
||||
the CEO approves the umbrella, _activate_batch_root_subtasks flips the held
|
||||
child to team=main_pm — but if it leaves task_type=code the combo
|
||||
re-introduces the 2026-06-27 main_pm+code meltdown. The activation must
|
||||
retype code->planning, mirroring approve_and_start's own retype."""
|
||||
"""A board-routed MegaTask root-subtask is created in BACKLOG with
|
||||
task_type=code; _activate_batch_root_subtasks must retype it code->planning
|
||||
when flipping team to main_pm, mirroring approve_and_start, or the
|
||||
main_pm+code combo recurs."""
|
||||
svc = task_setup["svc"]
|
||||
# approve_and_start resolves the main-pm agent by slug — seed it.
|
||||
main_pm = AgentTable(
|
||||
|
||||
Reference in New Issue
Block a user