@@ -20,10 +20,6 @@ public static string FormatReleasePost(string tagName, string releaseBody, strin
2020 {
2121 hook ??= Hooks [ Math . Abs ( tagName . GetHashCode ( StringComparison . Ordinal ) ) % Hooks . Length ] ;
2222 var baseUrl = repoUrl . TrimEnd ( '/' ) ;
23- var notesUrl = $ "{ baseUrl } /releases/tag/{ tagName } ";
24- var version = tagName . TrimStart ( 'v' , 'V' ) ;
25- var setupAsset = $ "CodeForge-Setup-{ version } -win32-x64.exe";
26- var downloadUrl = $ "{ baseUrl } /releases/download/{ tagName } /{ setupAsset } ";
2723 var improvements = SummarizeImprovements ( releaseBody ) ;
2824 var hashtags = "#AI #OpenSource #LocalLLM #CodingAgent #DeveloperTools #llama.cpp" ;
2925
@@ -44,17 +40,15 @@ public static string FormatReleasePost(string tagName, string releaseBody, strin
4440 }
4541
4642 sb . AppendLine ( ) ;
47- sb . AppendLine ( $ "Repo: { baseUrl } ") ;
48- sb . AppendLine ( $ "Download: { downloadUrl } ") ;
49- sb . AppendLine ( $ "Release notes: { notesUrl } ") ;
43+ sb . AppendLine ( baseUrl ) ;
5044 sb . AppendLine ( ) ;
5145 sb . Append ( hashtags ) ;
5246
5347 var text = sb . ToString ( ) ;
5448 if ( text . Length <= MaxLength )
5549 return text ;
5650
57- var footer = $ "\n \n Repo: { baseUrl } \n Download: { downloadUrl } \n Release notes: { notesUrl } \n \n { hashtags } ";
51+ var footer = $ "\n \n { baseUrl } \n \n { hashtags } ";
5852 var head = hook + $ "\n \n CodeForge { tagName } is out.\n \n What's new:\n ";
5953 var budget = MaxLength - head . Length - footer . Length - 1 ;
6054 var bullets = new StringBuilder ( ) ;
@@ -82,13 +76,23 @@ private static List<string> SummarizeImprovements(string releaseBody)
8276 if ( string . IsNullOrWhiteSpace ( releaseBody ) )
8377 return [ ] ;
8478
79+ // Prefer the "## What's new" section when present (skip AHA marketing prose).
80+ var body = releaseBody . Replace ( "\r \n " , "\n " ) ;
81+ var whatsNew = WhatsNewSectionRegex ( ) . Match ( body ) ;
82+ if ( whatsNew . Success )
83+ body = whatsNew . Groups [ 1 ] . Value ;
84+
8585 var items = new List < string > ( ) ;
86- foreach ( var raw in releaseBody . Replace ( " \r \n " , " \n " ) . Split ( '\n ' ) )
86+ foreach ( var raw in body . Split ( '\n ' ) )
8787 {
8888 var line = CleanMarkdownLine ( raw . TrimEnd ( ) ) ;
8989 if ( string . IsNullOrWhiteSpace ( line ) || IsNoiseLine ( line ) )
9090 continue ;
9191
92+ // Prefer real bullets over narrative paragraphs for LinkedIn.
93+ if ( ! ( line . StartsWith ( '•' ) || raw . TrimStart ( ) . StartsWith ( '-' ) || raw . TrimStart ( ) . StartsWith ( '*' ) ) )
94+ continue ;
95+
9296 var text = line . TrimStart ( '•' , '-' , '*' , ' ' ) . Trim ( ) ;
9397 if ( string . IsNullOrWhiteSpace ( text ) || IsNoiseLine ( text ) )
9498 continue ;
@@ -97,7 +101,7 @@ private static List<string> SummarizeImprovements(string releaseBody)
97101 text = text [ ..177 ] . TrimEnd ( ) + "…" ;
98102
99103 items . Add ( text ) ;
100- if ( items . Count >= 6 )
104+ if ( items . Count >= 5 )
101105 break ;
102106 }
103107
@@ -110,7 +114,8 @@ private static bool IsNoiseLine(string line)
110114 if ( lower . Length == 0 )
111115 return true ;
112116 if ( lower is "summary" or "what's new" or "whats new" or "what shipped" or "notes"
113- or "release notes" or "install" or "fixes" or "changes" )
117+ or "release notes" or "install" or "fixes" or "changes"
118+ or "the aha moment" or "measured on our local stack" or "not in this release" )
114119 return true ;
115120 if ( lower . StartsWith ( "try it" , StringComparison . Ordinal ) )
116121 return true ;
@@ -120,6 +125,10 @@ private static bool IsNoiseLine(string line)
120125 return true ;
121126 if ( lower . StartsWith ( "full notes" , StringComparison . Ordinal ) )
122127 return true ;
128+ if ( lower . StartsWith ( "release date" , StringComparison . Ordinal ) )
129+ return true ;
130+ if ( lower . StartsWith ( "linkedin draft" , StringComparison . Ordinal ) )
131+ return true ;
123132 if ( lower . StartsWith ( "download **" , StringComparison . Ordinal ) || lower . StartsWith ( "download " , StringComparison . Ordinal ) )
124133 return true ;
125134 if ( lower . StartsWith ( "codeforge" , StringComparison . Ordinal ) && lower . Contains ( "is out" , StringComparison . Ordinal ) )
@@ -151,4 +160,7 @@ private static string CleanMarkdownLine(string line)
151160
152161 [ GeneratedRegex ( @"`([^`]+)`" ) ]
153162 private static partial Regex InlineCodeRegex ( ) ;
163+
164+ [ GeneratedRegex ( @"##\s*What's new\s*\n([\s\S]*?)(?=\n##\s|\z)" , RegexOptions . IgnoreCase ) ]
165+ private static partial Regex WhatsNewSectionRegex ( ) ;
154166}
0 commit comments