Skip to main content
Version: Next

Quality Control Rules Design

Document Type: Rule Design (Tier 2) Domain: RULES-QC Domain Character: Algorithmic SRS References: rule-westgards.md, rule-minimum-fluorescence.md, rule-unexpected-fl.md, rule-baseline-check.md, rule-mincontrols.md, rule-extraction-controls.md Status: Draft Last Updated: 2026-01-25


1. Overview

1.0 Rule Summary

PropertyValue
IntentValidate PCR run quality by detecting statistical anomalies in control samples (Westgard rules), fluorescence threshold violations, baseline configuration issues, and control well presence requirements.
InputsControl well observations (CT, quantity, fluorescence readings), Westgard limit configurations (mean, SD), target configurations (thresholds), run target settings, extraction details
OutputsError codes at well level and target level; Westgard event records for Levey-Jennings reporting
PrecedenceAfter Runfile Import; Before Error Resolution

1.1 Purpose

The QC Rules domain implements quality control validation for PCR analysis runs. This encompasses:

  • Westgard Rules: Statistical process control using industry-standard Westgard methodology to detect systematic and random errors in control samples
  • Fluorescence Validation: Minimum and maximum fluorescence threshold checks to ensure signal quality
  • Baseline Validation: Automatic baseline check configuration validation
  • Control Presence: Validation that patient wells have required controls (PC/NC, PEC/NEC)

The rules operate independently but share common patterns for error assignment and resolution handling.

1.2 Requirements Covered

REQ IDTitlePriority
REQ-RULES-WG-001Exclude Resolved Controls from CalculationsMust
REQ-RULES-WG-002Use Same-Run Controls as HistoryMust
REQ-RULES-WG-003Scope WgInError to Affected Time RangeMust
REQ-RULES-WG-004Set INVALID_SD Error for Invalid Standard DeviationMust
REQ-RULES-WG-005Set WESTGARDS_MISSED ErrorMust
REQ-RULES-WG-006Trigger 1:2s RuleMust
REQ-RULES-WG-007Trigger 1:3s RuleMust
REQ-RULES-WG-008Trigger 1:4s RuleMust
REQ-RULES-WG-009Trigger 2:2s RuleMust
REQ-RULES-WG-010Strict Boundary EnforcementShould
REQ-RULES-WG-011Trigger 7T RuleMust
REQ-RULES-WG-012Trigger WG13S22S Combined RuleMust
REQ-RULES-WG-013Trigger WG7T13S Combined RuleMust
REQ-RULES-MINFL-001Validate Well Fluorescence Against Minimum ThresholdsMust
REQ-RULES-MINFL-002Propagate Control Well Fluorescence Failures to Target LevelMust
REQ-RULES-MINFL-003Allow Users to Skip Minimum Fluorescence Rule via Resolution CodeShould
REQ-RULES-UNEXPFL-001Validate Well Fluorescence Against Maximum ThresholdsMust
REQ-RULES-BASELINE-001Apply Well-Level Manual Baseline ErrorMust
REQ-RULES-BASELINE-002Apply Target-Level Manual Baseline ErrorMust
REQ-RULES-MINCTRL-001Skip Rule for Non-Patient WellsMust
REQ-RULES-MINCTRL-002Skip Rule When MINCONTROL Resolution ExistsMust
REQ-RULES-MINCTRL-003Set CONTROL_MISSING Error When Fallback DisabledMust
REQ-RULES-MINCTRL-004Check Backup Mix Controls When Fallback EnabledMust
REQ-RULES-EXTCTRL-001Validate Patient Well Extraction ControlsMust
REQ-RULES-EXTCTRL-002Report Error When Fallback DisabledMust
REQ-RULES-EXTCTRL-003Check Backup Mix When Fallback EnabledMust
REQ-RULES-EXTCTRL-004Recognize Quantification and PC Role as Positive ControlShould
REQ-RULES-EXTCTRL-005Exclude Label Error Wells from MINEXTRACT Control AssociationMust
REQ-RULES-EXTCTRL-006Exclude Label Error Wells from MINCONTROL Control AssociationMust

