@@ -3,12 +3,17 @@ import createOrGetConnection from '../../src/db';
33import { ChannelDigest } from '../../src/entity/ChannelDigest' ;
44import { ChannelHighlightDefinition } from '../../src/entity/ChannelHighlightDefinition' ;
55import { ChannelHighlightRun } from '../../src/entity/ChannelHighlightRun' ;
6- import { AGENTS_DIGEST_SOURCE } from '../../src/entity/Source' ;
6+ import { AGENTS_DIGEST_SOURCE , UNKNOWN_SOURCE } from '../../src/entity/Source' ;
77import {
88 PostHighlight ,
99 PostHighlightSignificance ,
1010} from '../../src/entity/PostHighlight' ;
11- import { ArticlePost , CollectionPost , Source } from '../../src/entity' ;
11+ import {
12+ ArticlePost ,
13+ CollectionPost ,
14+ SharePost ,
15+ Source ,
16+ } from '../../src/entity' ;
1217import {
1318 PostRelation ,
1419 PostRelationType ,
@@ -102,6 +107,41 @@ const saveCollection = async ({
102107 } ,
103108 } ) ;
104109
110+ const saveShare = async ( {
111+ id,
112+ sharedPostId,
113+ createdAt,
114+ sourceId = 'content-source' ,
115+ title = 'Shared story' ,
116+ upvotes = 0 ,
117+ private : isPrivate = false ,
118+ } : {
119+ id : string ;
120+ sharedPostId : string ;
121+ createdAt : Date ;
122+ sourceId ?: string ;
123+ title ?: string ;
124+ upvotes ?: number ;
125+ private ?: boolean ;
126+ } ) =>
127+ con . getRepository ( SharePost ) . save ( {
128+ id,
129+ shortId : id ,
130+ title,
131+ sourceId,
132+ sharedPostId,
133+ createdAt,
134+ metadataChangedAt : createdAt ,
135+ statsUpdatedAt : createdAt ,
136+ visible : true ,
137+ deleted : false ,
138+ banned : false ,
139+ private : isPrivate ,
140+ showOnFeed : true ,
141+ upvotes,
142+ type : PostType . Share ,
143+ } ) ;
144+
105145describe ( 'generateChannelHighlight worker' , ( ) => {
106146 beforeEach ( async ( ) => {
107147 await con
@@ -721,6 +761,144 @@ describe('generateChannelHighlight worker', () => {
721761 ] ) ;
722762 } ) ;
723763
764+ it ( 'should replace unknown-source candidates with the most upvoted public share before evaluation' , async ( ) => {
765+ const now = new Date ( '2026-03-03T12:40:00.000Z' ) ;
766+ await con . getRepository ( ChannelHighlightDefinition ) . save ( {
767+ channel : 'vibes' ,
768+ mode : 'publish' ,
769+ candidateHorizonHours : 72 ,
770+ maxItems : 3 ,
771+ } ) ;
772+ await con
773+ . getRepository ( Source )
774+ . save (
775+ createSource (
776+ UNKNOWN_SOURCE ,
777+ 'Unknown' ,
778+ 'https://daily.dev/unknown.png' ,
779+ undefined ,
780+ true ,
781+ ) ,
782+ ) ;
783+ await saveArticle ( {
784+ id : 'unk-orig-1' ,
785+ sourceId : UNKNOWN_SOURCE ,
786+ title : 'Unknown source story' ,
787+ createdAt : new Date ( '2026-03-03T12:20:00.000Z' ) ,
788+ } ) ;
789+ await saveShare ( {
790+ id : 'pub-share-1' ,
791+ sharedPostId : 'unk-orig-1' ,
792+ createdAt : new Date ( '2026-03-03T12:26:00.000Z' ) ,
793+ upvotes : 25 ,
794+ } ) ;
795+ await saveShare ( {
796+ id : 'pub-share-2' ,
797+ sharedPostId : 'unk-orig-1' ,
798+ createdAt : new Date ( '2026-03-03T12:25:00.000Z' ) ,
799+ upvotes : 50 ,
800+ } ) ;
801+ await saveShare ( {
802+ id : 'priv-share1' ,
803+ sharedPostId : 'unk-orig-1' ,
804+ createdAt : new Date ( '2026-03-03T12:27:00.000Z' ) ,
805+ upvotes : 100 ,
806+ private : true ,
807+ } ) ;
808+
809+ const evaluatorSpy = jest
810+ . spyOn ( evaluator , 'evaluateChannelHighlights' )
811+ . mockImplementation ( async ( { newCandidates } ) => ( {
812+ items : [
813+ {
814+ postId : newCandidates [ 0 ] . postId ,
815+ headline : 'Shared headline' ,
816+ significanceLabel : 'breaking' ,
817+ reason : 'test' ,
818+ } ,
819+ ] ,
820+ } ) ) ;
821+
822+ await expectSuccessfulTypedBackground < 'api.v1.generate-channel-highlight' > (
823+ worker ,
824+ {
825+ channel : 'vibes' ,
826+ scheduledAt : now . toISOString ( ) ,
827+ } ,
828+ ) ;
829+
830+ expect ( evaluatorSpy ) . toHaveBeenCalledTimes ( 1 ) ;
831+ expect ( evaluatorSpy . mock . calls [ 0 ] [ 0 ] . newCandidates ) . toEqual ( [
832+ expect . objectContaining ( {
833+ postId : 'pub-share-2' ,
834+ title : 'Unknown source story' ,
835+ } ) ,
836+ ] ) ;
837+
838+ const liveHighlights = await con . getRepository ( PostHighlight ) . find ( {
839+ where : { channel : 'vibes' , retiredAt : IsNull ( ) } ,
840+ } ) ;
841+ expect ( liveHighlights ) . toEqual ( [
842+ expect . objectContaining ( {
843+ postId : 'pub-share-2' ,
844+ headline : 'Shared headline' ,
845+ significance : PostHighlightSignificance . Breaking ,
846+ reason : 'test' ,
847+ } ) ,
848+ ] ) ;
849+ } ) ;
850+
851+ it ( 'should skip unknown-source candidates when no public share exists' , async ( ) => {
852+ const now = new Date ( '2026-03-03T12:41:00.000Z' ) ;
853+ await con . getRepository ( ChannelHighlightDefinition ) . save ( {
854+ channel : 'vibes' ,
855+ mode : 'publish' ,
856+ candidateHorizonHours : 72 ,
857+ maxItems : 3 ,
858+ } ) ;
859+ await con
860+ . getRepository ( Source )
861+ . save (
862+ createSource (
863+ UNKNOWN_SOURCE ,
864+ 'Unknown' ,
865+ 'https://daily.dev/unknown.png' ,
866+ undefined ,
867+ true ,
868+ ) ,
869+ ) ;
870+ await saveArticle ( {
871+ id : 'unk-orig-2' ,
872+ sourceId : UNKNOWN_SOURCE ,
873+ title : 'Unknown source story 2' ,
874+ createdAt : new Date ( '2026-03-03T12:21:00.000Z' ) ,
875+ } ) ;
876+ await saveShare ( {
877+ id : 'priv-share2' ,
878+ sharedPostId : 'unk-orig-2' ,
879+ createdAt : new Date ( '2026-03-03T12:28:00.000Z' ) ,
880+ upvotes : 100 ,
881+ private : true ,
882+ } ) ;
883+
884+ const evaluatorSpy = jest . spyOn ( evaluator , 'evaluateChannelHighlights' ) ;
885+
886+ await expectSuccessfulTypedBackground < 'api.v1.generate-channel-highlight' > (
887+ worker ,
888+ {
889+ channel : 'vibes' ,
890+ scheduledAt : now . toISOString ( ) ,
891+ } ,
892+ ) ;
893+
894+ expect ( evaluatorSpy ) . not . toHaveBeenCalled ( ) ;
895+
896+ const liveHighlights = await con . getRepository ( PostHighlight ) . find ( {
897+ where : { channel : 'vibes' , retiredAt : IsNull ( ) } ,
898+ } ) ;
899+ expect ( liveHighlights ) . toEqual ( [ ] ) ;
900+ } ) ;
901+
724902 it ( 'should exclude posts refreshed only by stats updates from incremental candidates' , async ( ) => {
725903 const now = new Date ( '2026-03-03T12:45:00.000Z' ) ;
726904 await con . getRepository ( ChannelHighlightDefinition ) . save ( {
0 commit comments