insight

package
v0.69.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package insight produces the proactive "what's broken / what to look at" digest — the verdict founders actually want instead of a dashboard. Every finding is computed exactly from the deterministic engine, so it can't be hallucinated. Shared by the dashboard, the /v1/notable API, the MCP tool, and the daily brief.

Index

Constants

View Source
const (
	KindDropoff   = "funnel_dropoff"
	KindSegment   = "segment"
	KindAnomaly   = "anomaly"
	KindTrend     = "trend"
	KindRetention = "retention"
	KindAIVis     = "ai_visibility"
	KindReadable  = "site_readable"
	KindCrawl     = "ai_crawl"
)

Kinds name the DETECTOR behind a finding. Downstream surfaces (the fix brief, the cloud's fix-PR runner) branch on these. They must never branch on Title: Title is a sentence written for a human and gets reworded whenever the wording improves, which would silently break a consumer in another repository with nothing failing loudly.

View Source
const ReadableEvent = "$site_readable"

ReadableEvent is what the cloud's scanner writes after checking the project's own site.

Variables

This section is empty.

Functions

func DetectJourney added in v0.29.0

func DetectJourney(evs []event.Event) []funnel.Step

DetectJourney is detectJourney, exported.

Other packages need the SAME funnel this package's verdict describes — the error report's impact join, for one. Exporting the existing detector rather than letting each caller write its own is the whole point: two detectors would eventually disagree, and then one screen would say "checkout dropped" about a funnel another screen never mentions.

func EventVerbIs added in v0.29.0

func EventVerbIs(name string) string

EventVerbIs returns the verb that agrees with HumanEventNoun(name) — "are" for the plural autocapture nouns, "is" otherwise. A custom event keeps "is": the operator named it "signup", not "signups", and "signup is up 6%" is what they expect to read.

func HumanEngine added in v0.19.0

func HumanEngine(name string) string

HumanEngine renders an engine name for prose. An engine we have not met still has to read as a name rather than as a row key, and the "-grounded" suffix has to become the thing it actually means.

func HumanEvent added in v0.16.1

func HumanEvent(name string) string

HumanEvent is the PAST-tense form, for "after they ___". Custom events are returned unchanged: the operator chose "signup" or "checkout" and it already reads as English, so dressing it up would be worse and would stop matching what they see in filters, the API and their own tracking code.

func HumanEventBase added in v0.16.1

func HumanEventBase(name string) string

HumanEventBase is the infinitive, for "go on to ___".

func HumanEventIng added in v0.16.1

func HumanEventIng(name string) string

HumanEventIng is the gerund, for "from ___ to ___".

func HumanEventNoun added in v0.16.1

func HumanEventNoun(name string) string

HumanEventNoun is the plural noun, for "___ dropped 20% in the last 24h", where an action cannot be the subject: "viewed a page dropped 100%" is not a sentence.

func HumanSegment added in v0.16.1

func HumanSegment(prop, value string) string

HumanSegment turns a raw property match into a phrase. `country=US` is how a filter is written, not how a person describes a group of visitors.

func HumanStep added in v0.16.1

func HumanStep(name string) string

HumanStep reads a funnel step inside "A → B".

func Text

func Text(findings []Finding) string

Text renders the digest as a plain-text brief (for the daily webhook/email).

func UpIsBad added in v0.29.0

func UpIsBad(name string) bool

UpIsBad reports whether a RISE in this event is the bad news rather than the good news.

Types

type Finding

type Finding struct {
	Severity string `json:"severity"` // warn | info
	Title    string `json:"title"`
	Detail   string `json:"detail"`

	// The machine half. Every value below was already in the detector's hand when it wrote the
	// sentence above, so acting on a finding never means re-reading its prose.
	Kind   string   `json:"kind"`
	Metric string   `json:"metric,omitempty"` // the event this is about
	Steps  []string `json:"steps,omitempty"`  // the funnel it was computed over
	From   string   `json:"from,omitempty"`   // the step users reach
	To     string   `json:"to,omitempty"`     // the step they fail to reach
	Prop   string   `json:"prop,omitempty"`   // the segment property being blamed
	Value  string   `json:"value,omitempty"`  // the segment value being blamed
	Rate   int      `json:"rate,omitempty"`   // the headline percentage (signed for deltas)
	N      int      `json:"n,omitempty"`      // the base the rate is computed over
}

Finding is one notable thing, ranked by severity ("warn" before "info").

func Generate

func Generate(evs []event.Event) []Finding

Generate returns the digest: the biggest funnel leak, the headline event's week-over-week change, and the retention read — computed exactly. Generate detects the journey itself. Use it where there is no page context: the CLI, the morning brief, an MCP call.

func GenerateForFunnel added in v0.15.4

func GenerateForFunnel(evs []event.Event, pageSteps []funnel.Step) []Finding

GenerateForFunnel is Generate over a CALLER-SUPPLIED funnel.

The dashboard picks its funnel one way (top events by volume, ordered by journey) and this package picked its own another way (first-touch coverage), so one page could show a funnel pane reading "$pageview → $engagement → $click" while its own verdict card said "overall $pageview→$deadclick conversion is 7%". Both were internally honest and the page still contradicted itself about what "the funnel" is. Passing the page's steps in makes the verdict describe the funnel the reader is actually looking at.

steps with fewer than 2 entries falls back to detecting, so existing callers are unchanged.

func GenerateForFunnelOpts added in v0.49.0

func GenerateForFunnelOpts(evs []event.Event, pageSteps []funnel.Step, fopts funnel.Options) []Finding

GenerateForFunnelOpts is GenerateForFunnel over the page's funnel DISCIPLINE as well as its steps.

Passing the steps was only half of it. The pane has an order selector (?forder=ordered|strict| unordered) and the verdict always computed with the default discipline, so on a product where people commonly fire the later event first, selecting "any order" made the pane read "100% continue · 0 dropped" while the card directly above it announced "only 75% go on to signup, so 10 people stop here". The page's headline diagnosis contradicting the pane it is diagnosing, because a control moved one of them and not the other.

func (Finding) Fingerprint added in v0.19.0

func (f Finding) Fingerprint() string

Fingerprint is a finding's identity ACROSS PROCESSES: sha1 of the lowercased, trimmed title, first 12 hex chars. The cloud's fix-PR runner derives its branch name and its idempotency key with the exact same recipe (lib/finding-id.ts). If the two ever diverge, a brief, the email link that opens it and the PR opened from it stop being about the same thing — and nothing errors. Do not change this on one side.

Jump to

Keyboard shortcuts

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