Enforce Behavior Annex condition restrictions across component categories and modes 🤖 - #3233
Merged
Merged
Conversation
AS5506/3 Rev. A D.3 restricts external conditions by component category and by in modes context: a thread and a subprogram must not use one, the transitions out of one complete state of a device must use either only external conditions or only dispatch conditions, and a subclause with an in modes statement must not use one. D.3 also applies an ancestor's subclauses to a descendant unless the descendant declares its own, which replace them completely. Issue3186Test models each restriction through ordinary embedded AADL validation and asserts the exact diagnostic, with a positive control beside each one: a process leaving an execution state on an event, a device leaving a mode-representing complete state on external conditions alone, and an in modes subclause using an execute condition. It also asserts that the triggers of an external condition out of a mode-representing complete state are compared with the corresponding mode transition, which is how a component of a category other than thread and subprogram describes a mode transition. The subprogram fixture triggers on an outgoing event port because core AADL admits no other event port on a subprogram, so no subprogram can name the incoming port the D.3 event_trigger production asks for. The rule constrains the form of the condition rather than its triggers. Inheritance.aadl and ModalSubclauses.aadl cover the access path: inheritance from an ancestor implementation, replacement by a descendant, fallback to the type of an implementation that declares none, every modal subclause of a classifier, and selection by mode including a subclause without an in modes statement. BehaviorAnnexGrammarTest matched a subclause by its annex text followed by a semicolon, so it silently skipped every subclause with an in modes statement, and where another subclause followed one it paired their delimiters across the two. Its pattern now accepts the statement, which brings ModalSubclauses.aadl and the existing InModes.aadl under that test. The corpus goldens record the new fixtures in both registration states. The one existing golden that changes is issue2147, whose thread group leaves a mode-representing complete state on an external condition while declaring no mode transition: the D.3.(C4) comparison now reads external condition triggers as well, so that model reports the finding its dispatch equivalent already produced. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ries and modes AadlBaConsistencyRulesChecker gains the two D.3 condition rules the rules driver can decide from the strict model. The first rejects an external condition in a thread or a subprogram, naming the conditions that category uses instead; the driver checks it once per declaration so a multi-source transition reports once. The second rejects a mixture of external and dispatch conditions out of one complete state of a device, reporting each condition of that state and naming it, the way every conflicting otherwise transition of a state is reported; the driver checks it once for the subclause because the rule compares the conditions of several transitions. Both rules are cited by section. The numbered rule list these classes follow comes from the 0.94 draft, which orders the D.3 rules differently, so no number carries over. D.3.(C4) now reads the triggers of an external condition as well as those of a dispatch condition. AS5506/3 Rev. A D.3 lets a component of any category other than thread and subprogram describe a mode transition with an external condition, and C4 exists to compare such a transition with the corresponding mode transition triggers; it previously returned false without a diagnostic for every condition that was not a dispatch condition. The comparison reads triggers without their logical operators, as it already did for dispatch conditions. BehaviorAnnexValidator rejects an external condition in a subclause with an in modes statement. Core AADL keeps that statement on the enclosing DefaultAnnexSubclause and the strict model does not carry it, so this rule is checked on the declarative model, where the complete-state mode-refinement rule already is. DeclarativeToStrictTranslator exposes hasInModes for it and defines canRefineModes as its negation, which changes no behavior. D.3 states no per-category restriction on internal conditions beyond the execution-state rule already enforced, so none is added. BehaviorAnnexUtil.getBehaviorAnnexSubclauses puts the D.3 inheritance and replacement rule on the public access path: the nearest classifier in the extends order that declares a subclause supplies all of them, and an implementation falls back to its type. A mode-selecting overload uses the in modes statement core AADL retains, matching mode names case insensitively because an applicable subclause can be declared by an ancestor. Mode applicability is not duplicated into the strict model: every consumer of getStrictModel already holds the subclause that carries it. The subcomponent override rule is not enforced. It selects which subclause a consumer interprets for an instance rather than constraining a declaration, so it belongs to the consumer that walks the instance hierarchy; conformance.md records that. Fixes #3186 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3186
Cause and correction
AS5506/3 Rev. A D.3 restricts external conditions by component category and by
in modescontext, and defines how a descendant classifier inherits or replaces the Behavior Annex subclauses of an ancestor. None of that was enforced, and the one C4 mode-related consistency check read only dispatch conditions.AadlBaConsistencyRulesCheckergains the two D.3 condition rules the rules driver can decide from the strict model. The first rejects an external condition in a thread or a subprogram, naming the conditions that category uses instead;AadlBaRulesCheckersDriverchecks it once per declaration, so a multi-source transition reports once. The second rejects a mixture of external and dispatch conditions out of one complete state of a device, reporting each condition of that state; the driver checks it once for the subclause because the rule compares the conditions of several transitions.falsewithout a diagnostic for every condition that was not a dispatch condition. The comparison reads triggers without their logical operators, as it already did for dispatch conditions.BehaviorAnnexValidatorrejects an external condition in a subclause with anin modesstatement. Core AADL keeps that statement on the enclosingDefaultAnnexSubclauseand the strict model does not carry it, so this rule is checked on the declarative model, where the complete-state mode-refinement rule already is.DeclarativeToStrictTranslatorexposeshasInModesfor it and definescanRefineModesas its negation, which changes no behavior.BehaviorAnnexUtil.getBehaviorAnnexSubclausesputs the D.3 inheritance and replacement rule on the public access path: the nearest classifier in the extends order that declares a subclause supplies all of them, and an implementation falls back to its type. A mode-selecting overload uses thein modesstatement core AADL retains, matching mode names case insensitively because an applicable subclause can be declared by an ancestor. Mode applicability is not duplicated into the strict model: every consumer ofgetStrictModelalready holds the subclause that carries it.Not enforced: the subcomponent override rule. It selects which subclause a consumer interprets for an instance rather than constraining a declaration, so it belongs to the consumer that walks the instance hierarchy;
ba/doc/conformance.mdrecords that, along with the V05 row update.Regression model and assertions
ba/org.osate.ba.tests/models/issue3186/is a separate OSATE project with one fixture per restriction and one per access-path case.Issue3186Test(15 tests) parses each through ordinary embedded AADL validation, asserts no unrelated issues, and then asserts the exact diagnostic, with a positive control beside each rejection:threadCannotUseAnExternalCondition,subprogramCannotUseAnExternalCondition, and the controlexternalConditionIsAcceptedOutOfAnExecutionState(a process leaving an execution state on an event).deviceCannotMixExternalAndDispatchConditionsOutOfOneCompleteStateand the controldeviceMayLeaveACompleteStateOnExternalConditionsAlone.externalConditionTriggersMustMatchTheModeTransition, the C4 comparison for a mode-representing complete state.inModesSubclauseCannotUseAnExternalConditionand the controlinModesSubclauseMayUseAnExecuteCondition.classifierSubclauseAppliesToItself,ancestorSubclauseAppliesToADescendantThatDeclaresNone,descendantSubclauseReplacesTheAncestorOne,typeSubclauseAppliesToAnImplementationThatDeclaresNone,everyModalSubclauseOfTheClassifierApplies,modalSubclausesAreSelectedByMode,subclauseWithoutInModesIsSelectedInEveryMode.The subprogram fixture triggers on an outgoing event port because core AADL admits no other event port on a subprogram, so no subprogram can name the incoming port the D.3
event_triggerproduction asks for; the rule constrains the form of the condition rather than its triggers.Two existing tests are touched:
BehaviorAnnexGrammarTest.parseAcceptedBehaviorAnnexCorpusmatched a subclause by its annex text followed by a semicolon, so it silently skipped every subclause with anin modesstatement, and where another subclause followed one it paired their delimiters across the two. The pattern now accepts the statement, which brings the newModalSubclauses.aadland the existingInModes.aadlunder that test.issue2147, whose thread group leaves a mode-representing complete state on an external condition while declaring no mode transition: with C4 now reading external condition triggers, that model reports the finding its dispatch equivalent already produced.Validation
Tests were run from the repository root with the local profile before the branch was pushed; all results below are from that run.
ba/org.osate.ba.tests: 174 tests, 0 failures, 0 errors, 0 skipped (Issue3186Testcontributes 15).ba/org.osate.xtext.aadl2.ba.tests: 15 tests, 0 failures, 0 errors.core/org.osate.core.tests: 876 tests, 0 failures, 0 errors.The clean root-reactor build documented in
CLAUDE.mdwas not carried through to completion on this branch at the user's direction; CI on this PR is the first complete build of it.Dependencies and merge order
None. The branch is based on
537f7ed139, already onmaster, and does not depend on any unmerged PR.Residual risk
issue2147's golden change is a behavior change for existing models: any component of a category other than thread or subprogram that leaves a mode-representing complete state on an external condition without a corresponding mode transition now reports the C4 finding. That is the intended effect of the rule, but it can surface new diagnostics in existing user models.getBehaviorAnnexSubclausesis new API onBehaviorAnnexUtil; no existing consumer calls it yet, so it is exercised only by the regression test.ba/doc/conformance.md.🤖 Generated with Claude Code