Decision Intelligence - Implementation Checklist¶
Package: mineproductivity.decision
Governing specification: docs/architecture/07_Decision_Intelligence_Design_Specification.md
Architecture Decision Record: docs/adr/ADR-0007-Decision-Intelligence.md
Status: Not started
Binding, locked implementation contract for decision - the second package built on top of the Foundation Layer, sitting directly above the now-locked analytics. 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. 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 (
07_Decision_Intelligence_Design_Specification.md) read in full by the implementer, including every cross-reference to specs 01–06. - ADR-0007 read in full; the rationale for
decisionexisting as a separate package aboveanalytics(not folded into it, not merged with a futureoptimization/decisioncombination) is understood, not merely accepted. -
core,events,ontology,registry,plugins,connectors,kpis,analyticsavailable and importable, exactly as released; no Foundation Layer oranalyticsfile is modified as a side effect of this work. - Confirmed:
decisionwill not importdigital_twin,simulation,optimization,visualization, oragentsunder any circumstance - none of those packages exist yet (design spec §5). - Confirmed: no lower package (
corethroughanalytics) will be modified to import or otherwise referencedecision(design spec §5, §3.5).
Package Structure¶
-
src/mineproductivity/decision/created matching design spec §6 exactly:abstractions.py,metadata.py,result.py,pipeline.py,rules.py,policy.py,thresholds.py,strategy.py,recommendation.py,ranking.py,explanation.py,root_cause.py,what_if.py,prioritization.py,planning.py,alerting.py,scoring.py,realtime.py,batch.py,audit.py,_registry.py,exceptions.py,__init__.py,README.md. -
decision/README.mdwritten following thecore/README.mdtemplate. - Confirmed
pipeline.pycontains zero strategy-specific branches (mechanical grep/AST check - design spec §9). - Confirmed
root_cause.py/what_if.pycontain zero concrete, non-test subclasses ofRootCauseAnalyzer/WhatIfEngine(design spec §18, §19, §34's interface-purity proof).
Public API¶
-
decision/__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 everydecisionsubmodule for a forbidden import (digital_twin,simulation,optimization,visualization,agents) - 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,analytics}/importsmineproductivity.decision(design spec §5, §3.5) - theanalytics-package precedent for this test (spec 06 checklist) extended one layer up.
Abstractions & Registry (§8, §31, §32)¶
-
DecisionModel(§8) -decide()non-overridable orchestration checking for at least oneKPIResult/AnalyticsResultin context;_decide()abstract. -
DecisionContext(§8) -kpi_results,analytics_results,scope, optionalevent_store, optionalas_of. -
DecisionMetadata/DecisionCategory(§30) -code,category,description,version;validate()rejects an emptycode. -
decision._registry.REGISTRY/register(§32) -Registry[str, type[DecisionModel]], raisingDecisionValidationErrorfor an empty code andDecisionVersionConflictErrorfor a materially-different re-registration under an existing code. -
EntryPointSpec(group="mineproductivity.decision", target_registry="decision")discovery wired viaregistry.EntryPointDiscovery(§32).
Decision Pipelines and Rule Engine (§9, §10, §11)¶
-
PipelineStage(ABC) andDecisionPipeline(§9) -run()chains stages in order, rejects a pipeline whose final stage does not yield aDecisionResult. -
ModelStage(§9) - the concrete terminal stage wrapping oneDecisionModel. -
Ruletype alias overcore.BaseSpecification[DecisionContext](§10) - no bespoke rule DSL introduced anywhere. -
RuleEngine.evaluate()(§10) - isolates one malformed rule's failure from the rest, returns triggered rule names in stable (sorted) order. -
RuleEngineStage(§10) - thePipelineStagewrapper composingRuleEngine+ aPolicyinto aDecisionPipeline. - Confirmed no second rule-composition mechanism exists anywhere in the package beyond
core.BaseSpecification's&/|/~(§11, §34).
Business Policies and Thresholds (§12, §13)¶
-
DecisionStatusenum (§12) - exactlyProposed/Active/Superseded/Retired, mirroringkpis.KPIStatus. -
Policy(§12) -code,version,status,rules,thresholds,strategy_code;validate()rejects an emptycodeor zero rules. -
PolicyConflictErrorraised for a re-registration attempt that changes anActivepolicy's rules/thresholds without a version bump and aSupersededtransition for the prior version (§12, §29). -
Threshold(§13) -field,comparator(exactly</<=/>/>=/==/!=),limit;validate()rejects an emptyfield. -
ThresholdBreach(§28) -threshold,observed_value,breached_at.
Decision Strategies, Recommendations, Ranking, Explanations (§14–§17)¶
-
DecisionStrategy(ABC) /ThresholdDecisionStrategy(§14) - evaluates aPolicy's rules against aDecisionContext, producesRecommendations for triggered, threshold-breaching rules. -
Recommendation(§15) -policy_code,triggered_rules,summary,severity,evidence, optionalexplanation; always traceable to specificPolicy/Rulenames andKPIResult.code/AnalyticsResult.model_codeevidence. -
RankingStrategy(ABC) /WeightedScoreRanking(§16) - ordersRecommendations intoRankedRecommendations byDecisionScore. -
ExplanationBuilder/ExplanationStage(§17) - walks aRecommendation's provenance into a structuredExplanation(premises,evidence_refs); composes as aDecisionPipelineterminal stage. - Confirmed ranking (§16) and prioritization (§20) remain distinct code paths, never collapsed into one score (§33).
Interface-Only Modules (§18, §19)¶
-
RootCauseAnalyzer(ABC) -_analyze(symptom, context) -> RootCauseResultsignature only; zero concrete subclasses shipped. -
WhatIfEngine(ABC) -_simulate(context, hypothesis, as_of) -> WhatIfResultsignature only, deliberately reusingevents.AsOf.scenario; zero concrete subclasses shipped. -
RootCauseResult,WhatIfResultresult types implemented per §18/§19 even though no producer of them ships in this release.
Action Prioritization and Planning (§20, §21)¶
-
ActionPriority(§20) -urgency,impact,effort,priority_scoreproperty; all three components retained alongside the aggregate. -
ActionPrioritizer.prioritize()(§20) - assignsActionPriorityto eachRankedRecommendation. -
ActionPlanner.plan()(§21) - topological ordering of prioritized actions respecting an optionaldependenciesmapping; returnsResult.erron a detected cycle rather than silently dropping it. - Confirmed
ActionPlannerimplements its own narrow ordering and does not reusekpis.DependencyGraph(§3.3, §21, §33 - the coupling-mismatch rule is the single most load-bearing design decision in this module). -
ActionPlan(§21) -ordered_actions,priorities.
Alerting and Scoring (§22, §23, §24)¶
-
AlertGenerator.from_breach()/from_recommendation()(§22) - producesAlertvalue objects only; confirmed no I/O/channel-delivery side effect exists anywhere in this class. -
Alert(§22) -message,severity,scope, optionaltriggered_by. -
DecisionScorer.score()(§23) -DecisionScore(value,components) as a function of severity, policy weight, and optionalConfidenceScore. -
ConfidenceScorer.score()(§24) -ConfidenceScore(value,basis) derived fromanalytics.DataQualityScoreplus rule-evidence strength; confirmed fallback to"rule_strength"basis when noDataQualityScoreis present in context, and that thebasisfield correctly records which path was taken.
Real-Time and Batch Evaluation, Audit Trail (§25–§28)¶
-
RealTimeDecisionSession(§25) - subscribes toevents.EventBus, refreshesKPIEngine/BatchAnalyticsRunneroutputs per relevant event, re-runsDecisionPipeline;start()returns theevents.Subscriptionhandle;latest()reads without re-running the pipeline. -
BatchDecisionRunner(§26) - thin, named wrapper overDecisionPipeline.run(). -
DecisionAuditTrail/DecisionAuditEntry(§27) - append-only;record()/query();source_event_idspopulated on a best-effort basis (§27's "what traceable means in practice" note) - an empty tuple is not an error. -
DecisionAuditTrailthread safety: concurrentrecord()calls proven safe under stress test (append-only lock or equivalent);query()proven non-blocking against a concurrentrecord(). - Real-time/batch parity proven:
RealTimeDecisionSession.latest()and aBatchDecisionRunnerrun over the same assembled context produce the sameDecisionResult(§34).
Result Models, Lifecycle, Metadata (§28–§30)¶
-
DecisionResultbase (model_code,computed_at,warnings) and every concrete subclass (Recommendation,RankedRecommendation,ActionPlan,Alert,RootCauseResult,WhatIfResult) implemented as frozencore.BaseValueObjects. -
Explanation,DecisionScore,ConfidenceScore,ActionPriority,Threshold,ThresholdBreachimplemented as plainBaseValueObjects (notDecisionResultsubclasses) per §28's explicit distinction. - Every result type serializes via
core.serialization(DataclassSerializer/to_dict) with no bespoke per-type serializer (§28). -
Policylifecycle (§29):Proposed → Active → Superseded → Retired, version bump +Supersededtransition enforced for any change to anActivepolicy's rules/thresholds. -
DecisionMetadata.version(§30) confirmed to version independently of anyPolicy's own version.
Thread Safety & Concurrency¶
- Every
DecisionModelsubclass confirmed stateless acrossdecide()calls (no instance mutation) - test proves concurrent invocation of one shared instance is safe (§8). -
decision.REGISTRYconfirmed read-only and thread-safe after startup discovery, inheritingRegistry's own contract (§8, spec 03 §24). -
DecisionAuditTrailconfirmed not thread-safe on its own without its internal synchronization mechanism; stress-tested under concurrentrecord()calls (§27).
Error Handling¶
- Full exception hierarchy (design spec §6
exceptions.py):DecisionValidationError,NoApplicablePolicyError,DecisionModelNotFoundError,DecisionVersionConflictError,PolicyConflictError- each subclassing the matchingcoreexception. - Confirmed
DecisionModel.decide()never raises for a legitimately no-recommendation input - returns aDecisionResultwith zero recommendations instead (§8, §33). -
DecisionVersionConflictError/PolicyConflictErrorproven to raise at registration time for a materially-different re-registration/re-publication, never deferred. -
Policyreferencing astrategy_codefor which noDecisionModelis registered proven to fail at activation time (DecisionModelNotFoundError), not silently at first evaluation (§12).
Performance & Memory¶
- Confirmed
decisionperforms no independent large-scale computation - rule evaluation profile dominated by already-smallDecisionContextobjects, not raw event/statistical volume (§35). -
RealTimeDecisionSessionconfirmed to delegate toKPIEngine.execute()/BatchAnalyticsRunnerrather than re-fetching or re-aggregating raw data itself (§35). -
DecisionAuditTrail.record()confirmed O(1) per entry;query()confirmed to support scope-based filtering without a full linear scan at production audit-trail sizes (§35). -
ActionPlanner.plan()confirmed O(V+E) over the declared action-dependency graph (§35). -
Policylookup confirmed registry-speed (in-memory), never a disk/network round-trip on the rule-evaluation hot path (§35).
Tests¶
-
tests/unit/decision/mirrorssrc/mineproductivity/decision/1:1. - Coverage ≥95%.
- Unit tests per concrete strategy (
ThresholdDecisionStrategy,WeightedScoreRanking) against hand-authoredPolicy/Thresholdfixtures with known expected outputs (§34). - Rule composition tests reusing
core.specification's own test patterns (§34). - Policy governance tests:
PolicyConflictErrorraised for an unversionedActive-policy change (§34). - Confidence-scoring correctness tests: with and without a
DataQualityScorepresent, asserting the correctbasisrecorded (§34). - Registry/discovery isolation tests mirroring
tests/integration/test_registry_plugin_discovery.py's healthy/broken fixture-plugin pattern, specialized forDecisionModel(§34). - Interface-only ABC contract tests for
RootCauseAnalyzer/WhatIfEngine(bare-ABC instantiation raisesTypeError) - no algorithmic-correctness test exists for either (§34). - Action-planning ordering tests: correct topological ordering and correct cycle rejection (§34).
- Real-time/batch parity tests (§34).
- The five package acceptance proofs in design spec §34 (no-fact-recomputation, rule-isolation, interface-purity, no-architectural-drift, audit-completeness) each independently verified and recorded in the PR description.
Documentation¶
-
decision/README.mdcomplete. - Every registered
DecisionModel's docstring restates itsDecisionMetadata.descriptionfor source-level readability.
Examples¶
-
examples/decision/01_pipeline_over_evidence.py- the design spec §9 worked example (fleet-availability policy evaluated againstUTIL.OEE+ its trend), end-to-end. -
examples/decision/02_action_planning.py-ActionPrioritizer+ActionPlannerproducing anActionPlanwith declared dependencies. -
examples/decision/03_realtime_session.py-RealTimeDecisionSessionover anEventBus, producing a liveDecisionResult. -
examples/decision/04_plugin_strategy.py- a third-party-styleDecisionStrategyregistered via entry points, mirroringexamples/registry/01_register_and_discover.py's pattern. - All examples pass
mypy --strict+ruff.
Benchmarks¶
-
RuleEngine.evaluate()throughput at representative policy/rule-count scale, recorded inbenchmark/reports/decision/. -
DecisionAuditTrailappend/query latency at representative audit-trail sizes.
Certification¶
- Design spec §34's five package acceptance proofs pass and are recorded in the PR description (duplicated here from Tests for merge-gate visibility).
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 (
digital_twin,simulation,optimization,visualization,agents) was introduced, and confirm no lower package gained a newdecisionimport. - Version bump proposed and reviewed.
- Design spec §34's acceptance proofs re-verified as final merge gate.
Derived from 07_Decision_Intelligence_Design_Specification.md. Keep in sync with the governing specification and with ADR-0007-Decision-Intelligence.md.