Repository navigation
What's Changed
- [FIX] -> Working-hours effective capacity is now a hard allocation cap, not a scoring nudge — a user cannot receive more items than
Truncate(WorkingHours × MaxAllowedDocs / FullWorkDayHours). - [FIX] -> Allocation scoring uses
score × remaining-headroom(greedy) instead of a plain score comparison, so the most-available user is consistently preferred over round-robin rotation. - [FIX] ->
PriorityActivityScoringSteppriority denominator is always ≥ 1 regardless of sign, eliminating the divide-by-zero that occurred when all users shared the same priority value. - [FIX] ->
PrimaryUserId/AlternativeUserIdtie-break inDistributionResultmirrors the allocator's own ascendingUserIdorder, making both properties deterministic across runs. - [FIX] ->
AllocationandTraceinDistributionResultare defensive copies — mutating the returned dictionary or collection does not affect subsequent engine runs. - [FIX] ->
CancellationTokenis checked between pipeline steps; a pre-cancelled token produces a failedIResultrather than throwingOperationCanceledExceptionto the caller. - [FIX] ->
UserLoad<TUserId>constructor throwsArgumentOutOfRangeExceptionfor negativecurrentLoad,capacity, orworkingHours; the helper surfaces such exceptions as a failedIResult. - [DEV] ->
DistributionResult<TUserId>exposesRequestedDocuments,UnallocatedDocuments(Max(0, Requested − TotalAllocated)), andIsFullyAllocatedto signal partial-allocation runs. - [DEV] ->
EngineConfig<TUserId>withAdditionalSteps(IReadOnlyList<IDistributionStep<TUserId>>) andAdditionalConstraints(IReadOnlyList<IConstraint<TUserId>>), plus a matchingDistributionSuggestionHelper<TUserId>(EngineConfig<TUserId>)constructor overload for consumer-supplied pipeline extensibility. - [DEV] ->
IDistributionStep<TUserId>.Executenow receivesIDistributionContext<TUserId>(a narrowed, read-only-plus-explicit-mutation contract) instead of the raw mutableDistributionContext<TUserId>. Custom steps must useSetScore/SetEffectiveCapacity/IncrementAllocation/AddTraceto mutate state; direct dictionary access (context.Scores[id] = x,context.Allocation[id]++,context.Trace.Add(...)) is no longer possible.DistributionContext<TUserId>no longer exposes raw mutableIDictionary/IListproperties —Scores,EffectiveCapacity, andAllocationare nowIReadOnlyDictionary, andTraceis no longer public. TheAbstractions.Pipelinelayer no longer depends onEngine.Pipeline(the layering smell is removed).
Full Changelog: v2.0.0.6122...v3.0.0.7577