Skip to main content
Version: 3.0.1

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-03-05


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 IDTitlePriorityComplexity
REQ-REANALYZE-001Bypass Rule Processing with SKIP Resolution CodeMustMedium
REQ-REANALYZE-002Display Outcome Messages with Export StatusMustLow
REQ-REANALYZE-003Exclude Resolved Controls from Westgard CalculationsMustHigh
REQ-REANALYZE-004Apply Date-Based Westgard Error PropagationMustHigh
REQ-REANALYZE-005Display Control Status on LJ PlotsMustLow
REQ-REANALYZE-006Select Resolution ProposalsMustMedium
REQ-REANALYZE-007Prevent Conflicting Resolution ProposalsMustMedium
REQ-REANALYZE-008Update Reanalysis Status for Westgard Series ChangesMustHigh
REQ-REANALYZE-009Track Archive Well DependenciesMustMedium
REQ-REANALYZE-010Flag Dependent Runs on Archive Status ChangeMustHigh
REQ-REANALYZE-011Confirm Archive Dependency ReanalysisMustLow
REQ-REANALYZE-012Flag Dependent Runs When Wells EditedMustMedium
REQ-REANALYZE-013Flag Dependent Runs When Wells ResolvedMustMedium
REQ-ANALYZER-002Exclude EXCLUDE-Status Wells from AnalysisMustHigh
REQ-HELP-001Display Context-Sensitive HelpMustLow
REQ-HELP-002Search Help ContentMustLow
REQ-HELP-003Configure Help ItemsMustMedium
REQ-HELP-004Manage Help VideosMustMedium
REQ-HELP-005Import/Export Help ConfigurationMustLow

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

DirectionComponentPurpose
ConsumesRun + WellsRun data with well state
Westgard LimitsControl limits for QC calculations
Resolution CodesConfigured resolution options
Kit ConfigurationRules, error codes, resolution mappings
ProducesRun Status UpdateReanalysis required status
Well State UpdateModified well outcomes
Reanalysis PromptUser notification of required actions
RelatedRUNFILE DomainProvides run and well data
ANALYTICS DomainAnalysis orchestration
Rules EngineRule execution during reanalysis

2. Component Architecture

2.1 Component Diagram

2.2 Component Responsibilities

ComponentFileResponsibilityREQ Trace
RunAnalyseJobJobs/RunAnalyseJob.phpQueue job entry point for run analysis/reanalysisREQ-REANALYZE-*
UpdateRunActionActions/Runs/UpdateRunAction.phpOrchestrates full reanalysis pipelineREQ-REANALYZE-001 through 008
AnalyzerAnalyzer/Analyzer.phpRule execution engine with reanalyze modeREQ-REANALYZE-001, 003, 004
FutureWellAnalyserExecutorAnalyzer/FutureWellAnalyser/FutureWellAnalyserExecutor.phpAnalyzes future runs for Westgard impactREQ-REANALYZE-004, 008
ReAnalyseMarkerAnalyzer/FutureWellAnalyser/ReAnalyseMarker.phpDetects Westgard changes and marks affected runsREQ-REANALYZE-008
UpdateStatusOfAffectedRunsActions/Runs/UpdateStatusOfAffectedRuns.phpUpdates run resolution status for Westgard changesREQ-REANALYZE-008
UpdateReanalyzeStatusOfCombinedRunsActions/Runs/UpdateReanalyzeStatusOfCombinedRuns.phpUpdates status for combined outcome changesREQ-REANALYZE-008
SetArchiveDependentWellsAnalyzer/Rules/Concerns/ArchiveDependentWells/SetArchiveDependentWells.phpCaches cross-run well dependencies during rule executionREQ-REANALYZE-009
UpdateArchiveDependentWellsActions/Runs/UpdateArchiveDependentWells.phpBatch-persists dependency arrays to wells JSON columnREQ-REANALYZE-009
ArchiveDependentRunsUpdaterActions/RunTags/ArchiveDependentRunsUpdater.phpFlags dependent runs on archive status changeREQ-REANALYZE-010
EditedResolvedWellsDependentRunsUpdaterActions/Runs/EditedResolvedWellsDependentRunsUpdater.phpFlags dependent runs on well edit/resolutionREQ-REANALYZE-012, 013
WellAnalyzer/Well.phpWell state with SKIP and resolution handlingREQ-REANALYZE-001, 006
ResolutionCodeResolutionCode.phpResolution code configuration modelREQ-REANALYZE-001, 006
ResolutionCodesControllerHttp/Controllers/ResolutionCodesController.phpResolution code CRUD operationsREQ-REANALYZE-001
PageHelpItemsControllerHttp/Controllers/PageHelpItemsController.phpHelp item retrieval by page contextREQ-HELP-001, 002
GetHelpItemsActionActions/GetHelpItemsAction.phpHelp item query with searchREQ-HELP-001, 002
HelpItemHelpItem.phpHelp item model with page associationsREQ-HELP-001, 002, 003, 005
HelpItemsControllerHttp/Controllers/HelpItemsController.phpHelp item configuration CRUDREQ-HELP-003, 004

