Documentation
¶
Index ¶
- Constants
- func BuildDigestFeeds(digests []models.Digest, outputDir, baseURL string) (rss []byte, err error)
- func DigestHTMLFilename(digest models.Digest) string
- func OnDiskLayoutExists(layout string) bool
- func ProfilesJSON(profiles []LandingProfile) ([]byte, error)
- func RenderDigestHTML(digest models.Digest, layout, theme string, opts ...RenderOption) ([]byte, error)
- func RenderDigestIndex(layout, theme string, opts ...RenderOption) ([]byte, error)
- func RenderReportsPage(reports []aggregatedReport, layout, theme string, opts ...RenderOption) ([]byte, error)
- func RenderReportsPageForDigests(digests []models.Digest, layout, theme string, opts ...RenderOption) ([]byte, error)
- func RenderSourcesPage(feeds []models.Feed, layout, theme string, opts ...RenderOption) ([]byte, error)
- func RenderSwipeHTML(digest models.Digest, digestFilename string, layout, theme string, ...) ([]byte, error)
- func SampleDigest(id string, createdAt time.Time) models.Digest
- func SendDiscordMessage(webhookURL, content string) error
- func SetAssetDir(dir string)
- func SetLayoutsDir(dir string)
- func SetTemplateDir(dir string)
- func SwipeHTMLFilename(digest models.Digest) string
- type ArticleEntry
- type DigestLister
- 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) PublishAndWait(digest models.Digest) error
- func (p *GitHubPagesPublisher) RemoveDigest(title string) (string, error)
- func (p *GitHubPagesPublisher) Republish(digest models.Digest, wait bool) error
- func (p *GitHubPagesPublisher) RepublishAll(digests []models.Digest, layout string, dryRun, wait, rebase bool) error
- func (p *GitHubPagesPublisher) RepublishIndex(dryRun, wait bool) error
- func (p *GitHubPagesPublisher) SendDigest(digest models.Digest) error
- func (p *GitHubPagesPublisher) SetDigestLister(fn DigestLister)
- func (p *GitHubPagesPublisher) SetLanding(profiles []LandingProfile)
- func (p *GitHubPagesPublisher) SetProfileContext(slug, theme string)
- func (p *GitHubPagesPublisher) SetProgress(pr PublishProgress)
- func (p *GitHubPagesPublisher) SetReportLister(fn ReportLister)
- func (p *GitHubPagesPublisher) SetSourceLister(fn SourceLister)
- func (p *GitHubPagesPublisher) WaitForPagesBuild(commitSHA string) error
- type GlossaryPanelEntry
- type Headline
- type LandingProfile
- type Manifest
- type ManifestEntry
- type Notifier
- type OverviewSection
- type PublishProgress
- type RenderOption
- type RenderedAnalysis
- type RenderedReport
- type ReportLister
- type SourceLister
- type TOCEntry
- type TOCGroup
- type TOCRow
- type TagCount
Constants ¶
const FeedDigestLimit = 7
FeedDigestLimit caps how many recent digests appear in the RSS feed.
const ManifestFilename = "manifest.json"
ManifestFilename is the basename of the manifest checked into the Pages branch.
const RSSFilename = "rss.xml"
RSSFilename is the basename of the subscription feed written at the root of the Pages branch on every push.
Variables ¶
This section is empty.
Functions ¶
func BuildDigestFeeds ¶ added in v0.2.0
BuildDigestFeeds renders an RSS feed for the given digests (expected newest-first). Each digest becomes one feed entry whose HTML body lists, for every article in the digest, its TLDR and key points. Links point at the published digest HTML page under baseURL/outputDir; when baseURL is empty the links are relative to the site root.
func DigestHTMLFilename ¶
DigestHTMLFilename returns a filesystem-safe filename for the digest HTML file.
func OnDiskLayoutExists ¶ added in v0.4.0
OnDiskLayoutExists reports whether dir/<layout> exists under the configured layouts directory. Used to validate profile-selected layouts that are not compiled into the binary.
func ProfilesJSON ¶ added in v0.4.0
func ProfilesJSON(profiles []LandingProfile) ([]byte, error)
ProfilesJSON serializes the landing profiles for profiles.json (consumed by the in-page profile switcher and any external tooling).
func RenderDigestHTML ¶
func RenderDigestHTML(digest models.Digest, layout, theme string, opts ...RenderOption) ([]byte, error)
RenderDigestHTML generates a self-contained HTML file for the given digest. The digest must have Articles, DigestAnalyses (with Analysis preloaded), and ProviderResults populated. layout selects the template set (a templates/<layout>/ directory); an empty string uses the default.
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 ¶
func RenderDigestIndex(layout, theme string, opts ...RenderOption) ([]byte, error)
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 RenderReportsPage ¶ added in v0.4.0
func RenderReportsPage(reports []aggregatedReport, layout, theme string, opts ...RenderOption) ([]byte, error)
RenderReportsPage generates the standalone "reports" page. Every referenced report is embedded as JSON so search, tag/category filtering, and sorting all run client-side with no fetch.
func RenderReportsPageForDigests ¶ added in v0.4.0
func RenderReportsPageForDigests(digests []models.Digest, layout, theme string, opts ...RenderOption) ([]byte, error)
RenderReportsPageForDigests aggregates the referenced reports across the given digests and renders the standalone reports page. It is the exported entry point for callers outside this package (the publisher and the dev preview server), since the aggregated report type is internal.
func RenderSourcesPage ¶ added in v0.4.0
func RenderSourcesPage(feeds []models.Feed, layout, theme string, opts ...RenderOption) ([]byte, error)
RenderSourcesPage generates the standalone "sources" page listing every enabled feed. The feeds are embedded server-side, so the rendered bytes are self-contained and need no client-side fetch. Disabled feeds are omitted.
func RenderSwipeHTML ¶
func RenderSwipeHTML(digest models.Digest, digestFilename string, layout, theme string, opts ...RenderOption) ([]byte, error)
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 SampleDigest ¶ added in v0.2.0
SampleDigest builds a small, fully-populated digest fixture for rendering without a database. It backs both the test suite and the digest dev server.
article-b scores 95 (Must Read) with full analysis and a referenced report; article-a scores 80 (Should Read) with minimal analysis.
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 SetAssetDir ¶ added in v0.4.0
func SetAssetDir(dir string)
SetAssetDir switches built-asset loading to read from dir on disk. Pass an empty string to fall back to the embedded assets. Intended for the dev preview server.
func SetLayoutsDir ¶ added in v0.4.0
func SetLayoutsDir(dir string)
SetLayoutsDir registers an on-disk directory holding custom layouts. Pass an empty string to use only the embedded layouts.
func SetTemplateDir ¶ added in v0.2.0
func SetTemplateDir(dir string)
SetTemplateDir switches template loading to read from dir on disk. Pass an empty string to fall back to the embedded templates. Intended for the dev preview server.
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 DigestLister ¶ added in v0.2.0
DigestLister returns up to limit newest digests with full payload (provider results + analyses). It lets the publisher build the RSS feed without depending on the store: callers that have DB or client access supply it via SetDigestLister. A nil lister disables feed generation.
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) PublishAndWait ¶ added in v0.4.0
func (p *GitHubPagesPublisher) PublishAndWait(digest models.Digest) error
PublishAndWait publishes the digest and blocks until the pushed commit's GitHub Pages build deploys. It is the deploy-aware counterpart to SendDigest.
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) Republish ¶ added in v0.2.0
func (p *GitHubPagesPublisher) Republish(digest models.Digest, wait bool) error
Republish removes a single digest from the archive and re-publishes it with the current templates (equivalent to remove followed by add). The removal is always awaited before the re-add is pushed: GitHub cancels an in-flight Pages build when a newer commit lands, so pushing the re-add immediately would skip deploying the removal. The final deploy is only awaited when wait is true.
func (*GitHubPagesPublisher) RepublishAll ¶
func (p *GitHubPagesPublisher) RepublishAll(digests []models.Digest, layout string, dryRun, wait, rebase 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. When wait is true (and not a dry run) it blocks until the resulting GitHub Pages build deploys.
When rebase is true (and not a dry run) the branch is rebuilt as a single orphan commit and force-pushed, discarding all prior history. The rendered tree is complete on its own, so this keeps the Pages branch from accumulating a commit per publish — at the cost of an unrecoverable history rewrite.
func (*GitHubPagesPublisher) RepublishIndex ¶
func (p *GitHubPagesPublisher) RepublishIndex(dryRun, wait 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. When wait is true (and not a dry run) it blocks until the resulting GitHub Pages build deploys.
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) SetDigestLister ¶ added in v0.2.0
func (p *GitHubPagesPublisher) SetDigestLister(fn DigestLister)
SetDigestLister attaches the lister used to fetch recent digests when building the RSS feed on each push. Passing nil disables feed generation.
func (*GitHubPagesPublisher) SetLanding ¶ added in v0.4.0
func (p *GitHubPagesPublisher) SetLanding(profiles []LandingProfile)
SetLanding supplies the public profile list. When more than one profile is given, the repo-root index.html becomes a landing page that links into each profile's section (plus a profiles.json), instead of mirroring a single profile's archive. With zero or one profile the historical single-site root index is kept.
func (*GitHubPagesPublisher) SetProfileContext ¶ added in v0.4.0
func (p *GitHubPagesPublisher) SetProfileContext(slug, theme string)
SetProfileContext records which profile is being published: its slug (for the switcher's active state) and its first-paint theme. Empty values keep today's defaults (no active highlight, dark theme).
func (*GitHubPagesPublisher) SetProgress ¶ added in v0.2.0
func (p *GitHubPagesPublisher) SetProgress(pr PublishProgress)
SetProgress attaches a PublishProgress sink so callers can render live step progress for publish/republish operations. Passing nil disables reporting.
func (*GitHubPagesPublisher) SetReportLister ¶ added in v0.4.0
func (p *GitHubPagesPublisher) SetReportLister(fn ReportLister)
SetReportLister attaches the lister used to gather referenced reports when building the reports page on each push. Passing nil disables the reports page.
func (*GitHubPagesPublisher) SetSourceLister ¶ added in v0.4.0
func (p *GitHubPagesPublisher) SetSourceLister(fn SourceLister)
SetSourceLister attaches the lister used to fetch the feed list when building the sources page on each push. Passing nil disables sources page generation.
func (*GitHubPagesPublisher) WaitForPagesBuild ¶
func (p *GitHubPagesPublisher) WaitForPagesBuild(commitSHA string) error
WaitForPagesBuild blocks until the GitHub Pages build for commitSHA has finished deploying. It is a thin wrapper over waitForDeploy that does not emit step progress; kept for callers that only need the sequencing behaviour.
type GlossaryPanelEntry ¶ added in v0.4.0
type GlossaryPanelEntry struct {
Term string
Type string
Definition string
Aliases []string // similar surface forms grouped under this term, shown as "also: …"
Lvl int // help tier: 1=advanced, 2=intermediate, 3=beginner
}
GlossaryPanelEntry is one deduplicated term shown in the right-side glossary drawer (term + semantic type + general definition; no per-article context).
type Headline ¶ added in v0.4.0
Headline is one article headline in a manifest entry, paired with its importance priority ("must"/"should"/"may"/"opt").
type LandingProfile ¶ added in v0.4.0
type LandingProfile struct {
Slug string `json:"slug"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Icon string `json:"icon,omitempty"`
Subdir string `json:"subdir"`
}
LandingProfile is one profile shown on the public root landing page and listed in profiles.json. Subdir is the (resolved) output directory the profile publishes under, used as the relative link target.
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) Prune ¶ added in v0.4.0
Prune removes entries whose PeriodStart is before cutoff, returning the count removed. Entries with a missing or unparseable PeriodStart are kept.
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"`
// PeriodStart and PeriodEnd are the canonical, honestly-named bounds of the
// digest's article-selection window (ISO "2006-01-02 15:04 UTC", machine-readable).
PeriodStart string `json:"period_start,omitempty"`
PeriodEnd string `json:"period_end,omitempty"`
// StartedAt is a deprecated legacy alias that holds the window END (not the
// start). It is still written so entries published before period_end existed
// keep round-tripping and the archive index can fall back to it. Prefer
// PeriodEnd; remove once all historical entries have aged out.
StartedAt string `json:"started_at"`
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 []Headline `json:"headlines"`
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 PublishProgress ¶ added in v0.2.0
type PublishProgress interface {
Start(step, label string) // begin a step (spinner row)
Update(step, label string) // relabel an in-flight step
Complete(step string, ok bool, note string) // finish a step (✓ / ✗)
}
PublishProgress receives coarse step updates during publish/republish so a CLI front-end can render live progress. A nil PublishProgress disables reporting (used by the automatic server publish path).
type RenderOption ¶ added in v0.4.0
type RenderOption func(*renderConfig)
RenderOption tunes how a page is rendered. The zero set of options produces a fully self-contained page (CSS and JS inlined) — the default that Discord HTML attachments and the dev preview server rely on. The gh-pages publisher passes WithExternalCSS to link external assets instead.
func WithExternalCSS ¶ added in v0.4.0
func WithExternalCSS() RenderOption
WithExternalCSS makes a render link sibling .css/.js files (via <link> and <script src>) instead of inlining them. Only the published GitHub Pages site uses this; the files are written alongside the pages by the publisher. The small theme-dynamic palette and the blocking pre-paint scripts stay inline either way. The name is historical (it now covers scripts too).
type RenderedAnalysis ¶
type RenderedAnalysis struct {
ProviderType string
ModelName string
Tldr template.HTML
PlainWords 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 ReportLister ¶ added in v0.4.0
ReportLister returns every digest created on/after since, newest first, with its Articles (incl. Tags) and DigestAnalyses (incl. Analysis) populated — the raw material the reports page aggregates. It lets the publisher build the reports page without depending on the store. A nil lister disables the page.
type SourceLister ¶ added in v0.4.0
SourceLister returns every configured feed. It lets the publisher build the "sources" page without depending on the store: callers that have DB or client access supply it via SetSourceLister. A nil lister disables the sources page.
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).