Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ sysml2tools help [lint|render|query [<query-verb>]|export]
| `--format markdown\|json` | Output format (default: `markdown`); distinct from `render`'s `--format` (`svg`/`png`) |
| `--output <file>` | Write query report to this **file** (default: stdout); differs from `render`'s `--output` dir |
| `--walk-depth <#>` | Maximum impact-walk depth (`impact` verb only) |
| `--include-connections` | `impact` only: follow `connect`/`bind` edges undirected (1 hop); off = not followed |
| `--direction up\|down\|both` | Traversal direction (`hierarchy` verb only) |
| `--kind <kind>` | Element-kind filter (`list`/`find` verbs only) |
| `--name <substring>` | Name substring filter (`list`/`find` verbs only) |
Expand Down
174 changes: 162 additions & 12 deletions docs/design/sysml2-tools-core/query.md

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions docs/design/sysml2-tools-tool/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,37 @@ flowchart TD
and `query <verb> --help`. Every printed line is sourced from `QueryStrings`, including the
`--output` help text, the workflow note, and the per-verb example/schema-hint enrichment.

#### Pass-Through Options

- `QueryCliArgumentParser` pre-extracts only `--output`; every other token is forwarded verbatim
to Core's `QueryArgumentParser`, and `Context` stores the resulting `QueryOptions` whole.
Adding a new Core option therefore requires no parsing change in this subsystem.
- `--include-connections` (connection-aware `impact` analysis, Core's
`QueryOptions.IncludeConnections`) is exactly such an option: the only Tool-side work is help
text, printed from four resx keys. `PrintGeneralHelp` writes the single line
`Query_GeneralOptionIncludeConnections` immediately after the `--include-stdlib` line:

```text
--include-connections Also follow connect/bind edges ('impact' verb only)
```

`PrintVerbHelp`'s `QueryVerb.Impact` arm writes the three-line block
`Query_OptionIncludeConnectionsImpact1`, `Query_OptionIncludeConnectionsImpact2`, and
`Query_OptionIncludeConnectionsImpact3` immediately after `Query_OptionWalkDepthImpact`:

```text
--include-connections Also follow connect/bind edges, undirected
(default: reference edges only). Connector
hops are bounded by --walk-depth, else 1.
```

All four keys live in `QueryStrings.resx` with matching `QueryStrings` accessor properties, as
the resx-parity tests require.
- Because the Tool does not parse the flag itself, keeping this help text in lockstep with
Core's accepted grammar is a Tool-subsystem responsibility, verified by one general-help test
and one `impact`-verb-help test; a Core-only option with no Tool help line would be silently
undiscoverable.

#### Output File Option

- `Context.QueryOutput` is a **file path** (not a directory) from `--output`; when omitted,
Expand Down Expand Up @@ -121,3 +152,5 @@ flowchart TD
| SysML2Tools-Tool-Query-ReportHeading | `HeadingDepth`; `QueryOptions.Heading`; `QueryResultRenderer.RenderMarkdown` |
| SysML2Tools-Tool-Query-HelpEnrichment | `QueryStrings.GetExample`/`Query_SchemaHint_*`; workflow-note lines |
| SysML2Tools-Tool-Query-OutputFile | `QueryCliArgumentParser.Parse`; `QueryCommand.RunAsync`; `QueryResultExporter` |
| SysML2Tools-Tool-Query-IncludeConnections | `QueryCliArgumentParser.Parse` pass-through to Core; `Context.Query` |
| SysML2Tools-Tool-Query-IncludeConnectionsHelp | `QueryStrings` keys via `PrintGeneralHelp` and `PrintVerbHelp` |
173 changes: 168 additions & 5 deletions docs/reqstream/sysml2-tools-core/query.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,175 @@ sections:
title: >-
The Query subsystem shall compute the transitive closure of incoming references from a
target element through the `impact` verb, optionally bounded by `WalkDepth` and guarded
against cycles.
against cycles, excluding `Connect` and `Binding` connector edges from that reference
closure.
justification: |
A single-hop reverse-reference view understates true blast radius for deeply-referenced
elements. A bounded transitive closure gives callers a practical, terminating answer to
"what is affected if this changes?".
"what is affected if this changes?". These reference-only semantics are the default and
are unchanged by the opt-in connection traversal described by
`SysML2Tools-Core-Query-ImpactConnections`; connector edges are followed only when
`IncludeConnections` is explicitly supplied.

