Skip to content

feat(home-feed): action append semantics + per-source cap [JARVIS-512]#25584

Merged
alex-nork merged 1 commit into
mainfrom
alex-nork/jarvis-512-feed-writer-changes
Apr 14, 2026
Merged

feat(home-feed): action append semantics + per-source cap [JARVIS-512]#25584
alex-nork merged 1 commit into
mainfrom
alex-nork/jarvis-512-feed-writer-changes

Conversation

@alex-nork
Copy link
Copy Markdown
Contributor

@alex-nork alex-nork commented Apr 14, 2026

Summary

First step of JARVIS-512 (follow-up to JARVIS-511). Reshapes the home-feed writer so action items behave like an activity log instead of a one-slot-per-source overwrite:

  • Drop 24h auto-fade on action items. They're the activity log — they must persist until the user dismisses them (.actedOn path already wired end-to-end). Callers that want expiry set expiresAt explicitly.
  • Append-without-replace for actions. mergeIncoming short-circuits before the (type, source) collapse so multiple background-job events for the same source don't overwrite each other. Digest/thread/nudge merge semantics are untouched.
  • Per-source volume cap via new MAX_ACTIONS_PER_SOURCE = 20 + pruneActionsPerSource pass. Keeps the log file from ballooning once producers get instrumented. Sourceless actions are unbounded.

The wrapper helper (emit-feed-event.ts) and the background-job instrumentation that depends on these semantics ship in follow-up PRs.

Test plan

  • bun test src/home/ — 137/137 pass
  • bun run typecheck — clean
  • bun run lint — clean
  • New tests: no-auto-fade, multi-action append, per-source cap (with unrelated sources / types untouched), sourceless actions unbounded
  • Manual smoke after emit-feed-event PR lands

🤖 Generated with Claude Code


Open with Devin

Drop the 24h auto-fade default on action items — they're the feed's
activity log and must persist until the user dismisses them. Callers
that want expiry now set expiresAt explicitly.

Exempt action items from (type, source) collapse in mergeIncoming so
multiple background-job events for the same source don't overwrite
each other. Bound per-source action volume via MAX_ACTIONS_PER_SOURCE
(20) in a new pruneActionsPerSource pass — keeps the log file from
ballooning as producers get instrumented.

Digest/thread/nudge merge semantics are untouched.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 4 additional findings in Devin Review.

Open in Devin Review

Comment on lines +279 to +280
// until the user dismisses them. The writer used to fill in a
// 24h default expiresAt; that behavior is intentionally gone.
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.

🔴 Test comment narrates removed code history, violating AGENTS.md comment rule

The comment at lines 279-280 says "The writer used to fill in a 24h default expiresAt; that behavior is intentionally gone." This violates the mandatory rule in assistant/AGENTS.md:21: "do not reference code that has been removed. Comments should describe the current state of the codebase, not narrate its history. Avoid phrases like 'no longer does X', 'previously used Y', or 'was removed in PR Z'." The phrases "used to fill in" and "intentionally gone" directly narrate the codebase's history rather than describing its current state.

Suggested change
// until the user dismisses them. The writer used to fill in a
// 24h default expiresAt; that behavior is intentionally gone.
// Action items are the feed's activity log — they persist
// until the user dismisses them or the per-source cap prunes them.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d44177a0d5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if (item.type !== "action") return true;
if (!item.source) return true;
if (!overflowing.includes(item.source)) return true;
return keepIds.has(item.id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Retain capped actions by unique entry, not shared id

The cap logic keeps overflowed actions via keepIds and later checks keepIds.has(item.id), which means retention is keyed only by id. If a source emits duplicate action IDs (or two overflowing sources reuse the same ID), an older action can be incorrectly preserved because a newer action with the same ID marked it as kept, so that source can stay above MAX_ACTIONS_PER_SOURCE and stale rows remain visible. Track retained rows by a per-entry key (e.g., source + createdAt + id, or item identity/index) instead of id alone.

Useful? React with 👍 / 👎.

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.

1 participant