STD: Well Discrepant CT Control Rule (WDCTC)
Version: v1.0.2
Status: Draft
SRS Source: docusaurus/docs/srs/rules/rule-wdctc.md
Rule Name: WDCTC
Domain: RULES-WDCTC
Overview
This document specifies tests for the WDCTC (Well Discrepant CT Control) rule using decision tables and test vectors. The rule detects CT discrepancies between pcr.ai calculated CT values and machine-reported CT values for Control wells.
Rule Characteristics:
- Pure business logic (no UI)
- Control wells only (patient wells handled by WDCT rule)
- Configurable suppression via max_ct_for_ct_discrepancy threshold
- Configurable skip via minimum_fluorescence_to_positive threshold
- Fixed CT discrepancy threshold of >2 cycles
Test Method: TM-API (per Test Plan Section 3.3 - Rules use automated API tests)
Verification Approach:
Rule verification is performed using data-driven test vectors. Each row in a decision table represents a complete verification scenario with defined inputs and expected outputs. This format enables exhaustive condition coverage while remaining concise and auditable.
Coverage Summary
| REQ ID | Title | Conditions | Test Vectors | Coverage | Gaps |
|---|
| REQ-RULES-WDCTC-001 | Core CT Discrepancy Detection | 8 | 17 | 100% | None |
| REQ-RULES-WDCTC-002 | Max CT Threshold Suppression | 4 | 7 | 100% | None |
| REQ-RULES-WDCTC-003 | Minimum Fluorescence Skip | 3 | 7 | 100% | None |
Totals: 3 REQs, 15 Conditions, 31 Test Vectors, 100% Coverage
| Variable | Type | Valid Values | Description |
|---|
well.type | string | Control, Patient | Well type |
obs.pcrai_ct | float | numeric | CT value calculated by pcr.ai engine |
obs.machine_ct | float | numeric | CT value reported by thermocycler |
obs.classification | string | Positive, Negative, Ambiguous | Classification result |
obs.final_ct | float | numeric | Final CT value for suppression check |
obs.readings | array | [float, ...] | Fluorescence readings |
target.max_ct_for_ct_discrepancy | float? | null, numeric | Suppression threshold (null = disabled) |
target.minimum_fluorescence_to_positive | float | numeric | Skip threshold |
Output Variables
| Variable | Type | Description |
|---|
well.errors | array | Error codes assigned to well |
target.errors | array | Error codes assigned to target |
rule_executed | bool | Whether the rule ran (false if skipped) |
error_generated | bool | Whether discrepancy errors were generated |
REQ-RULES-WDCTC-001: Core CT Discrepancy Detection
Decision Table: Well Type Filtering
| TV | well.type | rule_applies | Covers |
|---|
| TV-001-001 | Control | true | AC: Apply exclusively to Control wells |
| TV-001-002 | Patient | false | AC: Not patient wells |
Decision Table: Classification Filtering
Note: Negative classification alone does not cause the rule to skip. The skip requires both Negative classification and low fluorescence (max reading < minimum_fluorescence_to_positive). A Negative well with high fluorescence still proceeds to CT discrepancy evaluation. See REQ-RULES-WDCTC-003 and TV-COMB-007.
| TV | obs.classification | max_fluor vs fluor_threshold | ct_difference | error_generated | Covers |
|---|
| TV-001-003 | Negative | Below (low fluorescence) | 5 (>2) | false | AC: Neg CLS + low fluorescence skips rule |
| TV-001-004 | Positive | Above | 5 (>2) | true | AC: Evaluate non-negative |
| TV-001-005 | Ambiguous | Above | 5 (>2) | true | AC: Evaluate non-negative |
Decision Table: CT Discrepancy Threshold
| TV | obs.pcrai_ct | obs.machine_ct | abs_difference | error_generated | Covers |
|---|
| TV-001-006 | 30.0 | 35.0 | 5.0 | true | AC: Difference > 2 generates error |
| TV-001-007 | 30.0 | 32.1 | 2.1 | true | AC: Difference > 2 (boundary) |
| TV-001-008 | 30.0 | 32.0 | 2.0 | false | AC: Difference = 2 passes |
| TV-001-009 | 30.0 | 31.5 | 1.5 | false | AC: Difference < 2 passes |
| TV-001-010 | 35.0 | 30.0 | 5.0 | true | AC: Absolute value (pcrai > machine) |
Decision Table: Error Code Generation
| TV | ct_discrepancy_detected | well.errors | target.errors | Covers |
|---|
| TV-001-011 | true | [CONTROL_CTDISC_WELL] | [CONTROL_CTDISC_TARGET] | AC: Both error codes generated |
| TV-001-012 | false | [] | [] | AC: No errors when no discrepancy |
Decision Table: Gap Coverage — Core Detection Scenarios
| TV | Scenario | ct_discrepancy | classification | error_generated | Covers |
|---|
| TV-WDCTC-GAP-001 | Ambiguous classification for Control well | present | Ambiguous | true | AC: Ambiguous CLS triggers discrepancy |
| TV-WDCTC-GAP-002-A | Boundary at CT difference 2.0 — no discrepancy | 2.0 (= threshold) | Positive | false | AC: Boundary at exactly 2.0 passes |
| TV-WDCTC-GAP-002-B | Boundary at CT difference 2.1 — triggers discrepancy | 2.1 (> threshold) | Positive | true | AC: Boundary just above 2.0 triggers |
| TV-WDCTC-GAP-003 | Reversed CT values (pcrai CT > machine CT) | present (reversed) | Positive | true | AC: Absolute value of difference used |
| TV-WDCTC-GAP-004-B | No discrepancy baseline under WDCTC template config | absent | Positive | false | AC: No discrepancy produces no error |
REQ-RULES-WDCTC-002: Max CT Threshold Suppression
Decision Table: Suppression Logic
| TV | max_ct_for_ct_discrepancy | obs.final_ct | ct_discrepancy | error_generated | Covers |
|---|
| TV-002-001 | null | 36 | true | true | AC: Null threshold = disabled |
| TV-002-002 | 35 | 36 | true | false | AC: final_ct > threshold suppresses |
| TV-002-003 | 36 | 36 | true | false | AC: final_ct = threshold suppresses (>=) |
| TV-002-004 | 37 | 36 | true | true | AC: final_ct < threshold = normal |
| TV-002-005 | 35 | 34 | true | true | AC: final_ct below threshold = error |
| TV-002-006 | 40 | 38 | false | false | AC: No discrepancy = no error regardless |
| TV-WDCTC-GAP-004 | enabled | below threshold | false | false | AC: No discrepancy while threshold config enabled |
REQ-RULES-WDCTC-003: Minimum Fluorescence Skip
Decision Table: Fluorescence Skip Logic
Prerequisite: The fluorescence skip only applies when classification is Negative. Non-Negative classifications (Positive, Ambiguous) bypass this check entirely and proceed directly to CT discrepancy evaluation. See WdctcRule.php line 60: finalClsIsNegative() && maxReadingIsLessThanTargetMinFl().
| TV | classification | minimum_fluorescence_to_positive | max(obs.readings) | rule_executed | error_generated | Covers |
|---|
| TV-003-001 | Negative | 100 | 99 | false | false | AC: Neg CLS + max < threshold skips rule |
| TV-003-002 | Negative | 100 | 100 | true | (depends) | AC: Neg CLS + max = threshold evaluates (strict <) |
| TV-003-003 | Negative | 100 | 101 | true | (depends) | AC: Neg CLS + max > threshold evaluates |
| TV-003-004 | Negative | 50 | 49.9 | false | false | AC: Neg CLS + below threshold boundary |
| TV-003-005 | Negative | 50 | 50.1 | true | (depends) | AC: Neg CLS + above threshold boundary |
| TV-WDCTC-GAP-005 | Negative | configured | low fluorescence | true | true | AC: Low fluorescence control well interaction |
| TV-WDCTC-GAP-006 | Negative | configured | low fluorescence (combined) | true | true | AC: Combined low fluorescence and discrepancy |
Combined Scenario Decision Table
This table tests the complete rule execution path with all conditions.
| TV | well.type | max_fluor | fluor_threshold | classification | ct_diff | max_ct_thresh | final_ct | rule_executed | error_generated | Covers |
|---|
| TV-COMB-001 | Patient | 150 | 100 | Positive | 5 | null | 30 | false | false | Well type filter |
| TV-COMB-002 | Control | 99 | 100 | Negative | 5 | null | 30 | false | false | Neg CLS + low fluorescence skip |
| TV-COMB-003 | Control | 99 | 100 | Positive | 5 | null | 30 | true | true | Pos CLS bypasses fluorescence skip |
| TV-COMB-004 | Control | 150 | 100 | Positive | 1.5 | null | 30 | true | false | CT within tolerance |
| TV-COMB-005 | Control | 150 | 100 | Positive | 5 | 35 | 36 | true | false | Suppressed by max_ct |
| TV-COMB-006 | Control | 150 | 100 | Positive | 5 | null | 30 | true | true | Full error path |
| TV-COMB-007 | Control | 150 | 100 | Negative | 5 | null | 30 | true | true | Neg CLS + high fluorescence = evaluate |
Automation Status
| REQ ID | Test Vectors | Automation Status | Notes |
|---|
| REQ-RULES-WDCTC-001 | TV-001-001 to TV-001-012 | Automated | Core detection logic |
| REQ-RULES-WDCTC-002 | TV-002-001 to TV-002-006 | Automated | Suppression threshold |
| REQ-RULES-WDCTC-003 | TV-003-001 to TV-003-005 | Automated | Fluorescence skip |
| Combined | TV-COMB-001 to TV-COMB-007 | Automated | Integration scenarios |
Gap Analysis
Identified Gaps
| Gap | Requirement | Description | Priority | Owner |
|---|
| None | - | All acceptance criteria covered | - | - |
Boundary Value Coverage
| Boundary | Test Vector | Status |
|---|
| CT difference = 2.0 (threshold) | TV-001-008 | Covered |
| CT difference = 2.1 (just above) | TV-001-007 | Covered |
| Fluorescence = threshold | TV-003-002 | Covered |
| Fluorescence just below | TV-003-001, TV-003-004 | Covered |
| final_ct = max_ct_threshold | TV-002-003 | Covered |
| final_ct just above threshold | TV-002-002 | Covered |
| final_ct just below threshold | TV-002-005 | Covered |
Traceability to SRS Tests
| SRS Test | Test Vector | Status |
|---|
| Negative classification + low fluorescence bypasses rule | TV-001-003, TV-003-001, TV-COMB-002 | Mapped |
| Negative classification + high fluorescence evaluates normally | TV-COMB-007 | Mapped |
| CT discrepancy detected | TV-001-006, TV-001-011 | Mapped |
| CT difference within tolerance | TV-001-009 | Mapped |
| Null threshold - normal rule applies | TV-002-001 | Mapped |
| Final CT exceeds threshold - suppressed | TV-002-002 | Mapped |
| Final CT equals threshold - suppressed | TV-002-003 | Mapped |
| Final CT below threshold - normal rule applies | TV-002-004, TV-002-005 | Mapped |
| Max reading below threshold - rule skipped | TV-003-001 | Mapped |
| Max reading meets threshold - rule executes | TV-003-002 | Mapped |