Connector relationships are published into the semantic index alongside ordinary
reference edges, so the exclusion must be explicit. Without it the default walk followed
every connector as a plain incoming reference — directed rather than undirected,
attributed to the raw nested-port endpoint rather than its owning declaration, and
outside the connector hop bound. That was a defect: connector traversal became an
unbounded, direction-sensitive side effect of the reference walk instead of the bounded,
undirected, opt-in behavior it is meant to be, and where a connector endpoint was a
nested port the walk emitted qualified names that are not resolvable as query subjects.
Correcting it makes the default result smaller than in releases before this change, and
makes `IncludeConnections` a strict superset of the default.
tests:
- Impact_DepthOne_OnlyReachesDirectReferences
- Impact_Unbounded_ReachesTransitiveClosure
- Impact_IncludeConnectionsFlagAbsent_ReportsReferenceOnlyResult
- Impact_ChainedDeclaredConnectors_FlagAbsent_ReportsNoImpactedElements
- Impact_SourceSidePortEndpoint_FlagAbsent_ReportsNoImpactedElements

- id: SysML2Tools-Core-Query-ImpactConnections
title: >-
When `IncludeConnections` is supplied, the `impact` verb shall additionally traverse
resolved `Connect` and `Binding` connector relationships without regard to their
recorded endpoint order, so that the element at one end of a connector is reported when
the query subject is at the other end, whichever end each occupies.
justification: |
A connector's two ends carry no semantic "source causes target" direction, so the
reverse-only reference closure reports nothing for a part joined to the rest of the
assembly only by `connect` or `bind` statements — the exact case a change-impact
question is asked about. Answering that question correctly therefore requires the
connector to be followed from either end, and requires the caller to opt in explicitly,
because it broadens the answer beyond the reference-only default.
tests:
- Impact_IncludeConnections_ReachesConnectedSiblingPart
- Impact_IncludeConnections_QueriedFromFarEndpoint_ReachesOriginatingPart
- Impact_IncludeConnections_BindingEdges_AreTraversedUndirected
- Impact_IncludeConnections_ThroughPublicApi_ReturnsConnectedPartEntries

- id: SysML2Tools-Core-Query-ImpactConnectionEndpoints
title: >-
The `impact` verb shall treat a connector as attached to the query subject when an
endpoint of that connector is the subject element itself or a feature nested within it,
and shall report the element reached at the connector's other end.
justification: |
Users ask about parts, but a connector's declared endpoints are normally the ports
nested inside those parts. Unless a subject matches connectors reaching its nested
features, asking about a part whose ports are wired to the rest of the assembly returns
nothing, which is the opposite of the true answer.
tests:
- Impact_IncludeConnections_PortEndpoints_RollUpToOwningPartUsage
- Impact_IncludeConnections_SourceSidePortEndpoint_ReportsOwnerNotRawPort
- Impact_IncludeConnections_ReachesConnectedSiblingPart

- id: SysML2Tools-Core-Query-ImpactConnectionRollUp
title: >-
The `impact` verb shall report each connector endpoint it reaches as the nearest
declaration that owns that endpoint, and shall report the endpoint itself unchanged
when the endpoint is already a declared element.
justification: |
A nested port such as `System::hub::J1` is not itself a usable query subject, so
reporting it raw gives the caller a name they cannot act on and cannot feed back into
another query. Reporting the owning part instead makes every row actionable, while
leaving an already-declared endpoint alone prevents the answer from being widened to an
enclosing definition that the connector never named.
tests:
- Impact_IncludeConnections_PortEndpoints_RollUpToOwningPartUsage
- Impact_IncludeConnections_DeclaredFarEndpoint_ReportsEndpointItself
- Impact_IncludeConnections_DeclaredEndpointConnector_ReportsSiblingPartNotOwningDefinition
- Impact_IncludeConnections_SourceSidePortEndpoint_ReportsOwnerNotRawPort