1.3 Dependencies

DirectionComponentPurpose
ConsumesWell + ObservationsControl sample data with CT/quantity values
Westgard LimitsMean, SD, lot per target/role/date
Kit ConfigurationThresholds, role mappings, feature flags
Historical PEC WellsPrevious controls for multi-control rules
ProducesWell ErrorsError codes at well level
Target ErrorsError codes at run target level
LJ Report DataWestgard events for Levey-Jennings visualization

2. Component Architecture

2.1 Component Diagram

2.2 Component Responsibilities

ComponentFileResponsibilityREQ Trace
Wg12SRuleAnalyzer/Rules/Wg12SRule.php1:2s (2SD) threshold ruleREQ-RULES-WG-006
Wg13SRuleAnalyzer/Rules/Wg13SRule.php1:3s (3SD) threshold ruleREQ-RULES-WG-007
Wg14SRuleAnalyzer/Rules/Wg14SRule.php1:4s (4SD) threshold ruleREQ-RULES-WG-008
Wg22SRuleAnalyzer/Rules/Wg22SRule.php2:2s consecutive pattern ruleREQ-RULES-WG-009, REQ-RULES-WG-010
Wg7TRuleAnalyzer/Rules/Wg7TRule.php7T trend pattern ruleREQ-RULES-WG-011
Wg22S13SRuleAnalyzer/Rules/Wg22S13SRule.phpCombined 2:2s + 1:3s ruleREQ-RULES-WG-012
Wg7T13SRuleAnalyzer/Rules/Wg7T13SRule.phpCombined 7T + 1:3s ruleREQ-RULES-WG-013
WginerrorRuleAnalyzer/Rules/WginerrorRule.phpTime-scoped error propagationREQ-RULES-WG-003
MinFluorescenceRuleAnalyzer/Rules/MinFluorescenceRule.phpMinimum fluorescence validationREQ-RULES-MINFL-001, 002, 003
UnexpectedFlRuleAnalyzer/Rules/UnexpectedFlRule.phpMaximum fluorescence validationREQ-RULES-UNEXPFL-001
MinControlsRuleAnalyzer/Rules/MinControlsRule.phpPC/NC presence validationREQ-RULES-MINCTRL-001 to 004
MinextractRuleAnalyzer/Rules/MinextractRule.phpPEC/NEC extraction control validationREQ-RULES-EXTCTRL-001 to 006
ManualBaselineRuleAnalyzer/Rules/ManualBaselineRule.phpBaseline check configurationREQ-RULES-BASELINE-001, 002
SetErrorToWellAnalyzer/Rules/Concerns/SetErrorToWell.phpShared error assignmentAll
PecWellCollectionAnalyzer/PecWellCollection.phpHistorical PEC well queriesREQ-RULES-WG-001, 002, 009, 011

3. Data Design

3.1 Entities

This domain reads from configuration and historical data, writes to well and run target records:

EntityOwnerRead/WriteFields Used
wellsRUNRPTRead/Writeobservations, error_code, lims_status, resolution_codes
observationsRUNRPTRead/Writefinal_cls, final_ct, final_quantity, sd_from_mean, lot
run_targetsRUNRPTRead/Writeerror_codes, automatic_baseline_check
westgard_limitsKITCFGReadmean, sd, lot, valid_from, valid_to
targetsKITCFGReadminimum_fluorescence, maximum_fl
role_to_target_mappingsKITCFGReadbackup_mix
previous_pec_wellsRUNFILEReadHistorical control data for trend/pattern detection

See Database Reference for full schema.

3.2 Westgard Limit Structure

interface WestgardLimit {
id: string;
role_id: string;
target_id: string;
lot: string;
mean: number;
sd: number; // Standard deviation
valid_from: Date;
valid_to: Date | null;
extraction_instrument: string;
}

