Skip to content

Expand flow specifications over feature group arrays 🤖 - #3114

Open
lwrage wants to merge 2 commits into
masterfrom
3113_expand_flows_over_group_arrays
Open

Expand flow specifications over feature group arrays 🤖#3114
lwrage wants to merge 2 commits into
masterfrom
3113_expand_flows_over_group_arrays

Conversation

@lwrage

@lwrage lwrage commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #3113

Cause and correction

FlowSpecArrayExpander decided whether a flow specification end was an array element by testing
FeatureInstance.getIndex() on the end itself. A feature declared inside a feature group type is never
indexed — the index sits on the enclosing feature group instance — so an end reached through a feature
group that is an array looked like a scalar, the pairing was skipped, and every element but the first was
left without a flow specification instance. Nothing was reported.

ConnectionArrayExpander already treats an indexed enclosing feature group instance as a dimension of a
connection end, so the connection set covered every element while the flow specifications covered only
the first, and the end-to-end flows built over them inherited the disagreement.

The fix adds arrayEnd, which walks up from an end to the indexed feature instance — the end itself when
it is a feature array, the enclosing feature group instance otherwise — recording the features that lead
back down. The dimension size is the number of elements of that feature instance, and elementAt takes
the sibling with the paired-up index and follows the recorded features down again. A direct feature array
has an empty descent, so it behaves exactly as before.

At most one step of a path is ever indexed, because a feature declared inside a feature group type may not
be an array (AS5506D section 8 legality rule 3, enforced by the validator and reported by
InstantiateModel.instantiateFGFeatures). The nearest indexed ancestor is therefore the only one, which
the code and its javadoc state explicitly.

Nothing else needed changing. The pairing arithmetic in ArrayPatternExpansion does not care where an
index came from, and the end-to-end flows already fork over the flow specification instances of a
specification and keep a branch on its element by requiring the next connection instance to start exactly
at the previous element's destination feature instance.

Regression model and assertions

core/org.osate.core.tests/models/issue3113/Issue3113.aadl declares an array of feature groups on two
devices, a flow source and a flow path over it on one and a flow sink on the other, a feature group
connection that joins the two arrays, and an end-to-end flow over that connection. emit has one array
end and relay has two, which is the pairing the default One_To_One applies to.

Issue3113Test asserts:

  • one flow specification instance per element, named and paired the way Flow specifications need to be able to reference features in a feature array #2787 established for an end that
    is a feature array itself: emit_1/emit_2, relay_1/relay_2, absorb_1/absorb_2;
  • one end-to-end flow instance per element, ete_1 and ete_2, each over the connection instance of its
    own element;
  • the four connection instances, alongside the flows, so the assertions show the two sides agreeing rather
    than a bare count;
  • no diagnostics, so the silence is not traded for a warning.

Before the fix both tests failed with everything pinned to element 1: three flow specification instances
instead of six, and a single ete. The connection assertion passed before the fix, which is what
localizes the defect to the flow side.

Supporting change

Serializer1Test.testFlowSpecification recorded the old behavior for the one array feature group in its
fixture, so its f7 becomes f7_1 and f7_2. Its f6, an array declared inside a feature group type, is
still instantiated as a single feature and still a single flow. Folded into the fix commit so that every
commit on the branch is green.

Validation

  • mvn -Dtest=Issue3113Test -DfailIfNoTests=false: 2/2 pass; both fail before the fix for the intended
    reason.
  • Full org.osate.core.tests: 836 tests, 0 failures. Per-class non-zero counts confirmed for
    Issue2787Test (6), Issue1833Test (9), Issue3037ArrayFeatureGroupTest (7),
    Issue3037FeatureArrayTest (4), FlowSpecificationInstantiationTest (4),
    FeatureArrayInstantiationTest (3), FeatureGroupInstantiationTest (6), Issue3048Test, Issue3049Test.
  • Clean root-reactor build, mvn -s releng/osate.releng/settings.xml -Plocal -Dtycho.localArtifacts=ignore -Dpr.build=true -Dsign=false -Dspotbugs=false -Dcodecoverage=false -Djavadoc=false -DfailIfNoTests=false clean install: BUILD SUCCESS, 2862 tests, 0 failures, 0 errors. Reproduced with -T6.

Dependencies

None. Branched from master at 7729ae9 and independent of the other open issue branches.

Residual risk

elementAt still falls back to the original end when a lookup misses, as it always did, so an internal
inconsistency would pin the element rather than fail. No diagnostic was added, to keep the fix narrow.

Nested feature group arrays are not a concern for the reason above: a feature inside a feature group type
may not be an array, so no path has two indexed steps. Note that ConnectionArrayExpander carries a single
fgidx and makes the same assumption.

🤖 Generated with Claude Code

sei-lwrage and others added 2 commits August 26, 2026 15:33
A flow specification end reached through a feature group that is an array becomes a
single flow specification instance on the first element of that group. The expansion
decides whether an end is an array element from the index of the end itself, and a
feature of a feature group type is never indexed: the index sits on the enclosing
feature group instance.

The model declares an array of feature groups on two devices, a flow source and a flow
path over it on one and a flow sink on the other, a feature group connection that joins
the two arrays, and an end to end flow over that connection. Connection instantiation
already expands the connection across both elements, which the test asserts alongside
the flows, so the assertions show the two sides disagreeing rather than a bare count.

The flow specification assertion expects one instance per element, named and paired the
way issue #2787 established for an end that is a feature array itself, and the end to
end flow assertion expects one instance per element over the connection instance of that
element. Both fail today with everything pinned to element 1 and nothing reported. The
diagnostics assertion keeps the silence from being traded for a warning.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An end reached through a feature group that is an array kept the first element of that
group. The expansion decided whether an end was an array element from the index of the
end itself, and a feature of a feature group type is never indexed, so the pairing was
skipped and every element but the first was left without a flow specification instance,
silently. Connection instantiation expands a connection across the elements of such a
group, so the connection set and the flow specifications disagreed, and the end to end
flows built over the flow specification instances inherited the disagreement.

Find the array element an end belongs to by walking up from the end: the end itself when
it is a feature array, and otherwise the enclosing feature group instance that carries
the index, remembering the features that lead back down. The size of the dimension is
the number of elements of that feature instance, and the element for a paired-up index is
reached by taking the sibling with that index and following the remembered features down
again. An end that is a feature array itself has an empty descent, so it behaves as
before.

At most one step of a path is indexed: a feature declared inside a feature group type may
not be an array, so nothing below an indexed feature group instance is indexed in turn.
The nearest indexed ancestor is therefore the only one.

Nothing else needed a change. The pairing arithmetic does not care where an index came
from, and the end to end flows already fork over the flow specification instances of a
specification and keep a branch on its element by requiring the next connection instance
to start exactly at the previous element's destination feature instance.

The instance serializer characterization recorded the old behavior for the one array
feature group in its fixture, so its f7 becomes f7_1 and f7_2. Its f6, an array declared
inside a feature group type, is still a single feature and still a single flow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flow specifications are not expanded over an array of feature groups 🤖

2 participants