Skip to content

chore(release): 0.9.1 - #614

Merged
HuiJun merged 1346 commits into
mainfrom
release/0.9.1
Sep 30, 2026
Merged

HuiJun merged 1346 commits into
mainfrom
release/0.9.1

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Release branch for 0.9.1, cut from develop per docs/project/releasing.md § The release branch. It carries everything merged into develop since 0.9.0 up to 043c92948 (the merge of #743), plus the release bookkeeping below.

Scope decisions by the maintainer:

Bookkeeping commits on the branch:

  • f3fdf451 sets VERSION = "0.9.1"; 926a47ea6 sets every Node, Java, Rust and editor manifest to 0.9.1 (check_version.py --node/--java/--rust/--editors all report 0.9.1 under CIRCLE_TAG=v0.9.1).
  • c7b18504, c07d41cf, 70072f1b, d295dc4a0, dc5240dac fold every fragment under changes/unreleased/ into one ## 0.9.1 — 2026-09-26 section (Added/Changed/Fixed/Security/Performance); ## Unreleased is empty and only README.md remains under changes/unreleased/. Four entries folded earlier were refreshed to the wording their fragments later took on develop (deferred signals in both modes, -strict no longer listing deferrableTrigger, the metadata-column and library-root-name alias items).
  • 9e6777ef3 merges origin/develop. Conflicts (migrate writer/states/streams, internal/ir/view, annotations.go, stdlib.snapshot, MigrationMetadata.sysml, the pilot baseline) were all criss-cross merges of PRs this branch had taken from their feature branches before they landed on develop; each was resolved to develop's side, which superseded the two release-only expectation commits (87e1a313d, 50b6c754c). make proto-rust, make stdlib-snapshot and go run -C tools ./cmd/pilot-diff -update reproduce the committed files byte for byte.
  • 39ec96768, ca25f7583: shakedown findings — READMEs still naming 0.9.0, and the published client pom inheriting SCM URLs with a /opensysml-client suffix. 60437d518: publish-maven accepts GPG_PRIVATE_KEY base64-encoded on one line as well as armoured — the first rehearsal (pipeline 3469) failed at gpg --import because the CircleCI UI flattens a pasted multi-line key; every other release job passed with its publish step skipped.

Before tagging: re-run the CircleCI release rehearsal on this branch (release_rehearsal: true, see releasing.md § Rehearsing the release) after re-entering GPG_PRIVATE_KEY base64-encoded — the Maven job (GPG test-sign, Central token probe, signed verify of the renamed artifact) is the only one not yet exercised. make proto-breaking BUF_BREAKING_REF=origin/main passes. Branch protection: #676 renamed the required check to Go race tests (<shard>).

After merge: tag main as v0.9.1 (publishes GitHub release, PyPI, npm, Maven Central, crates.io), then merge main back into develop.

How it was verified

On dc5240dac: gofmt -l . empty, go build ./..., go vet ./..., go test -count=1 ./... all ok; corpus gates with every OPENSYSML_REQUIRE_*=1 (training, pilot corpora, pilot library XMI, PSSM, fUML) ok; make conformance 149 passed / 1 skipped / 0 failed; Python pytest client/python 1237 passed / 119 skipped; Node npm test 149/149; Java mvn -B -f client/java/pom.xml verify ok; Rust cargo test ok and cargo package -p opensysml --locked builds opensysml-0.9.1 (not published); python3 scripts/changelog.py check, python3 scripts/check-doc-links.py, make docs-check, bash scripts/ci-changed-areas-test.sh, make proto-breaking BUF_BREAKING_REF=origin/main all pass.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change (none: release bookkeeping)
  • 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 (a release folds the fragments into CHANGELOG.md by design)
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • 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/e0c5a204e0984415814ed38767578b41
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/e0c5a204e0984415814ed38767578b41?variant=devin
Requested by: @HuiJun

@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
devin-ai-integration Bot changed the base branch from develop to main September 26, 2026 12:38
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 26, 2026 13:15
devin-ai-integration Bot and others added 25 commits September 29, 2026 09:27
…nd-in-parameter-evaluation

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion' into HEAD

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

# Conflicts:
#	api/proto/sysml.pb.go
#	client/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java
#	client/node/src/generated/sysml_pb.ts
#	client/python/opensysml/proto/sysml_pb2.py
#	client/rust/conformance/sysml.descriptor.binpb
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…constraint-holds-questions

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

# Conflicts:
#	api/proto/sysml.pb.go
#	client/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java
#	client/node/src/generated/sysml_pb.ts
#	client/python/opensysml/proto/sysml_pb2.py
#	client/rust/conformance/sysml.descriptor.binpb
#	internal/frontend/grpc/service.go
…ns' into fix/verification-method-lookup

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

# Conflicts:
#	.agents/skills/testing-pilot-rejection/SKILL.md
#	README.md
#	docs/internals/architecture.md
#	docs/project/pilot-rejection-baseline.json
#	docs/project/pilot-rejection.md
#	internal/translate/export/rdf_in.go
-convert took one file and Convert refused a model_hash of several
documents; a file converted alone wrote a reference into another as an
unresolved name. The documents of a model are now analyzed together, as a
workspace analyzes them, and each is encoded over that one analysis: a
reference from one document to an element another declares links the
subject that document writes, by the name and identity its own encoder
gives it (a positional name included). Each document's root elements carry
sysx:sourceDocument.

- export.ModelToRDFWith, convert.ConvertModel
- sysml a.sysml b.sysml -convert ttl|api-json
- Convert of a multi-document model_hash to ttl or api-json; notation stays
  a one-document operation (FAILED_PRECONDITION, as before)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

Dependency takes PrefixMetadataAnnotation, not PrefixMetadataMember: the
metadata usage is the annotatingElement of an Annotation the dependency
owns. The reader takes that Annotation as the ownership edge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…thoring' into feature/verification-objective-metadata-authoring
…etadata-authoring' into feature/editor-metadata-prefix-existing
…xisting' into fix/unbound-in-parameter-evaluation
Co-Authored-By: jason.han <hanhuijun@gmail.com>
FlowDeclaration takes 'of' FlowPayloadFeatureMember: a FeatureMembership
owning a PayloadFeature. The declared payload is now written as that
feature (m.cmd reaches it), 'of T' as one typed by T, and the reader
rebuilds the 'of' clause from it instead of the sysx:payload expression.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven KerML Annex A examples begin with a blank line the rendering drops,
so hop 2's positions sit a line higher: whitespace-only, not stable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… features

Review: a graph from an earlier release states a flow's payload as
sysx:payload beside standard ends, and it lost its 'of' clause. It is read
again; a flow stating both shapes is refused. Only the one payload feature a
flow's head writes is kept out of its body; any other is refused, not dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r element

Review: sync minted the dependency prefix's Annotation an id of its own,
and minted the prefix metadata usage one it cannot declare, so the next
export moved both back. The Annotation is a derived satellite that follows
its metadata usage (_an, as _om does), and a '#' prefix is not minted.
An owned Annotation whose annotatedElement is not its owner is refused
rather than written as the owner's prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ions

* feat(edit): author import declarations

Add add_import end to end: the edit engine writes a membership or
namespace import (visibility indicator, recursive ::**, import all and
[expression] filters) into a namespace body or the document root after
the owner's existing imports, refusing duplicates, malformed targets,
enum-body owners and targets that fail to resolve. The service gates it
on the new import_authoring capability, and the Go, Python and Java
clients expose it (AddImport / Editor.add_import / Edit.AddImport) with
preflight checks.

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

* fix(edit): drop trailing whitespace splicing into a shared-line closing brace

When a body's closing brace shares its line with other text,
memberInsertion started the splice at the brace and left the spaces
before it behind on an otherwise-blank line. Extend the splice back
over the horizontal whitespace so single-line bodies expand cleanly.
Also start the Python downstream test from the single-line source and
parse the api-json array it actually returns.

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

* feat(edit): author documentation on new and existing declarations

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

* feat(edit): author constraint bodies, assert constraints, exhibit states and state subactions

Add constraint body expression authoring, asserted constraints, exhibit references, and state entry/do/exit actions across the edit checker, gRPC/LSP service, clients, and conformance suite.

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

* fix(export): write then-done as one SuccessionAsUsage to library done

A member-attached then whose target is the FinalNode it introduces now encodes like an explicit 'succession first x then done;': the target end reference-subsets Actions::Action::done, endForm stays "then", no targetMember, and the FinalNode is not encoded as a separate done Membership (which was also an invalid ReferenceSubsetting target). The edge carries the node's source lines so the line round-trips verbatim. Old-shape graphs (done Membership + sysx:targetMember) still read back, and the toolkit reader no longer synthesizes the Membership.

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

* fix(edit): write directed parameters without the implicit ref

A direction already marks a usage's parameter nature, so a directed ref is written 'in x : T;' — the canonical spelling the writer emits — instead of 'in ref x : T;'. Undirected refs and abstract directed refs keep the keyword (the parser reads 'in abstract x' as a plain usage).

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

* fix(edit): admit redefinition on new member kinds and tidy add-member parsing

Allow usage declarations to redefine inherited features, share indentation style detection, and parse Python add-member tuple fields once with strict expression validation.

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

* chore(client): regenerate python stubs with pinned grpcio-tools

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

* fix(conformance): avoid exhibit name collision in authoring scenario

Exercise exhibit references through a nested state whose final segment is not already declared by the host.

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

* feat(edit): author action-body sequencing with first/then members

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

* feat(edit): author verification objectives and metadata

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

* chore(proto): regenerate Python gRPC stubs with the pinned grpcio-tools

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

* style(edit): merge declaration in sequence lowering test for staticcheck

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

* fix(conformance): define feature used by constraint scenario

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

* fix(proto): align Python stubs with pinned generator

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

* fix(export): export same-named members of one namespace under distinct ids

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

* fix(python): regenerate gRPC stubs with pinned tool version

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

* fix(conformance): map constraint bodies through Go client

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

* chore(proto): regenerate Python stubs with pinned grpcio-tools 1.83.0

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

* fix(runtime): a performed action's unbound input fails that performance, not its performer's creation

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

* fix(parser): resolve bare accept transition payload types

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

* feat(solve): add violation queries and rounding-sound proofs

A violation query's models are the assignments violating an element's
claim: ConstraintViolation, RequirementViolation and
SatisfactionViolation translate the required conditions into one
negated assertion in the new violated-conditions role, keeping
assumptions as hypotheses. No definedness guard is hoisted in
violation mode, so a computed divisor, exponentiation or negative
root refuses rather than yield a false proof.

Query.RoundingSound re-encodes a query over the evaluator's float64
arithmetic: each real-sorted operation, widened integer and ratio is a
site bounded by every double the exact value could round to, guarded
by the conditions under which the evaluator computes it, and every
literal is the exact rational of its float64. (*Solver).Solve rechecks
an unsat answer over that encoding and records the agreement in
Result.RoundingProved — never replayed, so a float64 counterexample
stays not proved.

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

* feat(analysis): answer holds questions over violation queries

The solve engine claims Holds alongside Satisfiable, requiring
violation queries for the one and non-violation queries for the other
— the two ask opposite things of the same translation. Every queried
claim unsat (proved when the conditions round) proves it holds over
every assignment of the free features; a replay-confirmed sat is a
witnessed violation. Registry.Prove builds such a question, and the
check and smt engines refuse a Holds lacking their payloads rather
than panicking.

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

* feat(repl): count a proved rounded unsat as unsat

A rounded unsat the rounding-sound recheck proved is a real unsat, not
a false one the report should flag.

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

* fix(symbols): classify a kindless usage as a reference usage

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

* docs(runtime): record the performed-action input boundary as tool-defined

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

* fix(edit): place imports after body-bearing ones and accept $:: targets

An import written with a body ({ ... }) has no terminating semicolon, so
importStatementEnd now balances the braces instead of landing the next
import inside the body. importTarget accepts an optional $:: root,
which the post-parse check and duplicate comparison honor, and the
target docs note the rooted form.

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

* fix(edit): document named dependencies, multiplicities and relationships

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

* feat(api): ask holds and satisfiable on the verify requests

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

* feat(grpc): answer holds and satisfiable through the solvers

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

* feat(client): ask holds and satisfiable from every verify call

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

* feat(conformance): carry the question through the adapters

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

* docs: document the verification questions and update the self-model

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

* fix(solve): pin chain vars only when their root denotes the pinned object

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

* fix(solve): pin chain vars only for two-step subject or owner roots

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

* chore(ci): re-run checks

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

* fix(edit): write add_parameter's directed usages without ref, keep explicit ref

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

* test(editors): pass the new Verdict components in test constructors

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

* ci(python): install z3 so the solver-backed client tests run

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

* fix(java): keep body expression across withDirection and ignore empty bodies in preflight

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

* fix(edit): refuse declaration fields on a then reference

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

* fix(edit): place after-anchored sequence members before same-line siblings

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

* test(edit): align parameter helper expectations with the implicit kind

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

* fix(edit): mark an inline sequence member's start at its first byte

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

* chore(proto): regenerate python stubs with the pinned grpcio-tools

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

* fix(grpc): report a state machine performer's attributes in final_context

ExecuteState on a performer already bound the machine to the performer's
feature values; the executed response now carries the performer's
attributes under this., as an explored outcome's outputs do. Adds
runtime, gRPC and Python regression coverage for performer-dependent
guards and writes.

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

* End node spans at their last token, not the next token's start

spanFrom closed a span at the next token's offset, so every node span ran
on over the whitespace and comments after it, and every diagnostic, LSP
range and gRPC span built from one did too. It now ends at the last
consumed token, or at the /* */ body a comment node consumed.

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

* fix(runtime): keep a recorded performance failure across snapshots, images and failed starts

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

* fix(export): order toolkit members by ownedMembership when naming duplicates

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

* feat(edit): add reference assertions and result-expression bodies

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

* fix(runtime): end a failed performance's life and record its failure when the clock drives it

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

* fix(export): quote names that collide with positional identities

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

* feat(export): write a transition's trigger as metamodel structure

A transition's accept, after, at and when triggers are exported as its
triggerAction: an AcceptActionUsage under a TransitionFeatureMembership of
kind trigger, with a typed payloadParameter, a receiverArgument for via and
a TriggerInvocationExpression for time and change events. The decoder reads
the structure alone and keeps reading the earlier sysx:trigger form; the
OpenSysML when <name> injected-signal trigger keeps the extension predicate.

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

* fix(edit): resolve globally qualified sequence references from the root

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

* fix(edit): place after-anchored sequence members before the next member's comments

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

* feat(edit): add metadata prefixes to existing declarations

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

* docs(edit): tighten the after-placement comment

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

* fix(edit): resolve global sequence references through the index

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

* fix(edit): keep after-anchored sequence members out of block comments

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

* feat(edit): author comments and line notes; read comment bodies as KerML states them

Comment::body now follows KerML 1.1 8.2.3.3.2 body processing in the parser,
RDF/API JSON export and import, so documentation text is refused only when it
holds */ or a carriage return. ApplyEdits gains add_comment (field 16) and
add_note (field 18) behind the comment_authoring capability, with Go, Java
and Python client surfaces.

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

* chore(referee): re-record the pilot baseline for the moved examples

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

* Judge an expression complete by the parser cursor, not its span end

A value or kept notation followed by a comment parses as one expression,
but its node span now stops before the comment, so completeness is read
from the next token's offset instead.

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

* fix(semantics): a parameter with no written multiplicity takes its §7.6.3 effective multiplicity

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

* feat(authoring): add recursive action bodies and source multiplicity

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

* fix(authoring): address action body review feedback

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

* fix(rdf): preserve positional succession source multiplicity

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

* fix(runtime): bare parameters bind like [0..*] everywhere; keep the calc read rule as declared

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

* fix(grpc): report an action performer's attributes in performer_attributes

ExecuteActionResponse gains performer_attributes (field 7): the performer's
attributes as the run left them, keyed and selected as an explored outcome's
outputs key them (this.<attr>), via the Invocation performer logic outcomes
use. outputs stays the action's output parameters alone. The Go, Java and
Python clients expose the new field.

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

* test(edit): keep snapshot prefix fixture well-typed

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

* fix(export): refuse trigger links that disagree, and read a commented trigger keyword

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

* fix(export): refuse a contradicting payload parameter and a second receiver

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

* fix(export): escape quoted identity segments

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

* fix(parser): enforce action parameter prefix ordering

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

* fix(client/python): refuse a one-shot iterable as a comment's about list

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

* fix(solve): state why float64 overflow cannot falsify a rounding-sound proof

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

* fix(analysis): let a witnessed violation decide a holds batch

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

* fix(grpc): ask symbolic questions of the object that carries the element

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

* fix(solve): pin nested values the evaluator reads

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

* fix(authoring): preserve sequence edit semantics

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

* fix(export): quote names that begin with a quote

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

* fix(edit): resolve metadata prefix aliases and authoring capability

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

* fix(export): keep a reference key when its parser spelling is ambiguous

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

* chore(proto): regenerate merged Java protobuf documentation

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

* docs(authoring): clarify merged editor capabilities

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

* refactor(edit): drop unused indentUnit helper after documentation merge

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

* test(export): pin superseded then-done read-back

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

* chore(proto): regenerate Python stubs with the pinned grpcio-tools

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

* test(python): correct malformed add-member operation cases

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

* test(python): keep state-action type check assertion reachable

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

* fix(runtime): use effective parameter ranges for writes

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

* fix(runtime): clarify action parameter write ranges

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Review: a span runs on to the next token, so 'part a; /* note */' ended
a's range after the note. The range now ends at the last token that is not
trivia; a comment that is a declaration's body (doc /* ... */) stays in it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ible-column-state-transition-refs

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
lexesAsQualifiedName rejected every token the lexer marks Keyword, so a
target naming an element after a word that is reserved only in the other
language (type in SysML sources, part in KerML sources) was refused as
not a qualified name. Read the token stream the way the parser does:
a keyword of the file's own grammar is refused with a message telling
the modeler to quote it, a keyword of the other grammar reads as a name,
and KindUnknown reads as SysML.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 27 commits September 30, 2026 03:21
namesEdgeEnd read a control-node keyword followed by a name as a
two-ended succession to the member sharing the keyword's name. The
grammar gives the keyword its own declaration (ForkNode, JoinNode,
MergeNode, DecisionNode: 'fork' UsageDeclaration? ActionBody), so only
the bare `then <kw>;` beside such a member is an edge end.

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

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion and lint regressions

Shared-default and shared-verdict tracing recorded every path of a nested shared value per read, deduplicated reads through a key string built per read, spelled a dotted path at every ancestor to ask whether a binding governs it, and every journal mark cloned the clock's waiter list. The trace now records a nested value once, compares paths in place, prefilters the binding question by the features a type's bindings start at (memoized on Model.bindingRoots), and the clock replaces its waiter list instead of editing it so a mark keeps the slice it saw.

The migration writer reuses the buffers of closed blocks and indents from a table. The nested-usage subsetting memoizes declaredSubsettedNames on the runtime model and makes its deduplication and reachability sets on first use. The undeclared-signal lint walks the document once per analysis through kit.ScopedNodes instead of twice.

The performance record's findings 5–8 carry the attribution, the six-run benchstat tables against v0.9.0 and the tree before this change, the profile frames, and what remains as the price of a rule.

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

# Conflicts:
#	internal/translate/migrate/writer.go
* fix(edit): resolve an ApplyEdits batch's references against the whole batch

A succession reference or metadata prefix an operation writes is now
checked once against the model the batch leaves, so it may name a member
or metadata definition a later operation of the same batch declares.
Names are still taken in operation order, and a `first x` label no
longer takes or makes visible the name it borrows.

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

* fix(edit): follow a batch's deferred references through later renames

A succession end or metadata prefix an operation writes is now anchored to
the byte it starts at in the edited document and moved past the later
operations' splices, so the deferred check reads the name the batch leaves
there rather than the one the operation was given: a later rename of the
metadata definition, of the prefixed declaration or of the sequenced node
no longer refuses a valid prefix or skips the duplicate-prefix check.

ActionNodeOfBody and FeatureSymbolInScope look past a `first g;` label to
the inherited member of that name, so the label no longer hides it.

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

* fix(edit): judge a deferred succession end under its `$::` root

The end read back from the final AST is passed to the visibility check, and
reported, with the global root it was written with, so a `$::`-rooted end
resolves through the index rather than the edited document's scopes.

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ore-tag' into feature/release-rust-client-on-core-tag

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

# Conflicts:
#	.circleci/config.yml
#	docs/project/releasing.md
#	docs/project/roadmap.md
…claration

namesEdgeEnd read a control-node keyword followed by a name as a
two-ended succession to the member sharing the keyword's name. The
grammar gives the keyword its own declaration (ForkNode, JoinNode,
MergeNode, DecisionNode: 'fork' UsageDeclaration? ActionBody), so only
the bare `then <kw>;` beside such a member is an edge end.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
…tribution

Shared-default and shared-verdict tracing recorded every path of a nested shared value per read, deduplicated reads through a key string built per read, spelled a dotted path at every ancestor to ask whether a binding governs it, and every journal mark cloned the clock's waiter list. The trace now records a nested value once, compares paths in place, prefilters the binding question by the features a type's bindings start at (memoized on Model.bindingRoots), and the clock replaces its waiter list instead of editing it so a mark keeps the slice it saw.

The migration writer reuses the buffers of closed blocks and indents from a table. The nested-usage subsetting memoizes declaredSubsettedNames on the runtime model and makes its deduplication and reachability sets on first use. The undeclared-signal lint walks the document once per analysis through kit.ScopedNodes instead of twice.

The performance record's findings 5–8 carry the attribution, the six-run benchstat tables against v0.9.0 and the tree before this change, the profile frames, and what remains as the price of a rule.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
One pipeline parameter, release_rehearsal, runs the release workflow on a
branch with every check live and the irreversible commands - cosign signing,
ghr, twine upload, npm publish, mvn deploy, cargo publish - skipped. A
rehearsal exports a stand-in CIRCLE_TAG translated from _version.py (PEP 440
to SemVer), and rehearsals probe the GitHub, npm and Central tokens and build
and sign the Maven artifacts. The tag path is unchanged: the jobs drop only
the branches-ignore filter, which the workflow-level when now replaces.

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

* feat(client-java): lock the version to the core and auto-publish to Central

The pom and its consumers follow _version.py in lockstep, checked by
check_version.py --java and a pytest gate that also runs on a
manifest-only change; the release profile publishes the validated
deployment itself and waits until it is on Central.

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

* ci(release): publish the Java client to Maven Central from the core tag

publish-maven runs in the release workflow on the v* tag, beside
publish-pypi and publish-npm, signing and uploading at the core version
from the restricted maven-central context.

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

* docs(release): document the Maven Central publish

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

* test(release): import ElementTree at module level; tidy the context wording

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

* ci(release): read the Maven Central credentials from project variables

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

* ci(release): warn against debug output on the Maven publish step

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

* ci(release): read the Maven Central credentials from its context

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
…-core-tag

* feat(client-rust): lock the crate version to the core

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

* ci(release): publish the Rust client to crates.io from the core tag

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

* docs(release): document the crates.io publish

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

* ci(changed-areas): run the lockstep tests when an editor's client reference changes

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

* docs(release): drop --offline from the Cargo.lock refresh

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

* fix(client-rust): accept a literal-string crate version

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

* ci(release): read the registry credentials from the org contexts

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
The editors carry the core version the clients already follow: 0.9.0 in the
two package.json files (locks regenerated, only the version lines move), the
Cameo and SysON poms, and the child poms' <parent><version>. Nothing
publishes the editors, but check_version.py --editors now reads every editor
manifest - package.json, package-lock.json (both version copies must agree),
pom and child <parent><version> - through the shared lockstep check, so a
release tag fails early when one disagrees. The python changed-area trigger
covers every editor manifest, build-python-package runs --editors before
anything is built, and releasing.md's bump step lists the files.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
The editors carry the core version the clients already follow: 0.9.0 in the
two package.json files (locks regenerated, only the version lines move), the
Cameo and SysON poms, and the child poms' <parent><version>. Nothing
publishes the editors, but check_version.py --editors now reads every editor
manifest - package.json, package-lock.json (both version copies must agree),
pom and child <parent><version> - through the shared lockstep check, so a
release tag fails early when one disagrees. The python changed-area trigger
covers every editor manifest, build-python-package runs --editors before
anything is built, and releasing.md's bump step lists the files.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
* ci(release): add a no-publish release rehearsal

One pipeline parameter, release_rehearsal, runs the release workflow on a
branch with every check live and the irreversible commands - cosign signing,
ghr, twine upload, npm publish, mvn deploy, cargo publish - skipped. A
rehearsal exports a stand-in CIRCLE_TAG translated from _version.py (PEP 440
to SemVer), and rehearsals probe the GitHub, npm and Central tokens and build
and sign the Maven artifacts. The tag path is unchanged: the jobs drop only
the branches-ignore filter, which the workflow-level when now replaces.

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

* docs(release): state the rehearsal's limits without overclaiming

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

* ci(release): don't print Central's probe response in the rehearsal

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…t pom

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…narrating them twice

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit b9de3b0 into main Sep 30, 2026
23 checks passed
@HuiJun
HuiJun deleted the release/0.9.1 branch September 30, 2026 15:43
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.

2 participants