3.3 Control Matching Context

interface ControlMatchContext {
well: Well;
mix_id: string;
extraction_date: Date;
extraction_instrument: string;
batch_number: string | null;

// Computed during matching
has_pc: boolean;
has_nc: boolean;
has_pec: boolean;
has_nec: boolean;
fallback_enabled: boolean;
backup_mix_id: string | null;
}

4. Interface Design

4.1 Rule Interface

All QC rules implement the standard AnalyzerRuleContract:

interface AnalyzerRuleContract {
public function handle(
ConfigurationRepository $config,
AnalyzableObservation $observation,
RunMix $runMix,
RunTarget $runTarget,
AnalyzableWell $well,
WellCollection $wells,
PatientWellCollection $previousPatientWells,
PecWellCollection $previousPecWells,
RunTargetsCollection $runTargets
): void;
}

4.2 Key Internal APIs

MethodClassPurpose
getWestgardLimitForObservation()ConfigurationRepositoryRetrieve Westgard limit by observation
hasValidSd()WestgardLimitValidate SD > 0
setSdFromMeanFromWestgardLimit()ObservationCalculate SD deviation from mean
isSdFromMeanGreaterThanTwo/Three/Four()ObservationCheck threshold violations
sdFromMeanIsPositive()ObservationDetermine direction (high/low)
hasSdFromMeanGreaterThanTwoInLatestTwoWellsForWell()PecWellCollection2:2s pattern check
hasTrendInLatestSevenWellsForWell()PecWellCollection7T pattern check
hasAssociatePositiveControl()WellCollectionPC presence check
hasAssociateNegativeControl()WellCollectionNC presence check
hasAssociatePositiveExtractionControl()WellCollectionPEC presence check
hasAssociateNegativeExtractionControl()WellCollectionNEC presence check

5. Behavioral Design

5.1 Westgard Rules Family

5.1.1 Processing Order

WG14S (1st) -> WG13S (2nd) -> WG12S (3rd) -> WG22S -> WG7T -> Combined Rules

Higher SD thresholds are checked first. A 4SD violation takes precedence over 3SD.

5.1.2 Single-Control Rules (1:2s, 1:3s, 1:4s)

Algorithm: Evaluate Single-Control Westgard Rule

Inputs:
- well: Well - The control well being evaluated
- observation: Observation - Well's observation with CT/quantity
- westgard_limit: WestgardLimit - Configured mean and SD
- threshold_multiplier: number - 2, 3, or 4 (for respective rules)

Outputs:
- void (modifies well.error_code, run_target.errors)

Assumptions:
- Well is a control well (PEC)
- Westgard limit exists and has valid SD

Steps:
1. Resolution check:
IF well.resolution_codes contains rule code:
Apply LIMS status from resolution
RETURN

2. Westgard limit validation:
IF no westgard_limit found:
Set WESTGARDS_MISSED error
RETURN
IF westgard_limit.sd <= 0 OR not numeric:
Set INVALID_SD error
RETURN

3. Calculate deviation:
delta = ABS(observation.ct_or_quant - westgard_limit.mean)
sd_from_mean = delta / westgard_limit.sd
observation.setSdFromMean(sd_from_mean)

4. Skip conditions:
IF observation.final_cls is negative: RETURN
IF observation.final_ct is null: RETURN

5. Threshold check:
IF sd_from_mean > threshold_multiplier:
IF observation.value > westgard_limit.mean:
Set WGxxS_HIGH_WELL error on well
Set WGxxS_HIGH_TARGET error on run_target
ELSE:
Set WGxxS_LOW_WELL error on well
Set WGxxS_LOW_TARGET error on run_target
Create duplicate Westgard limit record for LJ

5.1.3 Westgard 1:2s/1:3s/1:4s Truth Table

