feat: add grouped publisher following activity - #2958
Conversation
|
@giodl73-repo is attempting to deploy a commit to the OpenClaw Foundation Team on Vercel. A member of the Team first needs to authorize it. |
|
Codex review: needs real behavior proof before merge. Reviewed July 22, 2026, 1:32 AM ET / 05:32 UTC. Summary Reproducibility: not applicable. This PR proposes a new product capability rather than reporting broken established behavior. The missing evidence is after-fix real behavior proof, not a bug reproduction. Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Make a maintainer-approved, pull-only publisher discovery feature land in a refreshed dependency order, with durable privacy invariants and redacted live proof covering the public API and signed-in UI flows. Do we have a high-confidence way to reproduce the issue? Not applicable: this PR proposes a new product capability rather than reporting broken established behavior. The missing evidence is after-fix real behavior proof, not a bug reproduction. Is this the best way to solve the issue? Unclear: the implementation is a coherent pull-based alternative to notification fanout, but whether ClawHub should own this durable public social surface requires explicit maintainer direction before it can be considered the best solution. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a9775fc39b10. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (5 earlier review cycles)
|
404620e to
1a780b6
Compare
Patrick-Erichsen
left a comment
There was a problem hiding this comment.
Reviewed exact head 1a780b6929e9bc16c5b6f113df192befcc5f6192. LOC: +2039/-1 (19 files). This adds durable private publisher-follow notifications and bounded continuation fanout. I found three actionable blockers; no approval submitted.
Best-fix verdict: too narrow / not merge-ready. Keep notifications discovery-only, but derive package eligibility from the inserted release, carry immutable publication time/audience eligibility through fanout, and repair the exact-head test regression. A synchronous unbounded fanout was considered and rejected because it would violate Convex transaction bounds; a durable event row or immutable eventAt passed through the existing cursor jobs is the appropriate layer.
Code read: publish callers in convex/skills.ts and convex/packages.ts; fanout/list/read paths in convex/publisherNotifications.ts; follow mutations/indexes in convex/publisherFollows.ts and convex/schema.ts; retention, HTTP/auth boundaries, tests, current origin/main, the local follow spec, and RFC 0009.
Remaining uncertainty: the PR provides no real Convex/API/browser proof, and no frontend currently consumes publisherNotifications.listMine.
| const notificationPublisher = notificationPublisherId | ||
| ? (ownerPublisher ?? (await ctx.db.get(notificationPublisherId))) | ||
| : null; | ||
| const notificationScanStatus = shouldPromoteLatest |
There was a problem hiding this comment.
[P1] Gate backport notifications on the inserted release
For a non-latest release, this falls back to pkg.scanStatus, which describes the existing latest package rather than releaseId. A clean latest plus a newly blocked backport therefore satisfies shouldNotifyPackageFollowers and advertises content that release visibility/download paths should reject. Derive notification eligibility from the inserted release resolved scan verdict using the same source/helper as public release visibility, and add a blocked non-latest regression test.
| resourceTitle: args.resourceTitle, | ||
| version: args.version, | ||
| }); | ||
| const now = Date.now(); |
There was a problem hiding this comment.
[P1] Snapshot publication time and audience eligibility
now is fanout-job time, while every page queries the current follow graph. A user who follows or unmutes after publication but before a delayed job runs receives the older event, and continuation pages can get different timestamps, so delayed/interleaved publications sort by worker timing rather than publication order. Pass an immutable eventAt from the publish mutation through every continuation, constrain eligible follows to the state that existed at that event (or persist an event/audience snapshot), and store that event time for ordering. Add follow/unmute-after-publish and interleaved-page tests.
| @@ -12654,6 +12654,33 @@ export const insertVersion = internalMutation({ | |||
| createdAt: now, | |||
| }); | |||
|
|
|||
| if (isPublicSkillDoc(nextSkill)) { | |||
| try { | |||
| await ctx.scheduler.runAfter( | |||
There was a problem hiding this comment.
[P1] Repair the exact-head scheduler regression
This added runAfter call makes convex/skills.rateLimit.test.ts fail at the existing expect(runAfter).not.toHaveBeenCalled() assertion for static-malicious publishes. Exact-head CI run 29430178303 and a local rerun both reproduce the failure. Update that test to identify scheduled functions with getFunctionName, assert that users:autobanMalwareAuthorInternal is absent, and separately assert the expected notification schedule so the safety invariant remains covered without rejecting all scheduling.
1a780b6 to
ba54abc
Compare
dd0a9c4 to
6681928
Compare
6681928 to
0c7c669
Compare
09d200a to
5705ced
Compare
5705ced to
0ad61f1
Compare
0ad61f1 to
03b7ba4
Compare
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing due to inactivity. |
Summary
followingandinboxprojections over the same grouped substrateProduct shape
This PR is backend-only.
followingincludes every followed publisher;inboxexcludes publishers whose delivery preference is muted. The next PR adds private Inbox read state and UI. A future Facebook/X-style Following page can render the same groups chronologically without a second event store or migration.This lane is independent of signed publisher-feed consumption in OpenClaw and has no trust, install, approval, email, or webhook implication.
Stack
Depends on #2950 (and transitively #2948). The branch is commit-stacked because cross-fork PRs cannot select another fork branch as their base.
Scale proof
Validation
git diff --check