Skip to content

Commit fdac1b7

Browse files
committed
fix: preserve discord report field notes
1 parent e1dcd1e commit fdac1b7

2 files changed

Lines changed: 98 additions & 2 deletions

File tree

internal/report/report.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
2429
type Options struct {
2530
Now time.Time
2631
AI AIOptions
@@ -272,21 +277,62 @@ func RenderMarkdown(report ActivityReport) (string, error) {
272277
}
273278

274279
func 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+
290336
func 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
`))

internal/report/report_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,56 @@ func TestBuildRenderAndUpdateReadme(t *testing.T) {
6161
require.NotContains(t, string(updated), "Latest archived message")
6262
}
6363

64+
func TestUpdateReadmePreservesAIFieldNotes(t *testing.T) {
65+
existing := []byte(`# Backup
66+
67+
<!-- discrawl-report:start -->
68+
## Discord Activity Report
69+
70+
Last updated: 2026-04-21 05:00 UTC
71+
72+
### AI Field Notes
73+
74+
- Funny: Build logs learned patience.
75+
- Trend: Activity clustered around launch prep.
76+
<!-- discrawl-report:end -->
77+
`)
78+
next := `## Discord Activity Report
79+
80+
Last updated: 2026-04-21 06:00 UTC
81+
82+
### AI Field Notes
83+
84+
` + aiDigestPlaceholder + `
85+
`
86+
updated := string(UpdateReadme(existing, next))
87+
require.Contains(t, updated, "Last updated: 2026-04-21 06:00 UTC")
88+
require.Contains(t, updated, "- Funny: Build logs learned patience.")
89+
require.NotContains(t, updated, aiDigestPlaceholder)
90+
}
91+
92+
func TestUpdateReadmeLetsAIReportReplaceFieldNotes(t *testing.T) {
93+
existing := []byte(`# Backup
94+
95+
<!-- discrawl-report:start -->
96+
## Discord Activity Report
97+
98+
### AI Field Notes
99+
100+
- Old: keep only until a new AI report lands.
101+
<!-- discrawl-report:end -->
102+
`)
103+
next := `## Discord Activity Report
104+
105+
### AI Field Notes
106+
107+
- New: fresh report.
108+
`
109+
updated := string(UpdateReadme(existing, next))
110+
require.Contains(t, updated, "- New: fresh report.")
111+
require.NotContains(t, updated, "- Old: keep only until")
112+
}
113+
64114
func TestWriteReadmeCreatesFile(t *testing.T) {
65115
path := filepath.Join(t.TempDir(), "README.md")
66116
require.NoError(t, WriteReadme(path, "## Report\n"))

0 commit comments

Comments
 (0)