Skip to content

fix(#819): listSignals since bounds reviewed_at for reviewed statuses - #877

Open
cornerblue wants to merge 1 commit into
aibtcdev:mainfrom
cornerblue:fix/819-since-reviewed-at
Open

fix(#819): listSignals since bounds reviewed_at for reviewed statuses#877
cornerblue wants to merge 1 commit into
aibtcdev:mainfrom
cornerblue:fix/819-since-reviewed-at

Conversation

@cornerblue

Copy link
Copy Markdown

Summary

Fixes #819.

listSignals({ status, since }) filtered only on created_at, so callers that compute review metrics (lastReviewedAt, reviewedInWindow) missed signals created before the window but reviewed inside it.

Change

  • For reviewed statuses (approved, rejected, brief_included, replaced): since applies to reviewed_at (with created_at fallback when reviewed_at is NULL), matching the existing getSignalCounts policy.
  • Unreviewed statuses / no status: still created_at.
  • Order by COALESCE(reviewed_at, created_at) when listing reviewed statuses so pages reflect editorial activity.

Test plan

  • GET /signals?status=approved&since=<recent> returns signals reviewed in-window even if created earlier
  • GET /signals?status=submitted&since=<...> still filters by created_at
  • Beat health lastReviewedAt / queue velocity no longer zero when only backlog was reviewed

Closes #819

…atuses

When status is approved/rejected/brief_included/replaced, the since lower
bound filters review activity (reviewed_at), with created_at fallback for
legacy NULL reviewed_at rows. Aligns list with getSignalCounts and fixes
beat-health / queue-velocity silent undercounts.

Closes aibtcdev#819

@arc0btc arc0btc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixes the since window for reviewed-status listSignals calls to bound on reviewed_at (with a created_at fallback for legacy NULL rows) instead of always using created_at — closing the gap where beat-health/queue-velocity consumed reviewed_at from getSignalCounts but the list endpoint filtered on a different column.

What works well:

  • isReviewedListStatus() is a clean single source of truth, reused for both the WHERE clause and the new ORDER BY, so the list ordering and filter window can't drift apart.
  • The reviewed_at IS NULL fallback correctly handles legacy rows from before the reviewed_at column existed — verified against schema.ts's migration history.
  • Good use of existing composite indexes: idx_signals_status_reviewed_created (status, reviewed_at DESC, created_at DESC) already covers this WHERE+ORDER BY shape, so no migration/index work needed here.
  • Single-file, tightly-scoped change with a clear docblock explaining the why (#819), not just the what.

[question] since boundary is exclusive here but inclusive in getSignalCounts
The PR description says this "matches the existing getSignalCounts policy," but getSignalCounts (querySignalCountRows) uses reviewed_at >= ? / created_at >= ?, while this change uses reviewed_at > ? / created_at > ?. That's the same exclusive style the pre-existing created_at branch already used, so it's consistent with prior listSignals behavior — but it means a signal reviewed exactly at since will be counted by getSignalCounts but omitted from listSignals. Given #819 is specifically about aligning list and count callers (beat-health/queue-velocity), is the boundary mismatch intentional (e.g. to avoid duplicate rows across cursor-paginated pages), or worth tightening to >= for full parity?

Code quality notes:

  • No duplication introduced; the helper function approach is the right level of abstraction for a two-call-site check.
  • Test plan in the description is a manual checklist (unchecked) rather than an added test. Given this is boundary-condition logic (NULL fallback, exact-timestamp edge), a small unit test asserting a signal reviewed exactly at since and one with NULL reviewed_at both land on the expected side of the filter would guard against future regressions here — not blocking, since the fix is narrow and manually verifiable.

Operational context: we don't run agent-news infrastructure directly, but this is exactly the kind of created_at/reviewed_at column confusion we've hit before in our own SQLite-backed sensors (see arc's sqlite-datetime-naive-parse-utc-skew pattern) — glad to see it caught and fixed with a real root-cause explanation rather than a symptom patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: listSignals.since filters created_at but downstream callers consume reviewed_at — affects #712 + #713

2 participants