scoring

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package scoring owns the article importance model: the rubric dimensions an LLM rates, the deterministic aggregation of those dimensions into a 0-100 score, and the tier thresholds used to bucket articles in digests.

The LLM no longer chooses the final score directly. It rates a handful of narrow, anchored sub-dimensions (0-4 each) and Compute combines them with tunable weights here. Because the raw dimensions are persisted alongside the computed score, the weights can be retuned later and scores recomputed in a batch without re-running the LLM.

Index

Constants

View Source
const (

	// AggregatorScore is the fixed score forced for aggregator/roundup articles,
	// preserving the previous prompt's "always set the score to exactly 40" rule.
	AggregatorScore = 40

	// EvergreenCap caps the score of pure-evergreen articles (Specificity == 0),
	// preserving the previous prompt's "generic/evergreen must score ≤60" rule.
	EvergreenCap = 60
)
View Source
const (
	TierMustRead   = 90
	TierShouldRead = 75
	TierMayRead    = 60
)

Read-tier thresholds (inclusive lower bounds) on the 0-100 score.

Variables

View Source
var Weights = struct {
	Specificity   float64
	Severity      float64
	Breadth       float64
	Novelty       float64
	Actionability float64
	Credibility   float64
}{
	Specificity:   0.20,
	Severity:      0.25,
	Breadth:       0.20,
	Novelty:       0.10,
	Actionability: 0.15,
	Credibility:   0.10,
}

Per-dimension weights, summing to 1.0. This is the single place to retune the relative influence of each dimension on the final score.

Functions

func Compute

func Compute(d Dimensions) int

Compute aggregates rubric dimensions into a 0-100 importance score.

Each dimension is normalised to 0-1, combined via Weights into a weighted average, and scaled to 0-100. Overrides are then applied: aggregator articles are forced to AggregatorScore, and pure-evergreen articles (Specificity == 0) are capped at EvergreenCap.

func PriorityKey

func PriorityKey(score int) string

PriorityKey returns the short bucket key for a 0-100 score, used for digest manifest priority tallies. Unlike ReadTier it has no "unscored" bucket; anything below TierMayRead falls into "opt".

func ReadTier

func ReadTier(score int) string

ReadTier returns the human-facing priority label for a 0-100 score, used for digest table-of-contents grouping.

Types

type Dimensions

type Dimensions struct {
	// Specificity: generic/evergreen concept (0) → single concrete, recent event (4).
	Specificity int `json:"specificity"`
	// Severity: informational (0) → active exploitation / critical patch / major breach (4).
	Severity int `json:"severity"`
	// Breadth: niche product (0) → ubiquitous software or whole sector affected (4).
	Breadth int `json:"breadth"`
	// Novelty: rehash of known facts (0) → genuinely new disclosure/finding (4).
	Novelty int `json:"novelty"`
	// Actionability: nothing to do (0) → clear defensive action, patch, IOCs, detection (4).
	Actionability int `json:"actionability"`
	// Credibility: unsourced blogspam (0) → primary source / vendor advisory / named researcher (4).
	Credibility int `json:"credibility"`
	// IsAggregator marks roundups / weekly recaps / link digests, which are forced
	// to AggregatorScore regardless of the other dimensions.
	IsAggregator bool `json:"is_aggregator"`
}

Dimensions are the rubric sub-scores rated by the LLM. Each numeric field is on a 0-4 scale; values outside that range are clamped by Compute.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL