outcome

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package outcome records, in an append-only JSONL ledger, whether an investigated incident later resolved and which answer was used for it — the "did it actually work?" signal the learning loop reads. The ledger keeps an in-memory index of still-open incidents, rebuilt by replaying the file on startup so a resolve survives a restart / leader failover.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Aggregate

type Aggregate struct {
	Recalls       int
	Resolved      int
	LastConfirmed time.Time
}

Aggregate is a per-entry roll-up of recall episodes: how often the entry was recalled, how often the incident then resolved, and when it last resolved.

type Episode

type Episode struct {
	Kind, Entry, Title, Resource string
	DupFingerprint               string // curator dedup fingerprint; stable join key for the curated-PR resolution check
	OpenedAt, ResolvedAt         time.Time
	Duration                     time.Duration
	Resolved                     bool
}

Episode is a matched open→resolve pair (or, from Episodes(), an unresolved open when Resolved is false).

type Event

type Event struct {
	Event          string `json:"event"`                     // "open" | "resolve"
	Fingerprint    string `json:"fingerprint"`               // Alertmanager fingerprint (stable firing↔resolved)
	DupFingerprint string `json:"dup_fingerprint,omitempty"` // curator dedup fingerprint (resource+cause); the curated-PR resolution join key

	Kind     string    `json:"kind,omitempty"`  // open: "recall" | "fresh"
	Entry    string    `json:"entry,omitempty"` // open+recall: the recalled entry path
	Title    string    `json:"title,omitempty"`
	Resource string    `json:"resource,omitempty"`
	At       time.Time `json:"at"`
}

Event is one ledger line: an investigation opened, or an incident resolved.

type Ledger

type Ledger struct {
	// contains filtered or unexported fields
}

Ledger is an append-only outcome log with an in-memory open-index.

func New

func New(path string) (*Ledger, error)

New opens (replaying) the ledger at path. An empty path returns a disabled, no-op ledger (the feature is off).

func (*Ledger) Episodes

func (l *Ledger) Episodes() ([]Episode, error)

Episodes replays the full ledger and turns every open into an Episode, pairing each resolve with the most-recent (LIFO) unresolved open for the same fingerprint — so recurrence is preserved (N opens + 1 resolve ⇒ N episodes, 1 resolved). Pairing is order-independent: a resolve that arrives BEFORE its open (a transient incident that cleared mid-investigation, so the resolve webhook landed before the open was recorded) is buffered and paired with the next open for that fingerprint. Episodes are returned in open order; all kinds are included. A disabled/empty ledger yields nil.

func (*Ledger) Open

func (l *Ledger) Open(e Event) error

Open records that an investigation completed for an incident (fingerprint).

func (*Ledger) OpenCounts

func (l *Ledger) OpenCounts() (map[string]Aggregate, error)

OpenCounts rolls Episodes up per catalog entry, counting recall episodes only (fresh investigations carry no entry). It is the input to recall decay: resolve-rate ≈ (Resolved+k)/(Recalls+k). A disabled/empty ledger yields an empty (non-nil) map.

func (*Ledger) Resolve

func (l *Ledger) Resolve(fp string, at time.Time) (Episode, bool, error)

Resolve records that an incident's alert cleared. When it matches an open investigation it returns the Episode (with duration + kind) and ok=true.

func (*Ledger) Status

func (l *Ledger) Status() Status

Status reports whether the ledger is configured and whether its file is actually present/non-empty where this process runs. A disabled ledger (path=="") reports Configured=false.

type Status

type Status struct {
	Path       string // the configured ledger path ("" when disabled)
	Configured bool   // a non-empty ledger_path was set
	Present    bool   // the file exists (true even when empty)
	Events     int    // number of replayable events (0 for absent/empty)
}

Status is a cheap snapshot of the ledger's on-disk reality, used to tell apart "feature off" (Configured=false) from "configured but the file the curate pod can see is absent/empty" (Configured=true, Present=false or Events==0) — the silent-no-op the `lore curate` startup warning surfaces. It re-reads the file (no cached open-index) so it reflects what a fresh process actually sees.

Jump to

Keyboard shortcuts

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