Documentation
¶
Overview ¶
Package analytics reconstructs team flow metrics (lead time, cycle time, stage dwell, bottlenecks) from the specs repo git history. It consumes plain git.LogEntry values and never shells out itself.
Index ¶
- Constants
- func BuildTimelines(events []Event, terminalStages []string) map[string]*Timeline
- func FormatDuration(d time.Duration) string
- func RenderFlowReport(r, prev *FlowReport) string
- func RenderSpecTimeline(tl *Timeline, now time.Time) string
- func RenderStageReport(r *FlowReport, stage string, timelines map[string]*Timeline, now time.Time) string
- func Sparkline(samples []time.Duration) string
- type AgingItem
- type AgingJSON
- type BlockedSpell
- type Coverage
- type Distribution
- type DistributionJSON
- type DurationJSON
- type Event
- type EventKind
- type EventSource
- type ExtractResult
- type FlowInput
- type FlowReport
- type ReportJSON
- type Reversion
- type ReversionBoundary
- type ReversionJSON
- type StageDwell
- type StageDwellJSON
- type StageVisit
- type Timeline
- type Window
Constants ¶
const StatusBlocked = "blocked"
StatusBlocked is the escape-hatch status stamped by `spec eject`. Mirrors pipeline.StatusBlocked without importing the pipeline engine.
Variables ¶
This section is empty.
Functions ¶
func BuildTimelines ¶
BuildTimelines replays extracted events (any order) into per-spec timelines. terminalStages marks completion; the first entry into any of them stamps CompletedAt.
func FormatDuration ¶
FormatDuration renders a duration compactly: minutes under an hour, tenths of hours under a day, tenths of days beyond.
func RenderFlowReport ¶
func RenderFlowReport(r, prev *FlowReport) string
RenderFlowReport renders the team flow report. prev, when non-nil, drives cross-window deltas; pass nil when no comparison window exists.
func RenderSpecTimeline ¶
RenderSpecTimeline renders a single spec's journey through the pipeline.
func RenderStageReport ¶
func RenderStageReport(r *FlowReport, stage string, timelines map[string]*Timeline, now time.Time) string
RenderStageReport renders a deep-dive for one stage: its dwell distribution, current occupants, and the reversion boundaries touching it.
Types ¶
type AgingItem ¶
type AgingItem struct {
SpecID string
Stage string
Dwell time.Duration
P85 time.Duration
Ratio float64
}
AgingItem flags an open spec dwelling beyond the historical p85 of its stage.
type AgingJSON ¶
type AgingJSON struct {
SpecID string `json:"spec_id"`
Stage string `json:"stage"`
Dwell DurationJSON `json:"dwell"`
P85 DurationJSON `json:"p85"`
Ratio float64 `json:"ratio"`
}
AgingJSON is one aging-WIP entry.
type BlockedSpell ¶
BlockedSpell is one closed eject→resume interval.
type Distribution ¶
type Distribution struct {
Samples []time.Duration
P50 time.Duration
P85 time.Duration
P95 time.Duration
}
Distribution summarises a set of duration samples with the percentiles that matter for flow analysis. Averages are deliberately absent: lead-time data is long-tailed and averages mislead.
func NewDistribution ¶
func NewDistribution(samples []time.Duration) Distribution
NewDistribution computes percentiles over the given samples.
type DistributionJSON ¶
type DistributionJSON struct {
Samples int `json:"samples"`
P50 DurationJSON `json:"p50"`
P85 DurationJSON `json:"p85"`
P95 DurationJSON `json:"p95"`
}
DistributionJSON is the percentile summary of a distribution.
type DurationJSON ¶
DurationJSON is a duration in machine and human form.
type Event ¶
type Event struct {
SpecID string
Kind EventKind
FromStage string // empty for scaffolds
ToStage string
At time.Time
Source EventSource
}
Event is a single stage transition (or scaffold) for one spec.
type EventSource ¶
type EventSource string
EventSource records which extraction tier attributed the event kind.
const ( SourceMessage EventSource = "message" SourceFrontmatter EventSource = "frontmatter" )
Extraction tiers: conventional commit messages (fast path) and frontmatter status diffs (truth path for manual edits and unconventional history).
type ExtractResult ¶
type ExtractResult struct {
Events []Event
CommitsScanned int
Transitions int // status transitions successfully attributed
Unattributable int // spec-file changes whose status could not be read
}
ExtractResult carries the extracted events plus honesty counters for the report footer ("analysed N/M transitions").
func ExtractEvents ¶
func ExtractEvents(entries []git.LogEntry, stageNames []string) ExtractResult
ExtractEvents replays the commit log (oldest-first) into typed lifecycle events. Frontmatter status diffs are the source of truth; commit messages only classify the kind when stage names are unknown to the pipeline.
type FlowInput ¶
type FlowInput struct {
Timelines map[string]*Timeline
Events []Event
Window Window
Now time.Time
StageNames []string // full pipeline order
Terminal []string // terminal stage names
WorkStages []string // engineer-owned stages (flow-efficiency numerator)
FastTrack map[string]bool // spec IDs flagged fast_track
Filter map[string]bool // optional spec-ID scope (nil = all)
}
FlowInput is everything ComputeFlow needs; it performs no I/O.
type FlowReport ¶
type FlowReport struct {
Window Window
Completed int
LeadTime Distribution
CycleTime Distribution
FastTrackLead Distribution // separate population, may be empty
FlowEfficiency float64 // work-stage time / lead time; -1 when unknown
ThroughputPerWeek float64
StageDwell []StageDwell // pipeline order, stages with samples only
Bottleneck string // stage with largest p50 dwell
Reversions []ReversionBoundary
TotalAdvances int
TotalReversions int
AgingWIP []AgingItem
BlockedSpecs int
BlockedTotal time.Duration
Coverage Coverage
}
FlowReport is the computed team flow picture for one window.
func ComputeFlow ¶
func ComputeFlow(in FlowInput) *FlowReport
ComputeFlow aggregates per-spec timelines into the team flow report.
func (*FlowReport) ToJSON ¶
func (r *FlowReport) ToJSON() ReportJSON
ToJSON converts a FlowReport into its machine-readable form.
type ReportJSON ¶
type ReportJSON struct {
Window struct {
From time.Time `json:"from"`
To time.Time `json:"to"`
Label string `json:"label"`
} `json:"window"`
Completed int `json:"completed"`
LeadTime DistributionJSON `json:"lead_time"`
CycleTime DistributionJSON `json:"cycle_time"`
FastTrackLead *DistributionJSON `json:"fast_track_lead,omitempty"`
FlowEfficiency *float64 `json:"flow_efficiency,omitempty"`
ThroughputPerWeek float64 `json:"throughput_per_week"`
StageDwell []StageDwellJSON `json:"stage_dwell"`
Bottleneck string `json:"bottleneck,omitempty"`
Reversions []ReversionJSON `json:"reversions"`
TotalAdvances int `json:"total_advances"`
TotalReversions int `json:"total_reversions"`
AgingWIP []AgingJSON `json:"aging_wip"`
BlockedSpecs int `json:"blocked_specs"`
BlockedTotal DurationJSON `json:"blocked_total"`
Coverage struct {
CommitsScanned int `json:"commits_scanned"`
Transitions int `json:"transitions"`
Unattributable int `json:"unattributable"`
} `json:"coverage"`
}
ReportJSON is the machine-readable flow report.
type ReversionBoundary ¶
ReversionBoundary counts backwards transitions across one stage boundary.
type ReversionJSON ¶
type ReversionJSON struct {
From string `json:"from"`
To string `json:"to"`
Count int `json:"count"`
}
ReversionJSON is one reversion boundary count.
type StageDwell ¶
type StageDwell struct {
Stage string
Dist Distribution
}
StageDwell is the dwell distribution for one stage over completed specs.
type StageDwellJSON ¶
type StageDwellJSON struct {
Stage string `json:"stage"`
Dwell DistributionJSON `json:"dwell"`
}
StageDwellJSON is one stage's dwell distribution.
type StageVisit ¶
StageVisit is one closed interval a spec spent in a stage.
func (StageVisit) Duration ¶
func (v StageVisit) Duration() time.Duration
Duration returns the visit's dwell.
type Timeline ¶
type Timeline struct {
SpecID string
Created time.Time
Visits []StageVisit // closed visits only
Blocked []BlockedSpell
Reversions []Reversion
Advances int
CurrentStage string // stage the spec occupies after the last event
CurrentSince time.Time // when it entered CurrentStage
CompletedAt time.Time // zero until the spec first enters a terminal stage
}
Timeline is the reconstructed journey of one spec through the pipeline.
func (*Timeline) FirstEntered ¶
FirstEntered returns when the spec first entered the given stage, or zero.