Repository navigation
[24076f98] Learning propagation appends to an in-memory notification queue that nothing reads and nothing prunes - #1406
Conversation
…nd rewrite the stale cell-scope test (learning.py) (#1401) * [5db9054b] Bound the in-memory learning notification queue in learning.py (cap growth; optional prune-on-ack) (#1119) * [5db9054b] fix(learning): bound in-memory notification queue with deque maxlen + prune-on-ack The queue grew monotonically in the orchestrator process (one entry per notified agent per learning; nothing in production acks so nothing was ever removed). Switch _notification_queue to a deque with a 256-entry maxlen so appends evict the oldest entries, and prune acknowledged entries inside acknowledge_notification. Public signatures of get_pending_notifications / acknowledge_notification are unchanged; _fetch_notify_agents fanout logic untouched. NotificationTable rows from _persist_notifications remain the durable record. Queue-lifecycle coverage added in tests/unit/services/test_learning.py: cap eviction of oldest entries, prune-on-ack behavior, and unchanged pending filtering. tests/integration/test_learning_service.py is deliberately untouched (owned by a sibling leaf). * [5db9054b] regenerate generated artifacts * [5db9054b] regenerate generated artifacts * [5db9054b] regenerate generated artifacts * [5db9054b] fix(generated): restore out-of-scope generated artifacts to base content * [5db9054b] docs(learning): document bounded in-memory notification queue --------- Co-authored-by: Backend Developer 2 <be-dev-2@roboco.tech> Co-authored-by: Backend Documenter <be-doc@roboco.tech> * [6d4baecf] Rewrite the stale cell-scope learning test to assert post-#914 fanout honestly (#1118) * [6d4baecf] test(learning): rewrite cell-scope test to assert post-#914 team filter honestly * [6d4baecf] regenerate generated artifacts * [6d4baecf] test(learning): drop trailing inline comments from cell-scope tests * [6d4baecf] revert stale generated artifacts regenerated against an old base * docs: CELL-scope learning test rewrite (post-#914) * [6d4baecf] regenerate generated artifacts * [6d4baecf] chore(generated): regenerate artifacts from this branch's spec before rebase * [6d4baecf] chore(docs): remove out-of-scope QA doc from cell-scope test PR --------- Co-authored-by: Backend Developer 1 <be-dev-1@roboco.tech> Co-authored-by: Renn F <rennf93@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Backend Documenter <be-doc@roboco.tech> Co-authored-by: Backend Developer 2 <be-dev-2@roboco.tech> --------- Co-authored-by: roboco-app[bot] <302741806+roboco-app[bot]@users.noreply.github.com> Co-authored-by: Backend Developer 2 <be-dev-2@roboco.tech> Co-authored-by: Backend Documenter <be-doc@roboco.tech> Co-authored-by: Renn F <rennf93@users.noreply.github.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Backend Developer 1 <be-dev-1@roboco.tech>
|
Thanks for opening your first pull request on RoboCo! Quick checklist before review (most of these are enforced by CI, but worth a glance):
See CONTRIBUTING.md for the full workflow and the Code of Conduct for the community standards we follow. Welcome aboard — a maintainer will review shortly. |
There was a problem hiding this comment.
In-path PR-review gate — PASSED ✅
Reviewed by pr_reviewer (RoboCo PR reviewer). Posted by the project bot account; the gate verdict is authoritative in RoboCo.
Checked each criterion against the code. Criterion 1: learning.py:344 makes _notification_queue a deque with maxlen=_NOTIFICATION_QUEUE_MAXLEN (256); acknowledge_notification (learning.py:321-326) prunes all acknowledged entries and keeps the maxlen; the Protocol type in _learning_propagation_types.py is updated to match. Unit tests cover eviction at the cap, prune-on-ack and pending filtering. Criterion 2: test_cell_scope_runs_without_role_filter is renamed to test_cell_scope_notifies_author_team_excludes_cross_cell, with a docstring that describes the post-#914 behaviour. It adds a Team.FRONTEND agent and asserts on persisted KNOWLEDGE_SHARE rows that the same-team peer is a recipient and the cross-cell agent is not. Criterion 3: _fetch_notify_agents and the TEAM/ORG branches are untouched; make quality is left to the CI guard. The docs file is in the established docs/backend/services location. Nits, not blocking: the doc cites PR #1119 (the cell PR) rather than #1406, and a harmless comment on the ORG truncation test was removed.
Only the CEO merges this PR into master.
Objective
Every recorded learning writes its notifications twice: once as DB rows via _persist_notifications, and once as in-memory LearningNotification objects appended by _enqueue_in_memory (roboco/services/learning.py:283-304), one row per notified agent. The in-memory copy has no production reader: get_pending_notifications and acknowledge_notification (learning.py:449-502) only filter and flip a flag, and no route, gateway verb, or service calls either (the notifications API acks through NotificationDeliveryService instead, see roboco/api/routes/notifications.py:107). Acknowledged entries are therefore never removed, and the queue grows monotonically in the orchestrator process until restart, one entry per notified agent per learning.
Note this task's original headline (CELL-scoped learnings notify the entire org because of a TODO in _fetch_notify_agents) is already fixed on master: commit 04eb61d (PR #914, 2026-08-12) filters CELL scope to the author's team. The remaining, still-real defects are the unbounded queue and the stale test that pretends that filter does not exist: test_cell_scope_runs_without_role_filter only passes because both of its fake agents are hardcoded Team.BACKEND. Fix: prune or bound the in-memory queue, or drop it in favor of the DB-backed notification path, and rewrite the stale cell-scope test.
Notes
Success Criteria