critical priority medium complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

AggregationStage enum is defined with exactly four values: fetching, categorising, deduplicating, distributing — in pipeline execution order
AggregationInitial state is defined as an immutable class with no fields
AggregationInProgress state is defined with a required currentStage field of type AggregationStage
AggregationWarning state is defined with a required deduplicationAnomalyCount field of type int and a human-readable anomalyDescription field of type String
AggregationFailed state is defined with a required errorMessage field of type String and a required onRetry field of type VoidCallback
AggregationComplete state is defined with a required summaryMetrics field of type AggregationSummaryData (defined in task-004)
RetryAggregation event is defined as an immutable class
StartAggregation event is defined with any required trigger parameters
All state and event classes implement Equatable for value comparison in tests
All classes are exported from a single barrel file: lib/features/bufdir/aggregation/bloc/aggregation_bloc.dart
Dart documentation comments are present on all public classes and fields
Unit tests verify that each state can be instantiated and compared for equality

Technical Requirements

frameworks
flutter
bloc
equatable
data models
AggregationSummaryData
AggregationStage
AggregationState
AggregationEvent
performance requirements
State classes must be immutable — use const constructors wherever possible
Equatable props must include all fields to ensure accurate BLoC stream diffing
security requirements
AggregationFailed error messages must not expose raw database error strings or stack traces — sanitise before populating the state
No personal identifiers should be included in any state class field

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Place all BLoC contracts in lib/features/bufdir/aggregation/bloc/. Use the standard BLoC pattern: separate files for events (aggregation_event.dart), states (aggregation_state.dart), and the bloc itself (aggregation_bloc.dart), all re-exported from aggregation_bloc.dart. Use the freezed package if the project already uses it for union types — it eliminates boilerplate for sealed state hierarchies. If not, use abstract base classes with Equatable.

The AggregationSummaryData type referenced in AggregationComplete should be defined in task-004 but declare it as a placeholder class now (with a TODO comment) to unblock dependent tasks. Keep the onRetry callback in AggregationFailed typed as VoidCallback (from Flutter foundation) — do not use Function() to keep it testable with mock callbacks.

Testing Requirements

Unit tests using flutter_test. Test file: test/features/bufdir/aggregation/bloc/aggregation_state_test.dart. Test cases: (1) each state class instantiates without error; (2) two instances of the same state with identical fields are equal via Equatable; (3) two instances with different fields are not equal; (4) AggregationInProgress with stage=fetching is not equal to AggregationInProgress with stage=categorising; (5) AggregationFailed.onRetry is callable. Achieve 100% line coverage on all state and event classes.

Epic Risks (2)
medium impact high prob scope

For NHF with 1,400 local chapters, rendering a geographic breakdown as a flat list in the AggregationSummaryWidget would produce an unscrollable wall of data that is unusable on a mobile screen. Coordinators need to verify geographic completeness before export, but the raw chapter list is too long to review.

Mitigation & Contingency

Mitigation: Design the geographic distribution section as a collapsible two-level hierarchy: regions are shown expanded by default with their aggregate count, individual chapters are collapsed under each region and expandable on tap. Show only non-zero regions by default with a 'show empty regions' toggle.

Contingency: If the hierarchical display is too complex to implement before the submission deadline, fall back to a region-only summary view with a total count of active chapters per region and a note that chapter-level detail is available in the full export file.

medium impact medium prob technical

The aggregation BLoC must handle a multi-stage async pipeline with partial success states, warning accumulation across stages, and retry logic for individual failed stages. If the state model is too simplistic (e.g., loading/success/error), warning states and partial results will be lost on retry, confusing coordinators who see warnings disappear and reappear.

Mitigation & Contingency

Mitigation: Model the BLoC state as a rich sealed class hierarchy: AggregationIdle, AggregationRunning(stage, completedStages, accumulatedWarnings), AggregationComplete(result, warnings), AggregationFailed(failedStage, accumulatedWarnings, error). Accumulated warnings persist across retry attempts so coordinators see the full warning history.

Contingency: If state management complexity causes repeated bugs near the deadline, simplify to a single AggregationResult value object that captures success, warnings, and error as nullable fields, and drive both UI components from that single object rather than a live BLoC stream.