SD from MeanWG14S ResultWG13S ResultWG12S Result
> 4ERROR--
> 3, <= 4-ERROR-
> 2, <= 3--WARNING*
<= 2No errorNo errorNo error

*WG12S severity is client-configurable (default: WARNING, Viracor: ERROR)

Precedence: WG14S before WG13S before WG12S. First match wins for the same observation.

Default: No error if SD from mean <= 2.

5.1.4 Multi-Control Rules (2:2s, 7T)

Westgard 2:2s Algorithm
Algorithm: Evaluate 2:2s Westgard Rule

Inputs:
- well: Well - Current control well
- observation: Observation - Current observation
- previous_pec_wells: PecWellCollection - Historical PEC wells

Steps:
1-4. Same validation as single-control rules

5. Pattern check:
IF previousPecWells.hasSdFromMeanGreaterThanTwoInLatestTwoWellsForWell(well):
- Check both current and previous control are >2SD
- Check both are on same side of mean (same direction)
- Check strict_boundary_enforcement config for >3SD exclusion

IF pattern matches:
Set WG22S_HIGH/LOW_WELL and WG22S_HIGH/LOW_TARGET errors
Westgard 2:2s Decision Logic
Current ControlPrevious ControlSame DirectionStrict BoundaryResult
> 2SD> 2SDYesN/AWG22S ERROR
> 2SD> 2SDNoN/ANo error
> 2SD> 3SDYesEnabledNo error (excluded)
> 2SD> 3SDYesDisabledWG22S ERROR
> 2SD< 2SD**No error
< 2SD***No error

Precedence: Evaluated after single-control rules.

Default: No error if pattern not matched.

Westgard 7T Algorithm
Algorithm: Evaluate 7T Westgard Rule

Steps:
1-4. Same validation as single-control rules

5. Trend check:
IF previousPecWells.hasTrendInLatestSevenWellsForWell(well):
- Retrieve last 7 control values including current
- Check all 7 trend in same direction (all increasing OR all decreasing)

IF trend detected:
Set WG7T_HIGH/LOW_WELL and WG7T_HIGH/LOW_TARGET errors

5.1.5 Combined Rules (WG13S22S, WG7T13S)

Algorithm: Evaluate WG13S22S Combined Rule

Steps:
1. Check for 1:3s violation (>3SD)
2. Check for 2:2s pattern (>2SD same direction)
3. IF both conditions met:
IF high direction: Set WG13S22S_HIGH_WELL, WG13S22S_HIGH_TARGET
ELSE: Set WG13S22S_LOW_WELL, WG13S22S_LOW_TARGET
Algorithm: Evaluate WG7T13S Combined Rule

Steps:
1. Check for 1:3s violation (>3SD)
2. Check for 7T trend pattern
3. IF both conditions met:
IF increasing trend: Set WG7T13S_HIGH_WELL, WG7T13S_HIGH_TARGET
ELSE: Set WG7T13S_LOW_WELL, WG7T13S_LOW_TARGET

5.1.6 Westgard Resolution and History Handling

Resolved Control Exclusion (REQ-RULES-WG-001):

When checking history for 2:2s or 7T patterns:
- Exclude wells with resolution codes (RPTNEG, RPTALL, RXTALL)
- A resolved 1:3s control followed by 1:2s does NOT trigger 2:2s

Same-Run History (REQ-RULES-WG-002):

Controls within the same run are processed sequentially.
The second control in a run uses the first as history for 2:2s evaluation.

5.2 Fluorescence Validation Rules

5.2.1 Minimum Fluorescence Algorithm

Algorithm: Validate Minimum Fluorescence

Inputs:
- well: Well
- observation: Observation with fluorescence readings
- minimum_fluorescence: number (from target config) or null

Steps:
1. Resolution check:
IF well.resolution_codes contains 'MIN_FLUORESCENCE': RETURN

2. Configuration check:
IF minimum_fluorescence is null:
Set MINIMUM_FLUORESCENCE_MISSED error
RETURN