3. Data Design

3.1 Entities

This domain reads from and writes to the following entities:

EntityOwnerRead/WriteFields Used
runsRUNFILERead/Writeid, resolution_status, num_pending_resolutions
wellsRUNFILERead/Writeid, error_code_id, resolution_codes, lims_status, export_date, extraction_date
westgard_limitsKITCFGRead/Writeid, in_error, deleted_at, caused_well_id
resolution_codesKITCFGReadresolution_code, lims_status, affected_lims_statuses, level
well_resolutionsREANALYZEWritewell_id, resolution_code_id, status
help_itemsHELPRead/Writetitle, description, pages_available, tags, order, help_video_id
help_videosHELPRead/Writename, 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

EndpointMethodPurposeREQ
/api/runs/{run}/analysePOSTTrigger run reanalysisREQ-REANALYZE-*
/api/wells/{well}PATCHUpdate well resolutionREQ-REANALYZE-006
/api/resolution-codesGETList resolution codesREQ-REANALYZE-001
/api/resolution-codesPOST/PUTConfigure resolution codesREQ-REANALYZE-001
/api/page-help-itemsGETGet help items for page(s)REQ-HELP-001, 002
/api/help-itemsGET/POST/PUT/DELETECRUD help itemsREQ-HELP-003, 004

4.2 Events

