Analytics Engine - Implementation Checklist¶
Package: mineproductivity.analytics
Governing specification: docs/architecture/06_Analytics_Engine_Design_Specification.md
Architecture Decision Record: docs/adr/ADR-0006-Analytics-Engine.md
Status: Not started
Binding, locked implementation contract for analytics - the first package built on top of the now-locked Foundation Layer (core, events, ontology, registry, plugins, connectors, kpis). Nothing described here may be implemented before this checklist and its governing specification exist in reviewed form, and nothing may be implemented that is not represented by an item on this list - an implementer who finds a gap corrects the governing specification and this checklist first, in a separate documentation PR, before writing the code the gap would have covered. Complete in order; every box must be checked or explicitly deferred with a linked issue and Chief Software Architect sign-off before merge.
Pre-Implementation Gate¶
- Design specification (
06_Analytics_Engine_Design_Specification.md) read in full by the implementer, including every cross-reference to specs 01–05. - ADR-0006 read in full; the rationale for
analyticsexisting as a separate package (not folded intokpis, not deferred untildecisionneeds it) is understood, not merely accepted. -
core,events,ontology,registry,plugins,connectors,kpisavailable and importable, exactly as released (v0.2.0–v0.7.0); no Foundation Layer file is modified as a side effect of this work (design spec Document Control). - Confirmed:
analyticswill not importdecision,digital_twin,optimization,simulation,agents, orvisualizationunder any circumstance - none of those packages exist yet (design spec §5). - Confirmed: no Foundation Layer file (
corethroughkpis) will be modified to import or otherwise referenceanalytics(design spec §5, §3.5).
Package Structure¶
-
src/mineproductivity/analytics/created matching design spec §6 exactly:abstractions.py,metadata.py,result.py,pipeline.py,aggregation.py,windowing.py,timeseries.py,statistics.py,rolling.py,trend.py,baseline.py,benchmarking.py,quality.py,forecasting.py,anomaly.py,outliers.py,batch.py,streaming.py,incremental.py,_registry.py,exceptions.py,__init__.py,README.md. -
analytics/README.mdwritten following thecore/README.mdtemplate (per every prior package's own precedent). - Confirmed
pipeline.pycontains zero model-specific branches (mechanical grep/AST check - design spec §9, mirroring spec 05 §37.1'sKPIEngineproof). - Confirmed
forecasting.py,anomaly.py,outliers.pycontain zero concrete, non-test subclasses ofForecastingModel/AnomalyDetector/OutlierDetector(design spec §16, §18, §19, §35's interface-purity proof).
Public API¶
-
analytics/__init__.pyexports exactly the symbol list in design spec §7, alphabetized__all__. -
test_public_api.pymirrorstests/unit/core/test_public_api.pyand every existing package's own copy of it. -
TestNoForbiddenDependenciesAST-walks everyanalyticssubmodule for a forbidden import (decision,digital_twin,optimization,simulation,agents,visualization) - mirrors every existing package's own copy of this test (design spec §5). - A second, reverse-direction test asserts no file under
src/mineproductivity/{core,ontology,events,registry,plugins,connectors,kpis}/importsmineproductivity.analytics(design spec §5, §3.5) - this is new relative to prior packages' checklists, sinceanalyticsis the first package for which "nothing below imports up" needs its own explicit proof.
Abstractions & Registry (§8, §32, §33)¶
-
AnalyticsModel(§8) -analyze()non-overridable orchestration enforcingmeta.min_observations;_analyze()abstract. -
AnalyticsContext(§8) - bundlesEventStore, optionalKPIEngine, optionalExecutionBackend. -
AnalyticsMetadata/AnalyticsCategory(§31) -code,category,description,min_observations,version;validate()rejects an emptycode. -
analytics._registry.REGISTRY/register(§33) -Registry[str, type[AnalyticsModel]], raisingAnalyticsValidationErrorfor an empty code andAnalyticsVersionConflictErrorfor a materially-different re-registration under an existing code. -
EntryPointSpec(group="mineproductivity.analytics", target_registry="analytics")discovery wired viaregistry.EntryPointDiscovery(§33).
Metric Pipelines & Aggregation (§9, §10)¶
-
PipelineStage(ABC) andAnalyticsPipeline(§9) -run()chains stages in order, rejects a pipeline whose final stage does not yield anAnalyticsResult. -
ModelStage(§9) - the concrete terminal stage wrapping oneAnalyticsModel. -
AggregationEngine.reduce()(§10) - pure statistical group-and-reduce over non-KPI series (sum/mean/median). -
AggregationEngine.reduce_kpi_results()(§10) - forADDITIVE/CUMULATIVE-aggregation KPIs, direct combination; forRATIO/AVERAGE/WEIGHTED_AVERAGE-aggregation KPIs, delegates toKPIEngine.execute()over the combined scope - never averages already-computedKPIResult.values for these aggregation kinds (design spec §10, §34 - the single most load-bearing correctness rule in this package, direct analogue ofkpis' own ratio-never-averaged rule, spec 05 §19, §13.3).
Windowing & Time-Series (§11, §12)¶
-
RollingSpec(§11) - exactly one oftime_window(wrappingkpis.RollingWindow) orperiods(count-based) set;validate()enforces this. -
TimeSeries/TimeSeriesPoint(§12) - ordered by timestamp;from_kpi_results()andfrom_event_query()construction paths implemented. - Confirmed no second, parallel time-window type is introduced anywhere in the package (design spec §34).
Trend, Baseline, Benchmarking (§13, §14, §15)¶
-
TrendModel(ABC) /LinearTrendModel(§14) - deterministic OLS fit;TrendResultcarriesslope,intercept,r_squared,direction. -
BaselineModel(ABC) /RollingBaselineModel(§15) - trailing mean/std band;Baselineresult carriesmean,std,lower,upper. -
BenchmarkModel(ABC) /BandBenchmarkModel(§13) - readsKPIMetadata.benchmark_bands/directionviaRegistry.metadata_for; correctly inverts comparison forLOWER_IS_BETTER, handlesTARGET_IS_BESTas distance-from-target. - Confirmed
BandBenchmarkModelintroduces no parallel band schema - every band classification traces to an existingKPIMetadata.benchmark_bandsentry (design spec §13, §34).
Interface-Only Modules (§16, §18, §19)¶
-
ForecastingModel(ABC) -_forecast(series, horizon, context) -> ForecastResultsignature only; zero concrete subclasses shipped. -
AnomalyDetector(ABC) -_detect(series, baseline, context) -> Sequence[AnomalyFlag]signature only; zero concrete subclasses shipped. -
OutlierDetector(ABC) -_detect(series, distribution, context) -> Sequence[OutlierFlag]signature only; zero concrete subclasses shipped. -
ForecastResult,AnomalyFlag,OutlierFlagresult types implemented per §16/§18/§19 even though no producer of them ships in this release.
Statistical Primitives (§17, §20–§24)¶
-
describe()→StatisticalSummary(§17). -
percentile()(§21) - linear-interpolation convention, matching NumPy's/pandas' default. -
histogram()→Histogram(§22) - supports both integer bin count and caller-supplied bin edges. -
distribution()→DistributionSummary(§23) - addsskewness/kurtosisbeyonddescribe(). -
confidence_interval()→ConfidenceInterval(§24) -normalandtmethods only; no resampling-based method in this release (§37). -
rolling_mean(),rolling_std(),rolling_apply()(§20) - absent-point (not sentinel-value) representation beforespec.min_periodsobservations are available.
Data Quality & Missing Data (§25, §26)¶
-
DataQualityScorer.score()→DataQualityScore(§25) -completeness,validity,overall_score,reasons. -
DataQualityStage(§6, §9) - thePipelineStagewrapper composingDataQualityScorerinto anAnalyticsPipeline. -
MissingDataPolicyenum (§26) - exactlyEXCLUDE,FLAG_ONLY,FORWARD_FILL,MEAN_FILL; no fifth, predictive/model-based member.
Execution Modes (§27, §28, §29)¶
-
BatchAnalyticsRunner(§28) - thin, named wrapper overAnalyticsPipeline.run(). -
StreamingAnalyticsSession(§27) -start()returns theevents.Subscriptionhandle fromEventBus.subscribe();snapshot()reads without touchingEventStore. -
IncrementalAccumulator(§29) - Welford's online algorithm;update()/snapshot(); per-key synchronization documented and implemented inStreamingAnalyticsSession(§29's thread-safety contract -IncrementalAccumulatoritself is not internally synchronized). - Streaming/batch parity proven:
IncrementalAccumulator's result andstatistics.describe()'s batch result agree within floating-point tolerance over the same dataset (§35, §36).
Result Models & Serialization (§30)¶
-
AnalyticsResultbase (model_code,computed_at,warnings) and every concrete subclass (StatisticalSummary,TrendResult,BenchmarkResult,Baseline,DistributionSummary,Histogram,ConfidenceInterval,DataQualityScore,ForecastResult) implemented as frozencore.BaseValueObjects. -
AnomalyFlag/OutlierFlagimplemented as plainBaseValueObjects (notAnalyticsResultsubclasses) per §30's explicit distinction. - Every result type serializes via
core.serialization(DataclassSerializer/to_dict) with no bespoke per-type serializer (§30).
Thread Safety & Concurrency¶
- Every
AnalyticsModelsubclass confirmed stateless acrossanalyze()calls (no instance mutation) - test proves concurrent invocation of one shared instance is safe (§8). -
analytics.REGISTRYconfirmed read-only and thread-safe after startup discovery, inheritingRegistry's own contract (§8, spec 03 §24). -
IncrementalAccumulatorconfirmed not thread-safe on its own;StreamingAnalyticsSession's per-key serialization mechanism (lock or equivalent) implemented and stress-tested under concurrentupdate()calls for the same key (§29). - Independent
IncrementalAccumulators (different keys) proven non-interfering under concurrent updates (§29).
Error Handling¶
- Full exception hierarchy (design spec §6
exceptions.py, used throughout §8–§33):AnalyticsValidationError,InsufficientDataError,AnalyticsModelNotFoundError,AnalyticsVersionConflictError- each subclassing the matchingcoreexception (ValidationError,ValidationError,NotFoundError,RegistrationErrorrespectively). - Confirmed
AnalyticsModel.analyze()never raises for a legitimately un-analyzable input (too few observations) - returns a warning-carryingAnalyticsResultinstead (§8, §34). -
AnalyticsVersionConflictErrorproven to raise at registration time for a materially-different re-registration under an existing code, never deferred (§33).
Performance & Memory¶
-
IncrementalAccumulatorconfirmed as the default posture for unbounded input in bothStreamingAnalyticsSessionand, where row counts are large,BatchAnalyticsRunner(§36). -
AggregationEngineconfirmed to accept and correctly delegate to an optionalkpis.ExecutionBackend, with a plain-Python fallback when none is supplied - no second vectorization abstraction introduced (§36). -
TimeSeries.from_event_query()confirmed to request onlyvalue_fieldplus scope/grouping fields, never a full envelope payload, when constructing a series for pure statistical description (§36).
Tests¶
-
tests/unit/analytics/mirrorssrc/mineproductivity/analytics/1:1. - Coverage ≥95%.
- Unit tests per concrete model (
LinearTrendModel,RollingBaselineModel,BandBenchmarkModel) against hand-computed reference values (§35). - Statistical primitive tests (
percentile,histogram,distribution,confidence_interval) against independently-verified reference values, not self-referential re-assertions (§35). -
AggregationEngine.reduce_kpi_resultsregression test reproducing spec 05 §13.3's exact worked example at the cross-group level (§10, §35). - Registry/discovery isolation tests mirroring
tests/integration/test_registry_plugin_discovery.py's healthy/broken fixture-plugin pattern, specialized forAnalyticsModel(§35). - Interface-only ABC contract tests for
ForecastingModel/AnomalyDetector/OutlierDetector(bare-ABC instantiation raisesTypeError; minimal test-only concrete subclass satisfies the signature) - no algorithmic-correctness test exists for any of the three (§35). - Streaming/incremental parity test (§29, §35).
- Data-quality scoring tests against rows with known, hand-counted missing/invalid fields (§35).
- The five package acceptance proofs in design spec §35 (no-KPI-recomputation, ratio-correctness-at-the-group-level, interface-purity, no-architectural-drift, streaming/batch parity) each independently verified and recorded in the PR description.
Documentation¶
-
analytics/README.mdcomplete. - Every registered
AnalyticsModel's docstring restates itsAnalyticsMetadata.descriptionfor source-level readability (mirrorskpis' equivalent convention, spec 05 checklist).
Examples¶
-
examples/analytics/01_pipeline_over_kpi_series.py- the design spec §9 worked example (90-dayPROD.TPHtrend, gated byDataQualityStage), end-to-end. -
examples/analytics/02_benchmarking.py-BandBenchmarkModelclassifying aKPIResultagainst itsKPIMetadata.benchmark_bands. -
examples/analytics/03_streaming_session.py-StreamingAnalyticsSessionover anEventBus, snapshotting a liveStatisticalSummary. -
examples/analytics/04_plugin_model.py- a third-party-styleAnalyticsModelregistered via entry points, mirroringexamples/registry/01_register_and_discover.py's pattern. - All examples pass
mypy --strict+ruff.
Benchmarks¶
-
IncrementalAccumulatorvs. full batchstatistics.describe()recompute - latency comparison at representative event-volume scale, recorded inbenchmark/reports/analytics/. -
AggregationEnginewith vs. without anExecutionBackendsupplied - throughput comparison at representative row counts.
Certification¶
- Design spec §35's five package acceptance proofs pass and are recorded in the PR description (duplicated here from Tests for merge-gate visibility, mirroring spec 05 checklist's own Certification section referencing its design spec's §37).
Type Hints, Mypy, Ruff, Coverage¶
- 100% type-hinted;
mypy --strictclean. -
ruff checkandruff format --checkclean. - Coverage report attached; ≥95%.
Release¶
-
CHANGELOG.mdupdated. - Root README dependency diagram cross-checked - confirm no forbidden import (
decision,digital_twin,optimization,simulation,agents,visualization) was introduced, and confirm no Foundation Layer file gained a newanalyticsimport. - Version bump proposed and reviewed.
- Design spec §35's acceptance proofs re-verified as final merge gate.
Derived from 06_Analytics_Engine_Design_Specification.md. Keep in sync with the governing specification and with ADR-0006-Analytics-Engine.md.