Skip to content

[24076f98] Learning propagation appends to an in-memory notification queue that nothing reads and nothing prunes - #1406

Merged
roboco-app[bot] merged 1 commit into
slavefrom
feature/main_pm/24076f98
Nov 3, 2026
Merged

roboco-app[bot] merged 1 commit into
slavefrom
feature/main_pm/24076f98

Conversation

@roboco-app

@roboco-app roboco-app Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

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

  • Evidence: roboco/services/learning.py:283-304 appends one in-memory row per notified agent on every record_learning; learning.py:449-502 never removes acknowledged entries and a repo-wide grep shows zero callers outside the module; roboco/api/routes/notifications.py:107 acks via NotificationDeliveryService, not this queue. CELL fanout was narrowed to the author's team by 04eb61d (PR [9efb36e4] CELL-scoped learning notifications bypass team filter — notify all agents #914, 2026-08-12), so the org-wide claim in the original finding is stale. tests/integration/test_learning_service.py:184-205 carries the pre-filter name, docstring, and a same-team-only assertion.
  • Delegation hint: originated as a backend item - delegate into the backend cell.

Success Criteria

  • The in-memory _notification_queue no longer grows without bound: acknowledged entries are pruned on acknowledge, or the queue is bounded, or it is removed in favor of the DB-backed notification path it duplicates (roboco/services/learning.py)
  • tests/integration/test_learning_service.py test_cell_scope_runs_without_role_filter is rewritten to assert the CELL team filter honestly: same-team agents are notified and cross-cell agents are excluded, under a name and docstring matching the post-[9efb36e4] CELL-scoped learning notifications bypass team filter — notify all agents #914 behavior
  • TEAM (same role) and ORG (all non-human agents) fanout behavior is unchanged, and make quality is green

…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>
@github-project-automation github-project-automation Bot moved this to Backlog in RoboCo Kanban Nov 3, 2026
@github-actions github-actions Bot added documentation Docs, README, CHANGELOG, governance files area: services Touches roboco/services/ (business logic, side effects) tests Test suite changes labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

Thanks for opening your first pull request on RoboCo!

Quick checklist before review (most of these are enforced by CI, but worth a glance):

  • make quality — ruff format check, ruff check, mypy, pytest (≥80% coverage), and the rest of the gate
  • Panel changes pass pnpm lint and pnpm exec tsc --noEmit (run from panel/)
  • No # noqa / # type: ignore shortcuts; pre-existing violations in touched files are fixed
  • Added an entry under ## [Unreleased] in CHANGELOG.md
  • Signed the CLA (the bot will prompt you on this PR)
  • Signed your commits — master requires verified signatures (SSH signing setup)
  • Updated any affected docs under docs/

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.

@roboco-app roboco-app Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@roboco-app
roboco-app Bot merged commit 1a0d4dc into slave Nov 3, 2026
16 of 20 checks passed
@roboco-app
roboco-app Bot deleted the feature/main_pm/24076f98 branch November 3, 2026 20:48
@github-project-automation github-project-automation Bot moved this from Backlog to Done in RoboCo Kanban Nov 3, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area: services Touches roboco/services/ (business logic, side effects) documentation Docs, README, CHANGELOG, governance files main-pm root tests Test suite changes to slave

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

0 participants