EventTriggerPayloadREQ
RunAnalyzeStartedAnalysis begins{ run_id }REQ-REANALYZE-008
RunUpdatedAnalysis completes{ run_id, user }REQ-REANALYZE-008
RunUpdateFailedAnalysis 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 SKIPRule.isReanalyzeRule.hasHandledSKIPResult
truefalsefalseSKIP (bypass rule)
truefalsetrueEXECUTE (already handled)
truetrue*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 ErrorAnalyzed ErrorHas WESTGARDS_MISSEDResult
WG_12SWG_22S*MARK (error changed)
WG_12Snull*MARK (error cleared)
nullWG_12S*MARK (new error)
WG_12SWG_12SfalseNO CHANGE
WG_12SWG_12StrueMARK (missed Westgard)
nullnullfalseNO CHANGE
nullnulltrueMARK (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

ConditionDetectionResponseFallback
No wells to analyzewells.isEmpty()Return early, no changesN/A
Analysis job failsException in handle()Emit RunUpdateFailed, rethrowJob retry (queue)
Resolution conflictConflict detection algorithmReturn error to userPrevent resolution save
Invalid resolution codeCode not in configurationValidation errorReject resolution
S3 video unavailableSigned URL generation failsReturn error messageDisplay without video
Westgard limit not foundSoft-deleted or missingSkip limit processingContinue with others

7. Configuration

SettingSourceDefaultEffectREQ
Resolution code with SKIPresolution_codes.resolution_code-Enables rule bypassREQ-REANALYZE-001
show_resolved_controlsclient_configurationsfalseLJ plot display toggleREQ-REANALYZE-005
help_s3_urlEnvironment-S3 bucket for videosREQ-HELP-004
help_s3_accessEnvironment-S3 access keyREQ-HELP-004
help_s3_secretEnvironment-S3 secret keyREQ-HELP-004
analyzer.max_execution_timeConfig90sMax analysis durationREQ-REANALYZE-*

See Configuration Reference for full documentation.


8. Implementation Mapping

8.1 Code Locations

ComponentPath
RunAnalyseJobJobs/RunAnalyseJob.php
UpdateRunActionActions/Runs/UpdateRunAction.php
AnalyzerAnalyzer/Analyzer.php
FutureWellAnalyserExecutorAnalyzer/FutureWellAnalyser/FutureWellAnalyserExecutor.php
ReAnalyseMarkerAnalyzer/FutureWellAnalyser/ReAnalyseMarker.php
UpdateStatusOfAffectedRunsActions/Runs/UpdateStatusOfAffectedRuns.php
UpdateReanalyzeStatusOfCombinedRunsActions/Runs/UpdateReanalyzeStatusOfCombinedRuns.php
SetArchiveDependentWellsAnalyzer/Rules/Concerns/ArchiveDependentWells/SetArchiveDependentWells.php
UpdateArchiveDependentWellsActions/Runs/UpdateArchiveDependentWells.php
ArchiveDependentRunsUpdaterActions/RunTags/ArchiveDependentRunsUpdater.php
ArchiveDependentWellsRelationArchiveDependentWellsRelation.php
EditedResolvedWellsDependentRunsUpdaterActions/Runs/EditedResolvedWellsDependentRunsUpdater.php
Well (Analyzer)Analyzer/Well.php
ResolutionCodeResolutionCode.php
ResolutionCodesControllerHttp/Controllers/ResolutionCodesController.php
PageHelpItemsControllerHttp/Controllers/PageHelpItemsController.php
GetHelpItemsActionActions/GetHelpItemsAction.php
HelpItemHelpItem.php
HelpItemsControllerHttp/Controllers/HelpItemsController.php

8.2 Requirement Traceability

REQ IDDesign SectionPrimary Code
REQ-REANALYZE-0015.1, 5.2Analyzer.php, Well.php::shouldSkipFromRule()
REQ-REANALYZE-002-Frontend (outcome message display)
REQ-REANALYZE-0035.3Well.php::handleWestgardResolutions()
REQ-REANALYZE-0045.4FutureWellAnalyserExecutor.php
REQ-REANALYZE-005-Frontend (LJ plot rendering)
REQ-REANALYZE-0065.1ResolutionCodesController.php, Well.php
REQ-REANALYZE-0075.5Well.php (conflict detection)
REQ-REANALYZE-0085.4ReAnalyseMarker.php, UpdateStatusOfAffectedRuns.php
REQ-REANALYZE-00910.1.3SetArchiveDependentWells.php, UpdateArchiveDependentWells.php
REQ-REANALYZE-01010.1.4ArchiveDependentRunsUpdater.php
REQ-REANALYZE-01110.1.5RequiredArchivedRunsReanalyze.js
REQ-REANALYZE-01210.2EditedResolvedWellsDependentRunsUpdater.php
REQ-REANALYZE-01310.2EditedResolvedWellsDependentRunsUpdater.php
REQ-ANALYZER-00210.3Analyzer.php, IsAnalyzableWell.php
REQ-HELP-0015.6PageHelpItemsController.php, GetHelpItemsAction.php
REQ-HELP-0025.6GetHelpItemsAction.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

DecisionRationaleAlternatives Considered
Reanalyze as flag on AnalyzerMinimal code duplication, same pipelineSeparate reanalyze job (rejected: too much duplication)
SKIP as meta-resolution codeConfigured in same table, consistent modelHard-coded SKIP logic (rejected: less flexible)
Soft-delete Westgard limitsMaintains audit trail, enables undoHard delete (rejected: loses history)
8-run optimization thresholdBalances thoroughness vs performanceNo limit (rejected: too slow), lower limit (rejected: misses changes)
Help items per-siteMulti-tenant isolationGlobal help (rejected: doesn't support customization)
S3 for video storageScalable, cost-effectiveLocal storage (rejected: not scalable), database BLOB (rejected: performance)

10. v3.0.1 Additions

Version

The following sections document features added in v3.0.1.

10.1 Archive Dependency Tracking (REQ-REANALYZE-009, 010, 011)

10.1.1 Overview

Archive dependency tracking records which wells from previous runs contributed to the analysis of each well in the current run. This enables the system to flag dependent runs for reanalysis when archived run state changes.

Key components:

ComponentFilePurpose
SetArchiveDependentWellsAnalyzer/Rules/Concerns/ArchiveDependentWells/SetArchiveDependentWells.phpAnalyzer concern: records cross-run well dependencies during rule execution
UpdateArchiveDependentWellsActions/Runs/UpdateArchiveDependentWells.phpBatch-persists dependency arrays to wells.archive_dependent_well_ids JSON column
ArchiveDependentRunsUpdaterActions/RunTags/ArchiveDependentRunsUpdater.phpFlags future/history runs when archive status changes
ArchiveDependentWellsRelationArchiveDependentWellsRelation.phpCustom Eloquent relation: resolves JSON ID array to Well models
RequiredArchivedRunsReanalyze.jsviews/run/support/required-reanalyzes/support/Frontend confirmation modal for archive reanalysis

10.1.2 Schema Change

ColumnTableTypePurpose
archive_dependent_well_idswellsJSON (nullable)Stores array of well IDs from other runs used during analysis

Example value: [1, 2, 3, 4, 5, 6]

10.1.3 Dependency Caching Algorithm (REQ-REANALYZE-009)

Algorithm: Cache Archive Dependencies During Rule Execution

Inputs:
- well: Well - Current well being analyzed
- usedWells: WellCollection - Wells from other runs used by the rule

Outputs:
- void (modifies well.archiveDependentWells in memory)

Steps:
1. Filter usedWells: remove wells where getId() == well.getId()
(same-run wells are NOT recorded as archive dependencies)
2. Merge filtered wells into well's existing archive dependency set
3. Register well in ConfigurationRepository for batch persistence

Notes:
- Called by each multi-run rule after it identifies cross-run wells
- Dependencies accumulate across rules (additive, not replacement)
- Persisted after all rules complete via UpdateArchiveDependentWells

Rules that cache archive dependencies (9 rules):

RuleWells CachedTrigger
WG7T6 previous trend wellshasTrendInLatestSevenWellsForWell()
WG7T13S6 previous trend wells + 3SDSame as WG7T
WG22S1 previous SD comparison wellhasSdFromMeanGreaterThanTwoInLatestTwoWellsForWell()
WG22S13S1 previous SD comparison well + 3SDSame as WG22S
WGInErrorWells that caused error statecaused_well_id lookup
WREPMatching previous patient wellgetMatchingObservationForObservation()
ADJ (AdjZika)Previous well for same accession/mixwellsForSameAccession().wellsForSameMix()
PicqualMatching previous patient wellhasMatchingWellForObservation()
Combined OutcomesCross-run wells used for outcomegetWellsForAssociateForCombinedOutcome() filter by different run

10.1.4 Archive Status Change Algorithm (REQ-REANALYZE-010)

Algorithm: Flag Dependent Runs on Archive Status Change

Inputs:
- affectedRunIds: Collection - Run IDs whose archive tag changed

Outputs:
- void (updates resolution_status on dependent runs)

Steps:
1. IF affectedRunIds is empty: RETURN

2. Update future runs (runs that depend on archived wells):
a. Collect well IDs from affected runs
b. Find runs whose wells have any of these IDs in archive_dependent_well_ids
c. Set resolution_status = "Results for wells in this run may be
affected by recently archived runs. Reanalysis optional."

3. Update history runs (runs used by archived wells):
a. Collect archive_dependent_well_ids from affected runs' wells
b. Find runs containing those wells
c. Set same resolution_status

Notes:
- Only direct dependencies are flagged (no transitive propagation)
- Triggered by StoreRunTagsAction when archive tag is applied/removed
- Both archive and unarchive trigger the check

Resolution status message: "Results for wells in this run may be affected by recently archived runs. Reanalysis optional."

10.1.5 User Confirmation (REQ-REANALYZE-011)

The frontend confirmation modal follows the same UX pattern as existing Westgard and Missing Mixes reanalysis prompts:

  1. User opens run with archive-dependency resolution status
  2. RequiredReanalyzes.js detects the status string and delegates to RequiredArchivedRunsReanalyze.js
  3. Modal displays: "Results for wells in this run may be affected by recently archived runs. Would you like to re-analyze the run to apply them?"
  4. If confirmed: audit message = "This run was re-analysed following changes to archived run dependencies."
  5. If declined: run remains in current state

10.1.6 Data Flow


10.2 Edited/Resolved Wells Reanalysis (REQ-REANALYZE-012, 013)

10.2.1 Overview

Extends the archive dependency infrastructure (Section 10.1) with two additional reanalysis triggers: well editing and well resolution. Reuses the same archive_dependent_well_ids column for dependency lookups.

Key components:

ComponentFilePurpose
EditedResolvedWellsDependentRunsUpdaterActions/Runs/EditedResolvedWellsDependentRunsUpdater.phpFlags dependent runs for edited/resolved wells
RequiredEditedWellsReanalyze.jsviews/run/support/required-reanalyzes/support/Frontend confirmation modal for edited wells
RequiredResolvedWellsReanalyze.jsviews/run/support/required-reanalyzes/support/Frontend confirmation modal for resolved wells

10.2.2 Integration Points

TriggerIntegration ClassMethodCondition
Well editUpdateRunActionupdateDependentRunsForEditedWells()Only when role_alias is in modifiedProperties
Well resolutionSetResolutionCodesToWellsActionupdateDependentRunsForResolvedWells()After resolution codes are persisted and well events stored

Critical constraint: Only role_alias changes trigger edited-wells reanalysis. Changes to other well properties (accession, extraction_date, etc.) do NOT trigger reanalysis because they do not affect which wells are used during analysis.

10.2.3 Algorithm

Algorithm: Flag Dependent Runs for Edited/Resolved Wells

Inputs:
- wellIds: Collection - IDs of wells that were edited or resolved
- resolutionStatus: string - Status message (edited vs resolved variant)

Outputs:
- void (updates resolution_status on dependent runs)

Steps:
1. IF wellIds is empty: RETURN

2. Flag future runs:
- Find runs whose wells have any wellId in archive_dependent_well_ids
- Set resolution_status to the provided message

3. Flag history runs:
- Collect archive_dependent_well_ids from the modified wells
- Find runs containing those referenced wells
- Set resolution_status to the provided message

Notes:
- Pattern is identical to ArchiveDependentRunsUpdater (Section 10.1.4)
- Two distinct resolution status messages differentiate the triggers

Resolution status messages:

TriggerMessage
Edited wells"Results for wells in this run may be affected by recently edited wells. Reanalysis required."
Resolved wells"Results for wells in this run may be affected by recently resolved wells. Reanalysis required."

10.2.4 Comparison with Archive Dependencies

PropertyArchiveEdited WellsResolved Wells
TriggerArchive tag changedrole_alias editedResolution codes applied
UpdaterArchiveDependentRunsUpdaterEditedResolvedWellsDependentRunsUpdaterSame class, different method
Called fromStoreRunTagsActionUpdateRunActionSetResolutionCodesToWellsAction
Infrastructurearchive_dependent_well_idsSameSame

10.3 EXCLUDE LIMS Status Well Filtering (REQ-ANALYZER-002)

10.3.1 Overview

Wells with lims_status = 'EXCLUDE' are filtered from analyzer rule evaluation at two layers. Wells with RPT and RXT statuses participate normally. This section documents the implementation detail of the two classification methods and two-phase filtering pattern.

10.3.2 Classification Methods

MethodReturns true whenUsed by
limsStatusIsExcluded()lims_status == 'EXCLUDE'6 core multi-run rules (WREP, Picqual, Picquant, Sbcheck, Rbact, AdjZika)
hasExclusiveLimsStatus()lims_status IN ('EXCLUDE', 'RPT', 'RXT')Combined outcome concern classes (pre-existing broader filter)

Both methods are implemented on:

  • app/IsAnalyzableWell.php (trait)
  • app/Analyzer/Well.php (analyzer model)

Bug fix (v3.0.1): The original limsStatusIsExcluded() had || logic that caused it to return true for any non-null lims_status. Corrected to check specifically for lims_status == 'EXCLUDE'.

10.3.3 Two-Phase Filtering Pattern

Each multi-run rule follows a cache-then-filter pattern:

Phase 1: Cache archive dependencies (ALL wells, including EXCLUDE)
- Record dependency via SetArchiveDependentWells
- This ensures archive tracking is complete

Phase 2: Filter EXCLUDE wells before analysis
- Check matchingWell.limsStatusIsExcluded()
- If true: treat as "no valid match", return early
- If false: proceed with normal rule logic

Layer 1 (Main Analyzer): Analyzer.php line 33 — rejects EXCLUDE wells from the current run before any rules execute:

$wells = $wells->reject(fn ($well) => $well->limsStatusIsExcluded());

Layer 2 (Per-Rule): Each of 6 rules applies the two-phase pattern to historical wells from previous runs.

10.3.4 Rules Affected

RuleFiltering Approach
WREPCache matching well, filter if EXCLUDE, skip comparison
PicqualCache matching well, filter if EXCLUDE, skip IC check
PicquantCache matching well, filter if EXCLUDE, treat as first-run
SbcheckCache BACT well, filter if EXCLUDE, treat as no-match
RbactCache all matching wells, reject->limsStatusIsExcluded() for analysis
AdjZikaCache matching well, filter if EXCLUDE, proceed with normal execution

10.4 Updated Requirements Covered

REQ IDTitleDesign SectionPrimary Code
REQ-REANALYZE-009Track Archive Well Dependencies10.1.3SetArchiveDependentWells.php, UpdateArchiveDependentWells.php
REQ-REANALYZE-010Flag Dependent Runs on Archive Change10.1.4ArchiveDependentRunsUpdater.php
REQ-REANALYZE-011Confirm Archive Dependency Reanalysis10.1.5RequiredArchivedRunsReanalyze.js
REQ-REANALYZE-012Flag Dependent Runs When Wells Edited10.2EditedResolvedWellsDependentRunsUpdater.php
REQ-REANALYZE-013Flag Dependent Runs When Wells Resolved10.2EditedResolvedWellsDependentRunsUpdater.php
REQ-ANALYZER-002Exclude EXCLUDE-Status Wells10.3Analyzer.php, IsAnalyzableWell.php, 6 rule files

10.5 Updated Resolution Status Values

The ResolutionStatus interface (Section 3.2) gains three new status strings in v3.0.1:

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.'
// v3.0.1 additions:
| 'Results for wells in this run may be affected by recently archived runs. Reanalysis optional.'
| 'Results for wells in this run may be affected by recently edited wells. Reanalysis required.'
| 'Results for wells in this run may be affected by recently resolved wells. Reanalysis required.';
}

DocumentRelevant Sections
SRS: reanalyze.mdRequirements source (REQ-REANALYZE-*)
SRS: analyzer.mdRequirements source (REQ-ANALYZER-002)
SRS: help.mdRequirements source (REQ-HELP-*)
SDS: Architecture OverviewSystem context
SDS: Data ArchitectureEntity relationships
SDS: Rules EngineRule execution framework
SDS: Westgard RulesWestgard rule implementation
SDS: Combined OutcomesCross-run association guard (v3.0.1)
SDS: Database Referencewells.archive_dependent_well_ids schema
SDS: Configuration ReferenceResolution and help settings