--- name: sysml-requirements description: > Author, inspect, validate, or verify SysML v2 requirements in a LunCoSim Twin. Use for `.sysml`/`.kerml`, requirements management, satisfy/verify traceability, `ValidateSysml`, `sysml_requirements`, source revisions, or `luncosim test --verification`. Do not use it to claim full KerML execution or to replace USD, Modelica, or Rhai ownership. --- # Manage SysML v2 requirements SysML v2 is implemented as a portable, source-backed requirements and system- structure boundary. It is not a second runtime physics engine and it is not a copy of the Twin's USD or Rhai state. Use this skill when the request mentions requirements, verification cases, SysML, KerML, traceability, or a missing capability that may already exist behind the optional SysML feature. ## Capability matrix and ownership Check the feature set and owner before saying that a capability is missing: | Concern | Authoritative owner | Normal availability | Use it for | |---|---|---|---| | System structure and requirement intent | standard SysML v2 `.sysml`/`.kerml` | default in the production app/core/server; `--no-default-features` remains available for a deliberately lean build | parts, ports, connections, requirements, satisfy/verify links, scalar literals | | Scene identity, topology, geometry and authored physical facts | USD | standard runtime path | prim paths, schemas, relationships, dimensions, materials, physics topology | | Continuous equations and domain state | Modelica | standard domain backend | propulsion, electrical, thermal and other continuous models | | Scenario policy, observations, checks and verdicts | Rhai | default scenario backend | runtime observation, actuation, generic requirement evaluation and test policy | | Bounded resolved-constraint IR | `lunco-sysml-ir` | default with SysML support | typed source-linked constraint compilation, diagnostics, fingerprints, and provider-neutral evaluation | | Bounded SysML-to-Modelica lowering | `lunco-sysml-modelica` through the Rumoca boundary | default with SysML support | typed scalar/fixed-array equation lowering; not SysML resolution or engineering intent | | Python integration | Python backend | `python` feature, opt-in | explicit one-shot or integration requests only; not the normal scenario workflow | | Generic parsing, resolution, transport and lifecycle mechanisms | Rust crates | feature-dependent | reusable substrate, not Twin-specific policy | The source-of-truth rule is strict: SysML states what the system must be and why; USD states what is authored and observable; Modelica states continuous equations; supported SysML constraint expressions execute through the neutral IR. Rhai selects providers, queries observations, orchestrates behavior, and formats evidence. A verification registry selects a scene and script but does not duplicate requirement text or thresholds. Windowed LunCoSim builds with the `sysml` feature also provide the **SysML Requirements** panel in `View → Editor`. It reads the active Twin's prepared analysis, displays requirement documentation, formal `require` criteria, resolved `verify` cases, parser diagnostics, and source locations. Selecting **SysML Requirements** from another perspective opens its owning Editor perspective. The panel starts with a compact requirement list and a detail pane; search and status filters narrow the list. **Open at line** opens the canonical `SysmlDocument` at the declaration or diagnostic location. **Save source** applies revision-checked `ApplySysmlOps` and `SaveSysmlDocument` commands. The text editor is read-only when the document is not writable or its source revision conflicts with the open draft. The presentation model rebuilds when Twin, analysis, source-document, or evidence inputs change. Empty lifecycle queues are read before a mutable registry drain; idle publishing must not mark documents changed. Use `sysml_requirements_rebuild` input flags when profiling repeated rebuilds. `CloseDocument` retires the SysML registry document and its shared lifecycle state, including dirty drafts. Twin replacement dispatches that command for every resident SysML document. Pending filesystem opens are admitted with an exact runtime owner and cannot install after that Twin closes. The panel presents three independent status dimensions with separate filters: structured requirement evidence, linked scene-test execution, and model coverage (`require` criteria and resolved `verify` links). Requirement details show evidence channel, verification identity, source revision, simulation tick, and captured check results. Up to 64 check details are retained per requirement; aggregate check and failure counts remain available for larger reports. Running a mapped case uses the same production headless scene-test runner as the CLI; the panel shows elapsed time and live output, supports cancellation, and retains the run summary and output for the Twin session. Save or discard open SysML edits before running because tests read saved Twin files. Results are cleared when their Twin closes. The panel lives in the existing workbench Editor alongside the other native document tools. The **Traceability** view maps one requirement's declared subject types, explicit standard `satisfy` relationships, resolved `verify` cases, Twin test registrations, run outcomes, and source-revision-scoped evidence. Do not treat a subject type as a satisfy link or infer missing relationships. Source-backed nodes navigate to their analyzed declarations, and a mapped test can run from the map. The **Structure** view presents a filterable package/part/item/ interface/port/connection hierarchy from the same prepared analysis and opens selected elements at their source lines. It is a hierarchy navigator, not full BDD/IBD diagram authoring or a general-purpose SysML editor. ### Preserve declared collection shape Read model values through the typed `SysmlModel.value` projection. Finite, unitless numeric constant initializers support resolved feature references, unary signs, and `+`, `-`, `*`, `/`, and integer powers, including each member of numeric tuples. Cross-package and local references use the same source snapshot. Authored expression text and classification stay intact alongside the numeric projection. This bounded source fold reuses the semantic unit-factor evaluator; it does not execute domain state or general KerML programs. Cycles, missing references, zero division, non-finite results, and unsupported initializers have no fabricated value; `model.value` reports a named error. Integer operands beyond the exactly representable f64 range remain unsupported in arithmetic rather than being silently rounded. A structured `Position` literal may lower to one native `DVec3`, while a declared `Position[n]` collection must remain an array of native `DVec3` values. The generic Rust projection distinguishes vector components from declared multiplicity. Do not recover missing model values by walking `AnalyzeSysml` AST records, parsing string encodings, or rebuilding arrays in Twin Rhai. If a declared shape is missing, fix the shared typed projection and keep the Twin policy declarative. For mission models with material-dependent structural, pressure, thermal, or electrical behavior, follow the [physical-material data gate](../interactive-component-authoring/references/mission-engineering-quality.md#physical-materials-and-engineering-properties). Use typed material definitions/usages and unit-bearing properties with their conditions and evidence; do not encode material identity or property arrays as strings. The current typed SysML projection is not itself a material catalogue or an automatic cross-domain binding—keep the limit visible until a generic resolver and consumer path are demonstrated. Model substrate and surface finish/coating as separate typed facts. Permit a component face/region to select a sourced finish independently of its bulk material. Keep visual `UsdShade` shader mapping distinct from optical/thermal engineering properties: a shader preset is not a source for absorptance, emittance, coating thickness, or Modelica thermal parameters. Record missing finish catalog and rendering adapters as generic tool gaps, not per-component string metadata. ### Keep resolved type identity typed Use the resolver-selected `SysmlTypeRef.element` handle for type comparisons and joins. If a typed contract needs a SysML type, carry that reference rather than its name. Its `qualified_name` is for reports and source navigation only; two semantic types must not be treated as equal because their display names match. The handle is scoped to its SysML source revision and fingerprint, so reject values assembled from a different snapshot. For unit-bearing model data, author standard quantity-value and unit-reference features where the model needs them. Keep a unit suffix from source syntax as source spelling; it is not a resolved unit definition. Provider observations must carry a native `Quantity` constructed with a resolved `EngineeringUnit`, and a binding contract's optional unit must also be an `EngineeringUnit`. Do not add a second `unit` string to an observation or pass `{ value, unit: "m" }`: those forms do not establish dimension or scale and are rejected by the adapter. The evaluator checks SI dimensions and converts compatible units during arithmetic and comparison. A resolved unit-bearing source literal now carries its measurement-unit feature handle, SI dimension, and source-derived scale. The AST resolver reads standard `MeasurementUnit` quantity-power factors and linear conversion relationships, including prefixes, reference-unit factors, and arithmetic unit definitions. Rhai exposes the resolved unit as a native `EngineeringUnit`; source verification and geometry adapters use that value without consulting a symbol table. Numeric conversion expressions support arithmetic, including integer powers; dimensional unit composition supports multiplication, division, and integer powers. Keep `unit_symbol` for source display only. The standard conversion `isExact` flag is projected onto native units as `scale_is_exact` and accumulated by native quantities as `conversion_is_exact`. These flags describe conversion exactness only, not measurement uncertainty. The bounded Modelica position adapter requires an exact SI scale before lowering to an unqualified vector. `MeasurementScale` mappings and unresolved or unsupported unit definitions do not produce an engineering unit and must remain unavailable; do not infer a scale from the spelling. For a mission Twin, apply the generic [mission and engineering quality gates](../interactive-component-authoring/references/mission-engineering-quality.md) alongside this parser/runtime contract. Requirements are the baselined bridge from mission intent and ConOps to component and interface acceptance; record provenance, assumptions, operating conditions, margins, and configuration revision. Keep verification against requirements separate from validation in a realistic nominal/off-nominal/recovery scenario, and make unresolved TBDs or fault-response requirements visible failures rather than defaults. The existing Rhai lint substrate is part of this path: `RunLint` executes the domain policy in `assets/scripting/policy/lint_.rhai` over Rust-produced facts, while Twin verification scripts use `assets/scripting/tools/sysml_requirements.rhai` to read the mounted SysML snapshot, bind composed USD observations, execute supported source constraints through the neutral IR, and emit structured evidence. Keep provider and component selection in Rhai; keep supported acceptance predicates in SysML; Rust supplies generic typed mechanisms, not mission- or component-specific assertions. Use `ValidateSysml` with the mounted Twin URI to review the full indexed source set and its structural lint findings. The `lint.sysml` policy flags requirement usages without typed source evidence, usages without an inherited or owned `require` acceptance predicate (`assume` memberships provide context but do not count as pass criteria), and identifier-like `String` values that appear to encode enumerators or member identities. Treat those findings as migration work, not as permission to preserve the encoding. Use an enum for a closed choice set; use typed part usages or references for named system members. A `verify` membership is required for each usage, and the Twin's verification registry must bind that case to its scene and observer. For example, from an in-app Rhai tool with the Twin mounted: ```rhai let report = query("ValidateSysml", #{path: "twin://astrobotic-griffin-1"}); ``` Review `report.errors`, `report.warnings`, and the structured `report.findings`. Use its stable `rule`, `severity`, `subject`, and `message` fields instead of parsing warning prose; SysML subjects include the qualified identity and source file/byte offset. Pay particular attention to `sysml-requirement-*` and `sysml-string-encoded-identities`. Relevant implementation and design references: - [`24-domain-sysml.md`](../../docs/architecture/24-domain-sysml.md) — domain boundary and supported subset. - [`sysml-requirement-verification.md`](../../docs/architecture/sysml-requirement-verification.md) — current Rhai bridge and verification contract. - [`crates/lunco-twin/src/manifest.rs`](../../crates/lunco-twin/src/manifest.rs) — `[sysml]` and `[verification]` manifest ownership. - [`assets/scripting/tools/sysml_requirements.rhai`](../../assets/scripting/tools/sysml_requirements.rhai) — generic evaluator implementation. ## Requirement quality gate Treat an informal request as a stakeholder expectation until it has enough information to become a requirement. A good requirement is singular, clear, necessary, feasible, implementation-independent, traceable, and individually verifiable. It states one subject and one normative behavior or characteristic, usually with `shall`, plus the measure, units, limit or tolerance, operating condition, and verification method needed to decide pass or fail. This follows the NASA requirements guidance for statements that are clear, correct, feasible, unambiguous, measurable/verifiable, and traceable: [`NASA Appendix C`](https://www.nasa.gov/reference/appendix-c-how-to-write-a-good-requirement/) and [`NPR 7123.1C`](https://nodis3.gsfc.nasa.gov/displayAll.cfm?Internal_ID=N_PR_7123_001C_&page_name=all). Before authoring or baselining a requirement, check: - **Subject and scope:** Which system, part, interface, or operating mode does it constrain? Name the subject and the condition or stimulus. - **Observable measure:** What will be measured, inspected, demonstrated, analyzed, or tested? Include units, sampling rule, time window, population, and reference/baseline when they affect the result. - **Pass criterion:** Give a numeric bound, range, tolerance, count, rate, state, or explicit finite acceptance rubric. “Good”, “stable”, “fast”, “intuitive”, “looks right”, and “make it look good” are not pass criteria. - **Single thought:** Split `and`, `or`, and compound paragraphs into separate requirements unless the clauses are inseparable for verification. - **Traceability and intent:** Record the requirement ID, source/parent goal, rationale, priority, and the qualified verification case. Keep design choices such as a particular class, algorithm, or shader implementation out unless they are themselves the required constraint. - **Normative content vs. implementation status:** Requirement text states the required behavior or characteristic and how it will be accepted. Keep current implementation status, nonconformance, incomplete assets, proxy caveats, missing source data, historical milestones, and unresolved work in the owning gap/status report. Keep source history and provenance in the typed evidence/source catalog. Do not use requirement prose to say that the current model fails, that a parameter is only a proxy, or that a value is not publicly available. Write the positive desired outcome in the requirement; report actual-vs-required status separately under that requirement ID. - **Time-dependent acceptance:** Identify the applicable mission phase or window, time scale, site/reference frame, and temporal envelope or sampling needed to accept a time-dependent requirement. Use one authoritative scene clock/epoch and derive environment state from its providers; keep a study epoch distinct from a mission schedule. Put unavailable schedule inputs and current verification coverage in the gap/status report. - **Failure behavior:** For safety, reliability, or resilience requirements, specify the trigger, detection deadline, required response, and recovery or safe state. “The system shall handle errors” is incomplete. Do not baseline an unmeasurable statement merely because its rationale is important. If a threshold, reference, or acceptance condition is missing, record the unresolved decision and required evidence in the gap/status report. Keep the requirement concise; put its sources in the evidence catalog and its verification evidence in the verification record. For example, a solar-layout requirement should state the required installation relationship and the mission Sun-envelope comparison used for acceptance. Whether the current Twin has the right panel count, whether its existing roots are only proxies, and which installation data are still missing belong in the gap/status report, not in the requirement definition. ### Ask the user when the requirement is underspecified It is correct to ask targeted questions before writing SysML. Ask only the questions that block a measurable, verifiable statement, and show the proposed rewritten requirement so the user can confirm the interpretation. Do not invent numbers, tolerances, reference images, operating conditions, or priorities. Use this compact question set as needed: 1. What exact subject is being constrained, and in which operating condition or scenario? 2. What observable quantity or finite outcome proves success? What are its units, range/threshold/tolerance, sampling rule, and time window? 3. What stimulus, initial state, environment, or reference baseline applies? 4. Should verification be by test, analysis, inspection, or demonstration, and what artifact or runtime evidence must be retained? 5. What stakeholder goal or parent requirement does it trace to, and what is the priority if it conflicts with another requirement? If the user answers only “make it look good”, convert that into a clarification, not a requirement. Ask for the approved reference and observable visual criteria—for example camera/lighting/exposure, reference patches or objects, allowed luminance/color deviation, frame window, and the inspection or image analysis method. A valid visual requirement can be: ```text Under the approved camera, sun direction, and exposure, the terrain surface shall keep the mean luminance of each of three approved reference patches within ±5% over a 10-second stationary capture. Verification: image analysis of 300 frames plus visual inspection against the approved albedo reference. ``` The numbers and reference artifacts in that example are placeholders, not defaults. Replace them with user-approved values before putting the statement in SysML. A similarly testable motion requirement names the scenario and window, for example: “During a 100 m straight run on a 10° slope at a commanded 1.0 m/s, the rover shall keep lateral error ≤0.5 m and speed within ±0.2 m/s for at least 90% of samples after the first 5 s.” Do not weaken a vague request by choosing a permissive tolerance merely to make the first run pass. If the user cannot yet provide a bound, record it as an open stakeholder expectation/TBD with an owner, rationale, and resolution date; do not baseline it as a verified SysML requirement. ## What is implemented, and what is not The current supported subset is source-backed and deterministic: - standard textual SysML v2 syntax in `.sysml` and `.kerml` files; - packages/imports, part definitions/usages, ports, connections, requirement definitions/usages with documentation and attributes; - standard external references plus `satisfy` and verification `verify` memberships; - qualified names, typed scalar/vector/array literal projections, source spans, diagnostics, source files, and a deterministic `source_revision`; numeric literals expose a validated native finite `number_value` alongside source identity; - Twin-indexed source-set discovery through the existing asset manifest, with `SysmlPlugin` opening the checked set automatically after `TwinAssetMounted`; - a Twin-owned verification registry mapping a qualified SysML verification name to one scene, one Rhai observer, and an optional verdict channel; - three generic Rust query boundaries: `ValidateSysml` for source status, diagnostics, and the structural `lint.sysml` pass; `AnalyzeSysml` for policy-neutral selectable typed facts; and `ReadActiveTwinContract` for active-Twin component/verification bindings; - Rhai policy layers that consume those same facts independently: `lint.sysml` for structural quality, `sysml_requirements.rhai` for requirement/source provenance and verification, and `sysml_modelica_constraints.rhai` for geometry-constraint selection and Modelica source assembly; - `sysml_value(path, qualified_name)` and `sysml_value_from_report(report, qualified_name)` return tagged typed outcomes. Successful values remain native (`Vec3`, `Quat`, Transform, quantity, enumeration, or array); failed lookups return `ok: false` with an error and add a scene-scoped warning to `RuntimeDiagnostics`. A policy may request selected attributes through `AnalyzeSysml`; a successful read clears only the warning for the same source path; - `sysml_model(path)` returns a read-only, revision-pinned `SysmlModel` backed by the cached Rust semantic snapshot. For a mounted Twin it hands back the prepared analysis directly (no per-call lint-fact rebuild), so accessors that open the model on demand stay cheap enough for per-tick mission policy; source diagnostics still reject the model. Use `model.value(qualified_name)` for repeated typed reads in one builder/verifier, and use `model.requirement(qualified_name)` or `model.verification(qualified_name)` for source-owned traceability. This keeps the parsed source set and its revision together and avoids rebuilding a dynamic report for every attribute. The Rhai `sysml_requirements::model()` helper opens the active Twin's `twin://` source; scripts must not read `.sysml` files directly or manufacture a second requirement-value table; - the `luncosim test --verification QUALIFIED_NAME` selector; and - structured per-check evidence emitted by `report_structured_verdict`. The summary event keeps small reports inline; larger reports emit one bounded `*_EVIDENCE_RESULT` event per observation with a stable `result_index`. Consumers must group by channel and source revision, then order by that index. This preserves the complete typed table without exceeding Rhai's bounded value budget. Check records may use qualified or validated short requirement/verification names; short names are preferred in repeated arrays to avoid duplicating package prefixes. The shared `sysml_requirements::evaluate` call resolves those short identities once against the mounted source report and rewrites each check to the canonical qualified name before observing USD or source-derived predicates. Verification coverage is evaluated from resolved snapshot-scoped SysML element handles, not by joining requirement and verification names into a string key. The authored name selects the source element; the resolved handle pair determines coverage. Missing or colliding identities fail the evaluation; observers must not add a package-prefix guess or a second registry. Use `sysml_requirements::requirement_name(report, id)` and `sysml_requirements::verification_name(report, id)` when a canonical identity is needed before constructing additional evidence. Unit-bearing literals expose `measurement_reference`, a snapshot-scoped handle to the resolved SysML measurement-unit feature and its declared unit type. Its `unit_definition` contains the standard-derived SI dimension and conversion; `engineering_unit` on the Rhai reference yields the native unit value. `unit_symbol` is only the spelling in source. New SysML verification and projection code must use the resolved reference; do not use the spelling as a unit registry key. Linear `MeasurementUnit` definitions are resolved from their quantity-power factors, standard SI base units, unit-conversion edges, and arithmetic initializers. Nonlinear or affine `MeasurementScale` mappings, malformed definitions, and expressions outside the resolver's supported arithmetic remain unavailable. Standard `isExact` metadata is projected and propagated through native quantity operations; it does not replace uncertainty or instrument-accuracy data. `engineering_units.rhai` serves explicit unit input at non-SysML boundaries; it is not authoritative for SysML source values. Before lowering a unit-bearing vector to shared `Vec3` or a Modelica parameter, validate the declared quantity kind, fixed cardinality, each resolved unit, and compatible dimensions. Do not read only `number_value` and drop unit identity. The bounded SysML-to-Modelica `LengthValue[3]` geometry path consumes the resolved measurement-reference unit and converts through the native SI quantity operation; it does not look up `unit_symbol`. Other physical-property quantities, including material properties, need the same unit-preserving treatment; capability-check the property kind and consumer before generating a model. For CAD/mechanical intent, keep the requirement and tolerance in SysML, then call the reloadable `assets/scripting/tools/mechanical_relations.rhai` policy with resolved native values. Its generic vocabulary includes distance, coincidence, signed plane distance, under/clearance, parallelism, perpendicularity, collinearity, coplanarity, mirroring, and plane/axis symmetry. It returns residual/evidence records and knows neither Griffin names nor USD paths. Do not add a product-specific relation predicate to Rust; add a generic Rust numeric primitive only when the operation is shared, hot, and not expressible safely with the Rhai standard math surface. `source_with_attributes()` is a bounded value projection and intentionally does not carry requirement/verification identity tables. Use `source_with_selection()` when evidence must retain source-linked requirement or verification identities. Identity and source revision remain Rust-owned. For a supported source predicate, create a generic `constraint_check` and pass it to `evaluate` or `evaluate_document`; Rhai selects explicit provider observations and the neutral IR returns `pass`, `fail`, `inconclusive`, or `error`. Do not collapse those states into a Twin-specific boolean assertion. Keep normative requirement tolerances in SysML evidence. Runtime settings such as `numerics.comparison.length_abs_m` and `numerics.solver.residual_abs` are algorithm/solver policy, resolved once per operation from the active Twin and passed through the call graph. They must not silently replace a SysML acceptance tolerance or collapse different physical dimensions into one epsilon. It does not provide a full SysML/KerML execution engine. Parsed generic elements, references, constraints, and relationships are source facts, not a claim that their behavior is executed. The bounded constraint path now compiles the resolved supported subset into `lunco-sysml-ir`; a Rhai policy selects provider bindings; and `lunco-sysml-modelica` renders a typed constraint into Modelica admitted through Rumoca. Native in-process policy can retain a `SysmlModel` handle, while API/MCP callers use the structured path-level functions `sysml_constraint_ir`, `sysml_modelica_constraint`, and `sysml_evaluate_constraint` without serializing a native handle. Authored source references use `lunco://`; a USD prim target remains a USD path. The current IR supports typed scalar expressions, conditional expressions, fixed primitive multiplicities, source-linked diagnostics, and deterministic fingerprints. It does not yet support feature-chain navigation, reusable constraint invocation/default arguments, collection/index/aggregate expressions, full quantity conversion, redefinition/subsetting semantics, null/invalid propagation across all providers, requirement membership execution, applicability, or state/behavior execution. Do not recreate those features with a hidden Rhai parser, Griffin-specific Rust, parallel arrays, or qualified-name fallback tables. Add the generic AST/IR/provider mechanism and then author the standard SysML construct. `sysml_requirements::constraint_check` binds a check table to that supported subset. Binding keys must match the source constraint parameter names; an unknown key is an error and an omitted observation is unavailable. Evidence retains the qualified constraint, source revision, fingerprint, provider observations, expression results, diagnostics, and four-state verdict. `evaluate_document(source, doc_id, checks)` gives the same generic checks an explicit Editor document scope for USD queries. Generic observation kinds include `not_exists` for absence requirements and typed source-vector component selection through `expected_index`. The `tolerance` argument on a check is numerical evaluator policy for equality comparisons; engineering acceptance bounds must remain parameters of the SysML constraint itself. The existing `CoincidentPointTranslation` policy can still run a bounded asynchronous Modelica solve, read native finite `f64` results by exact experiment identity, and produce a generation-bound typed USD placement plan. The plan remains dry and requires Editor review/commit; no result is applied automatically. This is a specific policy over the generic boundary, not arbitrary SysML constraint execution. General constraint/parametric execution, state and behavior execution, a dedicated SysML editor, full UI source-set browsing, and automatic SysML-to-USD projection remain outside the current runtime. If a request needs one of those, report the exact bounded gap after checking the current owner and dependencies. ## Source organization SysML files remain ordinary Twin files and must contain standard SysML syntax; do not add LunCo-specific annotations to make runtime wiring work. The Twin manifest owns source-set selection: ```toml [sysml] # Optional Twin-relative entry point; `.sysml` or `.kerml`. root = "requirements/system.sysml" # Additional Twin-relative roots. The indexed Twin files remain authoritative. paths = ["requirements"] [verification] [[verification.cases]] name = "Project::VerifyVisual" scene = "tests/visual.usda" script = "scenarios/tests/visual.rhai" verdict_channel = "VISUAL_REQUIREMENTS" ``` Important source-set rules: - `twin.toml` is configuration, not a replacement for SysML source text. - The Twin's indexed files are the discovery authority; `[sysml].root` puts the entry point first and `[sysml].paths` narrows the indexed set. - Paths in the verification registry are Twin-relative and are checked as indexed `.usda`/`.rhai` files. The registry selects execution; it does not define a requirement, a numeric limit, or a second backend. - Use qualified names such as `Project::VerifyVisual` as stable keys for requirements and verification cases. Do not rely on a short name when packages can contain collisions. - Use the existing `twin:///...` and `lunco://...` identity schemes. Do not add a filesystem walker, a global source registry, or raw `std::fs` reads in a runtime crate. ## Validate before runtime For an individual source, use the installed production executable. In the commands below, set `LUNCOSIM_BIN` to the GitHub-installed `luncosim` command or its absolute installed path. For a source checkout without an installed command, build the production binary and set `LUNCOSIM_BIN` to that executable. ```bash LUNCOSIM_BIN=luncosim "$LUNCOSIM_BIN" --validate requirements/system.sysml ``` The same command accepts `.kerml` and can validate several assets in one call. It parses and resolves the supplied source without constructing a window, scene, physics world, or GPU. A successful pre-flight is not runtime proof. For a Twin source set, `ValidateSysml` reports source validation status, structural `lint.sysml` findings, diagnostics, indexed source files, and source revision. Use `AnalyzeSysml` when a policy needs semantic facts; that query is independent of structural-lint findings. Use `ReadActiveTwinContract` for the active Twin's component/verification bindings. Rhai joins these inputs where policy requires it. Against a running production session, the generic fact query can be called from Rhai: ```rhai let facts = query("AnalyzeSysml", #{ path: "twin://my_twin", tables: ["requirements", "verifications"] }); if facts.ok != true { throw(facts.errors); } ``` Indexed SysML source loads retain the exact Workspace `TwinId` and live mount through installation. File opens use the shared worker-side `FileDocumentAdmission::read` and register the resolved runtime owner before document events. Browser picks instead prepare request-owned bytes and create a fresh pathless Application document; duplicate display filenames never share source identity. Invalid UTF-8 rejects the import before installation. Retirement checks stored document ownership after source replacement; saving a file does not reassign its lifetime. See the [source admission contract](../../docs/architecture/55-scene-addressing-and-roots.md#document-source-admission-and-lifetime). For a mounted Twin, `AnalyzeSysml` reads the identity-fenced snapshot prepared by the authored Twin lifecycle policy. Non-empty source sets resolve against the embedded standard library on the async analysis worker; an empty optional source set commits an empty ready snapshot without initializing that library. Until the snapshot is ready, the query returns an explicit preparation result. Saving an indexed SysML document invalidates the mounted Twin snapshot and reloads that exact `twin://` source before analysis runs again. After a save, retry the query until its preparation result becomes ready, then use the returned source revision for any paged join. Unsaved editor changes are not part of the Twin-wide snapshot. Use `AnalyzeSysml` for preflight, authoring, or explicit verification work; do not call it from a high-rate `on_tick` hook. Revision-stamped async analysis and admission are part of the cross-domain runtime contract in [`62-deterministic-runtime-and-async-boundaries.md`](../../docs/architecture/62-deterministic-runtime-and-async-boundaries.md). Single-file `ValidateSysml` and `AnalyzeSysml` use the one-shot preparation protocol: initial source/selection parameters return `pending` and an `operation_id`; poll with only that ID. Consume `ready.report` with its actual `source_revisions`, or the terminal `failed.diagnostic`. Consumed or retired IDs reject. Logical engine/Twin files use their registered reader; native paths and standard file URIs use captured bounded file admission. Mounted source-set `twin://` queries retain the direct prepared-snapshot contract. See [validate-assets](../validate-assets/SKILL.md#api--against-a-running-luncosim). `AnalyzeSysml` supports `elements`, `references`, `relationships`, `constraints`, `attributes`, `requirements`, `verifications`, and `diagnostics` tables. `attribute_names` narrows the attribute table to qualified or local names; ambiguous local names remain visible to the policy for explicit handling. Optional positive `limit` and non-negative `offset` page every selected table independently. `analysis.page.tables` reports each table's total, returned count, offset, limit, and `has_more`; every page also carries the source revision. Check that revision before assembling pages. Unpaged full analysis can exceed Rhai's bounded-value budget on Twin-scale sources, so prefer selected tables, selected names, or bounded pages. For editable Rhai runtime policy, `sysml_analysis(path)` provides a native snapshot for small bounded sources. Native synchronous constructors retain bounded source reads; browser constructors require an exact prepared mounted snapshot and reject other file sources explicitly. Ready file reports already contain the requested semantic facts: consume those fields rather than issuing an implicit synchronous file query. For Twin-scale sources use selected `AnalyzeSysml` pages or `sysml_requirements::source()`, which pages the requirement/verification tables, checks revision consistency, and retains only the compact identities and verification links needed for policy joins. Detailed selected requirement records remain available through `source_with_selection()`. Use `sysml_attribute(path, qualified_name)` when the policy needs the native `SysmlAttribute` object for one exact-name source read, and `sysml_value` only when it needs the typed literal rather than the attribute metadata. Keep acceptance checks (dimensions, ranges, counts, material eligibility, and geometry rules) in the authored policy so ordinary design changes do not require a Rust rebuild. Rust should expose the source semantics and reusable native conversion, not Griffin-specific pass/fail decisions. The generic `AnalyzeSysml` selectors remain useful for clients that need to limit language-neutral API payloads. For the active Twin, the requirements policy composes source facts and the Twin contract through: ```rhai let source = sysml_requirements::source(); ``` When a policy needs several literals, select them in one bounded request and reuse the returned report: ```rhai let source = sysml_requirements::source_with_attributes([ "Project::Vehicle::massKg", "Project::Vehicle::wheelRadiusM" ]); if source.ok != true { throw(source.error); } let mass = sysml_requirements::number(source, "Project::Vehicle::massKg"); let radius = sysml_requirements::number(source, "Project::Vehicle::wheelRadiusM"); ``` This requests the source-backed attributes once and reuses that typed Rhai report. Keep it local to the evaluation or task-construction boundary; do not turn it into a mutable global cache. Qualified selectors are preferred, and ambiguous short selectors remain an explicit error. `sysml_requirements::source()` is read-only. It fails visibly when there is no active Twin, no indexed SysML source, a parser diagnostic, a registry error, or a verification name that does not resolve in the source set, or when the source revision changes during page assembly. It joins the `AnalyzeSysml` result with `ReadActiveTwinContract` in Rhai; neither generic query implements that policy. Use native typed Rhai maps inside the workflow; JSON is reserved for explicit external transport/logging boundaries. Never reconstruct a short-name map that could silently collapse colliding component attributes. For a component-owned observer, resolve the manifest binding through the generic helper instead of repeating scene/script or qualified-verification selection logic: ```rhai let binding = sysml_requirements::component_binding(source, "vehicle.wheel"); if binding.ok != true { throw(binding.error); } let component = binding.component; let verification = binding.verification; ``` The helper fails closed on unavailable reports, registry errors, unknown or duplicate components, and missing or duplicate verification mappings. It does not replace the component's SysML checks; it only supplies the exact Twin-owned identity selected by the manifest. Repeated source queries reuse one immutable semantic snapshot only when the caller revision, ordered source-set fingerprint, embedded standard-library contents, and cache format all match. Do not treat a document generation or a short revision number as a complete source identity: separate documents or Twins can reuse those counters. The cache uses the shared `lunco-hash` fast tier and does not add a second source registry or durable content store. ## Write the Rhai verification observer The observer is the executable policy. It reads the canonical source snapshot, names the SysML requirement and verification, observes the composed USD stage, and emits the verdict: ```rhai let source = sysml_requirements::source(); let result = sysml_requirements::evaluate(source, [ #{ id: "VIS-001", component: "camera", requirement: "Project::CameraExists", verification: "Project::VerifyVisual", kind: "exists", path: "/Twin/VisualCamera", expected_type: "Camera", visible: true }, #{ id: "VIS-002", component: "vehicle.wheel.front_left", requirement: "Project::WheelRadius", verification: "Project::VerifyVisual", kind: "attribute", path: "/Twin/Vehicle/WheelFrontLeft", attr: "radius", expected_attr: "visualWheelRadiusM", tolerance: 0.001 } ]); report_structured_verdict(result, "VISUAL REQUIREMENTS", "VISUAL_REQUIREMENTS"); ``` Every check requires `id`, `requirement`, `verification`, and `kind`. The evaluator first proves that the requirement exists and that the selected verification covers it. It then observes USD through the existing query path; it does not open USD layers, mutate a stage, or reimplement the resolver. Available generic check kinds are: | Kind | Observation | Important fields | |---|---|---| | `coverage` | requirement/verification traceability only | no USD path | | `assert` | source-derived predicate, including cross-component interface checks | `ok`, optional `actual`, `expected`, `error`; no USD path | | `exists` | prim exists, optionally has type and visibility | `path`, `expected_type`, `visible` | | `children` | required child prims exist and are visible | `paths`, `visible` | | `attribute` | scalar USD attribute is near a SysML literal | `path`, `attr`, `expected_attr`, `tolerance` | | `attribute_component` | one vector component is near a SysML literal | `path`, `attr`, `index`, `expected_attr`, `tolerance` | | `extent_component` | derived geometry extent component is near a SysML literal | `path`, `index`, `expected_attr`, `tolerance` | | `bounds_component` | composed USD geometry bound component is near a SysML literal | `path`, `index`, `expected_attr`, `tolerance` | | `attribute_equals` | direct literal equality for an observed attribute | `path`, `attr`, `expected` | | `relationship` | authored relationship has the required target | `path`, `relationship`, `target` | For numeric limits, use `expected_attr` to read the literal from the authoritative SysML source. Prefer a qualified attribute name; a short name is accepted only when the selected source facts make it unique. Ambiguous names are explicit failures, never a first-match choice. `attribute_equals` is for direct equality such as strings or booleans and uses its explicit `expected` value. Do not copy a threshold into Rhai, TOML, a UI label, or a Rust constant. Do not infer a requirement from a screenshot or from an ambiguous short-name lookup. The result contains `verdict` (`pass`, `fail`, `inconclusive`, or `error`), `ok`, typed `results`, `failures` for standard fail records, and `non_pass_results` for every non-pass record. It also carries `check_count`, `requirement_count`, `requirement_names`, `requirement_summary`, separate `pass_count`, `failure_count`, `inconclusive_count`, `error_count`, `non_pass_count`, `verification`, `source_revision`, and `source_files`. `check_count` is the number of concrete observations (for example, one transform or attribute on one repeated part); `requirement_count` is the number of unique SysML requirement usages represented by those observations. Use `requirement_summary` for compact per-requirement `{ checks, passes, failures, inconclusive, errors }` counts and keep the complete result table as evidence. A missing observation is inconclusive when the source constraint evaluator cannot decide; an empty check set is inconclusive. Do not turn either case into a pass. The next performance seam is a native batch USD query; do not implement an ad-hoc Rhai cache that outlives one evaluation. ## Select and run a verification case Use the same resolved production executable and a qualified name: ```bash "$LUNCOSIM_BIN" test \ --scene tests/visual.usda \ --verification Project::VerifyVisual \ --max-ticks 120 ``` The selector is intentionally strict. Before constructing the simulation it checks that: 1. the scene is enclosed by the Twin manifest; 2. the registry has exactly the requested qualified case; 3. the registry has no duplicate/unsafe/empty entries; 4. the mapped scene matches the requested scene; and 5. the declared verdict channel is used unless the CLI explicitly overrides it. The selector does not execute SysML constraints for you. The mapped Rhai observer still has to call `sysml_requirements::evaluate` and emit the verdict. Make positive conformance evidence the default: run the authored requirement observer through the production scene-test binary and prove the required component/value/relationship. Add a failing or unavailable-source case only when rejection or fail-closed behavior is itself an explicit contract (for example, stale-source rejection or a safety-critical missing relationship). `--validate` alone cannot prove any of these runtime facts. In the desktop workbench, open **Editor → SysML Requirements** to inspect the active Twin, search requirements, filter by evidence, test, and coverage status, and open a linked source at its declaration. A failed structured check also offers direct navigation to the associated requirement declaration. The view projection reacts to active Twin/root/manifest/file-index and SysML domain changes, not to unrelated document focus or USD editor tabs. Opening or closing USD editors must not rebuild the SysML model; source, evidence, manifest, and Twin lifecycle changes must still invalidate it. The detail pane initially selects a requirement with a Twin-mapped test when one is available. **Run selected tests** runs the distinct mapped cases for the selected requirement. **Run all mapped tests** runs each distinct case linked from any requirement once, sequentially. The completed suite retains its source revision and outcome counts; **Show failures** filters the list to failed requirements and **Rerun failed** runs only failed cases. The active suite shows progress and can be stopped. The child runner returns a versioned structured report with its verdict, bounded typed check evidence, and runner-level reasons for readiness failures, runtime faults, and exhausted limits. Failure identity, component/path, message, actual, and expected values come from this report rather than output-text parsing. Bounded captured output remains available for diagnostics. Requirements without a resolved `verify` link or Twin test mapping remain visible as coverage gaps and are skipped. Save or discard open SysML edits before running; the runner reads the saved Twin source. The overview separates requirement usages, definitions, and source-file counts. Its actionable counters filter missing formal `require` criteria, missing `verify` links, unmapped Twin tests, or mapped tests without a current result. The virtualized table sorts by visible ID, kind, source, evidence, Twin test, model coverage, or overall status, keeping those status dimensions in separate columns. Click a header to sort, drag its dotted handle to reorder it, and drag its divider to resize. Role cells say Definition or Usage, and source cells show the file name and line. The table uses the full center pane; the docked Requirement details panel follows the selected row in the lower-right Editor pane. It summarizes the formal criterion, declared subjects, explicit `satisfy` links, verification mappings, and evidence. Use **Open full traceability** to move to the complete map. The action focuses or opens the center SysML Requirements panel before showing its Traceability tab, even when another center panel is active. When a verification case has no Twin test mapping, **Open Twin test mapping** opens the active Twin's `twin.toml` in the source viewer. The missing-verify counter applies to usages; unmapped counts flag elements with at least one unmapped case, and not-run counts flag elements whose mapped cases have no current result. Details show a usage statement or, when absent, text from an unambiguously resolved definition, with separate source links. Each verification case shows its scene path near **Run mapped test**. Status explanations live on column-heading and status-label hints. **Status details** opens aggregate counts on demand; the main workspace does not expand a status reference. Summary cards use stacked text and native button focus, disabled, and selected states. Their counts describe requirement entries; run-button counts describe unique mapped tests. The selected requirement's statement precedes source metadata. The application catalog exposes **Tutorials → LunCoSim → SysML Requirements**, an authored Rhai tour using the active Twin and existing guided-tour commands. The overall status is `VERIFIED` only when the analyzed model has no source diagnostics, a formal `require` criterion exists, all `verify` links map to Twin tests, current structured requirement evidence passes, and every linked mapped test passes. `FAILED` indicates a standard fail. `INCONCLUSIVE` means the evidence could not decide; `ERROR` means evaluation failed; `RUN ERROR` means the runner could not establish a trustworthy result. `INVALID MODEL`, `STALE`, `RUNNING`, and `INCOMPLETE` keep source diagnostics, old, active, and missing proof visible. The roll-up summarizes authored evidence; it does not imply full KerML constraint execution. Read the three status dimensions separately; they answer different questions: - **Requirement evidence** is `PASS`, `FAIL`, `INCONCLUSIVE`, `ERROR`, `STALE`, or `NO EVIDENCE`, based on structured `_EVIDENCE` summaries and check-result events for the active Twin and source revision. `NO EVIDENCE` means no current checks were emitted. - **Test execution** is per linked scene test. `PASS`, `FAIL`, `INCONCLUSIVE`, and `ERROR` are authored standard verdicts; `PARTIAL` means some linked tests passed while others still need results. `NOT RUN` means mapped tests have no current result; `RUNNING` includes elapsed time; `CANCELLED` has no verdict; `STALE` belongs to an older source revision; `NO VERDICT` means the runner finished without a verdict; `RUN ERROR` means the runner failed or the report/source revisions did not agree. A runner error never becomes a standard `FAILED` verdict. - **NO VERIFY** means the source has no resolved `verify` link. **NO RUNNER** means a link exists without a Twin test mapping. - **Model coverage** reports whether a formal `require` criterion exists and how many `verify` links have Twin test mappings. A missing criterion or link is a model gap; it does not mean a test failed. - **Overall requirement status** combines valid source analysis, coverage, current requirement evidence, and mapped test results. Parser/resolver diagnostics make the model `INVALID MODEL` and prevent verification runs. Missing criteria, links, evidence, or test results prevent `VERIFIED`; stale inputs remain `STALE` rather than being treated as current. - Panel results are in-session evidence for the source revision that was run. Rerun after edits; closing the Twin clears its result set. ## Development cycle For a change to a Twin's requirements or verification: 1. Read the owning source and this skill, then search the current checkout for existing SysML vocabulary, evaluator checks, manifest fields, commands and tests. Do not add a second parser, registry, or report format. 2. Confirm the binary feature set. SysML is enabled by default in the production app and server: `cargo build -p lunco-luncosim --bin luncosim -j 4`. Use `--no-default-features` only when a deliberately lean build is needed. Rhai is the default scenario backend. Python is a separate opt-in `python` feature and is not used by this workflow. 3. Author standard SysML source and put source-set/execution selection in `twin.toml`; keep USD facts in USD and runtime observation in Rhai. 4. Run the parse-only source gate, then `ValidateSysml` for the mounted Twin. 5. Add or update the generic Rhai observer and run the production scene test with the qualified `--verification` selector. 6. Inspect structured evidence: requirement/verification identities, exact USD paths, actual/expected values, source files and `source_revision`. 7. Review the full diff for duplicated thresholds, stale qualified names, unindexed files, compatibility fallbacks and claims beyond the supported subset. Run `git diff --check` and the smallest relevant validation. Keep behavior and policy tests in authored Rhai under `assets/scenarios/tests/`. Reserve Rust tests for parser, resolution, serialization and generic bridge mechanisms that the public Rhai/API surface cannot observe. If the change is only `.sysml`, `.kerml`, `twin.toml`, Rhai, or this skill, do not rebuild Rust unless the validation path itself changed. ## Common bounded diagnoses | Observation | Correct diagnosis/check | |---|---| | `ValidateSysml` is unknown | Check that the production binary/session is current and that the validation plugin is registered; do not conclude SysML is absent from one source file. | | `sysml_requirements::source()` is unavailable | Check the active Twin, the Rhai tool library, and the `sysml` feature; report the exact unwired boundary if one remains. | | No requirements are returned | Check the Twin index, `[sysml].paths`, source extension and parser diagnostics; do not create a duplicate requirements file in Rhai. | | Verification registry fails | Inspect the active Twin contract and exact Twin-relative scene/script paths; fix the manifest or indexed files. `ValidateSysml` reports source validation, not manifest policy. | | A short attribute name collides | Use a qualified attribute identity or resolve the ambiguous source fact explicitly. Do not let a new lookup rule choose silently. | | The selected case passes without evidence | Confirm the observer emitted structured evidence and that the result was not an empty/unavailable report; `--verification` only selects and validates the mapping. | | A request needs arbitrary KerML constraints or a full editor | State that this is outside the implemented subset after citing the domain review; do not emulate it with a hidden Rhai parser. | | A request mentions Python | Treat Python as optional integration only. Use `--features python` and the Python-specific contract if explicitly requested; keep normal examples in Rhai/Modelica. | When reporting a gap, use a bounded result: found and usable, implemented but unwired, present on another branch/version, not found in the searched scope, or externally blocked. Never generalize from an empty `skills/` search or from an executable built without the optional `sysml` feature.