- id: SysML2Tools-Core-Query-ImpactConnectionHopBound
title: >-
The `impact` verb shall follow at most `WalkDepth` connector relationships along any
single traversal path when `WalkDepth` is supplied, and at most one connector
relationship along any single traversal path when it is not.
justification: |
Connector graphs in real models are dense meshes in which an unbounded connector closure
degenerates to "the whole assembly" and answers nothing. A one-connector default keeps
the opt-in answer useful out of the box, while an explicit bound lets a caller widen the
blast radius deliberately and know exactly how far the reported answer reaches.
tests:
- Impact_IncludeConnections_NoWalkDepth_BoundsConnectionHopsToOne
- Impact_IncludeConnections_WalkDepthTwo_ReachesSecondConnectionHop
- Impact_IncludeConnections_ChainedDeclaredConnectors_StopsAtOneConnectorHop
- Impact_IncludeConnections_ChainedDeclaredConnectors_WalkDepthTwo_ReachesSecondHopOnly

- id: SysML2Tools-Core-Query-ImpactConnectionCycles
title: >-
The `impact` verb shall terminate and return a result for models whose connector
relationships form cycles.
justification: |
Connectors are routinely declared in both textual orders between the same two parts, so
cyclic connector topologies are ordinary models rather than corner cases. A
change-impact query that hangs on an ordinary model is unusable, so termination is a
user-visible obligation in its own right and not merely an implementation nicety.
tests:
- Impact_IncludeConnections_CyclicConnections_TerminatesWithoutDuplicates

- id: SysML2Tools-Core-Query-ImpactHopMinimality
title: >-
The `impact` verb shall report every element reachable by its traversal within the
applicable connector-hop bound, regardless of the order in which paths to that element
are discovered, and shall report each such element exactly once, at the depth and
relation of the first path by which it was reached.
justification: |
Connector-hop cost is not monotonic in traversal depth: an element first reached over a
connector can later be reached over a pure reference path that consumed none of the hop
budget, restoring the budget available beyond it. Unless that cheaper route is honored,
elements one connector hop past such an element are silently missing from the answer,
and which elements are missing depends on the order in which the walk happened to
discover paths rather than on the model itself. A change-impact answer that varies with
traversal order cannot be relied on or reproduced, so the reported set must be a
function of the model and the requested bound alone — while each impacted element must
still appear once, at the depth at which it first entered the answer, so callers can
read distance from the subject off the result.
tests:
- Impact_IncludeConnections_CheaperReferencePath_ReExpandsConnectorsFromReReachedElement
- Impact_IncludeConnections_ReReachedAtLowerHopCount_KeepsFirstArrivalDepthAndAttribution
- Impact_IncludeConnections_SourceSidePortEndpoint_ProducesExactlyOneEntry

- id: SysML2Tools-Core-Query-EntryTraversalMetadata
title: >-
Every traversal-produced result entry shall carry machine-readable `Depth` and
`Relation` values, and a `ViaQualifiedName` value naming the endpoint an entry was
attributed from whenever the reported element differs from that endpoint, alongside the
existing human-readable `Detail` text.
justification: |
Non-CLI API consumers previously had to parse the free-form `Detail` string to recover a
traversal depth, and had no way at all to tell which kind of relationship reached an
entry — a distinction that becomes essential once reference and connector results are
combined in one answer. Exposing the values structurally makes the API contract
authoritative, while retaining `Detail` keeps Markdown output human-readable.
tests:
- Impact_ConnectionEntry_RecordsDepthRelationAndViaQualifiedName
- Impact_ConnectionEntry_WithoutRollUp_OmitsViaQualifiedName
- Impact_ReferenceEntry_RecordsDepthAndReferenceRelation
- RenderMarkdown_ImpactEntry_DetailRemainsHumanReadableDepthText

