Skip to content

fix(runtime): hold a namespace-level feature read in its effective multiplicity - #1585

Merged
HuiJun merged 5 commits into
developfrom
fix/namespace-read-multiplicity
Oct 28, 2026
Merged

HuiJun merged 5 commits into
developfrom
fix/namespace-read-multiplicity

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

What and why

A feature read at namespace (model) level now holds its value in the feature's effective multiplicity, the way the same feature read on an object already does. On develop, with

package P {
  private import ScalarValues::*;
  attribute xs : Integer[0..*] = 4;
  part def D { attribute xs : Integer[0..*] = 4; }
  part d : D;
}

sysml -e P::xs printed = 4 while sysml -e P::d.xs printed = [4] (same in the REPL): a [0..*] feature holding exactly one value read bare at model level and as a one-element sequence on an object. P::ys = (1, 2) → [1, 2] and an empty [0..*] → [] were already right, so the one-value case was escaping the shape rule: a declared value was evaluated and returned as written, and declaredCollection only reshaped values that were already collections.

Found while triaging #1575; this is a separate, small inconsistency and does not address that issue.

The fix is in the runtime read path, not the formatter (runtime.FormatValue and the REPL's formatValue are untouched):

  • Context.admitted's shape logic is extracted into Context.heldShape(feat, val) — one predicate: an at-most-one feature holds a one-element collection's element bare, a multi-valued feature holds a collection however the value was written, with the element charging and set/sequence canonicalisation admitted already did.
  • Context.declaredCollection (the namespace-level read of a declared value, reached from conformHeld and denotedValue) now builds the EffectiveFeature for the declaration and applies that same heldShape, so -e, REPL bare expressions and %eval, gRPC Evaluate and MCP all read [4].
  • Consequence handled: a parameter stating no multiplicity is held to [0..*] (semantics.EffectiveParameterRange), so a calc-typed parameter's default (in calc f = twice, the library's in calc :>> eval = evaluationFunction) is now a one-element sequence holding the function. A call applies the one function such a feature holds: boundFunction and declaredFunction take soleElement of the read, as evalChainInvocation and invokeFunction already did.

Arithmetic and comparison over such a read are unchanged (P::xs + 1 → 5, P::xs == 4 → true).

Specification basis

KerML 1.0 §7.3.4.1 and §7.4.12: the values of a feature are a sequence its multiplicity constrains. SysML v2 §7.6.3: a parameter stating no multiplicity has no implied 1..1. The "performed action's parameter" row of docs/project/spec-compliance.md is extended with the namespace-level read (implementation and tests); its status is unchanged.

How it was verified

Fixture first, both failing on develop with 4 / int_value and passing here:

  • internal/frontend/repl/namespace_shape_test.go TestEvalNamespaceReadHoldsEffectiveMultiplicity: %eval and the bare expression agree for [0..*] valued 4 ([4]), the same feature on an object ([4]), (1, 2) ([1, 2]), empty [0..*] ([]), [1], [0..1] and bare attribute x : Integer (4), [2] ([4, 5]), [0..*] valued (4) ([4]), P::xs + 1 (5), P::xs == 4 (true).
  • tests/grpc evaluate_namespace_feature_multiplicity (P::xs → sequence[int_value 4]) beside evaluate_object_feature_multiplicity (P::d.xs, same).

Moved expectations, each adjudicated:

File Movement Category
internal/exec/runtime/robustness_usage_members_test.go (Probe::rig.fits.limit, a constraint's bare in limit : Real = 100.0) 100.0 → [100.0] same value wrapped in a one-element sequence (a bare parameter is [0..*], as the existing performed-pin rule holds)

No golden, trace or expected.json file moved: go test -count=1 ./internal/exec/runtime is green without re-recording (the trade-study conformance cases and function_value_qualified_default, which call a calc-typed parameter by name, pass through the soleElement consumer fix above, with their recorded traces unchanged). No codegen target is touched.

Gate, all local on this head: go build ./..., go vet ./..., gofmt -l . empty, go test -count=1 -timeout 40m ./... green (122 packages, with the training and pilot corpora downloaded so TestTrainingExamples and TestPilotCorpora ran rather than skipped; tests/grpc, tests/codegen and the docs transcript checks are in that run), python3 scripts/changelog.py check, python3 scripts/check-doc-links.py (0 broken links). The quick CI tier's runtime, model/export/graph, static, WebAssembly, conformance and documentation jobs are green.

Merged develop (e19d9beb3) in with merge commits, never a rebase; the docs/project/spec-compliance.md conflict took develop's refreshed citation column and kept this PR's row content, so the file differs from develop by that one row alone. Re-ran the gate on the merged head: go build ./..., go vet ./..., gofmt -l . empty, go test -count=1 -timeout 40m ./... green (123 packages, corpora present), go test -C tools over the census and referee packages, check-doc-links, check-doc-ids, check-doc-figures, changelog.py check, mkdocs_census-test.py; sysml -validate -format sarif examples over the tracked examples exits 0 on this head.

Dry-merged clean against the open runtime siblings #1571 and #1572 and against #1580.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build) — no gate count moved
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/4b614bc5d6204ee693145e91142acb0f
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/4b614bc5d6204ee693145e91142acb0f?variant=devin
Requested by: @HuiJun

…ltiplicity

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

…-multiplicity

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	docs/project/spec-compliance.md
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 28, 2026 14:18
@HuiJun
HuiJun merged commit 4299573 into develop Oct 28, 2026
33 of 54 checks passed
@HuiJun
HuiJun deleted the fix/namespace-read-multiplicity branch October 28, 2026 16:14
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.

1 participant