3. Threshold comparison:
min_reading = MIN(observation.readings)
IF min_reading < minimum_fluorescence:
Set LOW_FLUORESCENCE_WELL on well
IF well.isControlWell():
Set LOW_FLUORESCENCE_TARGET on run_target

Notes:
- Reading equal to threshold passes (no error)
- Only control wells (PC, NC, Quantification) propagate to target level

5.2.2 Minimum Fluorescence Decision Logic

ReadingThresholdWell TypeWell ErrorTarget Error
< thresholdConfiguredControlLOW_FLUORESCENCE_WELLLOW_FLUORESCENCE_TARGET
< thresholdConfiguredSampleLOW_FLUORESCENCE_WELLNone
>= thresholdConfigured*NoneNone
*null*MINIMUM_FLUORESCENCE_MISSEDNone

Precedence: Standard rule pipeline position.

Default: No error if reading >= threshold.

5.2.3 Unexpected (Maximum) Fluorescence Algorithm

Algorithm: Validate Maximum Fluorescence

Inputs:
- observation: Observation with readings
- maximum_fl: number (from target config) or null

Steps:
1. Configuration check:
IF maximum_fl is null:
Set MAXIMUM_FLUORESCENCE_MISSED error
RETURN

2. Rox normalization (if enabled):
IF target.rox_normalization:
Apply Rox divide to readings before calculating max

3. Threshold comparison:
max_reading = MAX(observation.readings)
IF max_reading > maximum_fl:
Set UNEXPECTED_FL error on well

5.3 Manual Baseline Rule

Algorithm: Validate Manual Baseline Check

Inputs:
- run_target: RunTarget with automatic_baseline_check setting

Steps:
1. Configuration check:
IF run_target.hasAutoBaseline() == true: RETURN

2. Apply errors:
Set MANUAL_BASELINE_CHECK_WELL on well
Set MANUAL_BASELINE_CHECK_TARGET on run_target

5.3.1 Manual Baseline Decision Logic

automatic_baseline_checkWell ErrorTarget Error
trueNoneNone
falseMANUAL_BASELINE_CHECK_WELLMANUAL_BASELINE_CHECK_TARGET

5.4 Control Presence Rules

5.4.1 MIN_CONTROLS Algorithm

Algorithm: Validate Control Presence

Inputs:
- well: Well
- wells: WellCollection (all wells in run)
- config: ConfigurationRepository

Steps:
1. Resolution check:
IF well.resolution_codes contains 'MINCONTROL': RETURN

2. Patient check:
IF NOT well.isPatientWell(): RETURN

3. Control presence check:
has_pc = wells.hasAssociatePositiveControl(config, well)
has_nc = wells.hasAssociateNegativeControl(config, well)

IF has_pc AND has_nc: RETURN (success)

IF fallback_shared_control enabled:
Check backup_mix for controls
IF backup_mix has controls: RETURN (success)

4. Error assignment:
Set CONTROL_MISSING error on well

5.4.2 MINEXTRACT Algorithm

Algorithm: Validate Extraction Controls

Inputs:
- well: Well (with extraction details)
- wells: WellCollection

Steps:
1-2. Same as MIN_CONTROLS (resolution, patient checks)

3. Extraction control matching:
Match controls on:
- Same mix (or backup_mix if fallback enabled)
- Same extraction_date
- Same extraction_instrument
- Same batch_number (if present)

Exclude wells with Label Error type errors

Accept "Quantification & PC" role as valid PEC

4. Error assignment:
IF NOT (has_pec AND has_nec):
Set EXTRACTION_CONTROLS_MISSING error on well

5.4.3 Control Presence Decision Logic

Well TypeResolutionPC PresentNC PresentFallbackBackup Has ControlsResult
Control*****Skip (no error)
PatientMINCONTROL****Skip (no error)
PatientNoneYesYes**No error
PatientNoneNo*Disabled*CONTROL_MISSING
PatientNone*NoDisabled*CONTROL_MISSING
PatientNoneNo*EnabledYesNo error
PatientNoneNo*EnabledNoCONTROL_MISSING

