Rule Catalog
Every diagnostic emitted by adsmd validate carries a rule identifier, shown as adsmd::R<n> in the terminal report. This page lists what each rule checks, why, and how to fix a finding.
adsmd has 38 rule identifiers: R0 for parse errors and the 37 checks below. The numbering is not contiguous (R4, R15 to R19, R27 and R44 are not used). adsmd rules prints the same list from the binary.
INFO
A given R<n> always refers to the same check. The id is what --rule and .adsmd.toml accept, and it appears in JSON output as a number (R6 is "rule_id": 6).
Severities and exit codes
| Severity | Meaning | Effect on the exit code of validate |
|---|---|---|
error | The engine fails on this input, or it runs on inputs that are not the ones intended | 2, unless --exit-on never |
warning | Suspicious, not fatal to the engine; needs human review | 0 by default; 1 with --exit-on warning or --exit-on info |
info | Cleanup and awareness hints | 0 by default; 1 with --exit-on info |
The severities below are the built-in ones. A project can switch a rule off or change its severity in .adsmd.toml; R0 cannot be changed.
| Severity | Rules |
|---|---|
error | R0, R1, R2 (missing directory), R3, R5, R6, R7, R9, R11, R12, R22, R23, R25, R28, R34, R35, R36, R37, R39, R40, R42, R43 |
warning | R2 (missing Input/), R8, R10, R14, R20, R21, R24, R26, R31, R38, R41 |
info | R13, R29, R30, R32, R33, R45 |
Cross-reference network
Rules drawn as edges between the files they connect. Arrows point from the file that holds a reference to the file that owns the name; dashed self-loops are checks inside one file.
R0 is not shown; it can fire on any parsed file.
R0: Parse error
| Severity | error |
|---|---|
| File family | any parsed file |
| Source | adsmd-parsers::ParseError::to_diagnostic |
Reported when a parser cannot produce a typed value for a file. Causes:
- a header keyword or a required label (
Truncation_probability,Curve_Name, …) is missing or in the wrong position; - a token cannot be parsed as the expected number type;
- the file ends partway through a row;
- a quoted string is not closed, or a required
key=valueentry is missing; Coded_Steps NinProcedures.txtdoes not match the number of rows that follow.
A parse error stops the parser of that file only. The file is absent from the manifest, rules that need it have nothing to check, and all other rules still run. R0 is always kept by --rule and cannot be configured in .adsmd.toml.
TIP
On BV4 this fires once, on SystemReliability.txt: the file declares System_Reliability 0 and then lists 14 rows. See the tutorial.
R1: ZiniADS input-deck resolves
| Severity | error |
|---|---|
| File | ZiniADS.txt |
| Source | adsmd-validate::rules::r1_input_deck_exists |
Reports an error when the input-deck path does not exist as written. When a file with the same name exists next to ZiniADS.txt (<dir-of-ZiniADS>/<basename>), the message names it and the fix hint gives the corrected line. The rule does not run when the project has no ZiniADS.txt.
Example: input-deck points into Input/ while the deck is in the project root
adsmd::R1
x input-deck path `…/tests/BV4/Input/BV4.i` does not exist; a file with the same name was found at `…/tests/
| BV4/BV4.i`
,-[…/tests/BV4/ZiniADS.txt:2:1]
1 | project-dir=…/tests/BV4
2 | input-deck=…/tests/BV4/Input/BV4.i
: ^^^^^^^^^^
`----
help: update ZiniADS.txt: `input-deck=…/tests/BV4/BV4.i`R2: ZiniADS project-dir layout
| Severity | error (not a directory) / warning (no Input/) |
|---|---|
| File | ZiniADS.txt |
| Source | adsmd-validate::rules::r2_project_dir_layout |
Checks the project-dir value of ZiniADS.txt: it must be an existing directory (error otherwise) and it should contain Input/ (warning otherwise). The rule does not run when the project has no ZiniADS.txt.
R3: Truncation bounds
| Severity | error |
|---|---|
| File | Input/Scheduler/ZCtrlPar.txt |
| Source | adsmd-validate::rules::r3_truncation_bounds |
Truncation_probability must be in (0, 1]; Truncation_time must be > 0. NaN fails both checks.
A file with the two lines swapped is reported by R0, because adsmd verifies the labels. R3 covers the case where the labels are correct and a value is out of range.
R5: Hydraulic channel cards are 9-digit RELAP5 numbers
| Severity | error |
|---|---|
| File | Input/System/RELAP5_channels.txt |
| Source | adsmd-validate::rules::r5_card_number_format |
Control_volume and Control_junction rows reference deck cards by 9-digit numbers. A card number outside [100000000, 999999999] does not resolve in the deck. The other sections (trips, interactive controls, heat structures, control variables) use shorter numbers and are not checked.
R6: Channel symbols are unique within a section
| Severity | error |
|---|---|
| File | Input/System/RELAP5_channels.txt |
| Source | adsmd-validate::rules::r6_channel_symbol_uniqueness |
Channel symbols (HV_204, HJ_527, CV_002, …) are referenced by name from other files, so a duplicate inside one section is ambiguous. All seven sections are checked. The diagnostic carries a related span that points at the first occurrence. The same symbol in two different sections is allowed.
R7: ControlPanel parameter channel symbols resolve
| Severity | error |
|---|---|
| Files | Input/Indicators/ControlPanel.txt ↔ Input/System/RELAP5_channels.txt |
| Source | adsmd-validate::rules::r7_parameter_channel_xref |
Every Control_Panel_Parameter row names a channel (HV_*, HJ_*, CV_*, …) that must be declared in some section of RELAP5_channels.txt. With a typo here the indicator is never updated. Up to three similar channel symbols are attached as "did you mean" related spans. Component-state rows are not checked by this rule.
R8: ControlPanel parameter display kinds are recognized
| Severity | warning |
|---|---|
| File | Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r8_parameter_display_kind |
The third token of each Control_Panel_Parameter row is a display kind. Recognized kinds (case-sensitive):
Value, Liquid_Temperature, Vapor_Temperature, Saturation_Temperature, Pressure, Mass_Flow_Rate, Liquid_Velocity, Vapor_Velocity, Boron_Density, Quality, Flow_Regime.
The list is built into adsmd, which is why an unknown kind is a warning and not an error.
R9: SPDS entries reference existing ControlPanel parameters
| Severity | error |
|---|---|
| Files | Input/Indicators/SPDS_input.txt ↔ Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r9_spds_parameter_xref |
SPDS_input.txt rows have the form <spds_name> <parameter_name> ..., and parameter_name must match the display_name of a Control_Panel_Parameter row. With a typo the SPDS indicator never updates.
R10: HW reliability x_symbol is an IE action symbol
| Severity | warning |
|---|---|
| Files | Input/HardwareReliability/SystemReliability.txt ↔ Input/System/Initiating_Event.txt |
| Source | adsmd-validate::rules::r10_hw_x_symbol_in_ie |
Each row in SystemReliability.txt declares an x_symbol (column 2). R10 warns when that symbol is not the action_symbol (column 4) of any Initiating_Event.txt row.
The engine resolves this symbol against the ControlPanel controls (Control_Panel_Controller and Controls_Panel_Fine_Adjust rows), not against the initiating events, and no adsmd rule checks that lookup. Treat an R10 warning as a prompt to check the symbol, not as proof of an error in the deck.
R11: HW reliability display_name resolves to a component state
| Severity | error |
|---|---|
| Files | Input/HardwareReliability/SystemReliability.txt ↔ Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r11_hw_display_in_component_states |
Each row in SystemReliability.txt has a display_name (column 1) that the engine looks up among the Control_Panel_Component_State rows. On a miss the engine logs an error and sets sim_err, and then dereferences the null result. R11 reports the dangling name at validation time.
R12: Every coded step has a step file
| Severity | error |
|---|---|
| Files | Input/Crew/Procedures/Procedures.txt ↔ ZProcedure_*.txt |
| Source | adsmd-validate::rules::r12_procedure_index_to_file |
Each (EOP, Step) row under Coded_Steps must have a step file. The match uses the (EOP, Step) pair declared in the header of each parsed ZProcedure_*.txt file; R14 checks that the header agrees with the file name. A step file that fails to parse (R0) does not count as present.
R13: Every step file is in the coded-step index
| Severity | info |
|---|---|
| Files | Input/Crew/Procedures/ZProcedure_*.txt ↔ Procedures.txt |
| Source | adsmd-validate::rules::r13_procedure_file_to_index |
The inverse of R12: a step file whose header pair has no row under Coded_Steps. Such a file is not reachable through the coded-step list. It can still be intentional (alternate variants, or steps entered from MPBG_* mental procedures), hence the info severity.
TIP
On BV4 this fires 149 times: 34 E_0, 81 E_3, 33 ECA_0.0 and 1 FRG_H.1 step files.
R14: Step file header matches its file name
| Severity | warning |
|---|---|
| Files | Input/Crew/Procedures/ZProcedure_*.txt (intra-file) |
| Source | adsmd-validate::rules::r14_procedure_header_matches_filename |
The first line of a step file declares <EOP> <Step>, and the file is named ZProcedure_<EOP>_<Step>.txt. A mismatch is a copy-and-paste slip that the engine accepts. File names that add _bypass or _Bypass to the expected name are accepted as variants of the same step.
R20: Step file type codes are known sim::* constants
| Severity | warning |
|---|---|
| Files | Input/Crew/Procedures/ZProcedure_*.txt ↔ src/ADSIDAC/Global/SimConstants.h |
| Source | adsmd-validate::rules::r20_procedure_type_codes |
Step bodies mix integer codes from the sim::* namespace (for example 3045 = Bool::None, 3074 = Action::Open) with parameter and threshold rows. A mistyped code changes what the step does without any message from the engine.
R20 looks at every pure-integer token with a value in 1 to 9 or 3000 to 3200 and checks it against the table in adsmd-validate::sim_constants, 162 values copied from SimConstants.h. The message names the nearest known constants. Because the table is a copy, a constant added to the header is flagged until the table is updated; that is why the severity is warning.
TIP
On BV4 this rule does not fire: every such token in the 452 parsed step files is a known constant.
R21: Step file header codes are in the right slot
| Severity | warning |
|---|---|
| Files | Input/Crew/Procedures/ZProcedure_*.txt (intra-file) |
| Source | adsmd-validate::rules::r21_procedure_header_kinds |
The two codes that follow the title of a step file are:
- proc_kind, the procedure family:
3151to3156(sim::Proc::{NOP, AOP, EOP, FRG, ECA, MentalProcedure}); - step_kind, the step variant:
3161to3165(sim::Proc::{ObjectiveRelated, PrerequisiteAction, MonitoringStep, VerificationStep, DiagnosisStep}).
R21 warns when either value is outside its range, which is what a swap of the two slots produces. The ranges are built into adsmd.
TIP
On BV4 this rule does not fire. The step files use 14 distinct (proc_kind, step_kind) pairs, all in range.
R22: KB diagnosis-action symbols resolve
| Severity | error |
|---|---|
| Files | KB_O{D,A}M_Diagnosis_Actions.txt ↔ Initiating_Event.txt, ControlPanel.txt, SystemReliability.txt |
| Source | adsmd-validate::rules::r22_kb_action_symbol_in_ie |
Each action_name in a KB diagnosis (typically an X_* symbol) must be one of:
- an
action_symbolinInitiating_Event.txt, - an
x_symbolof aControl_Panel_ControllerorControls_Panel_Fine_Adjustrow, - an
x_symbolinSystemReliability.txt.
An action with an unknown name has no effect in the engine. The rule sees the action_name tokens that the KB parser captured; the rest of each action block is not parsed. When none of the three lookup files parsed, the rule does not run.
R23: KB Bias_Factors parameters resolve
| Severity | error |
|---|---|
| Files | KB_O{D,A}M_Bias_Factors.txt ↔ Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r23_kb_bias_factor_xref |
Each bias-factor row names a parameter whose displayed value the crew model biases. The name must be the display_name of a Control_Panel_Parameter row. Only the rows inside the declared count are checked (BV4 declares 0).
R24: KB Safety_Parameters agree with SPDS_input.txt
| Severity | warning |
|---|---|
| Files | KB_O{D,A}M_Safety_Parameters.txt ↔ Input/Indicators/SPDS_input.txt |
| Source | adsmd-validate::rules::r24_kb_safety_parameters_xref |
KB_O{D,A}M_Safety_Parameters.txt uses the SPDS table layout. Each spds_name in it should also be defined in SPDS_input.txt. The engine reads the two lists independently, so a difference is a sign of stale configuration, not a failure. Up to three similar SPDS names are attached as "did you mean" related spans.
TIP
On BV4 this fires once: the OAT file lists SPDS_Tave-Tref, which SPDS_input.txt does not define.
R25: KB Scanned_Parameters items resolve in ControlPanel
| Severity | error |
|---|---|
| Files | KB_O{D,A}M_Scanned_Parameters.txt ↔ Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r25_kb_scanned_xref |
The scan lists name what the crew monitors. R25 checks each name against the matching ControlPanel subsection:
Number_of_Scanned_Parametersrows →Control_Panel_ParameterNumber_of_Scanned_Componentsrows →Control_Panel_Component_StateNumber_of_Scanned_Alarmsrows → any of the three alarm subsections
Both file layouts are accepted (with and without the Number_of_Scanned_Support_Systems section; see the format reference). The support-system rows are not checked by this or any other rule. In a three-section file with a nonzero alarm count, adsmd checks the rows as alarms while the engine loads them as support systems; R25 does not report that mismatch.
R26: Fault-tree failure probabilities are in [0, 1]
| Severity | warning |
|---|---|
| Files | Input/SupportSystemsReliability/*.fta |
| Source | adsmd-validate::rules::r26_fta_failure_probability_bounds |
An <ftaNode> may carry a failureProbability attribute. A value outside [0, 1], or NaN, is not a probability (typical slips: 1.5 meant as a rate, 30 meant as a percentage). The engine does not read .fta files, which is why the severity is warning. The diagnostic points at the file, and the message names the node id.
R28: Calculation_Aid input names resolve
| Severity | error |
|---|---|
| Files | Input/Crew/Calculation_Aid.txt ↔ Input/Indicators/ControlPanel.txt |
| Source | adsmd-validate::rules::r28_calc_aid_input_xref |
Each curve declares an Input_Name that the crew model evaluates the polynomial on. The name must be the display_name of a Control_Panel_Parameter row.
R29: Channel cards match a deck component
| Severity | info |
|---|---|
| Files | Input/System/RELAP5_channels.txt ↔ RELAP5 input deck |
| Source | adsmd-validate::rules::r29_channel_in_deck |
For each Control_volume, Control_junction and Heat_structure channel, the first three digits of the card number name the deck component (HV_204 → 204040000 addresses component 204, which appears in the deck as card 2040000). R29 reports a channel whose prefix is not the first three digits of any card number in the deck.
The check uses only the leading integer of each deck line and no RELAP5 grammar, so a hit is a hint to look, not a verdict. Trips, interactive controls and control variables use other numbering schemes and are not checked. The rule needs the deck path from ZiniADS.txt; without that file it does not run.
TIP
On BV4 with a ZiniADS.txt that points at BV4.i, this rule does not fire.
R30: StaticPIF.txt is not read
| Severity | info |
|---|---|
| File | Input/Crew/StaticPIF.txt |
| Source | adsmd-validate::rules::r30_static_pif_orphan |
No engine code opens Input/Crew/StaticPIF.txt. When the file exists, R30 says so, because edits to it have no effect on a simulation.
R31: Index files do not reference .bak/.orig/.pre names
| Severity | warning |
|---|---|
| Files | Procedures.txt, Initiating_Event.txt, SystemReliability.txt, KB_O{D,A}M_Diagnosis_Actions.txt |
| Source | adsmd-validate::rules::r31_index_references_no_editor_artifacts |
The counterpart of R32 for names inside files. R31 warns when one of these tokens ends in .bak, .orig or .pre, or contains such a suffix followed by a dot (case-insensitive):
- the EOP or step id of a coded step in
Procedures.txt, - an
action_symbolinInitiating_Event.txt, - an
x_symbolinSystemReliability.txt, - an
action_namein a KB diagnosis.
R32: .bak/.orig/.pre files under Input/
| Severity | info |
|---|---|
| Files | directory walk of <project-root>/Input/ |
| Source | adsmd-validate::rules::r32_orphan_artifacts_in_input |
One diagnostic per file under Input/ whose extension is bak, orig or pre (case-insensitive). The engine does not read these files; they make it harder to see which file is the real one. Only the final extension counts, so ZProcedure_ES_0.1_Step_4.2.bak.txt is not reported.
TIP
On BV4 this fires 6 times, all in Input/Crew/Procedures/: four .bak and two .pre files.
R33: No ZiniADS.txt in the project root
| Severity | info |
|---|---|
| Files | project root |
| Source | adsmd-validate::rules::r33_bv3_style_layout_note |
A directory without ZiniADS.txt is still recognised as a plant project when it has Input/Scheduler/ and Input/System/. R33 notes the absence: R1, R2 and R29 do not run in that case. The engine takes project-dir and input-deck from a ZiniADS.txt in its working directory or from the --project-dir and --input-deck options. The fix hint shows the two lines to add.
TIP
tests/*/ZiniADS.txt is git-ignored, so R33 fires on a fresh checkout of tests/BV4 and tests/BV3.
R34: Alarm_for_Parameter_State references an existing parameter
| Severity | error |
|---|---|
| Files | Input/Indicators/ControlPanel.txt (alarms ↔ parameters) |
| Source | adsmd-validate::rules::r34_alarm_param_xref |
Each Alarm_for_Parameter_State row watches a parameter (parameter_name, column 2), which must be a Control_Panel_Parameter row in the same file. With a typo the alarm never fires.
R35: Alarm_for_Component_State references an existing component state
| Severity | error |
|---|---|
| Files | Input/Indicators/ControlPanel.txt (alarms ↔ component states) |
| Source | adsmd-validate::rules::r35_alarm_component_xref |
Each Alarm_for_Component_State row names a component state (column 2), which must be a Control_Panel_Component_State row in the same file.
R36: Alarm_for_Difference references two existing parameters
| Severity | error |
|---|---|
| Files | Input/Indicators/ControlPanel.txt (alarms ↔ parameters) |
| Source | adsmd-validate::rules::r36_alarm_difference_xref |
Each Alarm_for_Difference_Between_two_Values row watches the difference between two parameters. Both must be Control_Panel_Parameter rows. One diagnostic is emitted per unresolved name, so a row with two unknown names produces two diagnostics.
R37: KB HardWired_Diagnosis probabilities are in [0, 1]
| Severity | error |
|---|---|
| Files | KB_O{D,A}M_HardWired_Diagnosis.txt (intra-file) |
| Source | adsmd-validate::rules::r37_kb_diagnosis_probability_bounds |
Each hard-wired diagnosis declares an activation_probability and a branch_probability. Both must be finite and lie in [0, 1]; one diagnostic is emitted per offending field.
R38: KB Bias_Factors kind is a known sim::* constant
| Severity | warning |
|---|---|
| Files | KB_O{D,A}M_Bias_Factors.txt ↔ src/ADSIDAC/Global/SimConstants.h |
| Source | adsmd-validate::rules::r38_kb_bias_factor_kind_is_sim_constant |
Each bias-factor row carries a kind integer (for example 3007 = Compare::GE, 3112 = Trend::Decreasing) that selects how the engine interprets the bias. The value is checked against the same built-in table as R20, with the same warning severity.
R39: KB Bias_Factors threshold is finite and non-negative
| Severity | error |
|---|---|
| Files | KB_O{D,A}M_Bias_Factors.txt (intra-file) |
| Source | adsmd-validate::rules::r39_kb_bias_factor_threshold_bounds |
threshold is the deviation magnitude the crew model treats as significant. NaN, infinity and negative values are reported.
R40: Procedures.txt multipliers are positive finite numbers
| Severity | error |
|---|---|
| Files | Input/Crew/Procedures/Procedures.txt (head of the file) |
| Source | adsmd-validate::rules::r40_procedure_multiplier_bounds |
The named entries before Coded_Steps (Step_Transfer_Time, normal_procedure_multiplier, verification_step_multiplier, …; 13 in BV4) scale step durations. R40 reports a value that does not parse as a number, and a value that is zero, negative or not finite.
R41: KB diagnosis action_type is a known sim::* constant
| Severity | warning |
|---|---|
| Files | KB_O{D,A}M_Diagnosis_Actions.txt ↔ src/ADSIDAC/Global/SimConstants.h |
| Source | adsmd-validate::rules::r41_kb_action_type_is_sim_constant |
Each KB action declares an action_type integer (for example 3074 = Action::Open). The value is checked against the same built-in table as R20 and R38. An action block in which the parser found no action_type keyword is skipped.
R42: HW reliability parameters are positive finite numbers
| Severity | error |
|---|---|
| Files | Input/HardwareReliability/SystemReliability.txt (intra-file) |
| Source | adsmd-validate::rules::r42_hw_reliability_parameter_bounds |
Checked fields, all of which must be finite and > 0:
- subsection 1:
failure_alpha,failure_beta,recovery_alpha,recovery_beta; - subsection 2:
failure_rate,delta_t,recovery_alpha,recovery_beta.
A Beta distribution is undefined for non-positive shape parameters. Subsection 3 (fault-tree references) has no numeric fields. One diagnostic is emitted per offending field.
R43: Calculation_Aid coefficients are finite
| Severity | error |
|---|---|
| Files | Input/Crew/Calculation_Aid.txt (intra-file) |
| Source | adsmd-validate::rules::r43_calculation_aid_coefficient_finite |
Each curve carries six polynomial coefficients. NaN and infinite values are reported, one diagnostic per coefficient.
R45: IE time is within Truncation_time
| Severity | info |
|---|---|
| Files | Input/System/Initiating_Event.txt ↔ Input/Scheduler/ZCtrlPar.txt |
| Source | adsmd-validate::rules::r45_ie_time_within_truncation |
An initiating event whose time is greater than Truncation_time in ZCtrlPar.txt does not fire in a run that uses that truncation time. Negative time values are never greater than the truncation time and are not reported. The rule does not run when Truncation_time is not a positive finite number (R3 reports that case).
The engine option --truncation-time replaces the value from ZCtrlPar.txt at run time; adsmd compares against the file.
TIP
On BV4 (Truncation_time 15.5 s) this fires for the 9 events with time = 850: SG_B_SGTR, SG_A_FWRV_Failure, Turbine_Trip, Loss_of_MF_Pump_A, Loss_of_Main_Feedwater, Aux_Spray_Open, Open_PORV, MSLB_Outside_Cont, Reactor_Trip.