Created
Jul 08, 02:50
Started
Jul 08, 05:47
Completed
Jul 08, 07:12
DevOps handoff
Type
Bug
Shape
ui-only
Worktree Slug
filter-live-activities
Repositories
mcritchie-studio
Release Slug
—
Branch
feat/filter-live-activities
Acceptance Criteria
Expected Test Plan
Checks Run
How long this task spent in each testing phase — Build → Local Certification → CI → Review → Operator Acceptance.
Build
3 minutes
Completed
Local Certification
—
Missing
CI
—
Missing
Review
6 minutes
Completed
Operator Acceptance
about 10 hours so far
In progress
Stage Timeline
Who handled each stage, the time it took (measured), and the model / tokens / cost reported (best-effort) — plus who's on it right now. — means the agent didn't report that metric.
Conversation
QA review feedback, agent handoffs, and follow-up notes for this task.
Scout report: merge-ready - Light second read clean: broadcaster fans out global+session streams; filtered pages subscribe session-scoped only. All 3 acceptance criteria mechanically satisfied and test-covered. CI green on PR head. Reporter: jasper Outcome: merge-ready Findings: - Non-blocker: PR is still a draft; fix is gh pr ready at the submit seam - Non-blocker: deliver_action_created/updated now load the full agent_activity record (one extra query per action broadcast) instead of the id; needed for session routing Questions: - none Checks: - gh pr view 452: OPEN, base release, MERGEABLE, CI scan_ruby/scan_js/lint/test all SUCCESS - branch contains current origin/release (merge-base ancestor check); no other agents_activities subscribers on release
Scout report: request-changes - Stream scoping only works on full page loads: the live-stream partial renders OUTSIDE turbo-frame aa-activities-frame while filter/pager/clear links navigate the frame only, so in-page filter clicks keep the stale subscription and nonmatching payloads still patch into the visible filtered table. Reporter: shannon Outcome: request-changes Findings: - BLOCKER app/views/agents/activities.html.erb:21 — render of agents/activities_live_streams sits outside <turbo-frame id=aa-activities-frame>; sidebar/chip/pager links are in-frame link_to with no _top target, so a frame swap never re-renders the turbo-cable-stream-source tags. Unfiltered load then filter click keeps the GLOBAL subscription (acceptance: nonmatching payloads stay outside filtered lists FAILS in the primary interactive path); filtered load then Clear-all keeps the session-only subscription (unfiltered append behavior FAILS). Fix: move the render inside the frame top so subscriptions swap with content, and add an assertion that stream sources render within the frame. - non-blocker: when a filtered page has zero rows the hb-empty state replaces the table, so no thead#aa-activities-head target exists and the first matching live activity cannot append — pre-existing on the unfiltered path, just more visible with filters - non-blocker: deliver_action_created/updated now load action.agent_activity (one extra PK lookup per action broadcast on the capture hot path) where the FK id sufficed before; needed for session_id, acceptable Questions: - none Checks: - bin/dor-check filter-live-activities PASS (component tier green, full-suite-bypass noted, GitHub CI green 4 checks) - full-suite-bypass ACCEPTED: CI on exact head a34c0834 green incl full test job at 05:01Z — clean-CI full suite supersedes the SIGTERM 143 local run - merge safety: single commit atop current origin/release tip bc38e331; MERGEABLE/CLEAN; zero file overlap with open PRs 453/454/455 - broadcaster + view + integration tests assert session-scoped signing on full-page render; none cover the in-frame filter-click subscription path
BLOCKING (shannon primary; jasper light approved full-page paths): the live stream sources do not follow in-frame filter changes. app/views/agents/activities.html.erb:21 renders agents/activities_live_streams OUTSIDE turbo-frame#aa-activities-frame (frame opens ~line 37), while every filter control (sidebar session toggles, active-filter chips, Clear all, pager) is an in-frame link_to. Frame navigation swaps only frame children, so the initial-load turbo-cable-stream-source tags persist: (1) load unfiltered then click a session filter -> page stays subscribed to the global agents_activities stream and nonmatching payloads still append to the filtered table (acceptance 2 fails); (2) load ?sessions=sess-A then Clear all -> page stays session-only and the unfiltered table misses other sessions' live appends (acceptance 3 fails). The fix works only on full page loads, which is why current tests pass - they assert full-page render output. FIX: move the activities_live_streams render inside the top of the turbo-frame so stream sources swap with filtered content (Turbo connects/disconnects cable sources on insert/remove), and add a test asserting the sources render within turbo-frame#aa-activities-frame. AT RESUBMIT: run gh pr ready 452 (PR is still draft) and post bin/task note --resolves-feedback. NON-BLOCKING nits: empty filtered page renders hb-empty with no thead#aa-activities-head target so the first matching live activity cannot append (pre-existing, fix optional); extra agent_activity PK lookup per action broadcast is acceptable. What is good: dual-broadcast design (global + session streams, single-scope subscription) is sound, and green CI on head a34c0834 supersedes the local SIGTERM full-suite bypass - keep it.
Addressed blocker: moved activities live stream subscriptions inside turbo-frame#aa-activities-frame so filter/pager frame navigation swaps websocket subscriptions; added frame-scoped regression coverage. Tests: bin/rails test test/integration/agents_activities_test.rb; focused activities suite 55/224 green; bin/rubocop clean on amended commit 909b9485.
Scout report: merge-ready - Re-review confirms fix: stream sources render INSIDE turbo-frame#aa-activities-frame via new _activities_live_streams partial; old outside-frame turbo_stream_from removed; in-frame filter nav now swaps subscriptions correctly. Regression coverage is genuine: frame-scoped assert_select turbo-frame#aa-activities-frame turbo-cable-stream-source plus filtered-page refute of the global signed stream name. All 4 CI lanes green. Reporter: jasper Outcome: merge-ready Findings: - Placement fix verified: partial renders as first child inside the frame, so filter/Clear-all frame swaps disconnect stale sources and connect scoped ones - Broadcaster fans out to global + session-scoped streams; pages subscribe to exactly one scope (never both) so no duplicate inserts - Controller parse_session_ids and streams_for_filters normalize identically (strip/reject-blank/uniq); blank session_id activities safely hit global only - Non-blocker: session-filtered broadcasts render each partial twice (global + session stream) — acceptable fan-out cost for this feed Questions: - none Checks: - gh pr view 452: OPEN, not draft, base release, CI scan_ruby/scan_js/lint/test all SUCCESS - branch merge-base equals current origin/release tip bc38e331 — zero release drift
Scout report: merge-ready - Re-review: prior blocker fixed — stream sources render inside turbo-frame#aa-activities-frame and swap on frame navigation; regression tests assert in-frame placement + session-scoped subscription; CI green on amended head 909b9485; PR undrafted Reporter: shannon Outcome: merge-ready Findings: - Prior cert tree d949a8dd != head tree d009397b, but CI full test lane green on exact head supersedes the local SIGTERM bypass - Nit: session-scoped broadcasts render the row partial once per stream (2x when filtered) — fine at current volume Questions: - none Checks: - dor-check pass (DoR-to-Merge met, CI 4/4 green) - diff vs acceptance: filtered pages subscribe only to matching session streams; unfiltered keeps single global stream
Avi review approved on resubmit; ready for Steffon's qa-release sweep. Round-1 blocker (stream sources outside turbo-frame) verified fixed at head 909b9485 with placement-asserting regression tests; PR #452 undrafted; CI 4/4 green on head.
Scout report: merge-ready - Light second read clean: session-scoped streams exactly mirror the HTTP filter (only filter dimension is sessions, exact-match where(session_id:)); subscriptions live inside aa-activities-frame so filter navigation swaps them; unfiltered path keeps global stream with identical actions/targets; broadcast errors surface via Studio::Cable.safe_broadcast -> ErrorLog. Reporter: jasper Outcome: merge-ready Findings: - Non-blocker: stream_for_session strips stored session_id while HTTP filter matches the raw stored value - a whitespace-padded stored id would live-append to a filtered page that excludes it in render; pathological since ids are machine-generated. - Non-blocker: every activity/action after_commit now renders+publishes 2x (global + session stream) even with no session subscriber - fine today, watch if capture volume grows. - Note: checks_run carries [full-suite-bypass] (SIGTERM 143 under concurrent load) - primary owns that gate call; PR CI test job is green (05:54Z) which corroborates the same-diff green claim. Questions: - none Checks: - diff read vs origin/release (single commit 909b9485, cleanly rebased on bc38e331) - controller filter predicate vs broadcast stream scoping mirrored - subscription lifecycle inside turbo-frame verified in view + integration test
Scout report: merge-ready - Primary re-review at head 909b9485: round-1 blocker genuinely fixed (stream sources render inside turbo-frame#aa-activities-frame, swap on frame nav) with placement + session-scope regression tests. Full-suite-bypass resolved via CI: cert tree d949a8dd != head tree d009397b (not same-diff), but CI test job (db:test:prepare test test:system) green on exact head supersedes. Independent second-wave confirmation; task already reviewed by prior wave. Reporter: shannon Outcome: merge-ready Findings: - Non-blocker: bypass note claims 'prior same-diff' but trees differ (d949a8dd vs d009397b); CI-on-head covers it - Non-blocker: empty filtered page lacks thead#aa-activities-head target so first matching live activity cannot append (pre-existing) - Non-blocker: stream_for_session strips session_id while HTTP filter matches raw stored value; whitespace-padded ids pathological Questions: - none Checks: - bin/dor-check pass (ui-only, component tier green, CI green noted) - gh pr view 452: base release, not draft, MERGEABLE/CLEAN, CI 4/4 SUCCESS on 909b9485 - merge-base == origin/release tip bc38e331; zero file overlap with 6 open release PRs
Avi review approved; ready for Steffon's qa-release sweep.
Sealed-bid sizing
Edit →Alex (PM)
—
Avi (PO)
—
Dev
SMALL
Actual
MEDIUM
We emailed a one-tap sign-in link to . It expires shortly and can only be used once.
No email? Check spam, or close this and try again.