Documentation
¶
Index ¶
- Constants
- func DigestHTMLFilename(digest models.Digest) string
- func RenderDigestHTML(digest models.Digest, theme string) ([]byte, error)
- func RenderDigestIndex() ([]byte, error)
- func RenderSwipeHTML(digest models.Digest, digestFilename string) ([]byte, error)
- func SendDiscordMessage(webhookURL, content string) error
- func SwipeHTMLFilename(digest models.Digest) string
- type ArticleEntry
- type DiscordEmbed
- type DiscordEmbedField
- type DiscordEmbedFooter
- type DiscordEmbedImage
- type DiscordNotifier
- type DiscordWebhookPayload
- type GitHubPagesPublisher
- func (p *GitHubPagesPublisher) InitPages(reinit bool) error
- func (p *GitHubPagesPublisher) ManifestTitles() ([]string, error)
- func (p *GitHubPagesPublisher) RemoveDigest(title string) (string, error)
- func (p *GitHubPagesPublisher) RepublishAll(digests []models.Digest, theme string, dryRun bool) error
- func (p *GitHubPagesPublisher) RepublishIndex(dryRun bool) error
- func (p *GitHubPagesPublisher) SendDigest(digest models.Digest) error
- func (p *GitHubPagesPublisher) WaitForPagesBuild(commitSHA string) error
- type Manifest
- type ManifestEntry
- type Notifier
- type OverviewSection
- type RenderedAnalysis
- type RenderedReport
- type TOCEntry
- type TOCGroup
- type TOCRow
- type TagCount
Constants ¶
const ManifestFilename = "manifest.json"
ManifestFilename is the basename of the manifest checked into the Pages branch.
Variables ¶
This section is empty.
Functions ¶
func DigestHTMLFilename ¶
DigestHTMLFilename returns a filesystem-safe filename for the digest HTML file.
func RenderDigestHTML ¶
RenderDigestHTML generates a self-contained HTML file for the given digest. The digest must have Articles, DigestAnalyses (with Analysis preloaded), and ProviderResults populated. theme selects the visual style; an empty string or "dark" uses the default dark theme.
The provider/model switcher in the rendered page is populated client-side from manifest.json - the page itself only embeds the digest id and a hash of its article set used to filter siblings.
func RenderDigestIndex ¶
RenderDigestIndex generates the index HTML shell. The digest list is populated client-side by fetching manifest.json, so the rendered bytes are constant for a given template.
func RenderSwipeHTML ¶
RenderSwipeHTML generates the self-contained Tinder-style triage page for a digest. digestFilename is the filename of the companion list-view page (used for the back link).
func SendDiscordMessage ¶
SendDiscordMessage posts a plain-text message to a Discord webhook URL. Intended for lightweight one-line notifications (e.g. "new page published").
func SwipeHTMLFilename ¶
SwipeHTMLFilename returns the filename for the swipe triage view of a digest.
Types ¶
type ArticleEntry ¶
type ArticleEntry struct {
Id string
Title string
Source string
Link string
PublishedAt string
Category string // article category (one of the fixed set), empty if unset
Tags []string // entity tags (actors/tools/techniques/country/stakeholders), without '#'
ImportanceScore int
ReadTag string
DuplicateGroup string
IsMostComprehensive bool
HasAnalysis bool
AnalysisError string // non-empty when HasAnalysis is false and a classified error is available
Analysis *RenderedAnalysis
}
ArticleEntry holds enriched article data for template rendering
type DiscordEmbed ¶
type DiscordEmbed struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Color int `json:"color,omitempty"`
Fields []DiscordEmbedField `json:"fields,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
Image *DiscordEmbedImage `json:"image,omitempty"`
}
DiscordEmbed represents a Discord embed
type DiscordEmbedField ¶
type DiscordEmbedField struct {
Name string `json:"name"`
Value string `json:"value"`
Inline bool `json:"inline,omitempty"`
}
DiscordEmbedField represents a field in a Discord embed
type DiscordEmbedFooter ¶
type DiscordEmbedFooter struct {
}
DiscordEmbedFooter represents a footer in a Discord embed
type DiscordEmbedImage ¶
type DiscordEmbedImage struct {
URL string `json:"url"`
}
DiscordEmbedImage represents an image in a Discord embed
type DiscordNotifier ¶
type DiscordNotifier struct {
// contains filtered or unexported fields
}
DiscordNotifier implements the Notifier interface for Discord webhooks
func NewDiscordNotifier ¶
func NewDiscordNotifier(webhookURL string) *DiscordNotifier
NewDiscordNotifier creates a new Discord notifier
func (*DiscordNotifier) SendDigest ¶
func (d *DiscordNotifier) SendDigest(digest models.Digest) error
SendDigest sends a digest to Discord
func (*DiscordNotifier) SendHTMLFile ¶
func (d *DiscordNotifier) SendHTMLFile(filename string, data []byte) error
SendHTMLFile uploads a digest HTML file to the Discord webhook as an attachment.
type DiscordWebhookPayload ¶
type DiscordWebhookPayload struct {
Content string `json:"content,omitempty"`
Embeds []DiscordEmbed `json:"embeds,omitempty"`
}
DiscordWebhookPayload represents the Discord webhook message structure
type GitHubPagesPublisher ¶
type GitHubPagesPublisher struct {
// contains filtered or unexported fields
}
GitHubPagesPublisher publishes digest HTML files to a GitHub Pages repository.
Each publish writes the new digest HTML and updates a manifest.json that lists every published digest. Both the per-digest switcher and the index page are static shells that read manifest.json in the browser, so old HTML files are never rewritten on subsequent publishes.
func NewGitHubPagesPublisher ¶
func NewGitHubPagesPublisher(cfg models.GitHubPagesNotificationConfig) *GitHubPagesPublisher
NewGitHubPagesPublisher creates a new GitHubPagesPublisher.
func (*GitHubPagesPublisher) InitPages ¶
func (p *GitHubPagesPublisher) InitPages(reinit bool) error
InitPages sets up (or re-initialises) the GitHub Pages repository.
It creates the remote branch as a clean orphan if it is absent, optionally configures the GitHub Pages source via the API (when configure_pages is true), clones the branch locally, and seeds the initial static files (manifest.json and index pages). Files that already exist are not overwritten — the operation is idempotent.
When reinit is true the remote branch and the local clone directory are deleted before re-creating them from scratch.
func (*GitHubPagesPublisher) ManifestTitles ¶
func (p *GitHubPagesPublisher) ManifestTitles() ([]string, error)
ManifestTitles clones (or updates) the repo and returns the list of digest titles from the manifest, newest-first. Returns an empty slice when the manifest has no entries.
func (*GitHubPagesPublisher) RemoveDigest ¶
func (p *GitHubPagesPublisher) RemoveDigest(title string) (string, error)
RemoveDigest removes the digest identified by title from the archive. It resolves the title to a filename via the manifest, deletes both the digest and swipe HTML files, updates manifest.json, commits, and pushes. It returns the SHA of the pushed commit so callers can wait for the corresponding GitHub Pages build to deploy (see WaitForPagesBuild).
func (*GitHubPagesPublisher) RepublishAll ¶
func (p *GitHubPagesPublisher) RepublishAll(digests []models.Digest, theme string, dryRun bool) error
RepublishAll re-renders every digest with the current templates and pushes the result as a single commit. The manifest is rebuilt from scratch so stale entries are removed. Pass dryRun=true to render and stage locally without committing or pushing.
func (*GitHubPagesPublisher) RepublishIndex ¶
func (p *GitHubPagesPublisher) RepublishIndex(dryRun bool) error
RepublishIndex re-renders the archive index pages with the current templates and pushes the result as a single commit. The manifest and digest HTML files are not touched. Pass dryRun=true to write locally without committing.
func (*GitHubPagesPublisher) SendDigest ¶
func (p *GitHubPagesPublisher) SendDigest(digest models.Digest) error
SendDigest renders the digest HTML, updates manifest.json, and pushes the result to the GitHub Pages repo. Old digest pages are not touched.
func (*GitHubPagesPublisher) WaitForPagesBuild ¶
func (p *GitHubPagesPublisher) WaitForPagesBuild(commitSHA string) error
WaitForPagesBuild blocks until the GitHub Pages build for commitSHA has finished deploying. GitHub serialises Pages builds and cancels an in-flight build when a newer commit is pushed, so a flow that pushes twice in quick succession (republish: remove then re-add) would otherwise only ever deploy the second commit — the removal would never go live. Polling the builds API until the removal commit is "built" lets the caller sequence the two pushes.
Requires the token to have Pages read access. A timeout or an unavailable builds endpoint (404) is logged and returned as nil so the caller can still proceed rather than leave a digest removed-but-not-re-added.
type Manifest ¶
type Manifest struct {
GeneratedAt string `json:"generated_at"`
SourceRepo string `json:"source_repo"`
Digests []ManifestEntry `json:"digests"`
}
Manifest is the JSON document checked into the Pages branch listing every published digest. The digest index reads it directly in the browser.
func LoadManifest ¶
LoadManifest reads the manifest at path. When the file is missing, it returns an empty manifest in the current schema.
func (*Manifest) FindByTitle ¶
func (m *Manifest) FindByTitle(title string) (ManifestEntry, bool)
FindByTitle returns the first entry whose Title matches title (case-insensitive). The second return value is false when no match is found.
func (*Manifest) Remove ¶
Remove removes the entry with the given filename from the manifest. Returns true if an entry was found and removed.
func (*Manifest) Upsert ¶
func (m *Manifest) Upsert(entry ManifestEntry)
Upsert inserts entry or replaces an existing entry with the same filename, then re-sorts newest-first by filename timestamp.
type ManifestEntry ¶
type ManifestEntry struct {
Filename string `json:"filename"`
StartedAt string `json:"started_at"`
PeriodStart string `json:"period_start,omitempty"`
TimeWindow string `json:"time_window"`
ArticleCount int `json:"article_count"`
MustCount int `json:"must_count"`
ShouldCount int `json:"should_count"`
MayCount int `json:"may_count"`
OptCount int `json:"opt_count"`
Provider string `json:"provider"`
Model string `json:"model"`
Models []string `json:"models,omitempty"` // all unique model names across summary + article analysis
Title string `json:"title,omitempty"`
Headlines []string `json:"headlines"`
HeadlinePriorities []string `json:"headline_priorities,omitempty"`
Summary string `json:"summary"`
}
ManifestEntry describes a single published digest in the manifest.
func ManifestEntryFromDigest ¶
func ManifestEntryFromDigest(d models.Digest) ManifestEntry
ManifestEntryFromDigest builds a ManifestEntry for the given digest using the archive-index manifest schema.
type OverviewSection ¶
type OverviewSection struct {
Tag string // e.g. "EXEC", "01", "02"
Title string // section heading
Body template.HTML // rendered markdown body
}
OverviewSection is a single cell in the Intelligence Brief 2-column grid.
type RenderedAnalysis ¶
type RenderedAnalysis struct {
ProviderType string
ModelName string
Tldr template.HTML
Justification template.HTML
BriefOverview template.HTML
StandardSynthesis template.HTML
ComprehensiveSynthesis template.HTML
KeyPoints []template.HTML
Insights []template.HTML
ReferencedReports []RenderedReport
}
RenderedAnalysis holds markdown-converted HTML versions of analysis text fields. Text fields are template.HTML because matched entity tags are wrapped in <mark class="tag-hl"> at build time (see highlight* helpers).
type RenderedReport ¶
type RenderedReport struct {
Title string
URL string
Publisher string
Category string
Primary bool
Context template.HTML
}
RenderedReport is a referenced report prepared for the digest template, with its context prose tag-highlighted.
type TOCEntry ¶
type TOCEntry struct {
Id string
Title string
Category string // article category (one of the fixed set), empty if unset
ImportanceScore int
ScoreTip string // rubric dimension breakdown shown on hover, empty if no dimensions
ReadTag string
DuplicateGroup string
IsMostComprehensive bool
}
TOCEntry holds data for a single article row in the table of contents.
type TOCRow ¶
type TOCRow struct {
IsCluster bool
Entry TOCEntry // used when IsCluster == false
Canonical TOCEntry // used when IsCluster == true: the most-comprehensive article
Others []TOCEntry // used when IsCluster == true: remaining members
Group string // duplicate group key, used for colour
Detail *ArticleEntry // full detail for non-cluster row
CanonDetail *ArticleEntry // full detail for cluster canonical
OtherDetails []*ArticleEntry // full detail for each cluster member
}
TOCRow is a single rendered row in a TOC group: either a plain article entry or a duplicate cluster (one canonical article + its alternates in a <details> block).