Precedence: After basic well validation.

Default: Error if required controls not found.


6. Error Handling

ConditionDetectionResponseError Code
Westgard limit not foundConfig lookup returns nullSet error, skip ruleWESTGARDS_MISSED
Invalid SD (0 or non-numeric)SD validationSet error, skip ruleINVALID_SD
Missing fluorescence configConfig null checkSet errorMINIMUM_FLUORESCENCE_MISSED, MAXIMUM_FLUORESCENCE_MISSED
Missing controlsControl lookup failsSet errorCONTROL_MISSING, EXTRACTION_CONTROLS_MISSING
Control with label errorError type checkExclude from matchingN/A (continue search)

7. Configuration

SettingPathDefaultEffectREQ
westgard_limit.meanKit ConfigRequiredMean value for Westgard calculationWG-006 to WG-013
westgard_limit.sdKit ConfigRequiredStandard deviation (must be > 0)WG-004
wg12s_severityClient ConfigWARNINGSeverity for 1:2s ruleWG-006
wg13s_severityClient ConfigERRORSeverity for 1:3s ruleWG-007
strict_boundary_enforcementClient ConfigvariesExclude >3SD from 2:2s pairingWG-010
target.minimum_fluorescenceKit ConfignullMinimum FL thresholdMINFL-001
target.maximum_flKit ConfignullMaximum FL thresholdUNEXPFL-001
target.rox_normalizationKit ConfigfalseEnable Rox divide before max FLUNEXPFL-001
run_target.automatic_baseline_checkRun ConfigtrueAutomatic baseline modeBASELINE-001, 002
fallback_shared_controlKit ConfigfalseEnable backup mix fallbackMINCTRL-003, 004, EXTCTRL-002, 003
role_to_target_mapping.backup_mixKit ConfignullBackup mix for fallbackMINCTRL-004, EXTCTRL-003

See Configuration Reference for full documentation.


8. Implementation Mapping

8.1 Code Locations

ComponentPath
Wg12SRuleapp/Analyzer/Rules/Wg12SRule.php
Wg13SRuleapp/Analyzer/Rules/Wg13SRule.php
Wg14SRuleapp/Analyzer/Rules/Wg14SRule.php
Wg22SRuleapp/Analyzer/Rules/Wg22SRule.php
Wg7TRuleapp/Analyzer/Rules/Wg7TRule.php
Wg22S13SRuleapp/Analyzer/Rules/Wg22S13SRule.php
Wg7T13SRuleapp/Analyzer/Rules/Wg7T13SRule.php
WginerrorRuleapp/Analyzer/Rules/WginerrorRule.php
MinFluorescenceRuleapp/Analyzer/Rules/MinFluorescenceRule.php
UnexpectedFlRuleapp/Analyzer/Rules/UnexpectedFlRule.php
MinControlsRuleapp/Analyzer/Rules/MinControlsRule.php
MinextractRuleapp/Analyzer/Rules/MinextractRule.php
ManualBaselineRuleapp/Analyzer/Rules/ManualBaselineRule.php
SetErrorToWellapp/Analyzer/Rules/Concerns/SetErrorToWell.php
PecWellCollectionapp/Analyzer/PecWellCollection.php

8.2 Requirement Traceability

