Documentation
¶
Overview ¶
Package classify is the single source of truth for classifying a line (or block) of process output into a severity + category, and — where the format is recognised — structured fields (file/line/col/code, or a folded multi-line error).
It merges what used to be two independent, drifting banks:
- internal/overlay/alerts_defaults.go — broad per-line toast patterns
- internal/tools/build_error_parsers.go — precise structured build errors
Both the overlay AlertScanner and the `proc output` extract path now source their classification rules from this package, so the rule set has one definition instead of two that silently drift.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsStructuralPrefix ¶
IsStructuralPrefix reports whether a line is a block header/banner that precedes a cause line and should be folded by a structured parser rather than surfaced standalone (it would otherwise trip the catch-all as `unparsed` noise — e.g. "prisma:error" contains "error", the invocation banner contains "Invalid"). The cause line that follows reaches back for these via the recent ring. A prefix with no following recognized cause is simply dropped — a bare header is not independently actionable.
Types ¶
type BuildError ¶
type BuildError struct {
Tool string `json:"tool"` // "tsc","eslint","vite","webpack","go","rust","pytest","jest","gotest"
Severity string `json:"severity,omitempty"` // "error" (default) or "warning"; eslint surfaces both
File string `json:"file,omitempty"`
Line int `json:"line,omitempty"`
Col int `json:"col,omitempty"`
Code string `json:"code,omitempty"` // e.g. "TS2322", "E0308"
Rule string `json:"rule,omitempty"` // e.g. "no-console" (eslint only)
Test string `json:"test,omitempty"` // pytest/jest/gotest test identifier
Message string `json:"message,omitempty"` // diagnostic text minus location
RawLine string `json:"raw_line,omitempty"`
}
BuildError is a structured error parsed from a build tool's output. The fields are deliberately optional — different tools surface different metadata (webpack often omits line/col, pytest omits col entirely) — so the JSON output uses `omitempty` aggressively. Tool is always set when the parser fires; callers can use it as a "did anything match?" check.
func ParseBuildErrors ¶
func ParseBuildErrors(lines []string) []BuildError
ParseBuildErrors scans a slice of output lines and returns the structured errors recognised by any of the parsers in the bank. Multi-line formats (rust header → location, vite header → location, jest header → at-frame, go test header → location, webpack header → build-failed line, eslint file-header → indented row) consume two adjacent lines and emit one BuildError; the parser advances past the consumed location line.
Unknown formats are silently dropped — the caller's line-level classification surfaces them via ClassifyLine / the catch-all.
The parsers are mutually exclusive on the *header* line: a tsc-style error TS#### line cannot also match the rust header (different prefix); a Go compile error cannot also match a go test location (which is indented and emitted only after a "--- FAIL:" header). Order of attempts matters only when two formats could plausibly fire on the same line; today none do.
type LineRule ¶
type LineRule struct {
ID string
Pattern *regexp.Regexp
Severity Severity
Category string // e.g. "dotnet", "webpack", "go", "generic"
Description string
}
LineRule is one broad, per-line classification pattern. It produces a boolean ("this line is an alert") plus severity, category, and a short description. Moved verbatim from the former overlay alert pattern bank.
func DefaultLineRules ¶
func DefaultLineRules() []LineRule
DefaultLineRules returns the built-in per-line classification rules for common dev-server frameworks and languages.
Adding a new framework: if a single boolean "this line is an error/warning" is enough, add a LineRule here. If an agent needs structured location/code fields, add a structured parser (build.go / structured.go) instead — the structured parsers take precedence over these broad rules in ClassifyLine.
type Severity ¶
type Severity string
Severity orders output by urgency. The string values match the legacy overlay.AlertSeverity / incident.Severity constants so consumers can convert with a plain string cast.
type StructuredError ¶
type StructuredError struct {
Kind string // "prisma", "db-auth", "db-conn"
Category string // alert category for downstream grouping
Severity Severity
Message string // primary cause/message (the actionable text)
Op string // failing operation, e.g. prisma.user.findUnique() (optional)
FileLine string // file:line call site (optional)
Hint string // remediation hint, carried for routing (not in Compact line)
}
StructuredError is a compact, parsed representation of a multi-line or otherwise noisy error block. Structured parsers fold a raw stderr block (banner + call-site + cause spread across several lines) into a single token-efficient line so consumers emit {kind, message, file:line, cause} instead of a dump.
This is the layer over the catch-all: the catch-all guarantees no real error is dropped (surfacing it verbatim as `unparsed`); the structured parsers upgrade the highest-value, recognizable shapes (Prisma/ORM, DB-auth) to a compact classified line. Pattern anchors are informed by the research docs under docs/error-formats/.
func RunStructuredLine ¶
func RunStructuredLine(signal string, recent []string) (*StructuredError, bool)
RunStructuredLine returns the first structured match for signal, or false.
func (StructuredError) Compact ¶
func (e StructuredError) Compact() string
Compact renders the structured error as one line:
[kind] message (op @ file:line)
The remediation Hint is deliberately NOT concatenated here — it is carried as a struct field for the routing layer, keeping the surfaced line as short as possible. Absent op/file:line are omitted.