Documentation
¶
Overview ¶
Package core provides a deterministic TOC constraint analyzer.
The analyzer classifies pipeline stages from observation data and identifies the system constraint (drum) via hysteresis. It has no goroutines, no channels, no time.Now() — same inputs produce same outputs, enabling deterministic simulation replay.
Consumers call Analyzer.Step once per analysis window with StageObservation values for all stages. The analyzer returns a Diagnosis with per-stage classification and constraint identity.
Observations use abstract Work units (nanoseconds for runtime pipelines, ticks for simulations). The classifier only uses ratios (BusyWork/CapacityWork) so the unit doesn't matter for classification. All observations fed to a single Analyzer must use the same unit.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultThresholds = Thresholds{
BrokenError: 0.2,
StarvedIdle: 0.5,
BlockedBlocked: 0.3,
SaturatedBusy: 0.7,
SaturatedIdle: 0.3,
SaturatedBlock: 0.2,
HysteresisWindows: 3,
DemotionWindows: 3,
ConfidenceMin: 10,
}
Default classification thresholds (from Goldratt/TameFlow conventions).
Functions ¶
This section is empty.
Types ¶
type Analyzer ¶
type Analyzer struct {
// contains filtered or unexported fields
}
Analyzer is the deterministic constraint identifier. No goroutines, no time.Now(), no channels. Same inputs → same outputs.
Internally tracks an incumbent (confirmed constraint) and a challenger (candidate building toward promotion). Promotion requires [Thresholds.HysteresisWindows] consecutive windows as sole top saturated stage. Demotion requires [Thresholds.DemotionWindows] consecutive unsupported windows.
Call Analyzer.Step once per analysis window with observations for all stages. The analyzer maintains hysteresis state between calls.
func NewAnalyzer ¶
NewAnalyzer creates a deterministic constraint analyzer. Panics if HysteresisWindows < 1 or DemotionWindows < 1.
func (*Analyzer) SetDrum ¶
SetDrum sets or clears the manual constraint override. Pass empty string to revert to automatic identification.
func (*Analyzer) Step ¶
func (a *Analyzer) Step(observations []StageObservation) Diagnosis
Step processes one analysis window. Returns classification for each stage and the current constraint identity.
Deterministic: same sequence of inputs produces the same sequence of outputs. No wall-clock dependency.
type ConstraintSource ¶ added in v0.4.0
type ConstraintSource int
ConstraintSource identifies how the constraint was determined.
const ( ConstraintSourceUnspecified ConstraintSource = iota // non-Identified states ConstraintSourceInferred // analyzer determined from evidence ConstraintSourceManualOverride // set by WithDrum / SetDrum )
func (ConstraintSource) String ¶ added in v0.4.0
func (s ConstraintSource) String() string
type ConstraintState ¶ added in v0.4.0
type ConstraintState int
ConstraintState classifies the analyzer's current constraint determination.
const ( ConstraintUnspecified ConstraintState = iota // zero value / proto default ConstraintUnknown // no usable diagnosis signal ConstraintUnconstrained // stages observed, none saturated ConstraintAmbiguous // tie among saturated candidates ConstraintEmerging // challenger building hysteresis ConstraintIdentified // incumbent confirmed )
func (ConstraintState) String ¶ added in v0.4.0
func (s ConstraintState) String() string
type Diagnosis ¶
type Diagnosis struct {
ConstraintState ConstraintState // why the constraint is or isn't identified
ConstraintSource ConstraintSource // how it was determined (only set for Identified)
Constraint string // incumbent stage name when Identified; empty otherwise
CandidateConstraint string // challenger stage name when Emerging; empty otherwise
SupportFreshness float64 // incumbent support streak: supportN/10, [0,1]; 0 when not identified
UnsupportedCount int // incumbent staleness; 0 when supported or not identified
Stages []StageDiagnosis // ordered by input order
StarvationCount int // consecutive windows incumbent was starved
}
Diagnosis is the output of one Analyzer.Step call. Contains per-stage classification and constraint identity.
type ObservationMask ¶
type ObservationMask uint32
ObservationMask distinguishes "not observed" from "observed zero." The classifier degrades gracefully when signals are missing — it skips checks that depend on absent data.
const ( HasIdle ObservationMask = 1 << iota // IdleWork is valid HasBlocked // BlockedWork is valid HasCompleted // Completions is valid HasFailed // Failures is valid HasQueue // QueueDepth is valid )
type Option ¶
type Option func(*Analyzer)
Option configures an Analyzer.
func WithDrum ¶
WithDrum sets a manual constraint override. Bypasses automatic identification — the analyzer will report this stage as Identified with ConstraintSourceManualOverride on every Step.
func WithThresholds ¶
func WithThresholds(t Thresholds) Option
WithThresholds sets custom classification thresholds.
type StageDiagnosis ¶
type StageDiagnosis struct {
Stage string
State StageState
Utilization float64 // BusyWork / CapacityWork
IdleRatio float64 // IdleWork / CapacityWork (0 if !HasIdleRatio)
BlockedRatio float64 // BlockedWork / CapacityWork (0 if !HasBlockedRatio)
HasIdleRatio bool // false when observation lacked idle data
HasBlockedRatio bool // false when observation lacked blocked data
ErrorRate float64 // Failures / Completions, bounded [0,1]
QueueGrowth int64 // currQueueDepth - prevQueueDepth (count delta)
// Passthrough counts for consumer rate computation.
Completions int64
Failures int64
Arrivals int64
}
StageDiagnosis holds the classification for one stage. Contains ratios and counts, NOT rates. The caller converts to rates using their own time model (wall-clock or ticks).
type StageObservation ¶
type StageObservation struct {
Stage string // stage identifier
Mask ObservationMask // which optional fields are valid
// Work accounting over the analysis window.
// All in the same unit. Ratios are unit-independent.
BusyWork Work // time workers spent executing (service time)
IdleWork Work // time workers spent waiting for input
BlockedWork Work // time workers spent blocked on output
CapacityWork Work // total worker-capacity over the window
// Item counters over the window.
Arrivals int64 // items entering the stage
Completions int64 // items where processing finished (includes failures)
Failures int64 // subset of Completions that errored
// Point-in-time gauges (end of window).
QueueDepth int64 // items buffered at observation time
Workers int32 // active workers at observation time
}
StageObservation is the canonical input to the analyzer. One per stage per analysis window. Produced by runtime adapters (from cumulative counter deltas), simulation engines (from tick state), or network adapters (from protobuf).
Invariant: BusyWork + IdleWork + BlockedWork <= CapacityWork. Equality holds when all worker time is accounted for. Inequality when some time is untracked (e.g., scheduling overhead). Adapters should aim for equality; the analyzer tolerates inequality.
Failures is a subset of Completions. A completion that errors is still a completion.
type StageState ¶
type StageState int
StageState classifies a stage's operational state from one analysis window.
const ( StateUnknown StageState = iota // insufficient data StateHealthy // normal operation StateStarved // high idle, waiting for input StateBlocked // high output-blocked StateSaturated // high busy — constraint candidate StateBroken // elevated errors )
func (StageState) String ¶
func (s StageState) String() string
type Thresholds ¶
type Thresholds struct {
BrokenError float64 // error rate above this → Broken
StarvedIdle float64 // idle ratio above this → Starved
BlockedBlocked float64 // blocked ratio above this → Blocked
SaturatedBusy float64 // utilization above this → Saturated candidate
SaturatedIdle float64 // idle must be below this for Saturated
SaturatedBlock float64 // blocked must be below this for Saturated
HysteresisWindows int // consecutive windows before challenger promotes; >= 1
DemotionWindows int // consecutive unsupported windows before incumbent demotes; >= 1
ConfidenceMin int64 // minimum completions for confident classification
}
Thresholds configures classification sensitivity.
type Work ¶
type Work uint64
Work represents abstract worker-time units. The actual unit (nanoseconds, ticks, etc.) is defined by the adapter producing observations. The classifier only uses ratios so the unit doesn't matter for classification. All observations fed to a single Analyzer must use the same unit.