@@ -21,6 +21,11 @@ const (
2121 EndMarker = "<!-- discrawl-report:end -->"
2222)
2323
24+ const (
25+ aiFieldNotesHeading = "### AI Field Notes"
26+ aiDigestPlaceholder = "_AI digest not generated in this run. The daily report job fills this in when `OPENAI_API_KEY` is configured._"
27+ )
28+
2429type Options struct {
2530 Now time.Time
2631 AI AIOptions
@@ -272,21 +277,62 @@ func RenderMarkdown(report ActivityReport) (string, error) {
272277}
273278
274279func UpdateReadme (readme []byte , section string ) []byte {
275- replacement := StartMarker + " \n " + strings .TrimSpace (section ) + " \n " + EndMarker
280+ section = strings .TrimSpace (section )
276281 text := string (readme )
277282 start := strings .Index (text , StartMarker )
278283 end := strings .Index (text , EndMarker )
279284 if start >= 0 && end >= start {
285+ existingSection := text [start + len (StartMarker ) : end ]
286+ section = preserveAIFieldNotes (existingSection , section )
280287 end += len (EndMarker )
288+ replacement := StartMarker + "\n " + section + "\n " + EndMarker
281289 return []byte (text [:start ] + replacement + text [end :])
282290 }
291+ replacement := StartMarker + "\n " + section + "\n " + EndMarker
283292 text = strings .TrimRight (text , "\n " )
284293 if text == "" {
285294 return []byte (replacement + "\n " )
286295 }
287296 return []byte (text + "\n \n " + replacement + "\n " )
288297}
289298
299+ func preserveAIFieldNotes (existingSection string , nextSection string ) string {
300+ if ! strings .Contains (nextSection , aiDigestPlaceholder ) {
301+ return nextSection
302+ }
303+ existingNotes := extractAIFieldNotes (existingSection )
304+ if existingNotes == "" || strings .Contains (existingNotes , aiDigestPlaceholder ) {
305+ return nextSection
306+ }
307+ return replaceAIFieldNotes (nextSection , existingNotes )
308+ }
309+
310+ func extractAIFieldNotes (section string ) string {
311+ idx := strings .Index (section , aiFieldNotesHeading )
312+ if idx < 0 {
313+ return ""
314+ }
315+ notes := section [idx + len (aiFieldNotesHeading ):]
316+ if next := strings .Index (notes , "\n ### " ); next >= 0 {
317+ notes = notes [:next ]
318+ }
319+ return strings .TrimSpace (notes )
320+ }
321+
322+ func replaceAIFieldNotes (section string , notes string ) string {
323+ idx := strings .Index (section , aiFieldNotesHeading )
324+ if idx < 0 {
325+ return section
326+ }
327+ start := idx + len (aiFieldNotesHeading )
328+ tail := section [start :]
329+ end := len (tail )
330+ if next := strings .Index (tail , "\n ### " ); next >= 0 {
331+ end = next
332+ }
333+ return section [:start ] + "\n \n " + strings .TrimSpace (notes ) + strings .TrimRight (tail [end :], "\n " )
334+ }
335+
290336func WriteReadme (path string , section string ) error {
291337 current , err := os .ReadFile (path )
292338 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
@@ -388,6 +434,6 @@ Archive size: {{ formatInt .TotalMessages }} messages, {{ formatInt .TotalChanne
388434{{- if .AISummary }}
389435{{ .AISummary }}
390436{{- else }}
391- _AI digest not generated in this run. The daily report job fills this in when ` + "`OPENAI_API_KEY`" + ` is configured._
437+ ` + aiDigestPlaceholder + `
392438{{- end }}
393439` ))
0 commit comments