- id: SysML2Tools-Core-Query-EntryMetadataJsonOmission
title: >-
A result entry's `Depth`, `Relation`, and `ViaQualifiedName` values shall each be
omitted from JSON output when that value is null.
justification: |
Verbs that perform no traversal populate none of these values. Emitting them as explicit
`null`s would change the JSON payload shape of every pre-existing verb and break
consumers that key off property presence, so a purely additive contract requires null
values to be absent rather than present-and-null.
tests:
- RenderJson_EntryWithoutTraversalMetadata_OmitsDepthRelationAndVia

- id: SysML2Tools-Core-Query-EntryRelationSerialization
title: >-
A result entry's `Relation` value shall be written to JSON as the name of the
relationship kind it records.
justification: |
A consumer reading `"Relation": "Connect"` can distinguish "connected to" from
"referenced by" without any lookup table, and the emitted contract stays stable if the
underlying set of relationship kinds is ever reordered — which an ordinal encoding would
silently break.
tests:
- RenderJson_EntryWithDepthAndRelation_IncludesBothFieldsAndRoundTrips

- id: SysML2Tools-Core-Query-Describe
title: >-
Expand Down Expand Up @@ -168,9 +329,11 @@ sections:
including dotted feature-chain resolution, and shall label each entry with the
connector keyword that produced it.
justification: |
Resolved connection edges do not live in the semantic index's global edge list, so the
Query subsystem must perform the node walk on behalf of callers that need connection
topology.
A `SysmlEdge` records only its source, target, and kind — not the connector keyword
(`connect`/`connection`/`message`/`bind`) that produced it — so the Query subsystem
must perform the node walk on behalf of callers that need connection topology labeled
by the syntax that declared it. The same walk is shared with the `impact` verb's
connector traversal so the two verbs can never disagree about connection topology.
tests:
- Connections_ReportsResolvedEndpointsIncludingFeatureChain
- Connections_ConnectionsExampleFixture_ReportsAtLeastOneEndpoint
Expand Down
27 changes: 27 additions & 0 deletions docs/reqstream/sysml2-tools-tool/query.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,33 @@ sections:
- QuerySubsystem_QueryVerbHelp_MentionsExampleInvocationAndSchemaHints
- QuerySubsystem_QueryHelp_NoVerb_MentionsTypicalWorkflow

- id: SysML2Tools-Tool-Query-IncludeConnections
title: >-
The query command shall accept the `--include-connections` option on its command line
and, when it is supplied with the `impact` verb, shall produce a report that includes
elements reached through connections.
justification: |
Connection-aware impact analysis changes the answer the `impact` verb gives, so it
must be an explicit, discoverable user choice rather than a silent default. Users
invoke the analysis through this command, so the command is where accepting the choice
and acting on it must be guaranteed.
tests:
- Context_Create_QueryCommand_WithIncludeConnectionsFlag_SetsIncludeConnectionsTrue
- Impact_IncludeConnections_ReachesConnectedSiblingPart

- id: SysML2Tools-Tool-Query-IncludeConnectionsHelp
title: >-
The query command's general help and its `impact` verb help shall each document the
`--include-connections` option, in localized text.
justification: |
An option that changes the meaning of a result is useless if a user cannot find it.
Users look in two places — the command's overall option list and the specific verb's
help — so the option must be discoverable from both, and in the user's own language
like every other help line.
tests:
- QuerySubsystem_QueryHelp_NoVerb_MentionsIncludeConnectionsOption
- QuerySubsystem_ImpactVerbHelp_MentionsIncludeConnectionsOption

- id: SysML2Tools-Tool-Query-OutputFile
title: >-
The query command shall write its rendered document to the file path supplied via
Expand Down
Loading
Loading