Reanalyze Domain Design
Document Type: Domain Design (Tier 2) Domain: REANALYZE + HELP Domain Character: Algorithmic SRS Reference: reanalyze.md, help.md Status: Draft Last Updated: 2026-01-25
1. Overview
1.1 Purpose
The Reanalyze domain manages the reanalysis of PCR run results after initial processing, enabling users to define final well outcomes while maintaining quality control integrity. This domain also encompasses the context-sensitive help system that assists users throughout the application.
Key capabilities:
- Trigger reanalysis based on user actions or system state changes
- Apply SKIP resolution codes to bypass rule processing
- Manage Westgard control exclusions and their downstream effects
- Detect and propagate reanalysis requirements across affected runs
- Provide context-sensitive help content based on current screen
1.2 Requirements Covered
| REQ ID | Title | Priority | Complexity |
|---|---|---|---|
| REQ-REANALYZE-001 | Bypass Rule Processing with SKIP Resolution Code | Must | Medium |
| REQ-REANALYZE-002 | Display Outcome Messages with Export Status | Must | Low |
| REQ-REANALYZE-003 | Exclude Resolved Controls from Westgard Calculations | Must | High |
| REQ-REANALYZE-004 | Apply Date-Based Westgard Error Propagation | Must | High |
| REQ-REANALYZE-005 | Display Control Status on LJ Plots | Must | Low |
| REQ-REANALYZE-006 | Select Resolution Proposals | Must | Medium |
| REQ-REANALYZE-007 | Prevent Conflicting Resolution Proposals | Must | Medium |
| REQ-REANALYZE-008 | Update Reanalysis Status for Westgard Series Changes | Must | High |
| REQ-HELP-001 | Display Context-Sensitive Help | Must | Low |
| REQ-HELP-002 | Search Help Content | Must | Low |
| REQ-HELP-003 | Configure Help Items | Must | Medium |
| REQ-HELP-004 | Manage Help Videos | Must | Medium |
| REQ-HELP-005 | Import/Export Help Configuration | Must | Low |
1.3 Constraints
Tier 2 Constraint: This document describes ownership, patterns, and design rationale. It links to reference docs for full schemas.
1.4 Dependencies
| Direction | Component | Purpose |
|---|---|---|
| Consumes | Run + Wells | Run data with well state |
| Westgard Limits | Control limits for QC calculations | |
| Resolution Codes | Configured resolution options | |
| Kit Configuration | Rules, error codes, resolution mappings | |
| Produces | Run Status Update | Reanalysis required status |
| Well State Update | Modified well outcomes | |
| Reanalysis Prompt | User notification of required actions | |
| Related | RUNFILE Domain | Provides run and well data |
| ANALYTICS Domain | Analysis orchestration | |
| Rules Engine | Rule execution during reanalysis |
2. Component Architecture
2.1 Component Diagram
2.2 Component Responsibilities
| Component | File | Responsibility | REQ Trace |
|---|---|---|---|
RunAnalyseJob | Jobs/RunAnalyseJob.php | Queue job entry point for run analysis/reanalysis | REQ-REANALYZE-* |
UpdateRunAction | Actions/Runs/UpdateRunAction.php | Orchestrates full reanalysis pipeline | REQ-REANALYZE-001 through 008 |
Analyzer | Analyzer/Analyzer.php | Rule execution engine with reanalyze mode | REQ-REANALYZE-001, 003, 004 |
FutureWellAnalyserExecutor | Analyzer/FutureWellAnalyser/FutureWellAnalyserExecutor.php | Analyzes future runs for Westgard impact | REQ-REANALYZE-004, 008 |
ReAnalyseMarker | Analyzer/FutureWellAnalyser/ReAnalyseMarker.php | Detects Westgard changes and marks affected runs | REQ-REANALYZE-008 |
UpdateStatusOfAffectedRuns | Actions/Runs/UpdateStatusOfAffectedRuns.php | Updates run resolution status for Westgard changes | REQ-REANALYZE-008 |
UpdateReanalyzeStatusOfCombinedRuns | Actions/Runs/UpdateReanalyzeStatusOfCombinedRuns.php | Updates status for combined outcome changes | REQ-REANALYZE-008 |
Well | Analyzer/Well.php | Well state with SKIP and resolution handling | REQ-REANALYZE-001, 006 |
ResolutionCode | ResolutionCode.php | Resolution code configuration model | REQ-REANALYZE-001, 006 |
ResolutionCodesController | Http/Controllers/ResolutionCodesController.php | Resolution code CRUD operations | REQ-REANALYZE-001 |
PageHelpItemsController | Http/Controllers/PageHelpItemsController.php | Help item retrieval by page context | REQ-HELP-001, 002 |
GetHelpItemsAction | Actions/GetHelpItemsAction.php | Help item query with search | REQ-HELP-001, 002 |
HelpItem | HelpItem.php | Help item model with page associations | REQ-HELP-001, 002, 003, 005 |
HelpItemsController | Http/Controllers/HelpItemsController.php | Help item configuration CRUD | REQ-HELP-003, 004 |
3. Data Design
3.1 Entities
This domain reads from and writes to the following entities:
| Entity | Owner | Read/Write | Fields Used |
|---|---|---|---|
runs | RUNFILE | Read/Write | id, resolution_status, num_pending_resolutions |
wells | RUNFILE | Read/Write | id, error_code_id, resolution_codes, lims_status, export_date, extraction_date |
westgard_limits | KITCFG | Read/Write | id, in_error, deleted_at, caused_well_id |
resolution_codes | KITCFG | Read | resolution_code, lims_status, affected_lims_statuses, level |
well_resolutions | REANALYZE | Write | well_id, resolution_code_id, status |
help_items | HELP | Read/Write | title, description, pages_available, tags, order, help_video_id |
help_videos | HELP | Read/Write | name, url, site_id |
See Database Reference for full schema.
3.2 Reanalysis State
interface ReanalysisContext {
run: Run;
wells: Well[];
originalWells: Well[]; // Snapshot before analysis
// Westgard tracking
westgardChangedWells: Well[];
runsToReanalyzeForWestgards: string[];
runsToReanalyzeForCombinedOutcomes: string[];
runsToReanalyzeForMissingMixes: string[];
// Resolution tracking
wellResolutions: WellResolution[];
pendingResolutions: Resolution[];
}
interface ResolutionStatus {
status: 'No Resolution'
| 'Reanalysis required (Westgard)'
| 'Reanalysis required (Missing mixes uploaded)'
| 'Results for wells in this run may be affected by recently uploaded runs. Reanalysis optional.';
}
3.3 Help Configuration
interface HelpItem {
id: string;
title: string;
description: string;
pages_available: number[]; // Page IDs
tags: string[]; // Searchable keywords
order: number;
help_video_id: string | null;
site_id: string;
}
interface HelpVideo {
id: string;
name: string;
url: string; // S3 signed URL
site_id: string;
}
4. Interface Design
4.1 APIs Provided
| Endpoint | Method | Purpose | REQ |
|---|---|---|---|
/api/runs/{run}/analyse | POST | Trigger run reanalysis | REQ-REANALYZE-* |
/api/wells/{well} | PATCH | Update well resolution | REQ-REANALYZE-006 |
/api/resolution-codes | GET | List resolution codes | REQ-REANALYZE-001 |
/api/resolution-codes | POST/PUT | Configure resolution codes | REQ-REANALYZE-001 |
/api/page-help-items | GET | Get help items for page(s) | REQ-HELP-001, 002 |
/api/help-items | GET/POST/PUT/DELETE | CRUD help items | REQ-HELP-003, 004 |
4.2 Events
| Event | Trigger | Payload | REQ |
|---|---|---|---|
RunAnalyzeStarted | Analysis begins | { run_id } | REQ-REANALYZE-008 |
RunUpdated | Analysis completes | { run_id, user } | REQ-REANALYZE-008 |
RunUpdateFailed | Analysis fails | { run_id, error } | - |
5. Behavioral Design
5.1 Reanalysis Trigger Algorithm (REQ-REANALYZE-001, 003, 004, 008)
Algorithm: Execute Run Reanalysis
Inputs:
- run: Run - The run to reanalyze
- user: User - User triggering reanalysis
- editedWells: Well[] | null - Optional subset of wells edited
Outputs:
- void (modifies run and well state, updates affected runs)
Assumptions:
- Run exists and is accessible
- User has permission to trigger reanalysis
- Configuration is loaded for the run's site
Steps:
1. Load run with site context
2. Collect wells to analyze:
a. IF editedWells provided: merge with unedited wells from run
b. ELSE: load all wells from run
3. Load observations for wells
4. Capture original extraction dates for change tracking
5. Normalize wells and observations (apply configuration mappings)
6. Execute analysis:
a. Filter out exported wells (hasExportDate = true)
b. Filter out EXCLUDE wells (limsStatus = 'EXCLUDE')
c. Handle Westgard resolutions on remaining wells
d. Execute rules in precedence order with reanalyze flag enabled
e. Execute Westgard rules for future runs (detect propagation)
7. Summarize results (update run/mix/target counts)
8. Persist updates:
a. Update run (status, modified_user)
b. Update or create run targets
c. Update or create run mixes
d. Batch update wells
e. Batch update observations
9. Update reanalysis status of affected runs:
a. Combined outcome associations
b. Association removals
c. Westgard propagation
10. Store new/removed Westgard limits
11. Emit RunUpdated event
Notes:
- Wells with export dates are preserved but not re-analyzed
- EXCLUDE wells are removed from analysis but kept for counts
- Westgard resolution handling may soft-delete Westgard limits
5.2 SKIP Resolution Algorithm (REQ-REANALYZE-001)
Algorithm: Check SKIP Resolution
Inputs:
- well: Well - The well being evaluated
- rule: Rule - The current rule being executed
Outputs:
- bool - Whether to skip rule execution for this well
Assumptions:
- Well has resolution codes populated
- Rule has not already handled SKIP
Steps:
1. IF rule.hasHandledSKIP(): RETURN false
2. skipCodes = well.getUnitResolutionCodes()
3. IF 'SKIP' IN skipCodes AND NOT rule.isReanalyze():
RETURN true
4. RETURN false
Notes:
- SKIP only applies during initial analysis, not reanalysis
- Once a rule handles SKIP, subsequent rules see hasHandledSKIP = true
- SKIP is a meta-resolution that bypasses all subsequent rules
5.2.1 SKIP Decision Logic
| Well Has SKIP | Rule.isReanalyze | Rule.hasHandledSKIP | Result |
|---|---|---|---|
| true | false | false | SKIP (bypass rule) |
| true | false | true | EXECUTE (already handled) |
| true | true | * | EXECUTE (reanalyze mode) |
| false | * | * | EXECUTE |
Precedence: Evaluated before rule execution. Default: Rules execute normally when no SKIP code present. Unreachable: None.
5.3 Westgard Resolution Algorithm (REQ-REANALYZE-003, 004)
Algorithm: Handle Westgard Resolutions
Inputs:
- well: Well - Control well with potential Westgard resolutions
- config: ConfigurationRepository - Access to Westgard limits
Outputs:
- void (modifies Westgard limit state)
Assumptions:
- Well has been matched to a run mix
- Westgard limits are loaded in configuration
Steps:
1. IF NOT well.hasWestgardResolutions():
a. Revert caused Westgard limits:
- westgardLimits = config.getWestgardLimitCausedByWell(well)
- FOR EACH limit: set deleted_at = now()
b. RETURN
2. Resolve Westgard errors on observations:
FOR EACH observation IN well.getObservations():
observation.handleResolvedWestgardError(config)
Notes:
- Resolving a control soft-deletes its Westgard limits
- Soft-deletion triggers reanalysis of downstream runs
- Date-based propagation is handled by FutureWellAnalyserExecutor
5.4 Future Run Impact Detection Algorithm (REQ-REANALYZE-004, 008)
Algorithm: Detect Future Run Westgard Impact
Inputs:
- otherRunsWells: Well[] - Wells from other runs (same sample names)
- sameRunWells: Well[] - Wells from current run
- minExtractionDate: Date - Earliest date to consider
Outputs:
- void (marks affected runs for reanalysis)
Assumptions:
- Wells are sorted by extraction date
- Westgard rules are configured
Steps:
1. Get run mixes and targets from otherRunsWells
2. Filter future wells (extraction_date >= minExtractionDate)
3. Group future wells by run_id
4. Initialize nonChangedRunCount = 0
5. FOR EACH run IN future runs (ordered by extraction date):
a. Clone wells as originalWells (snapshot before analysis)
b. Remove post-Westgard errors from wells
c. Execute Westgard rules on wells
d. Compare original vs analyzed Westgard status:
- IF Westgard error code changed: mark run for reanalysis
- IF WESTGARDS_MISSED error appears: mark run for reanalysis
e. IF run marked for reanalysis:
- config.addRunsToReanalyzeForWestgards(runId)
- nonChangedRunCount = 0
f. ELSE:
- nonChangedRunCount++
g. IF nonChangedRunCount >= 8: BREAK (optimization)
Notes:
- Stops after 8 consecutive unchanged runs (diminishing returns)
- Uses extraction date as primary ordering, run creation as secondary
- Soft-deleted Westgard limits affect downstream calculations
5.4.1 Westgard Change Detection Logic
| Original Error | Analyzed Error | Has WESTGARDS_MISSED | Result |
|---|---|---|---|
| WG_12S | WG_22S | * | MARK (error changed) |
| WG_12S | null | * | MARK (error cleared) |
| null | WG_12S | * | MARK (new error) |
| WG_12S | WG_12S | false | NO CHANGE |
| WG_12S | WG_12S | true | MARK (missed Westgard) |
| null | null | false | NO CHANGE |
| null | null | true | MARK (missed Westgard) |
Precedence: Evaluated per-run in extraction date order. Default: No reanalysis marked if no changes detected. Unreachable: None.
5.5 Resolution Conflict Detection Algorithm (REQ-REANALYZE-007)
Algorithm: Detect Resolution Conflicts
Inputs:
- control: Well - Control proposing resolution
- proposedResolution: Resolution - Resolution being proposed
- affectedPatientWells: Well[] - Patient wells affected by resolution
Outputs:
- ConflictError | null - Error if conflict exists
Assumptions:
- Resolution codes are configured with affected well types
- Pending resolutions are tracked per well
Steps:
1. FOR EACH patientWell IN affectedPatientWells:
a. pendingResolutions = patientWell.getPendingResolutions()
b. FOR EACH pending IN pendingResolutions:
- IF pending.controlId != control.id:
- RETURN ConflictError("Patient well has pending resolution from another control")
2. RETURN null (no conflicts)
Notes:
- Conflict detection occurs before resolution is saved
- In two-step workflows, detection occurs at proposal time
- In one-step workflows, detection occurs before save
5.6 Help Item Retrieval Algorithm (REQ-HELP-001, 002)
Algorithm: Get Help Items for Page
Inputs:
- user: User - Authenticated user
- pages: number[] | null - Page IDs to filter by
- search: string | null - Search query
Outputs:
- HelpItem[] - Matching help items
Assumptions:
- User is authenticated with logged_in_site_id
- Help items are configured for the site
Steps:
1. Build query for help_items table:
- Filter by site_id = user.logged_in_site_id
- IF search provided:
- Add LIKE filter on title, description, tags
2. Load help video relationships
3. Filter by pages:
- IF pages provided:
- Keep items where pages_available intersects pages
- ELSE: keep all items
4. Transform results:
- Add signed video URLs for items with videos
- Map page IDs to page names
5. RETURN transformed items
Notes:
- Tags are searchable but not displayed to non-admin users
- Video URLs are signed for secure access
- Order field determines display sequence
6. Error Handling
| Condition | Detection | Response | Fallback |
|---|---|---|---|
| No wells to analyze | wells.isEmpty() | Return early, no changes | N/A |
| Analysis job fails | Exception in handle() | Emit RunUpdateFailed, rethrow | Job retry (queue) |
| Resolution conflict | Conflict detection algorithm | Return error to user | Prevent resolution save |
| Invalid resolution code | Code not in configuration | Validation error | Reject resolution |
| S3 video unavailable | Signed URL generation fails | Return error message | Display without video |
| Westgard limit not found | Soft-deleted or missing | Skip limit processing | Continue with others |
7. Configuration
| Setting | Source | Default | Effect | REQ |
|---|---|---|---|---|
| Resolution code with SKIP | resolution_codes.resolution_code | - | Enables rule bypass | REQ-REANALYZE-001 |
show_resolved_controls | client_configurations | false | LJ plot display toggle | REQ-REANALYZE-005 |
help_s3_url | Environment | - | S3 bucket for videos | REQ-HELP-004 |
help_s3_access | Environment | - | S3 access key | REQ-HELP-004 |
help_s3_secret | Environment | - | S3 secret key | REQ-HELP-004 |
analyzer.max_execution_time | Config | 90s | Max analysis duration | REQ-REANALYZE-* |
See Configuration Reference for full documentation.
8. Implementation Mapping
8.1 Code Locations
| Component | Path |
|---|---|
| RunAnalyseJob | Jobs/RunAnalyseJob.php |
| UpdateRunAction | Actions/Runs/UpdateRunAction.php |
| Analyzer | Analyzer/Analyzer.php |
| FutureWellAnalyserExecutor | Analyzer/FutureWellAnalyser/FutureWellAnalyserExecutor.php |
| ReAnalyseMarker | Analyzer/FutureWellAnalyser/ReAnalyseMarker.php |
| UpdateStatusOfAffectedRuns | Actions/Runs/UpdateStatusOfAffectedRuns.php |
| UpdateReanalyzeStatusOfCombinedRuns | Actions/Runs/UpdateReanalyzeStatusOfCombinedRuns.php |
| Well (Analyzer) | Analyzer/Well.php |
| ResolutionCode | ResolutionCode.php |
| ResolutionCodesController | Http/Controllers/ResolutionCodesController.php |
| PageHelpItemsController | Http/Controllers/PageHelpItemsController.php |
| GetHelpItemsAction | Actions/GetHelpItemsAction.php |
| HelpItem | HelpItem.php |
| HelpItemsController | Http/Controllers/HelpItemsController.php |
8.2 Requirement Traceability
| REQ ID | Design Section | Primary Code |
|---|---|---|
| REQ-REANALYZE-001 | 5.1, 5.2 | Analyzer.php, Well.php::shouldSkipFromRule() |
| REQ-REANALYZE-002 | - | Frontend (outcome message display) |
| REQ-REANALYZE-003 | 5.3 | Well.php::handleWestgardResolutions() |
| REQ-REANALYZE-004 | 5.4 | FutureWellAnalyserExecutor.php |
| REQ-REANALYZE-005 | - | Frontend (LJ plot rendering) |
| REQ-REANALYZE-006 | 5.1 | ResolutionCodesController.php, Well.php |
| REQ-REANALYZE-007 | 5.5 | Well.php (conflict detection) |
| REQ-REANALYZE-008 | 5.4 | ReAnalyseMarker.php, UpdateStatusOfAffectedRuns.php |
| REQ-HELP-001 | 5.6 | PageHelpItemsController.php, GetHelpItemsAction.php |
| REQ-HELP-002 | 5.6 | GetHelpItemsAction.php, HelpItemQueryBuilder.php |
| REQ-HELP-003 | - | HelpItemsController.php |
| REQ-HELP-004 | - | HelpItemsController.php, HelpVideo.php |
| REQ-HELP-005 | - | HelpItemsExport.php, HelpItemsImportSheet.php |
9. Design Decisions
| Decision | Rationale | Alternatives Considered |
|---|---|---|
| Reanalyze as flag on Analyzer | Minimal code duplication, same pipeline | Separate reanalyze job (rejected: too much duplication) |
| SKIP as meta-resolution code | Configured in same table, consistent model | Hard-coded SKIP logic (rejected: less flexible) |
| Soft-delete Westgard limits | Maintains audit trail, enables undo | Hard delete (rejected: loses history) |
| 8-run optimization threshold | Balances thoroughness vs performance | No limit (rejected: too slow), lower limit (rejected: misses changes) |
| Help items per-site | Multi-tenant isolation | Global help (rejected: doesn't support customization) |
| S3 for video storage | Scalable, cost-effective | Local storage (rejected: not scalable), database BLOB (rejected: performance) |
10. Related Documents
| Document | Relevant Sections |
|---|---|
| SRS: reanalyze.md | Requirements source (REQ-REANALYZE-*) |
| SRS: help.md | Requirements source (REQ-HELP-*) |
| SDS: Architecture Overview | System context |
| SDS: Data Architecture | Entity relationships |
| SDS: Rules Engine | Rule execution framework |
| SDS: Westgard Rules | Westgard rule implementation |
| SDS: Configuration Reference | Resolution and help settings |