REQ IDDesign SectionPrimary Code
REQ-RULES-WG-001SS5.1.6PecWellCollection.php
REQ-RULES-WG-002SS5.1.6PecWellCollection.php
REQ-RULES-WG-003SS5.1WginerrorRule.php
REQ-RULES-WG-004SS5.1.2Wg12SRule.php, Wg13SRule.php, Wg14SRule.php
REQ-RULES-WG-005SS5.1.2All Westgard rules
REQ-RULES-WG-006SS5.1.2, SS5.1.3Wg12SRule.php
REQ-RULES-WG-007SS5.1.2, SS5.1.3Wg13SRule.php
REQ-RULES-WG-008SS5.1.2, SS5.1.3Wg14SRule.php
REQ-RULES-WG-009SS5.1.4Wg22SRule.php
REQ-RULES-WG-010SS5.1.4Wg22SRule.php, Wg22S13SRule.php
REQ-RULES-WG-011SS5.1.4Wg7TRule.php
REQ-RULES-WG-012SS5.1.5Wg22S13SRule.php
REQ-RULES-WG-013SS5.1.5Wg7T13SRule.php
REQ-RULES-MINFL-001SS5.2.1MinFluorescenceRule.php
REQ-RULES-MINFL-002SS5.2.1, SS5.2.2MinFluorescenceRule.php
REQ-RULES-MINFL-003SS5.2.1MinFluorescenceRule.php
REQ-RULES-UNEXPFL-001SS5.2.3UnexpectedFlRule.php
REQ-RULES-BASELINE-001SS5.3ManualBaselineRule.php
REQ-RULES-BASELINE-002SS5.3ManualBaselineRule.php
REQ-RULES-MINCTRL-001SS5.4.1MinControlsRule.php
REQ-RULES-MINCTRL-002SS5.4.1MinControlsRule.php
REQ-RULES-MINCTRL-003SS5.4.1, SS5.4.3MinControlsRule.php
REQ-RULES-MINCTRL-004SS5.4.1, SS5.4.3MinControlsRule.php
REQ-RULES-EXTCTRL-001SS5.4.2MinextractRule.php
REQ-RULES-EXTCTRL-002SS5.4.2, SS5.4.3MinextractRule.php
REQ-RULES-EXTCTRL-003SS5.4.2, SS5.4.3MinextractRule.php
REQ-RULES-EXTCTRL-004SS5.4.2MinextractRule.php
REQ-RULES-EXTCTRL-005SS5.4.2MinextractRule.php, WellCollection.php
REQ-RULES-EXTCTRL-006SS5.4.2MinControlsRule.php, WellCollection.php

9. Design Decisions

DecisionRationaleAlternatives Considered
Separate classes per Westgard ruleDifferent thresholds and behaviors, easier testingSingle class with multiplier parameter (rejected: combined rules need different logic)
Westgard processing order (4S->3S->2S)Higher threshold = more severe, should take precedenceEvaluate all and report highest (rejected: multiple errors confusing)
Resolved control exclusionIndustry standard - resolved issues shouldn't affect future controlsInclude all (rejected: violates Westgard methodology)
Label error exclusion from control matchingWells with uncertain identity shouldn't validate patient wellsInclude all controls (rejected: could validate with wrong control)
Dual-level error (well + target)Well-level for detail, target-level for Assay Summary reportingWell-level only (rejected: loses aggregate view)
Fallback shared control as feature flagDifferent lab workflows; some labs share controls across mixesAlways enabled (rejected: changes existing behavior)

10. Performance Considerations

ScenarioConcernMitigation
Large control history (7T rule)Query performance for 7 historical wellsIndex on target/role/date; limit lookback period
Multiple Westgard rules per wellRepeated Westgard limit lookupsSingle lookup, cached for rule duration
Control presence with fallbackDouble-check (primary + backup mix)Early return if primary satisfies

DocumentRelevant Sections
SRS: rule-westgards.mdWestgard requirements
SRS: rule-minimum-fluorescence.mdMin FL requirements
SRS: rule-unexpected-fl.mdMax FL requirements
SRS: rule-baseline-check.mdBaseline requirements
SRS: rule-mincontrols.mdMIN_CONTROLS requirements
SRS: rule-extraction-controls.mdMINEXTRACT requirements
SDS: Rules EngineFramework overview
SDS: Outcome RulesRQUAL fallback
SDS: Domain RUNRPTWell/observation data