pyfcstm.diagnostics.codes
Loader for the structured diagnostic code registry.
This module loads codes.yaml (the single source of truth for diagnostic
codes emitted by pyfcstm diagnostic pipelines) at import time and exposes the
parsed table as CODE_REGISTRY. Downstream consumers — including the
research_ideas LLM agent loop, IDE integrations, and the future
jsfcstm visualization layer — can mirror this registry to drive their
own dispatch logic without depending on exception message text.
The loader performs structural validation on import so that schema drift
in codes.yaml fails fast. Validation failures raise
CodesSchemaError (subclass of ValueError), so callers can
distinguish “the diagnostics package is structurally broken” from a generic
business-level ValueError further up the stack.
The module contains:
CodeFieldSpec- Per-field schema describing arefspayload key.CodeSpec- Full specification for one diagnostic code.CodesSchemaError- Raised whencodes.yamlis structurally invalid.CODE_REGISTRY- Mappingcode -> CodeSpecloaded at import time.load_codes()- Parse a YAML file path and return the registry.
Note
_ALLOWED_REF_TYPES and _ALLOWED_SEVERITIES are documentation-level
enumerations used to validate the YAML schema. They do not enforce
runtime isinstance checks on emitted ModelDiagnostic.refs values
— type-checking refs payloads at emit time is the emitter’s responsibility.
The schema’s job is to give downstream tooling a contract to mirror, not
to act as a runtime type system.
Example:
>>> from pyfcstm.diagnostics import CODE_REGISTRY
>>> spec = CODE_REGISTRY['E_UNDEFINED_VAR']
>>> spec.severity
'error'
>>> 'var_name' in spec.refs_schema
True
CODE_REGISTRY
- pyfcstm.diagnostics.codes.CODE_REGISTRY: Mapping[str, CodeSpec] = mappingproxy({'E_UNDEFINED_VAR': CodeSpec(code='E_UNDEFINED_VAR', severity='error', description='A guard, effect, or lifecycle-action block references a name that was never declared with a top-level `def` statement.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='The undeclared identifier as it appeared in the source.', enum=None), 'referenced_in': CodeFieldSpec(name='referenced_in', type='str', required=True, description='Which kind of block contained the reference.', enum=('guard', 'effect', 'enter', 'during', 'exit', 'during_aspect', 'init')), 'state_path': CodeFieldSpec(name='state_path', type='str_or_null', required=False, description='Dotted path of the state that owns the offending block, when the reference is inside a state body (not a guard/effect on a transition).', enum=None), 'expr_text': CodeFieldSpec(name='expr_text', type='str_or_null', required=False, description='Original expression text containing the reference.', enum=None), 'is_temporary': CodeFieldSpec(name='is_temporary', type='bool', required=False, description='``True`` when the identifier looked like a block-local temporary (the read occurred before the variable was assigned within the same ``enter`` / ``during`` / ``exit`` / ``effect`` block). Layer 2 merges what jsfcstm previously emitted as ``fcstm.readBeforeAssignTemporary`` into this single ``E_*`` code plus this flag. Defaults to ``False`` / absent for "real" undefined variables that have no matching ``def`` declaration anywhere.', enum=None)}), example_dsl='def int x = 0;\nstate Root { state A; state B; A -> B : if [unknown_var > 0]; }\n', capability='pure_static', for_llm=ForLlmSpec(summary="A variable identifier appears in an expression (guard, effect, or action block) but has not been declared with ``def`` at the file top, has not been assigned earlier in the same block (so the block-local temporary path doesn't apply), and is not a known function name. The model refuses to bind unknown identifiers because the generated code would not compile.", recommended_actions=(mappingproxy({'kind': 'add_definition', 'target': 'file_top', 'rationale': 'If the variable is genuinely program state, declare it with ``def <type> <name> = <initial>;`` at the file top so the generated runtime allocates storage for it.'}), mappingproxy({'kind': 'assign_first', 'target': 'same_block', 'rationale': 'If the name was meant to be a block-local temporary, assign to it before reading. Block-local temps only exist after their first assignment in the enclosing concrete block.'}), mappingproxy({'kind': 'fix_typo', 'target': 'expression', 'rationale': 'If the identifier was meant to be an existing variable, correct the spelling. ``refs.var_name`` carries the exact spelling from the source.'})), do_not=('Do not declare the variable inside an action block expecting it to leak out — block-local temps are discarded at block exit.', 'Do not rely on Python-style implicit None for the missing identifier; the generated runtime will fail to compile.')), emit_tier='static_pipeline', suggested_fix=None, span_object='expression'), 'E_DUPLICATE_VAR': CodeSpec(code='E_DUPLICATE_VAR', severity='error', description='A top-level `def` statement re-declares an identifier that was already defined earlier in the file.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='The duplicated identifier.', enum=None), 'previous_span': CodeFieldSpec(name='previous_span', type='Span', required=False, description='Source position of the first declaration.', enum=None)}), example_dsl='def int x = 0;\ndef int x = 1;\nstate Root { state A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='Two ``def`` declarations at the file top use the same variable name. The model allocates one storage slot per name, so a duplicate definition is ambiguous.', recommended_actions=(mappingproxy({'kind': 'drop_duplicate', 'target': 'variable_definition', 'rationale': 'If both definitions are meant to declare the same logical variable, keep the first one and delete the second.'}), mappingproxy({'kind': 'rename_one', 'target': 'variable_definition', 'rationale': 'If both definitions are meant to be separate variables, rename the second to give it its own storage slot.'})), do_not=('Do not assume the second ``def`` overrides the first — the generated runtime treats this as an error and refuses to compile.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='variable_declaration'), 'E_MISSING_STATE': CodeSpec(code='E_MISSING_STATE', severity='error', description='A transition target references a state path that cannot be resolved in the surrounding hierarchy.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='The unresolved dotted state path.', enum=None), 'referenced_from': CodeFieldSpec(name='referenced_from', type='str_or_null', required=False, description='Dotted path of the state from which the reference was made.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=False, description='Short tag describing the resolution failure mode.', enum=('not_found', 'parent_missing', 'ambiguous', 'event_path_not_found'))}), example_dsl='state Root { state A; A -> NoSuch; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='A transition references a state name that does not exist in the machine. The transition target / source must resolve to a state declared in this file or imported.', recommended_actions=(mappingproxy({'kind': 'fix_typo', 'target': 'transition', 'rationale': 'If the name was meant to refer to an existing state, correct the spelling. ``refs.state_name`` carries the missing token.'}), mappingproxy({'kind': 'declare_state', 'target': 'composite_state', 'rationale': 'If the state is genuinely missing, add ``state <name>;`` (or a composite block) under the appropriate composite parent.'})), do_not=('Do not silently delete the transition; the original intent of the missing state is lost.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='state_identifier'), 'E_DUPLICATE_STATE': CodeSpec(code='E_DUPLICATE_STATE', severity='error', description='Two states share the same name within the same parent scope.', refs_schema=mappingproxy({'state_name': CodeFieldSpec(name='state_name', type='str', required=True, description='The duplicated state name.', enum=None), 'parent_path': CodeFieldSpec(name='parent_path', type='str', required=True, description='Dotted path of the parent that contains both states.', enum=None), 'previous_span': CodeFieldSpec(name='previous_span', type='Span', required=False, description='Source position of the first declaration.', enum=None)}), example_dsl='state Root { state A; state A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='Two state declarations under the same composite parent use the same name. State names must be unique inside their immediate composite scope.', recommended_actions=(mappingproxy({'kind': 'drop_duplicate', 'target': 'state_definition', 'rationale': 'If both declarations describe the same logical state, keep one and remove the other (merge any actions/transitions onto the survivor).'}), mappingproxy({'kind': 'rename_one', 'target': 'state_definition', 'rationale': 'If the two declarations are meant to be distinct states, rename one to give it its own identity inside the parent.'})), do_not=('Do not assume the second declaration overrides the first — duplicate state names produce a hard error.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='state_identifier'), 'E_EVENT_REF_INVALID': CodeSpec(code='E_EVENT_REF_INVALID', severity='error', description="The textual form of an event reference is syntactically invalid (e.g. bare '/', trailing dots, going beyond the root state).", refs_schema=mappingproxy({'event_ref': CodeFieldSpec(name='event_ref', type='str', required=True, description='The raw event reference text.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing why the reference is invalid.', enum=('empty', 'bare_slash', 'invalid_absolute', 'invalid_relative', 'trailing_dots', 'beyond_root'))}), example_dsl='state Root { state A; state B; A -> B : /; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='An event reference (``::``, ``:``, or ``/`` scoped) cannot resolve to a known event under the indicated scope. The grammar accepts the syntactic form, but the resolver cannot bind it to a real event object.', recommended_actions=(mappingproxy({'kind': 'fix_scope_operator', 'target': 'transition', 'rationale': 'The three scope operators do not interchange freely. ``::`` is source-local, ``:`` is parent-chain, ``/`` is root-absolute. Pick the one that matches where the event is actually declared.'}), mappingproxy({'kind': 'declare_event', 'target': 'composite_state', 'rationale': 'If the event was supposed to exist, add an ``event <name>;`` declaration in the matching scope.'})), do_not=("Do not invent a new event by silently aliasing — the dispatcher won't fire on an undeclared name.",)), emit_tier='lookup_api', suggested_fix=None, span_object='event_declaration'), 'E_EVENT_NOT_FOUND': CodeSpec(code='E_EVENT_NOT_FOUND', severity='error', description='An event reference parses correctly but does not resolve to any event defined in the targeted scope.', refs_schema=mappingproxy({'event_ref': CodeFieldSpec(name='event_ref', type='str', required=True, description='The raw event reference text.', enum=None), 'scope': CodeFieldSpec(name='scope', type='str', required=True, description='Resolution scope used.', enum=('local', 'chain', 'absolute')), 'searched_from': CodeFieldSpec(name='searched_from', type='str_or_null', required=False, description="Dotted state path of the **caller** that initiated the lookup (i.e. the state on which `.resolve_event()` was invoked, or, for `StateMachine.resolve_event`, the state machine's root). This is the originating location of the bad reference in source — not the effective search root, which is always the model root for absolute references.", enum=None)}), example_dsl='state Root { state A; state B; A -> B :: NoEvent; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='A dotted event path could not be resolved against the assembled state hierarchy. The path syntax was valid but no event with that name exists at the resolved state.', recommended_actions=(mappingproxy({'kind': 'fix_event_path', 'target': 'transition', 'rationale': 'Confirm the dotted path matches the state hierarchy that actually exists after imports have been merged.'}), mappingproxy({'kind': 'declare_event', 'target': 'composite_state', 'rationale': 'Add the missing ``event <name>;`` declaration under the intended state.'})), do_not=('Do not paper over the error by introducing a wildcard alias — events are uniquely bound by their scope.',)), emit_tier='lookup_api', suggested_fix=None, span_object='event_declaration'), 'E_DANGLING_TRANSITION': CodeSpec(code='E_DANGLING_TRANSITION', severity='error', description='A transition cannot resolve either its source or its target.', refs_schema=mappingproxy({'src': CodeFieldSpec(name='src', type='str_or_null', required=False, description='Raw source state expression as written in the DSL.', enum=None), 'tgt': CodeFieldSpec(name='tgt', type='str_or_null', required=False, description='Raw target state expression as written in the DSL.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing the dangling reason.', enum=('src_not_found', 'tgt_not_found', 'both_not_found'))}), example_dsl='state Root { state A; NoSuch -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary="A transition's source or target points at a state that exists neither in the local composite scope nor in any ancestor scope. The transition cannot be wired into the dispatch graph.", recommended_actions=(mappingproxy({'kind': 'fix_typo', 'target': 'transition', 'rationale': 'If the dangling name is misspelled, correct it. ``refs.state_path`` carries the location of the offending transition.'}), mappingproxy({'kind': 'declare_target_state', 'target': 'composite_state', 'rationale': 'Declare the missing state if the transition was intentional.'}), mappingproxy({'kind': 'drop_transition', 'target': 'transition', 'rationale': 'Remove the transition if it was speculative — leaving a dangling reference blocks the whole file.'})), do_not=('Do not pretend the transition resolves to ``[*]`` — that has a specific entry/exit semantics.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'E_TYPE_MISMATCH': CodeSpec(code='E_TYPE_MISMATCH', severity='error', description='A guard, effect, or assignment uses an expression whose type does not match the expected category (arithmetic vs boolean).', refs_schema=mappingproxy({'expected': CodeFieldSpec(name='expected', type='str', required=True, description="Expected category. One of: 'numeric', 'boolean'.", enum=None), 'actual': CodeFieldSpec(name='actual', type='str', required=True, description='Actual category produced by the expression.', enum=None), 'expr_text': CodeFieldSpec(name='expr_text', type='str', required=True, description='Original expression text.', enum=None)}), example_dsl='def int x = 0;\nstate Root { state A; state B; A -> B : if [x]; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='An expression mixes an arithmetic and a boolean subexpression in a way the grammar does not allow. ``num_expression`` and ``cond_expression`` are strictly separated; comparison operators bridge them, ternary ``? :`` converts boolean → arithmetic.', recommended_actions=(mappingproxy({'kind': 'wrap_in_ternary', 'target': 'expression', 'rationale': 'If you wanted to assign a boolean test, wrap it as ``(cond) ? 1 : 0`` so the right-hand side is arithmetic.'}), mappingproxy({'kind': 'add_comparison', 'target': 'guard', 'rationale': 'If you wanted to gate on a numeric value, compare against a constant (``counter > 0``) instead of using the value directly as a boolean.'})), do_not=('Do not rely on numeric → boolean implicit coercion; the generated runtimes treat the two domains as distinct.',)), emit_tier='partial_static_pipeline', suggested_fix=None, span_object='expression'), 'E_FORCED_TRANSITION_EXPANSION': CodeSpec(code='E_FORCED_TRANSITION_EXPANSION', severity='error', description='A forced transition (`!State -> ...` or `!*`) cannot be expanded because the source or target reference is invalid.', refs_schema=mappingproxy({'original_raw': CodeFieldSpec(name='original_raw', type='str', required=True, description='Raw forced-transition text as written.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing why expansion failed.', enum=('src_not_found', 'tgt_not_found', 'src_is_root', 'wildcard_no_descendants'))}), example_dsl='state Root { state A; !NoSuch -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='A forced transition (``!Source -> Target`` or ``!* -> Target``) failed to expand cleanly — typically because the source name cannot be found, or because the expansion would create an empty/inconsistent fan-out under the current scope.', recommended_actions=(mappingproxy({'kind': 'fix_source', 'target': 'forced_transition', 'rationale': 'Confirm the ``!Name`` source is a real state inside the current composite scope. ``!*`` only matches direct substates; deeper descendants need explicit names.'}), mappingproxy({'kind': 'relocate_forced_transition', 'target': 'composite_state', 'rationale': 'Move the forced transition into the composite whose substates you actually want to receive the event.'})), do_not=('Do not add an ``effect { ... }`` block to a forced transition — forced transitions cannot carry effects and the expansion would fail anyway.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'E_INITIAL_TRANSITION_INVALID': CodeSpec(code='E_INITIAL_TRANSITION_INVALID', severity='error', description='A composite state either lacks an entry transition (`[*] -> child`) or declares one whose target is not a direct child of the composite.', refs_schema=mappingproxy({'composite_path': CodeFieldSpec(name='composite_path', type='str', required=True, description='Dotted path of the offending composite state.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing the failure.', enum=('missing_entry', 'target_not_child'))}), example_dsl='state Root { state Outer { state Inner; } }\n', capability='pure_static', for_llm=ForLlmSpec(summary='A composite state lacks a valid ``[*] -> Child`` initial transition, or its declared initial target is not actually a child of this composite. The runtime cannot decide which child to enter when this composite is activated.', recommended_actions=(mappingproxy({'kind': 'add_initial_transition', 'target': 'composite_state', 'rationale': 'Add ``[*] -> <ChildName>;`` inside the composite, picking a direct substate as the entry point.'}), mappingproxy({'kind': 'fix_initial_target', 'target': 'initial_transition', 'rationale': 'If an initial transition already exists, retarget it at a direct child of this composite (not a grandchild).'})), do_not=('Do not rely on a default ordering of substates; the runtime requires an explicit initial transition.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'E_DUPLICATE_FUNCTION_NAME': CodeSpec(code='E_DUPLICATE_FUNCTION_NAME', severity='error', description='Two named lifecycle actions (enter / during / exit / during-aspect) within the same state share the same name. Named actions are referenced via `ref <name>` and must be uniquely identifiable.', refs_schema=mappingproxy({'function_name': CodeFieldSpec(name='function_name', type='str', required=True, description='The duplicated named-action name.', enum=None), 'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the state declaring the duplicates.', enum=None), 'stage': CodeFieldSpec(name='stage', type='str', required=True, description='Lifecycle stage where the duplicate appears.', enum=('enter', 'during', 'exit', 'during_aspect'))}), example_dsl='state Root {\n state A {\n enter Foo { }\n enter Foo { }\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='Two named action / function blocks share the same name within the same scope. Named blocks must be uniquely identifiable so ``ref`` lookups can bind to a single definition.', recommended_actions=(mappingproxy({'kind': 'rename_one', 'target': 'named_action', 'rationale': 'Give one of the named blocks a distinct identifier so ``ref <name>`` calls resolve unambiguously.'}), mappingproxy({'kind': 'drop_duplicate', 'target': 'named_action', 'rationale': 'If the two declarations are meant to be the same logical block, keep one and update its callers to reference it.'})), do_not=('Do not assume the second declaration shadows the first — the resolver treats this as a hard error.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='named_action_declaration'), 'E_DURING_ASPECT_INVALID': CodeSpec(code='E_DURING_ASPECT_INVALID', severity='error', description="A `during` block is declared inconsistently with the host state's leaf/composite kind. Leaf states must use `during { ... }` without an aspect modifier; composite states must use `during before { ... }` or `during after { ... }` (the aspect is mandatory on composites). The global ``>> during before/after`` aspect form is **also** invalid on a leaf state — aspect actions fan out to every descendant leaf, and a leaf has nothing to fan into.", refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the offending state.', enum=None), 'state_kind': CodeFieldSpec(name='state_kind', type='str', required=True, description='Kind of the host state.', enum=('leaf', 'composite')), 'aspect': CodeFieldSpec(name='aspect', type='str_or_null', required=False, description="The aspect token that was actually used. ``'before'`` or ``'after'`` for ``during before`` / ``during after`` and ``>> during before/after``; ``null`` when the user wrote a bare ``during`` on a composite state. ``null`` is intentional — the consumer should branch on the bare-during case rather than treat it as an enum value.", enum=None)}), example_dsl='state Root {\n state A {\n during before { }\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='A ``during before`` / ``during after`` or ``>> during ...`` aspect declaration was placed on a state that cannot legally receive it (typically a leaf state with no descendant for the aspect to fan out to).', recommended_actions=(mappingproxy({'kind': 'move_to_composite', 'target': 'aspect_declaration', 'rationale': 'Aspect actions only make sense on composite states. Move the declaration to a composite ancestor whose descendants should receive the aspect.'}), mappingproxy({'kind': 'drop_aspect', 'target': 'aspect_declaration', 'rationale': 'If the aspect was speculative and the state is genuinely a leaf, remove the aspect declaration entirely.'})), do_not=('Do not convert the leaf into a composite just to host the aspect — that changes the runtime entry/exit semantics.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='lifecycle_action'), 'E_PSEUDO_NOT_LEAF': CodeSpec(code='E_PSEUDO_NOT_LEAF', severity='error', description='A state was declared with the `pseudo` keyword but has nested substates. Pseudo states must be leaves: they skip ancestor `>> during` aspects and only make sense without inner structure.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the offending pseudo state.', enum=None)}), example_dsl='state Root {\n pseudo state Outer {\n state Inner;\n [*] -> Inner;\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='A ``pseudo state`` declaration was given a composite body (or otherwise treated as if it had descendants). Pseudo states must be leaves: they cannot host substates because their semantics explicitly skip ancestor ``>> during`` aspects.', recommended_actions=(mappingproxy({'kind': 'drop_pseudo_marker', 'target': 'state_definition', 'rationale': 'If the state genuinely needs substates, remove the ``pseudo`` keyword and treat it as a normal composite.'}), mappingproxy({'kind': 'flatten_pseudo', 'target': 'state_definition', 'rationale': 'If the state is meant to be a transient pseudo (e.g. an internal junction), remove its substates and turn it back into a leaf.'})), do_not=('Do not rely on pseudo states for normal hierarchy modeling — they exist solely to bypass ``>> during`` aspect application.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='state_identifier'), 'E_NAMED_FUNCTION_REF_CYCLE': CodeSpec(code='E_NAMED_FUNCTION_REF_CYCLE', severity='error', description='A lifecycle action `ref` chain forms a cycle and therefore never reaches a concrete or abstract action implementation.', refs_schema=mappingproxy({'ref_path': CodeFieldSpec(name='ref_path', type='str', required=True, description='Dot-separated action path where cycle validation started.', enum=None), 'cycle_path': CodeFieldSpec(name='cycle_path', type='str', required=True, description='Dot-separated action path chain that closes the cycle.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing the failure.', enum=('action_ref_cycle',))}), example_dsl=None, capability='pure_static', for_llm=ForLlmSpec(summary='An ``enter ref ...`` / ``exit ref ...`` / ``during ref ...`` clause ultimately points back to itself through one or more named actions.', recommended_actions=(mappingproxy({'kind': 'break_ref_cycle', 'target': 'action_ref', 'rationale': 'Replace one link in the cycle with a concrete action block or an abstract action declaration so the reference chain terminates.'}),), do_not=('Do not execute or render cyclic lifecycle references; reject the model before runtime execution.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='named_action_declaration'), 'E_NAMED_FUNCTION_REF_NOT_FOUND': CodeSpec(code='E_NAMED_FUNCTION_REF_NOT_FOUND', severity='error', description='A `ref` lifecycle action could not resolve its target named action. Either the path walks through a state that does not exist, or the final segment is not a named action defined inside the resolved state.', refs_schema=mappingproxy({'ref_path': CodeFieldSpec(name='ref_path', type='str', required=True, description='Dotted path of the unresolved reference.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing the resolution failure.', enum=('state_not_found', 'named_function_not_found')), 'missing_segment': CodeFieldSpec(name='missing_segment', type='str_or_null', required=False, description="The path segment that failed to resolve. For 'state_not_found' this is the state name that does not exist under the parent path; for 'named_function_not_found' this is the action name searched for in the resolved state.", enum=None)}), example_dsl='state Root {\n state A {\n enter ref NoSuch.NoSuch;\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='An ``enter ref ...`` / ``exit ref ...`` / ``during ref ...`` clause points at a named action that does not exist. The resolver could not find a matching named block in the indicated scope.', recommended_actions=(mappingproxy({'kind': 'fix_ref_path', 'target': 'action_ref', 'rationale': 'Confirm the dotted ref path matches a real named action. Use ``/`` to anchor at the root, or a relative name for the current state.'}), mappingproxy({'kind': 'declare_named_action', 'target': 'composite_state', 'rationale': 'Add the missing ``enter <Name> { ... }`` / similar block in the resolving scope.'})), do_not=('Do not silently swap ``ref`` with an inline block — that loses the deduplication that ``ref`` was meant to provide.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='named_action_declaration'), 'E_IMPORT_NOT_FOUND': CodeSpec(code='E_IMPORT_NOT_FOUND', severity='error', description='An ``import`` statement points at a source file that cannot be found, cannot be read, or fails to parse.', refs_schema=mappingproxy({'source_path': CodeFieldSpec(name='source_path', type='str', required=True, description='The source-path token from the import statement, exactly as it appeared in the DSL.', enum=None), 'alias': CodeFieldSpec(name='alias', type='str', required=True, description='The alias under which the import was declared.', enum=None), 'host_state_path': CodeFieldSpec(name='host_state_path', type='str', required=True, description='Dotted path of the composite state hosting the import statement.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Why resolution failed.', enum=('file_not_found', 'read_error', 'parse_error', 'no_root_state'))}), example_dsl='state System {\n import "missing.fcstm" as Sub;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='An import target could not be resolved. Inspect ``refs.reason`` to branch the fix: ``file_not_found`` means the path is wrong or the file does not exist; ``read_error`` means the file exists but the I/O layer rejected it (permissions / encoding); ``parse_error`` means the file was loaded but is not valid FCSTM DSL; ``no_root_state`` means the file parses but declares no ``state Root { ... }`` block. The four reasons need different fixes — do not collapse them. Cross-end note (I2 from PR #115 final review): jsfcstm currently only distinguishes ``file_not_found`` and ``no_root_state``; its workspace index treats I/O failures and parse failures alike as ``missing`` and emits ``file_not_found`` for both. When consuming jsfcstm-side diagnostics, treat ``file_not_found`` as "any pre-no_root_state failure" and inspect the imported file directly to disambiguate read vs parse failures.', recommended_actions=(mappingproxy({'kind': 'fix_path', 'target': 'import_statement', 'applies_to_reason': 'file_not_found', 'rationale': 'For ``file_not_found``, adjust the source_path to a real file relative to the host file, or remove the import if the sub-machine is no longer required.'}), mappingproxy({'kind': 'create_file', 'target': 'import_target', 'applies_to_reason': 'file_not_found', 'rationale': 'For ``file_not_found``, if the file should exist, create it with at least a top-level ``state Root { ... }`` so its root state can be merged in.'}), mappingproxy({'kind': 'fix_permissions', 'target': 'import_target', 'applies_to_reason': 'read_error', 'rationale': 'For ``read_error``, the file exists but the I/O layer could not read it. Check file permissions, encoding (FCSTM expects UTF-8 or auto-detected text), and that the path is not a directory.'}), mappingproxy({'kind': 'fix_dsl_in_imported_file', 'target': 'import_target', 'applies_to_reason': 'parse_error', 'rationale': 'For ``parse_error``, the file was read but contains invalid FCSTM DSL. Open the imported file directly; the underlying grammar parse error is reported with its own line/column when you run ``pyfcstm`` on it standalone.'}), mappingproxy({'kind': 'add_root_state', 'target': 'import_target', 'applies_to_reason': 'no_root_state', 'rationale': 'For ``no_root_state``, the file parses but declares no top-level ``state <Name> { ... }``. Add one — the merge needs a root state to inline.'})), do_not=('Do not silently rename the alias to dodge the missing file.', 'Do not add a placeholder state under the alias — the import must resolve to a real file.', 'Do not give the same recommended_action regardless of reason — the LLM consumer should branch on ``refs.reason`` and apply only the matching ``applies_to_reason`` actions.')), emit_tier='static_pipeline', suggested_fix=None, span_object='import_statement'), 'E_IMPORT_CIRCULAR': CodeSpec(code='E_IMPORT_CIRCULAR', severity='error', description='A cycle was detected while resolving ``import`` statements between two or more state-machine source files.', refs_schema=mappingproxy({'source_path': CodeFieldSpec(name='source_path', type='str', required=True, description='The source-path token that closed the cycle.', enum=None), 'alias': CodeFieldSpec(name='alias', type='str', required=True, description='The alias under which the cyclic import was declared.', enum=None), 'host_state_path': CodeFieldSpec(name='host_state_path', type='str', required=True, description='Dotted path of the composite state hosting the import.', enum=None), 'cycle_chain': CodeFieldSpec(name='cycle_chain', type='list[str]', required=True, description='Ordered list of file paths that participate in the cycle, starting and ending at the same file.', enum=None)}), example_dsl='# a.fcstm\nstate A { import "b.fcstm" as B; }\n# b.fcstm\nstate B { import "a.fcstm" as A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='Two or more state-machine files import each other transitively. The compiler refuses to resolve cycles to keep the merged hierarchy tractable.', recommended_actions=(mappingproxy({'kind': 'refactor', 'target': 'import_statement', 'rationale': 'Break the cycle by extracting the shared state(s) into a third file that both ends import without depending on each other.'}), mappingproxy({'kind': 'drop_back_edge', 'target': 'import_statement', 'rationale': 'If the cycle is accidental, remove the import statement that closes the loop (the one named in ``source_path``).'})), do_not=('Do not duplicate the imported states inline to break the cycle — that defeats the purpose of imports.', 'Do not introduce a stub alias that re-exports the cycle from another file.')), emit_tier='static_pipeline', suggested_fix=None, span_object='import_statement'), 'E_IMPORT_ALIAS_CONFLICT': CodeSpec(code='E_IMPORT_ALIAS_CONFLICT', severity='error', description='An ``import`` alias clashes with an existing child state (or with another import alias) under the same composite state.', refs_schema=mappingproxy({'alias': CodeFieldSpec(name='alias', type='str', required=True, description='The conflicting alias name.', enum=None), 'host_state_path': CodeFieldSpec(name='host_state_path', type='str', required=True, description='Dotted path of the composite state hosting the import.', enum=None), 'conflicting_kind': CodeFieldSpec(name='conflicting_kind', type='str', required=True, description='What the alias clashed with.', enum=('existing_substate', 'previous_import_alias'))}), example_dsl='state System {\n state Worker;\n import "worker.fcstm" as Worker;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The import alias collides with an already-defined name in the same composite scope. The merged hierarchy cannot have two children sharing a name.', recommended_actions=(mappingproxy({'kind': 'rename_alias', 'target': 'import_statement', 'rationale': 'Pick a unique alias for the import; references to the imported machine elsewhere in the file must follow the new alias.'}), mappingproxy({'kind': 'rename_other', 'target': 'existing_substate', 'rationale': 'If the existing substate is the one that should be renamed, update its declaration and every transition referencing it.'})), do_not=('Do not silently drop one of the conflicting definitions.', 'Do not add a numeric suffix to the alias as an automatic fix without checking downstream references.')), emit_tier='static_pipeline', suggested_fix=None, span_object='import_statement'), 'E_IMPORT_DUPLICATE_MAPPING': CodeSpec(code='E_IMPORT_DUPLICATE_MAPPING', severity='error', description='Two or more mapping clauses under the same ``import { ... }`` block target the same source name (event or variable), or two source names target the same host name.', refs_schema=mappingproxy({'alias': CodeFieldSpec(name='alias', type='str', required=True, description='The import alias whose mapping is duplicated.', enum=None), 'mapping_kind': CodeFieldSpec(name='mapping_kind', type='str', required=True, description='Which mapping flavor was duplicated.', enum=('event', 'variable')), 'duplicated_name': CodeFieldSpec(name='duplicated_name', type='str', required=True, description='The source-side or target-side name that appears more than once.', enum=None), 'direction': CodeFieldSpec(name='direction', type='str', required=True, description='Which side of the mapping was duplicated.', enum=('source_duplicated', 'target_duplicated')), 'host_state_path': CodeFieldSpec(name='host_state_path', type='str', required=True, description='Dotted path of the composite state hosting the import.', enum=None)}), example_dsl='state System {\n import "sub.fcstm" as Sub {\n def x = a;\n def x = b;\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='An import-mapping block contains a duplicate source or target name. Each source identifier can be mapped at most once; each target host slot can receive at most one source.', recommended_actions=(mappingproxy({'kind': 'drop_duplicate', 'target': 'mapping_clause', 'rationale': 'Delete the duplicated mapping line — keep the intended one.'}), mappingproxy({'kind': 'rename_target', 'target': 'mapping_clause', 'rationale': 'If both sources are needed, give them distinct host-side names via a fresh mapping target.'})), do_not=('Do not merge mappings by concatenating their values.', 'Do not introduce wildcard selectors to mask the duplicate.')), emit_tier='static_pipeline', suggested_fix=None, span_object='import_statement'), 'E_IMPORT_MAPPING_INVALID': CodeSpec(code='E_IMPORT_MAPPING_INVALID', severity='error', description='An import-mapping clause refers to a source name that does not exist in the imported machine, uses an invalid selector / template, or points at a host target that cannot host the mapped element.', refs_schema=mappingproxy({'alias': CodeFieldSpec(name='alias', type='str', required=True, description='The import alias whose mapping is malformed.', enum=None), 'mapping_kind': CodeFieldSpec(name='mapping_kind', type='str', required=True, description='Mapping flavor.', enum=('event', 'variable')), 'host_state_path': CodeFieldSpec(name='host_state_path', type='str', required=True, description='Dotted path of the composite state hosting the import.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Short tag describing the failure mode.', enum=('source_not_found', 'target_invalid', 'selector_invalid', 'template_invalid', 'empty_path', 'host_root_mismatch')), 'detail': CodeFieldSpec(name='detail', type='str', required=True, description='Human-readable specifics of the mapping failure (mapping text, selector / template literal, or path that failed to resolve).', enum=None)}), example_dsl='state System {\n import "sub.fcstm" as Sub {\n def x = no_such_var;\n }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='An ``import { ... }`` mapping clause is malformed or points at a non-existent element on the source side / a non-receivable element on the host side.', recommended_actions=(mappingproxy({'kind': 'fix_source', 'target': 'mapping_clause', 'rationale': 'Update the source-side name to match a real def / event in the imported file.'}), mappingproxy({'kind': 'fix_target', 'target': 'mapping_clause', 'rationale': 'Update the host-side target to a valid identifier that the merge can attach the imported element to.'}), mappingproxy({'kind': 'drop_clause', 'target': 'mapping_clause', 'rationale': 'Remove the mapping if it was speculative — unmapped imports still merge under their alias.'})), do_not=('Do not invent fake source names to make the selector match.', 'Do not silently widen the selector to a wildcard if the original was specific.')), emit_tier='static_pipeline', suggested_fix=None, span_object='import_statement'), 'W_UNREACHABLE_STATE': CodeSpec(code='W_UNREACHABLE_STATE', severity='warning', description="A state is not reachable from the model's root entry path via any sequence of normal or forced transitions.", refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the unreachable state.', enum=None)}), example_dsl='state Root {\n state Idle;\n state Orphan;\n [*] -> Idle;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary="This state cannot be entered at runtime; the surrounding transitions never lead to it. It is dead from the machine's perspective.", recommended_actions=(mappingproxy({'kind': 'add_inbound_transition', 'target': 'state', 'rationale': 'Add a transition that reaches the state if it was meant to be used.'}), mappingproxy({'kind': 'remove_state', 'target': 'state', 'rationale': 'Remove the state if it was added speculatively.'})), do_not=('Do not add a self-loop to mask the unreachability.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='state_identifier'), 'W_GUARD_CONST_FALSE': CodeSpec(code='W_GUARD_CONST_FALSE', severity='warning', description="A transition's guard condition folds to the boolean literal ``false`` using the built-in constant folder, so the transition can never fire. The folder is intentionally side-effect free: it handles literal-only boolean, comparison, arithmetic, bitwise, unary, and ternary expressions, but does not evaluate variables, functions, solvers, or runtime state.", refs_schema=mappingproxy({'transition_span': CodeFieldSpec(name='transition_span', type='Span', required=False, description='Source span of the transition declaration.', enum=None), 'folded_value': CodeFieldSpec(name='folded_value', type='bool', required=True, description='Constant-folded guard value (always ``false``).', enum=None), 'from_path': CodeFieldSpec(name='from_path', type='str', required=False, description='Source state path of the transition, or ``[*]`` for an initial transition.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=False, description='Target state path of the transition, or ``[*]`` for an exit transition.', enum=None), 'guard_text': CodeFieldSpec(name='guard_text', type='str', required=False, description='Normalized guard expression text used to disambiguate spanless inspect diagnostics. Pyfcstm and jsfcstm both render this with the shared inspect expression format: canonical boolean/operator spelling, decimal integer literals, and normalized spacing.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='state Root {\n state A;\n state B;\n [*] -> A;\n A -> B : if [(0x0F & 0xF0) != 0];\n}\n', capability='const_fold', for_llm=ForLlmSpec(summary="The transition's guard is statically known to be ``false`` and the transition is effectively dead code.", recommended_actions=(mappingproxy({'kind': 'fix_guard', 'target': 'transition', 'rationale': 'Rewrite the guard so it can become true under some valid state.'}), mappingproxy({'kind': 'remove_transition', 'target': 'transition', 'rationale': 'Remove the transition if it was placeholder / debug.'})), do_not=('Do not silently remove the guard — that would change the semantics.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_GUARD_CONST_TRUE': CodeSpec(code='W_GUARD_CONST_TRUE', severity='warning', description="A transition's guard condition folds to the boolean literal ``true`` using the built-in constant folder, so the guard is redundant for all runtime states covered by that literal-only expression.", refs_schema=mappingproxy({'transition_span': CodeFieldSpec(name='transition_span', type='Span', required=False, description='Source span of the transition declaration.', enum=None), 'guard_span': CodeFieldSpec(name='guard_span', type='Span', required=False, description='Source span of the removable guard suffix, including the leading trigger separator when needed. This is reserved for future emitters that can provide a stable guard-only span; the current inspect emitters intentionally omit it.', enum=None), 'folded_value': CodeFieldSpec(name='folded_value', type='bool', required=True, description='Constant-folded guard value (always ``true``).', enum=None), 'from_path': CodeFieldSpec(name='from_path', type='str', required=False, description='Source state path of the transition, or ``[*]`` for an initial transition.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=False, description='Target state path of the transition, or ``[*]`` for an exit transition.', enum=None), 'guard_text': CodeFieldSpec(name='guard_text', type='str', required=False, description='Normalized guard expression text used to disambiguate spanless inspect diagnostics. Pyfcstm and jsfcstm both render this with the shared inspect expression format: canonical boolean/operator spelling, decimal integer literals, and normalized spacing.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='state Root {\n state A;\n state B;\n [*] -> A;\n A -> B : if [(1 + 2) == 3];\n}\n', capability='const_fold', for_llm=ForLlmSpec(summary="The transition's guard is statically known to be ``true`` and does not constrain the transition.", recommended_actions=(mappingproxy({'kind': 'remove_guard', 'target': 'transition', 'rationale': 'Remove the guard if the transition is meant to be unconditional.'}), mappingproxy({'kind': 'fix_guard', 'target': 'transition', 'rationale': 'Rewrite the guard if it was intended to depend on runtime state.'})), do_not=('Do not add a dummy variable dependency only to silence the diagnostic.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_DURING_CONST_ASSIGN': CodeSpec(code='W_DURING_CONST_ASSIGN', severity='warning', description='A concrete ``during`` action assigns a variable to the same literal-only numeric value every cycle. The analyzer only checks the direct statements in ordinary ``during { ... }`` blocks; it skips abstract actions, refs, composite ``during before`` / ``during after`` actions, aspect actions, functions, variables, and nested control flow.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the state that owns the during action.', enum=None), 'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable assigned by the constant during statement.', enum=None), 'value': CodeFieldSpec(name='value', type='number', required=True, description='JSON-stable numeric value assigned on every cycle.', enum=None)}), example_dsl='def int counter = 0;\nstate Root {\n state Idle {\n during { counter = (2 + 3) * 4; }\n }\n [*] -> Idle;\n}\n', capability='const_fold', for_llm=ForLlmSpec(summary='The during block writes the same constant numeric value on every cycle, which often indicates initialization logic was placed in ``during`` instead of ``enter``.', recommended_actions=(mappingproxy({'kind': 'move_to_enter', 'target': 'action', 'rationale': 'Move the assignment to ``enter`` if it should run once on state entry.'}), mappingproxy({'kind': 'rewrite_expression', 'target': 'assignment', 'rationale': 'Use runtime state in the expression if the value should evolve each cycle.'})), do_not=('Do not suppress the warning by adding a meaningless arithmetic no-op.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='lifecycle_action'), 'W_UNUSED_EVENT': CodeSpec(code='W_UNUSED_EVENT', severity='warning', description='An ``event`` declaration is never referenced by any transition.', refs_schema=mappingproxy({'event_qualified_name': CodeFieldSpec(name='event_qualified_name', type='str', required=True, description='Fully qualified event name (e.g. ``Root.SubA.Pause``).', enum=None), 'scope': CodeFieldSpec(name='scope', type='str', required=True, description='Scope at which the event is declared.', enum=('local', 'chain', 'absolute'))}), example_dsl='state Root {\n event Unused;\n state A;\n state B;\n [*] -> A;\n A -> B :: SomethingElse;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary="An event is declared but never triggers any transition, so it is unused from the machine's perspective.", recommended_actions=(mappingproxy({'kind': 'wire_event', 'target': 'transition', 'rationale': 'Add a transition that uses the event if it was meant to be emitted.'}), mappingproxy({'kind': 'remove_event', 'target': 'event_declaration', 'rationale': 'Remove the event if it was added speculatively.'})), do_not=('Do not rename the event to dodge the warning — that just shifts the problem.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='event_declaration'), 'W_DEADLOCK_LEAF': CodeSpec(code='W_DEADLOCK_LEAF', severity='warning', description='A non-pseudo leaf state has no outgoing transition.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the deadlocking leaf state.', enum=None), 'parent_path': CodeFieldSpec(name='parent_path', type='str', required=False, description="Dotted path of the leaf state's parent. Present only when an exit-transition quick-fix can be inserted inside a parent state.", enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Why the leaf is considered a deadlock.', enum=('no_outgoing_transition',)), 'suggested_fix': CodeFieldSpec(name='suggested_fix', type='dict', required=False, description='Structured quick-fix payload for adding a parent exit transition.', enum=None)}), example_dsl='state Root {\n state A;\n [*] -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='This leaf state has no outgoing transition, so once the machine enters it there is no modeled way to leave.', recommended_actions=(mappingproxy({'kind': 'add_transition', 'target': 'state', 'rationale': 'Add a modeled transition to the next intended state.'}), mappingproxy({'kind': 'add_exit_transition', 'target': 'state', 'rationale': 'Add ``State -> [*];`` if the leaf is meant to finish its parent.'})), do_not=('Do not add a self-loop just to silence the warning.',)), emit_tier='static_pipeline', suggested_fix=SuggestedFixSpec(kind='insert', target='deadlock_leaf_exit_transition', anchor_ref='refs.parent_path', text_template='{state_name} -> [*];\n', rationale='Add an exit transition so the leaf can finish its parent state.'), span_object='state_identifier'), 'W_INITIAL_UNCONDITIONAL_MISSING': CodeSpec(code='W_INITIAL_UNCONDITIONAL_MISSING', severity='warning', description='A composite state has no unconditional ``[*] -> child`` entry transition. Guarded or event-triggered entry transitions do not provide a guaranteed initial child.', refs_schema=mappingproxy({'composite_path': CodeFieldSpec(name='composite_path', type='str', required=True, description='Dotted path of the composite state.', enum=None), 'existing_conditional_count': CodeFieldSpec(name='existing_conditional_count', type='int', required=True, description='Number of existing initial transitions that are not unconditional.', enum=None), 'first_child_name': CodeFieldSpec(name='first_child_name', type='str', required=False, description='First declared non-pseudo child state name used as the fallback insertion target.', enum=None), 'suggested_fix': CodeFieldSpec(name='suggested_fix', type='dict', required=False, description='Structured quick-fix payload for inserting an unconditional entry transition.', enum=None)}), example_dsl='def int ready = 0;\nstate Root {\n state A;\n [*] -> A : if [ready > 0];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The composite state can fail to choose an initial child because no unconditional entry transition is declared.', recommended_actions=(mappingproxy({'kind': 'add_unconditional_initial', 'target': 'composite_state', 'rationale': 'Add a fallback ``[*] -> Child;`` entry transition.'}), mappingproxy({'kind': 'simplify_initial', 'target': 'initial_transition', 'rationale': 'Remove the guard or event if the current initial transition should always run.'})), do_not=('Do not assume a guarded initial transition always fires without proving the guard.',)), emit_tier='static_pipeline', suggested_fix=SuggestedFixSpec(kind='insert', target='unconditional_initial_transition', anchor_ref='refs.composite_path', text_template='[*] -> {first_child_name};\n', rationale='Add an unconditional fallback entry transition for the composite state.'), span_object='composite_block'), 'W_FORCED_NEVER_EXPANDS': CodeSpec(code='W_FORCED_NEVER_EXPANDS', severity='warning', description='A forced transition declaration has no concrete child state in its declaration scope to expand from.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the state containing the forced transition.', enum=None), 'original_raw': CodeFieldSpec(name='original_raw', type='str', required=True, description='Original forced transition DSL text.', enum=None)}), example_dsl='state Root {\n state A {\n !* -> [*];\n }\n [*] -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The forced transition declaration expands to zero concrete transitions, so it has no runtime effect.', recommended_actions=(mappingproxy({'kind': 'move_transition', 'target': 'forced_transition', 'rationale': 'Move the forced transition to a composite scope that owns matching children.'}), mappingproxy({'kind': 'remove_transition', 'target': 'forced_transition', 'rationale': 'Remove it if it was speculative.'})), do_not=('Do not leave a zero-expansion forced transition as documentation.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'W_DEAD_NAMED_ACTION': CodeSpec(code='W_DEAD_NAMED_ACTION', severity='warning', description='A named action belongs to an unreachable state and is not referenced by any reachable action ref.', refs_schema=mappingproxy({'function_name': CodeFieldSpec(name='function_name', type='str', required=True, description='Named action identifier.', enum=None), 'defined_in': CodeFieldSpec(name='defined_in', type='str', required=True, description='Dotted path of the state where the action is defined.', enum=None)}), example_dsl='state Root {\n state A;\n state B { enter Cleanup {} }\n [*] -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='This named action cannot run through the reachable state graph and is not referenced from elsewhere.', recommended_actions=(mappingproxy({'kind': 'connect_state', 'target': 'state', 'rationale': 'Add a transition path to the owning state if the action matters.'}), mappingproxy({'kind': 'remove_action', 'target': 'action', 'rationale': 'Remove the action if it is unused scaffolding.'})), do_not=('Do not add an unrelated ref just to silence the warning.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='named_action_declaration'), 'W_UNREFERENCED_VAR': CodeSpec(code='W_UNREFERENCED_VAR', severity='warning', description='A variable cannot affect any transition guard either directly or through the action/effect use-def graph, and no abstract action is visible that might use it outside the DSL.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable name.', enum=None), 'init_value': CodeFieldSpec(name='init_value', type='str', required=True, description='Source text of the initial value.', enum=None), 'definition_delete_anchor': CodeFieldSpec(name='definition_delete_anchor', type='str', required=False, description='Variable name repeated only when the declaration has no DSL reads or writes, so deleting the declaration alone is a safe quick-fix.', enum=None), 'suggested_fix': CodeFieldSpec(name='suggested_fix', type='dict', required=False, description='Structured quick-fix payload for removing the variable definition.', enum=None)}), example_dsl='def int unused = 0;\ndef int ready = 0;\nstate Root {\n state A;\n state B;\n [*] -> A;\n A -> B : if [ready > 0];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary="This variable does not participate in model decisions. It is dead from the DSL's guard-affect data-flow perspective.", recommended_actions=(mappingproxy({'kind': 'remove_variable', 'target': 'variable_definition', 'rationale': 'Remove the variable and related writes if it was speculative scaffolding.'}), mappingproxy({'kind': 'connect_to_guard', 'target': 'guard_or_assignment', 'rationale': 'Add the missing data-flow path if the variable should affect a transition decision.'})), do_not=('Do not add a dummy guard reference only to silence the diagnostic.',)), emit_tier='static_pipeline', suggested_fix=SuggestedFixSpec(kind='delete', target='variable_definition', anchor_ref='refs.definition_delete_anchor', text_template='', rationale='Remove the declaration-only variable because it has no DSL reads or writes.'), span_object='variable_declaration'), 'I_UNREFERENCED_VAR_MAYBE_ABSTRACT': CodeSpec(code='I_UNREFERENCED_VAR_MAYBE_ABSTRACT', severity='info', description='A variable cannot affect any transition guard through DSL data-flow, but at least one visible abstract action may use it outside the DSL.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable name.', enum=None), 'abstract_actions_in_scope': CodeFieldSpec(name='abstract_actions_in_scope', type='list[str]', required=True, description='Abstract action owners that may access the variable. FCSTM variables are global, so this is the full machine abstract-action inventory.', enum=None)}), example_dsl='def int maybe_external = 0;\ndef int ready = 0;\nstate Root {\n state A { enter abstract ExternalHook; }\n state B;\n [*] -> A;\n A -> B : if [ready > 0];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='This variable is unused by DSL guard-affect data-flow, but abstract action implementations may still use it.', recommended_actions=(mappingproxy({'kind': 'inspect_abstract_action', 'target': 'abstract_action', 'rationale': 'Check the external implementation before removing the variable.'}), mappingproxy({'kind': 'remove_variable', 'target': 'variable_definition', 'rationale': 'Remove it only if the abstract action does not need it.'})), do_not=('Do not remove the variable without checking the abstract implementation.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='variable_declaration'), 'W_GUARD_VARS_NEVER_CHANGE': CodeSpec(code='W_GUARD_VARS_NEVER_CHANGE', severity='warning', description='A transition guard reads variables that are never changed by any lifecycle action or transition effect, so the guard only depends on initial values.', refs_schema=mappingproxy({'from_path': CodeFieldSpec(name='from_path', type='str', required=True, description='Source state path of the transition, or [*] for an entry marker.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=True, description='Target state path of the transition, or [*] for an exit marker.', enum=None), 'guard_vars': CodeFieldSpec(name='guard_vars', type='list[str]', required=True, description='Guard variables that never change.', enum=None)}), example_dsl='def int ready = 0;\nstate Root {\n state A;\n state B;\n [*] -> A;\n A -> B : if [ready > 0];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='This guard is controlled only by initial variable values. If those values never change, the transition condition is effectively fixed.', recommended_actions=(mappingproxy({'kind': 'add_write', 'target': 'action_or_effect', 'rationale': 'Add the missing state update if the guard should evolve at runtime.'}), mappingproxy({'kind': 'simplify_guard', 'target': 'transition', 'rationale': 'Simplify or remove the guard if the initial value is intentional.'})), do_not=('Do not add a meaningless self-assignment; it does not model a real change.', 'Do not rewrite the guard to a meaningless constant only to silence this diagnostic.')), emit_tier='static_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_UNWRITTEN_READ_VAR': CodeSpec(code='W_UNWRITTEN_READ_VAR', severity='warning', description='A variable is read in guards or actions but is never written by any lifecycle action or transition effect.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable name.', enum=None), 'read_states': CodeFieldSpec(name='read_states', type='list[str]', required=True, description='State paths where the variable is read.', enum=None), 'init_value': CodeFieldSpec(name='init_value', type='str', required=True, description='Source text of the initial value.', enum=None)}), example_dsl='def int ready = 0;\nstate Root {\n state A;\n state B;\n [*] -> A;\n A -> B : if [ready > 0];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The variable is used as input but never updated after its initial definition, so model behavior may be accidentally constant.', recommended_actions=(mappingproxy({'kind': 'add_write', 'target': 'action_or_effect', 'rationale': 'Add the intended update if the variable should change.'}), mappingproxy({'kind': 'simplify_guard', 'target': 'expression', 'rationale': 'Replace the read with a literal if the value is intentionally constant.'})), do_not=('Do not add a meaningless self-assignment.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='variable_declaration'), 'W_WRITE_ONLY_VAR': CodeSpec(code='W_WRITE_ONLY_VAR', severity='warning', description='A variable is written by actions or effects but is never read by any guard, action, or transition effect expression.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable name.', enum=None), 'written_states': CodeFieldSpec(name='written_states', type='list[str]', required=True, description='State paths where the variable is written.', enum=None)}), example_dsl='def int counter = 0;\nstate Root {\n state A { during { counter = 1; } }\n [*] -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The variable is updated but never influences model behavior.', recommended_actions=(mappingproxy({'kind': 'add_read', 'target': 'guard_or_action', 'rationale': 'Read the variable where it should affect behavior.'}), mappingproxy({'kind': 'remove_variable', 'target': 'variable_definition', 'rationale': 'Remove the variable and writes if they are dead scaffolding.'})), do_not=('Do not add an unused read just to silence the warning.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='variable_declaration'), 'W_REDUNDANT_TRANSITION': CodeSpec(code='W_REDUNDANT_TRANSITION', severity='warning', description='Multiple transitions share the same source, target, event, guard, and effect. Forced and normal transitions with the same behavioral key are counted here as redundant and may also emit W_FORCED_OVERRIDES_NORMAL.', refs_schema=mappingproxy({'from_path': CodeFieldSpec(name='from_path', type='str', required=True, description='Dotted source state path.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=True, description='Dotted target state path.', enum=None), 'duplicate_spans': CodeFieldSpec(name='duplicate_spans', type='list[Span]', required=True, description='Source spans for the duplicate transition declarations, using null for declarations whose span is unavailable.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='state Root {\n state A;\n state B;\n [*] -> A;\n A -> B :: Go;\n A -> B :: Go;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='These transitions are indistinguishable by source, target, event, guard, and effect, so later copies do not add behavior.', recommended_actions=(mappingproxy({'kind': 'remove_duplicate', 'target': 'transition', 'rationale': 'Keep one transition and remove redundant copies.'}), mappingproxy({'kind': 'differentiate_transition', 'target': 'transition', 'rationale': 'Change event, guard, target, or effect if the copy was meant to do something else.'})), do_not=('Do not keep duplicate transitions as comments.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'W_SELF_TRANSITION_NOP': CodeSpec(code='W_SELF_TRANSITION_NOP', severity='warning', description='A leaf self transition has no event, guard, effect, own lifecycle action, or ancestor aspect action.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the state with the no-op self transition.', enum=None), 'from_path': CodeFieldSpec(name='from_path', type='str', required=False, description='Dotted source state path.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=False, description='Dotted target state path.', enum=None), 'transition_span': CodeFieldSpec(name='transition_span', type='Span', required=False, description='Source span of the no-op self transition when available.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='state Root {\n state A;\n [*] -> A;\n A -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The transition points from a state to itself and has no trigger, guard, effect, or re-entry lifecycle behavior, so it does not model useful behavior.', recommended_actions=(mappingproxy({'kind': 'remove_transition', 'target': 'transition', 'rationale': 'Remove the no-op transition.'}), mappingproxy({'kind': 'add_effect_or_trigger', 'target': 'transition', 'rationale': 'Add the missing behavior if this transition is intentional.'})), do_not=('Do not apply this warning to self transitions whose re-entry would run enter, during, exit, or ancestor aspect actions.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'W_EFFECT_SELF_ASSIGN': CodeSpec(code='W_EFFECT_SELF_ASSIGN', severity='warning', description='An effect statement assigns a variable directly to itself.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Source state path when known.', enum=None), 'transition_span': CodeFieldSpec(name='transition_span', type='Span', required=False, description='Source span of the transition containing the effect.', enum=None), 'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Variable assigned to itself.', enum=None), 'effect_self_assign_anchor': CodeFieldSpec(name='effect_self_assign_anchor', type='str', required=False, description='Variable name repeated only when the self-assignment occurrence can be uniquely mapped back to a non-initial effect statement for the same source state and variable.', enum=None), 'suggested_fix': CodeFieldSpec(name='suggested_fix', type='dict', required=False, description='Structured quick-fix payload for removing the no-op effect statement.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='def int x = 0;\nstate Root {\n state A;\n state B;\n [*] -> A;\n A -> B effect { x = x; }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The assignment does not change model state and is likely dead code.', recommended_actions=(mappingproxy({'kind': 'remove_statement', 'target': 'effect_statement', 'rationale': 'Delete the self-assignment.'}), mappingproxy({'kind': 'fix_rhs', 'target': 'expression', 'rationale': 'Replace the right-hand side with the intended expression.'})), do_not=('Do not replace it with another no-op expression.',)), emit_tier='static_pipeline', suggested_fix=SuggestedFixSpec(kind='delete', target='effect_self_assign_statement', anchor_ref='refs.effect_self_assign_anchor', text_template='', rationale='Remove the no-op self-assignment statement.'), span_object='effect_statement'), 'W_FORCED_OVERRIDES_NORMAL': CodeSpec(code='W_FORCED_OVERRIDES_NORMAL', severity='warning', description='A forced transition expands to the same source, target, event, and guard as a normal transition.', refs_schema=mappingproxy({'from_path': CodeFieldSpec(name='from_path', type='str', required=True, description='Dotted source state path.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=True, description='Dotted target state path.', enum=None), 'forced_declaration_span': CodeFieldSpec(name='forced_declaration_span', type='Span', required=False, description='Source span of the forced transition when available.', enum=None), 'normal_transition_span': CodeFieldSpec(name='normal_transition_span', type='Span', required=False, description='Source span of the normal transition when available.', enum=None)}), example_dsl='state Root {\n state A;\n state B;\n [*] -> A;\n A -> B :: Go;\n !A -> B :: Go;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The forced transition duplicates a normal transition, which can make the forced declaration misleading or redundant.', recommended_actions=(mappingproxy({'kind': 'remove_duplicate', 'target': 'forced_transition', 'rationale': 'Remove the forced transition if the normal one already covers it.'}), mappingproxy({'kind': 'adjust_forced_scope', 'target': 'forced_transition', 'rationale': 'Change the forced declaration if it should cover different states.'})), do_not=('Do not keep both unless the generated runtime intentionally treats forced metadata differently.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'W_SHADOWED_EVENT': CodeSpec(code='W_SHADOWED_EVENT', severity='warning', description='A local event name shadows a chain or absolute event with the same leaf name.', refs_schema=mappingproxy({'event_name': CodeFieldSpec(name='event_name', type='str', required=True, description='Shared event leaf name.', enum=None), 'local_path': CodeFieldSpec(name='local_path', type='str', required=True, description='Qualified local event path.', enum=None), 'chain_path': CodeFieldSpec(name='chain_path', type='str', required=True, description='Qualified chain or absolute event path.', enum=None)}), example_dsl='state Root {\n event Tick;\n state A;\n state B;\n [*] -> A;\n A -> B : Tick;\n B -> A :: Tick;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The same event leaf name exists in local and broader scopes, which can make transition triggers easy to misread.', recommended_actions=(mappingproxy({'kind': 'rename_event', 'target': 'event', 'rationale': 'Use distinct event names for different scopes.'}), mappingproxy({'kind': 'adjust_scope', 'target': 'transition_trigger', 'rationale': 'Use ``:`` or ``::`` deliberately and consistently.'})), do_not=('Do not rename only one trigger without checking all emitters.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='event_declaration'), 'W_NAMED_ACTION_SHADOWS_ANCESTOR': CodeSpec(code='W_NAMED_ACTION_SHADOWS_ANCESTOR', severity='warning', description='A named lifecycle action reuses the same function name as an ancestor-scoped named action.', refs_schema=mappingproxy({'function_name': CodeFieldSpec(name='function_name', type='str', required=True, description='Reused named action identifier.', enum=None), 'inner_state_path': CodeFieldSpec(name='inner_state_path', type='str', required=True, description='Dotted path of the state containing the shadowing action.', enum=None), 'outer_state_path': CodeFieldSpec(name='outer_state_path', type='str', required=True, description='Dotted path of the ancestor state containing the shadowed action.', enum=None)}), example_dsl='state Root {\n enter Sync { }\n state Child { enter Sync { } }\n [*] -> Child;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='A nested state defines a named action with the same name as an ancestor action. Relative action refs can become hard to audit because the same leaf name means different functions at different hierarchy levels.', recommended_actions=(mappingproxy({'kind': 'rename_inner_action', 'target': 'named_action', 'rationale': 'Give the nested action a distinct name when it implements different behavior.'}), mappingproxy({'kind': 'use_ref', 'target': 'action', 'rationale': 'Use ``ref`` to reuse the ancestor action when the behavior should be shared.'})), do_not=('Do not leave the shadowing name in place unless the scope distinction is intentional and documented outside the DSL.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='named_action_declaration'), 'W_LITERAL_TYPE_NARROWING': CodeSpec(code='W_LITERAL_TYPE_NARROWING', severity='warning', description='An ``int`` variable is initialized or assigned directly from a floating-point literal, which can imply silent narrowing in generated code. Compound expressions containing floating-point literals are out of scope for this warning.', refs_schema=mappingproxy({'var_name': CodeFieldSpec(name='var_name', type='str', required=True, description='Target variable name.', enum=None), 'target_type': CodeFieldSpec(name='target_type', type='str', required=True, description='Declared target variable type.', enum=('int',)), 'source_expr': CodeFieldSpec(name='source_expr', type='str', required=True, description='Source text of the direct float literal.', enum=None)}), example_dsl='def int truncated = 3.5;\nstate Root { state A; [*] -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary="A direct float literal value flows into an ``int`` variable. The model may truncate or generate target-language code with a narrowing conversion; compound expressions such as ``3.0 + 0.5`` are intentionally outside this warning's scope.", recommended_actions=(mappingproxy({'kind': 'change_type', 'target': 'variable_definition', 'rationale': 'Use ``def float`` when fractional values are intended.'}), mappingproxy({'kind': 'change_literal', 'target': 'expression', 'rationale': 'Use an integer literal or explicit rounding expression when integer behavior is intended.'})), do_not=('Do not silently rely on target-language truncation rules.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='expression'), 'W_ASPECT_NO_DESCENDANT_LEAF': CodeSpec(code='W_ASPECT_NO_DESCENDANT_LEAF', severity='warning', description='A ``>> during`` aspect is attached to a state with no descendant non-pseudo leaf states, so the aspect cannot affect any leaf cycle.', refs_schema=mappingproxy({'composite_path': CodeFieldSpec(name='composite_path', type='str', required=True, description='Dotted path of the state declaring the aspect.', enum=None), 'aspect': CodeFieldSpec(name='aspect', type='str', required=True, description='Aspect direction.', enum=('before', 'after'))}), example_dsl='state Root {\n pseudo state Marker;\n [*] -> Marker;\n >> during before { }\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The aspect action has no descendant leaf state to wrap, so it has no modeled runtime target.', recommended_actions=(mappingproxy({'kind': 'add_leaf', 'target': 'composite_state', 'rationale': 'Add the intended descendant leaf state under this composite.'}), mappingproxy({'kind': 'move_or_remove_aspect', 'target': 'aspect_action', 'rationale': 'Move the aspect to a composite with leaves, or remove it if it is dead scaffolding.'})), do_not=('Do not replace it with a normal during action unless the execution semantics really should change.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='lifecycle_action'), 'W_HIGH_VAR_TO_LEAF_RATIO': CodeSpec(code='W_HIGH_VAR_TO_LEAF_RATIO', severity='warning', description='The number of variables is high relative to the number of non-pseudo leaf states.', refs_schema=mappingproxy({'n_vars': CodeFieldSpec(name='n_vars', type='int', required=True, description='Number of top-level variable definitions.', enum=None), 'n_leaf_states': CodeFieldSpec(name='n_leaf_states', type='int', required=True, description='Number of non-pseudo leaf states.', enum=None), 'actual': CodeFieldSpec(name='actual', type='number', required=True, description='Actual ``n_vars / max(n_leaf_states, 1)`` ratio.', enum=None), 'threshold': CodeFieldSpec(name='threshold', type='number', required=True, description='Effective threshold used for this inspection call.', enum=None)}), example_dsl='def int a = 0;\ndef int b = 0;\ndef int c = 0;\nstate Root { state A; [*] -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='The model has many variables for its number of leaf states, which often indicates flag bloat or speculative state that does not belong in the DSL.', recommended_actions=(mappingproxy({'kind': 'audit_variables', 'target': 'variable_definitions', 'rationale': 'Remove or consolidate variables that do not represent durable machine state.'}), mappingproxy({'kind': 'split_model', 'target': 'state_machine', 'rationale': 'If every variable is meaningful, consider whether the model is combining too many concerns.'})), do_not=('Do not raise the threshold without checking whether the variables influence behavior.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='composite_block'), 'W_DEEP_HIERARCHY': CodeSpec(code='W_DEEP_HIERARCHY', severity='warning', description='The state hierarchy exceeds the configured maximum depth.', refs_schema=mappingproxy({'max_depth': CodeFieldSpec(name='max_depth', type='int', required=True, description='Maximum hierarchy depth found in the model.', enum=None), 'deepest_path': CodeFieldSpec(name='deepest_path', type='str', required=True, description='One deepest state path that triggered the warning.', enum=None), 'actual': CodeFieldSpec(name='actual', type='int', required=True, description='Actual maximum hierarchy depth.', enum=None), 'threshold': CodeFieldSpec(name='threshold', type='int', required=True, description='Effective threshold used for this inspection call.', enum=None)}), example_dsl='state Root { state A { state B { state C; [*] -> C; } [*] -> B; } [*] -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='The hierarchy is deeper than the configured readability threshold, making lifecycle order and transition scope harder to reason about.', recommended_actions=(mappingproxy({'kind': 'flatten_hierarchy', 'target': 'state_tree', 'rationale': 'Collapse levels that do not add lifecycle or transition semantics.'}), mappingproxy({'kind': 'extract_submachine', 'target': 'composite_state', 'rationale': 'Split a deeply nested concern into a separate machine when appropriate.'})), do_not=('Do not flatten a level that carries required enter, exit, during, or aspect semantics.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='state_identifier'), 'W_LARGE_COMPOSITE': CodeSpec(code='W_LARGE_COMPOSITE', severity='warning', description='A composite state has more direct children than the configured threshold.', refs_schema=mappingproxy({'composite_path': CodeFieldSpec(name='composite_path', type='str', required=True, description='Dotted path of the large composite state.', enum=None), 'n_children': CodeFieldSpec(name='n_children', type='int', required=True, description='Number of direct child states.', enum=None), 'actual': CodeFieldSpec(name='actual', type='int', required=True, description='Actual direct child count.', enum=None), 'threshold': CodeFieldSpec(name='threshold', type='int', required=True, description='Effective threshold used for this inspection call.', enum=None)}), example_dsl='state Root { state A; state B; state C; [*] -> A; }\n', capability='pure_static', for_llm=ForLlmSpec(summary='A single composite state owns many direct children, which can make transition review and initial-state reasoning difficult.', recommended_actions=(mappingproxy({'kind': 'group_children', 'target': 'composite_state', 'rationale': 'Introduce meaningful nested composites to group related child states.'}), mappingproxy({'kind': 'split_machine', 'target': 'state_machine', 'rationale': 'Move unrelated child groups into separate machines if they represent separate concerns.'})), do_not=('Do not add arbitrary grouping states that have no semantic meaning.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='composite_block'), 'I_TRANSITION_TO_SELF_VIA_PARENT': CodeSpec(code='I_TRANSITION_TO_SELF_VIA_PARENT', severity='info', description='A composite state transitions to itself, which can intentionally force a re-entry path through child initialization and lifecycle actions.', refs_schema=mappingproxy({'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted path of the self-transitioning composite state.', enum=None), 'crosses_composite': CodeFieldSpec(name='crosses_composite', type='bool', required=True, description='Always ``True`` for this info because the state is composite.', enum=None)}), example_dsl='state Root {\n state Active { state Leaf; [*] -> Leaf; }\n [*] -> Active;\n Active -> Active;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='This is an informational observation rather than a defect: a composite self-transition may be a deliberate reinitialization pattern.', recommended_actions=(mappingproxy({'kind': 'preserve_if_intentional', 'target': 'transition', 'rationale': 'Keep the transition when the model should re-run composite entry semantics.'}), mappingproxy({'kind': 'review_lifecycle', 'target': 'composite_state', 'rationale': 'Confirm the enter/exit and initial-child actions are intended to run.'})), do_not=('Do not delete this transition automatically; it may be the intended reset path.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'I_TRANSITION_NEVER_EVENT_TRIGGERED': CodeSpec(code='I_TRANSITION_NEVER_EVENT_TRIGGERED', severity='info', description='A normal transition has no event and no guard, so it is an unconditional fall-through candidate.', refs_schema=mappingproxy({'from_path': CodeFieldSpec(name='from_path', type='str', required=True, description='Dotted source state path.', enum=None), 'to_path': CodeFieldSpec(name='to_path', type='str', required=True, description='Dotted target state path.', enum=None), 'transition_span': CodeFieldSpec(name='transition_span', type='Span', required=False, description='Source span of the transition when available.', enum=None), 'transition_index': CodeFieldSpec(name='transition_index', type='int', required=False, description='Zero-based index in parent-first model transition order, including expanded forced transitions at their declaring state before ordinary transitions and descendant-state transitions. This is used only as a source-range disambiguation hint when spans are unavailable.', enum=None)}), example_dsl='state Root {\n state A;\n state B;\n [*] -> A;\n A -> B;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The transition is not event-triggered and has no guard. This may be a deliberate unconditional fall-through, so treat it as context rather than a fix target.', recommended_actions=(mappingproxy({'kind': 'keep_if_fallthrough', 'target': 'transition', 'rationale': 'Keep it when the state should immediately advance.'}), mappingproxy({'kind': 'add_trigger_or_guard', 'target': 'transition', 'rationale': 'Add the missing event or guard if the transition should wait.'})), do_not=('Do not add a meaningless event just to silence this info.',)), emit_tier='static_pipeline', suggested_fix=None, span_object='transition'), 'I_NONTRIVIAL_SCC': CodeSpec(code='I_NONTRIVIAL_SCC', severity='info', description='A non-trivial strongly connected component exists in the guard-agnostic leaf-level topology graph.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('topological_only',)), 'representative_state_path': CodeFieldSpec(name='representative_state_path', type='str', required=True, description='One state path from the reported strongly connected component.', enum=None), 'scc': CodeFieldSpec(name='scc', type='list[str]', required=True, description='State paths in the non-trivial strongly connected component.', enum=None)}), example_dsl='state System {\n state A;\n state B;\n [*] -> A;\n A -> B;\n B -> A;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The topology contains a cycle. This is often intentional in state machines, so treat it as a review prompt rather than a direct defect.', recommended_actions=(mappingproxy({'kind': 'review_cycle', 'target': 'topology', 'rationale': 'Confirm the cycle has a deliberate runtime exit or event-driven purpose.'}), mappingproxy({'kind': 'add_exit', 'target': 'transition', 'rationale': 'Add an exit path if the component should not be able to loop forever.'})), do_not=('Do not delete cyclic transitions automatically; cyclic control flow can be valid FCSTM behavior.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='state_identifier'), 'W_TOPOLOGICAL_NOEXIT': CodeSpec(code='W_TOPOLOGICAL_NOEXIT', severity='warning', description='A root-reachable leaf or cycle has no guard-agnostic route to the root exit sink.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('topological_only',)), 'representative_state_path': CodeFieldSpec(name='representative_state_path', type='str', required=True, description='One state path from the no-exit counterexample.', enum=None), 'counterexample_kind': CodeFieldSpec(name='counterexample_kind', type='str', required=True, description='Shape of the topological counterexample.', enum=('trap_cycle', 'deadlock')), 'scc': CodeFieldSpec(name='scc', type='list[str]', required=True, description='Trap-cycle component paths, or an empty list for a deadlock leaf.', enum=None)}), example_dsl='state System {\n state A;\n state B;\n [*] -> A;\n A -> B;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='From the current topology, execution can enter a region that has no structural path to terminate at the root exit.', recommended_actions=(mappingproxy({'kind': 'add_exit_transition', 'target': 'topology', 'rationale': 'Add a route from the stuck state or cycle to an exit-capable path.'}), mappingproxy({'kind': 'mark_intentional', 'target': 'review_note', 'rationale': 'If the model intentionally never exits, keep the behavior and document it.'})), do_not=('Do not add an unconditional exit without checking lifecycle and event semantics.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='state_identifier'), 'I_TOPOLOGICAL_NON_TERMINATING': CodeSpec(code='I_TOPOLOGICAL_NON_TERMINATING', severity='info', description='The topology does not force all root-reachable executions to eventually reach the root terminator.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('topological_only',)), 'representative_state_path': CodeFieldSpec(name='representative_state_path', type='str', required=True, description='One state path from the non-terminating counterexample.', enum=None), 'counterexample_path': CodeFieldSpec(name='counterexample_path', type='list[str]', required=True, description='Representative cycle or deadlock path reported by topology verify.', enum=None)}), example_dsl='state System {\n state A;\n [*] -> A;\n A -> A;\n A -> [*];\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The structural graph allows a path that can avoid termination forever. This may be a valid service loop, but it should be reviewed explicitly.', recommended_actions=(mappingproxy({'kind': 'review_nontermination', 'target': 'topology', 'rationale': 'Decide whether the non-terminating path is intended.'}), mappingproxy({'kind': 'add_progress_transition', 'target': 'transition', 'rationale': 'Add an exit or progress edge if all executions should eventually finish.'})), do_not=('Do not treat every loop as a bug; long-running control loops are common state-machine behavior.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='state_identifier'), 'W_EVENT_UNREACHABLE_EMIT': CodeSpec(code='W_EVENT_UNREACHABLE_EMIT', severity='warning', description='A used event has no consumer source that is reachable in the guard-agnostic topology graph.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('topological_only',)), 'event_name': CodeFieldSpec(name='event_name', type='str', required=True, description='Qualified event name whose consumers are unreachable.', enum=None), 'consumer_count': CodeFieldSpec(name='consumer_count', type='int', required=True, description='Number of unreachable consumer transitions represented by this finding.', enum=None)}), example_dsl='state System {\n event Panic;\n state A;\n state LostA;\n state LostB;\n [*] -> A;\n LostA -> A : Panic;\n LostB -> A : Panic;\n}\n', capability='pure_static', for_llm=ForLlmSpec(summary='The event is used by transitions, but those transition sources are not reachable from the root entry topology.', recommended_actions=(mappingproxy({'kind': 'connect_consumer', 'target': 'transition_source', 'rationale': 'Add a topology path that reaches the state consuming the event.'}), mappingproxy({'kind': 'remove_dead_event_path', 'target': 'transition', 'rationale': 'Remove or rewrite the unreachable event transition if it is dead scaffolding.'})), do_not=('Do not add an emitter for this event if no reachable state can consume it.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='event_declaration'), 'W_DEAD_GUARD': CodeSpec(code='W_DEAD_GUARD', severity='warning', description='A transition guard is unsatisfiable under model variable type and runtime-definedness constraints.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the guarded transition.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None)}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A;\n A -> B : if [x > 1 && x < 0];\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='SMT proves the guard cannot become true for any valid variable valuation. This differs from W_GUARD_CONST_FALSE, which only reports literal-only guards folded syntactically to false.', recommended_actions=(mappingproxy({'kind': 'fix_guard', 'target': 'transition', 'rationale': 'Relax or correct the contradictory guard condition.'}), mappingproxy({'kind': 'remove_transition', 'target': 'transition', 'rationale': 'Remove the transition if the guard intentionally makes it unreachable.'})), do_not=('Do not replace the guard with true unless the transition really should become unconditional.', 'Do not confuse this SMT finding with W_GUARD_CONST_FALSE; variables and runtime-definedness matter here.')), emit_tier='verify_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_GUARD_TAUTOLOGY': CodeSpec(code='W_GUARD_TAUTOLOGY', severity='warning', description='A transition guard is true for every variable valuation that satisfies model type and runtime-definedness constraints.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the guarded transition.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None)}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A;\n A -> B : if [x >= 0 || x < 0];\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='SMT proves the guard is always true under the modeled variable constraints. This differs from W_GUARD_CONST_TRUE, which only reports literal-only guards folded syntactically to true.', recommended_actions=(mappingproxy({'kind': 'remove_redundant_guard', 'target': 'transition', 'rationale': 'Remove the guard if the transition should be unconditional.'}), mappingproxy({'kind': 'tighten_guard', 'target': 'transition', 'rationale': 'Replace the guard if it was intended to restrict when the transition fires.'})), do_not=('Do not assume every tautological guard is wrong; it may document intent.', 'Do not confuse this SMT finding with W_GUARD_CONST_TRUE; variables and runtime-definedness matter here.')), emit_tier='verify_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_FORCED_GUARD_UNSAT': CodeSpec(code='W_FORCED_GUARD_UNSAT', severity='warning', description='A forced-transition guard cannot be satisfied under declaration initializer values.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the forced transition.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None), 'scope': CodeFieldSpec(name='scope', type='str', required=True, description='Initial-value scope used by the verify algorithm.', enum=('dsl_def_init_only',))}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A;\n !A -> B : if [x > 0];\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='The forced transition expands structurally, but its guard is false under top-level declaration initializers.', recommended_actions=(mappingproxy({'kind': 'adjust_initializer', 'target': 'variable_definition', 'rationale': 'Change the initializer if the forced transition must be possible at startup.'}), mappingproxy({'kind': 'adjust_forced_guard', 'target': 'transition', 'rationale': 'Correct the guard if it does not match the intended forced-transition entry condition.'})), do_not=('Do not delete the forced transition solely because it is impossible at declaration time; later runtime values may still matter for normal guards.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='guard_expression'), 'W_EFFECT_SMT_NO_OP': CodeSpec(code='W_EFFECT_SMT_NO_OP', severity='warning', description='A transition effect leaves all model variables unchanged for every guarded, runtime-defined execution.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the transition with the effect.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None)}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A;\n A -> B : if [x >= 0] effect { x = x + 0; };\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='Symbolic execution proves the effect does not change any persistent model variable when its guard is enabled.', recommended_actions=(mappingproxy({'kind': 'remove_effect', 'target': 'effect_block', 'rationale': 'Remove the effect if it is dead or only placeholder logic.'}), mappingproxy({'kind': 'change_assignment', 'target': 'effect_statement', 'rationale': 'Update the effect so it changes the intended persistent variable.'})), do_not=('Do not report block-local temporary-only changes as state changes; they disappear after the effect block.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='effect_statement'), 'I_EFFECT_GUARD_CONTRADICT': CodeSpec(code='I_EFFECT_GUARD_CONTRADICT', severity='info', description='A transition effect makes the same transition guard false after every guarded, runtime-defined execution.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the transition with the effect.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None)}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A;\n A -> B : if [x > 0] effect { x = 0; };\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='The effect immediately invalidates the guard that enabled the transition. This may be a deliberate one-shot or latch reset pattern.', recommended_actions=(mappingproxy({'kind': 'review_one_shot', 'target': 'transition', 'rationale': 'Confirm the effect is meant to falsify the enabling guard.'}), mappingproxy({'kind': 'adjust_effect_or_guard', 'target': 'transition', 'rationale': 'Change either side if the post-state should still satisfy the guard.'})), do_not=('Do not treat this info as an automatic defect; guard-reset effects are often intentional.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='effect_statement'), 'W_TRANSITION_SHADOWED': CodeSpec(code='W_TRANSITION_SHADOWED', severity='warning', description='A later outgoing transition is fully covered by earlier same-source triggers and therefore cannot be selected.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'transition': CodeFieldSpec(name='transition', type='dict', required=True, description='Raw verify transition payload for the shadowed transition.', enum=None), 'transition_summary': CodeFieldSpec(name='transition_summary', type='str', required=True, description='Stable human-readable transition summary derived from the raw payload.', enum=None), 'source_state_path': CodeFieldSpec(name='source_state_path', type='str', required=True, description='Dotted source state path whose outgoing order creates the shadowing.', enum=None), 'reason': CodeFieldSpec(name='reason', type='str', required=True, description='Shadowing reason classification.', enum=('guard_shadow', 'duplicate_event', 'unconditional_catchall', 'prior_trigger_cover')), 'shadowed_by_count': CodeFieldSpec(name='shadowed_by_count', type='int', required=True, description='Number of earlier transitions covering this transition.', enum=None), 'shadowed_by': CodeFieldSpec(name='shadowed_by', type='list[str]', required=True, description='Stable summaries of earlier transitions that shadow this transition.', enum=None)}), example_dsl='state System {\n state A;\n state B;\n state C;\n [*] -> A;\n A -> B;\n A -> C;\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='Transition ordering means an earlier same-source transition consumes all cases that could have reached this later transition.', recommended_actions=(mappingproxy({'kind': 'reorder_transitions', 'target': 'transition_list', 'rationale': 'Move the more specific transition before the broader predecessor if both are needed.'}), mappingproxy({'kind': 'remove_shadowed_transition', 'target': 'transition', 'rationale': 'Remove the later transition if the predecessor intentionally covers all cases.'})), do_not=('Do not reorder transitions without checking FCSTM first-match semantics.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='transition'), 'I_ENTER_DURING_CONTRADICT': CodeSpec(code='I_ENTER_DURING_CONTRADICT', severity='info', description='Entry-time assignments make a first-cycle during branch condition predetermined; the enter postcondition does not leave both during branches feasible.', refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'state_path': CodeFieldSpec(name='state_path', type='str', required=True, description='Dotted leaf state path inspected by the lifecycle algorithm.', enum=None), 'condition': CodeFieldSpec(name='condition', type='str', required=True, description='First-cycle during condition proven predetermined.', enum=None), 'condition_source': CodeFieldSpec(name='condition_source', type='str', required=True, description='Source label for the condition inside the during operation block.', enum=None), 'branch_taken': CodeFieldSpec(name='branch_taken', type='str', required=True, description='Branch direction forced after entry.', enum=('true', 'false'))}), example_dsl='def int x = 0;\nstate System {\n state A {\n enter { x = 1; }\n during {\n if [x > 0] { x = x + 1; } else { x = x - 1; }\n }\n }\n [*] -> A;\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='After entering the leaf, the first during cycle already has a fixed branch decision. This may be intentional initialization logic, but the branch is not genuinely conditional on the first cycle.', recommended_actions=(mappingproxy({'kind': 'review_enter_during_relation', 'target': 'lifecycle_action', 'rationale': 'Check whether enter assignments intentionally force the first during branch.'}), mappingproxy({'kind': 'adjust_condition_or_enter', 'target': 'state', 'rationale': 'Change the enter action or during condition if both branches should remain possible.'})), do_not=('Do not remove the enter action just to make the first-cycle branch variable; entry side effects may be required.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='lifecycle_action'), 'W_COMPOSITE_INIT_INCOMPLETE': CodeSpec(code='W_COMPOSITE_INIT_INCOMPLETE', severity='warning', description="A composite state's initial transitions do not jointly cover all variable and event inputs.", refs_schema=mappingproxy({'algorithm_name': CodeFieldSpec(name='algorithm_name', type='str', required=True, description='Verify registry algorithm that produced the raw finding.', enum=None), 'verification_scope': CodeFieldSpec(name='verification_scope', type='str', required=True, description='Verify scope for this finding.', enum=('smt_local',)), 'composite_path': CodeFieldSpec(name='composite_path', type='str', required=True, description='Dotted composite state path whose initial transitions have a coverage gap.', enum=None), 'init_transition_count': CodeFieldSpec(name='init_transition_count', type='int', required=True, description='Number of initial transitions considered for the composite.', enum=None), 'init_transitions': CodeFieldSpec(name='init_transitions', type='list[str]', required=True, description='Stable summaries of the initial transitions considered.', enum=None), 'witness': CodeFieldSpec(name='witness', type='str_or_null', required=False, description='Solver model demonstrating an uncovered input valuation, when available.', enum=None)}), example_dsl='def int x = 0;\nstate System {\n state A;\n state B;\n [*] -> A : if [x > 0];\n [*] -> B : if [x < 0];\n}\n', capability='requires_solver', for_llm=ForLlmSpec(summary='There is a variable/event assignment for which none of the composite initial transitions can fire, so entry can get stuck at the composite.', recommended_actions=(mappingproxy({'kind': 'add_catch_all_initial', 'target': 'composite_state', 'rationale': 'Add an unconditional fallback initial transition if one child should be the default.'}), mappingproxy({'kind': 'cover_missing_guard_case', 'target': 'initial_transition', 'rationale': 'Adjust guarded initial transitions so their union covers the missing valuation.'})), do_not=('Do not add overlapping initial transitions without reviewing declaration order and guard intent.',)), emit_tier='verify_pipeline', suggested_fix=None, span_object='composite_block')})
Mapping
code -> CodeSpecloaded fromcodes.yamlat import time. Wrapped intypes.MappingProxyTypeso downstream callers cannot mutate the registry by accident.
CodesSchemaError
- class pyfcstm.diagnostics.codes.CodesSchemaError[source]
Raised when
codes.yamlis structurally invalid.Subclasses
ValueErrorso genericexcept ValueErrorhandlers still catch it, but downstream tooling that wants to distinguish “diagnostics package broken” from a domain-levelValueErrorcan use a tighter handler.
CodeFieldSpec
- class pyfcstm.diagnostics.codes.CodeFieldSpec(name: str, type: str, required: bool, description: str, enum: Tuple[str, ...] | None = None)[source]
Schema for a single field inside
CodeSpec.refs_schema.- Parameters:
name (str) – Field name as it will appear in
ModelDiagnostic.refs.type (str) – Field type token. Must be one of the allowed type tokens documented at the top of
codes.yaml.required (bool) – Whether this field must be present when the diagnostic is emitted.
description (str) – Human-readable explanation of the field.
enum (Optional[Tuple[str, ...]]) – Optional tuple of allowed string values for the field. When present, downstream emit-test infrastructure (and any future runtime validator) checks that
refs[field]is a member of the tuple.Nonemeans the field has no enumeration constraint.
ForLlmSpec
- class pyfcstm.diagnostics.codes.ForLlmSpec(summary: str, recommended_actions: Tuple[Mapping[str, Any], ...], do_not: Tuple[str, ...])[source]
Structured guidance attached to a diagnostic code for downstream LLM consumers.
Emitted
E_*,W_*, andI_*codes carry this payload so that LLM agent loops can read structured fix recommendations instead of regex-ing the human-readablemessage. All catalogued codes are expected to provide this field unless the loader is explicitly handling a forward-compatibility case.- Parameters:
summary (str) – One-line description aimed at LLM consumers.
recommended_actions (Tuple[Mapping[str, Any], ...]) – Ordered list of concrete fix suggestions. Each entry is a free-form dict; downstream tooling is expected to treat the list as a hint rather than a closed schema.
do_not (Tuple[str, ...]) – List of anti-pattern strings the LLM should avoid.
SuggestedFixSpec
- class pyfcstm.diagnostics.codes.SuggestedFixSpec(kind: str, target: str, anchor_ref: str, text_template: str, rationale: str)[source]
Structured auto-fix metadata declared by
codes.yaml.- Parameters:
kind (str) – Edit operation kind:
insert,delete, orreplace.target (str) – Semantic target kind, such as
variable_definition.anchor_ref (str) – Reference to a field in the emitted refs payload, written as
refs.<field>.text_template (str) – Optional edit text template.
insertandreplaceuse it;deletenormally leaves it empty.rationale (str) – Short reason suitable for LLM/UI display.
CodeSpec
- class pyfcstm.diagnostics.codes.CodeSpec(code: str, severity: str, description: str, refs_schema: Mapping[str, CodeFieldSpec], example_dsl: str | None = None, capability: str = 'pure_static', for_llm: ForLlmSpec | None = None, emit_tier: str = 'static_pipeline', suggested_fix: SuggestedFixSpec | None = None, span_object: str | None = None)[source]
Full specification for a single diagnostic code.
- Parameters:
code (str) – Stable code identifier (e.g.
'E_UNDEFINED_VAR').severity (str) –
'error','warning', or'info'.description (str) – Human-readable description of when the code fires.
refs_schema (Mapping[str, CodeFieldSpec]) – Mapping
field_name -> CodeFieldSpecdescribing the structured payload for diagnostics with this code. The mapping itself is atypes.MappingProxyTypeso downstream callers cannot mutate the registry by accident.example_dsl (str, optional) – Minimal DSL snippet that triggers the code, defaults to
None.capability (str, optional) – Which analysis tier this code belongs to. Layer 2 declares this required when present; unset means
'pure_static'for grandfathered Layer 1 codes.for_llm (ForLlmSpec, optional) – Structured guidance for downstream LLM consumers. Expected on catalogued codes so downstream tooling can consume structured remediation guidance. Still typed as
Optionalso the loader can tolerate forward-compatibility cases.emit_tier (str, optional) – Which emit pipeline actually fires this code.
'static_pipeline'(default) means the code fires duringparse_dsl_node_to_state_machine/ the equivalent jsfcstmcollectDocumentDiagnosticsstatic analysis pass.'lookup_api'means the code only fires through explicit runtime resolver APIs (e.g.State.resolve_event) and is never produced by the static pipeline.'partial_static_pipeline'marks codes whose static-pipeline emit is implemented on one end only (typically jsfcstm) — downstream LLM consumers should not block waiting for the missing end.'verify_pipeline'marks diagnostics emitted only by optional Python verify integration. The field lets dispatchers register handlers based on the actual emit channel.span_object (str, optional) – Semantic source object identified by the primary diagnostic span. Repository entries declare this to make source-slice assertions and downstream UI behavior explicit.
load_codes
- pyfcstm.diagnostics.codes.load_codes(path: str) Dict[str, CodeSpec][source]
Load and validate a
codes.yamlfile from disk.- Parameters:
path (str) – Filesystem path to the YAML file.
- Returns:
Mapping
code -> CodeSpecparsed from the file.- Return type:
Dict[str, CodeSpec]
- Raises:
FileNotFoundError – If
pathdoes not exist.CodesSchemaError – If the YAML structure does not match the expected schema, or if a code uses an unknown severity / type token. Subclasses
ValueErrorfor backwards compatibility with genericexcept ValueErrorhandlers.
Example:
>>> import os >>> from pyfcstm.diagnostics.codes import load_codes >>> path = os.path.join(os.path.dirname(__file__), 'codes.yaml')