Skip to content

chore(release): 0.9.0 - #564

Merged
HuiJun merged 2185 commits into
mainfrom
release/0.9.0
Sep 24, 2026
Merged

HuiJun merged 2185 commits into
mainfrom
release/0.9.0

Conversation

@devin-ai-integration

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

Copy link
Copy Markdown
Contributor

What and why

Release branch for 0.9.0, cut from develop at 1d02c68 (everything merged since v0.8.1, through #566). Per docs/project/releasing.md:

  • python3 scripts/changelog.py release 0.9.0 folded the 229 unreleased fragments into CHANGELOG.md as ## 0.9.0 — 2026-09-24 (Added 140 / Changed 82 / Fixed 85 / Performance 7) and removed them from changes/unreleased/.
  • client/python/opensysml/_version.py: VERSION = "0.5.0" → "0.9.0", so the v0.9.0 tag publishes the matching opensysml wheel.
  • Includes the changelog note on the cold-references cost of per-document dependency invalidation (the fragment from docs(changelog): note the cold references cost of per-document invalidation #540), so that accepted trade-off is recorded in the release notes.

Do not squash: merge with a merge commit, tag main as v0.9.0, then merge main back into develop.

How it was verified

On the release head (3b054bf):

  • gofmt -l . (empty), go build ./..., go vet ./..., make lint, go test -run TestStdlibConformance ./internal/workspace/libs
  • go test -race -count=1 -p 1 ./... — 83 packages, all pass
  • Corpus gates with all four corpora required (OPENSYSML_REQUIRE_TRAINING_CORPUS/PILOT_CORPORA/PILOT_LIBRARY_XMI/PSSM_SUITE=1, go test ./tests/corpus ./tests/identity) — pass, no baseline movement vs v0.8.1: training 100/100, pilot ratchets unchanged, PSSM referee 36 → 60 pass, validation census 156 → 157 faithful.
  • make build-grpc + pytest client/python/tests/ — 983 passed, 94 skipped; python client/python/scripts/check_version.py --tag v0.9.0 prints 0.9.0
  • python3 scripts/changelog.py check, python3 scripts/check-doc-links.py, python3 scripts/check-doc-ids.py, go run ./cmd/doc-counts -check (already current)
  • make proto-breaking BUF_BREAKING_REF=origin/main — no breaking schema changes
  • Performance vs v0.8.1: BatchConstraints 260 ms → 9.5 ms, WorkspaceEdit 100 → 49 ms, RenameWarm −66%, runtime geomean −30%; the undefined-operator check no longer walks every node (about 7% off LoadModel); whole-binary -validate on Apollo 0.38 → ~0.45 s and a 12k-element generated model 0.37 → ~0.50 s (residual, attributed mostly to per-document dependency journaling in the resolver); LSP cold references after an edit slower by design, as noted in the changelog. Validate-hang repros (30 exposes, 25-deep nested calls) complete in ~0.02 s.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change (release bookkeeping only)
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog folded on the release branch as docs/project/releasing.md prescribes
  • 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/bb80cf5ab72a4155979b6b455ff3b1f8
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/bb80cf5ab72a4155979b6b455ff3b1f8?variant=devin
Requested by: @HuiJun

devin-ai-integration Bot and others added 30 commits September 23, 2026 02:26
A feature a view exposes from outside its owner cannot be written private:
v2 hides a private member from the qualified path an expose (and any layout
annotation naming it) must resolve, so such references came out unresolved.
planViews now records each shown element a placed view exposes through
m.exposed — the mechanism featureVisibility and hiddenFromHeirs already
consult — so its declaration keeps its reachability and the report notes
"private visibility is not written: view ... exposes it".

Co-Authored-By: jason.han <hanhuijun@gmail.com>
A non-recursive membership import (import P::x, expose x) surfaces only its
last segment or the target's short name, so an unqualified lookup of any
other name cannot match it. importPrefixAvailable now prunes such imports
before their target is resolved: previously each import's target resolution
re-walked the scope's members and so resolved every sibling import's target
in turn, making lookups in a namespace with many expose/import members
factorial in their number (a view with 30+ exposes never finished
-validate).

The prune consults Index.ShortNamed, which reports whether a name is
registered as some symbol's short name. Its reads are tracked by a new
ReadSegment kind on symbols.ReadRecorder so a document's frame is
invalidated precisely when a name under a consulted segment is registered
or dropped, rather than forcing re-analysis on any edit.

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

A feature a view exposes from outside its owner cannot be written private:
v2 hides a private member from the qualified path an expose (and any layout
annotation naming it) must resolve, so such references came out unresolved.
planViews now records each shown element a placed view exposes through
m.exposed — the mechanism featureVisibility and hiddenFromHeirs already
consult — so its declaration keeps its reachability and the report notes
"private visibility is not written: view ... exposes it".

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jason.han <hanhuijun@gmail.com>
Explicit table rows go into one Union whose other is Named over every
row; WhereType and WhereMetadata take several names, so a table with
many row types filters once per kind instead of once per type; the
remaining joins nest as a balanced tree. The deepest generated query
chain drops from 47 calls to 7.

Collaborator paragraphs are placed by the view their ownerId names
within the document their viewId names; paragraphs no view shows are
kept as stray paragraphs.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
«ValueProperty», «PartProperty», «SharedProperty», «ReferenceProperty» and
«ConstraintProperty» applied from MagicDraw's SysML customization profile to
a UML Property, with no tag, say what the usage keyword already says. They
are dropped in annotated(), beside «ConstraintParameter», so metadata
usages, comments and the report agree; a same-named stereotype from another
profile, a tagged marker, and a marker on a property written as another
kind are still written.

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

A «PartProperty» on a constraint parameter is dropped as its `in ref part`
form says, since a parameter is a reference by necessity; a «ValueProperty»
on a block-typed parameter or a «ReferenceProperty» on a value-typed one
contradicts the written form and is kept, as elsewhere.

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

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Typing a call re-read its arguments for every reader of the enclosing
call — the argument check, the result type, the held element type — so
each level of nesting doubled the work and validating a generated query
nesting twenty calls did not finish. The checker now memoizes a call's
argument types and scalar type per scope for the silent checkers spawned
from one reporting checker, tracking calls still being typed so a
re-entered call is never recorded as its provisional unknown type. The
reporting checker itself never answers from the memo, so each diagnostic
is still reported once where it arose. SelectCall answers a memoized
selection without retyping the call's arguments.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
The graph the RDF and api-json mappings write now carries the
relationship elements the metamodel defines beside the collapsed
properties: FeatureTyping/Subclassification/Subsetting/
ReferenceSubsetting/Redefinition ends, MultiplicityRange bounds,
ConjugatedPortDefinition/PortConjugation, SubjectMembership,
RequirementConstraintMembership, ResultExpressionMembership,
ElementFilterMembership, the Membership an expression referent is
carried by, and an OwningMembership for a declared relationship
member. Decoding accepts the materialized elements where the
collapsed properties imply them and refuses them where they
contradict; perform/exhibit/include/assert usages take their own
metaclasses and kindless or unnamed members read as ReferenceUsage.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
ReadAPIJSON now decodes the toolkit's compact-json and full-json to
byte-identical notation: the root Namespace wrapper is transparent,
@ref and unresolved-derived targets read as the names they spell, and
stated defaults collapse back off isImpliedIncluded elements while
ends the notation cannot place are refused. -convert takes -id uuid
to mint name-based uuids the way the library convention does; the
form reads back with its derived ids implied rather than annotated.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Spell out the materialized relationship elements, the sysx extension
metaclasses an element-form consumer does not read, toolkit
compact/full import behavior, and the uuid id form; add the matching
compliance rows and changelog fragments.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Drop the unread 'out' initializer in subjectOf's uuid branch, remove the
unused isParameterMembership helper, and restructure the subject-parameter
verify loop so the early return is not unconditional — referent-by-referent
matching against the satisfy's stated subjects, erroring only when one
matches none. Name the element-form detection for what the API element
form states (every default) rather than who wrote it.

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

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>
…collapsed kind

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…argets by value

An element whose target ends name what a literal collapsed property never states is refused, as it is under IRI targets; a literal collapsed target counts as stated by its value, an element end spelled as the element the literal names joins to it by that name, and an end spelled as an element the graph names nothing for — a legacy graph's bare uuid — stays vacuous.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
A referent or targetFeature membership minted in the element namespace was never claimed, so a declared element id landing on its IRI merged the two subjects silently; it now records the same UnsupportedError as a minted relationship.

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

A child whose metaclass maps to two collapsed kinds deleted its target from both, so a feature stating the same target under two kinds was covered by a single element; coverage now consumes the first kind still stating it, and the encoder mints the feature-specializes Subsetting under a _sp suffix so the two kinds never merge onto one subject.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
A quoted segment may carry ::, so unescapeName now parses the written form with source.QualifiedNameSegments and re-spells it canonically, and qualifiedNameText prints written names by their own segments; the feature-chain segment's element spelling prefers declaredName over splitting the unescaped qualified name.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
The uuid id form keyed each root's package namespace on the root's name alone, so two scopes' roots of one name would derive one namespace and collide; the derivation now feeds the scoped root IRI and returns the uuid IRI through ScopedElementIRIForID, keeping the project scope on every derived subject.

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

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 9 commits September 24, 2026 10:27
…n without a title page

The acm theme documented 9pt tables but sized only the landscape wide-table
path; an ordinary table stayed at the 10pt body. A --sysml-table-font-size
token now applies to every acm table in HTML and PDF.

The nasa companion reset the page counter on the first main page, which was
the bare title heading when a contents list was asked for without a title
page: the title counted 1, the contents ii and the body continued at 3. The
title heading leading a contents list now shares its front page, and the
article itself is the main page, so running text ahead of the first section
opens the body at 1.

Installed-toolchain tests read the table size back under each convention
theme and the footer sequence back from a nasa report under every
title-page and contents combination.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ptions in the convention's face

The nasa companion kept the page counter for the front matter and reset
it on the first main page, so a body opening on a landscape wide page
printed the physical page number and the next portrait page restarted at
1. The cover and front pages now leave the page counter at 0 and count in
roman on a front counter, so the body opens at 1 whichever named page it
starts on. nasa table captions take the sans face like the rest of the
table; acm captions take the text face acmart sets them in.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
* fix(view): leave layout annotations and render members out of renderings

A view's DiagramLayout annotations and its render members describe the
picture, not the model; the shared member walk now skips them so every
graphical form omits them, while ordinary metadata usages stay shown.

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

* fix(view): head a member drawn under its owner by its name below that owner

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

* feat(view): fit a stated box's label to it and draw symbol kinds as their notation

A node a Layout sizes keeps its box: the head word-wraps at the width and
shrinks from 14pt to 8pt until it fits the height, the keyword and detail
lines follow only while height remains, and a head too long at 8pt is cut
and ellipsized. Decision, merge and choice nodes in stated boxes are drawn
as diamonds, forks and joins as filled bars, initial nodes as the filled
dot, final nodes and terminate actions as the double ring, and ports as
their square, with no text inside; a name is set beside the symbol unless
the node marks it as synthesized. A terminate action usage is kinded as
one, so the notation's final node is recognised.

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

* docs(view): describe the fitted labels, symbols, owner-relative heads and the bookkeeping left undrawn

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

* fix(view): draw an initial or final node with a synthesized name as the dot or ring

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

* fix(view): clip an edge at a stated junction's radius

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

* fix(view): head a member below its owner's drawn type, and write an enclosing box before the boxes in it

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

* feat(migrate): mark the names a migration makes up and draw those elements unnamed

A bundled MigrationMetadata::SynthesizedName metadata def, written once per
body as an about list over the names the migration made up; the semantic
model reads it (Model.NameSynthesized), the view IR carries it on nodes, and
the graphical writers draw such an element as its source did: a bare control
symbol, an edge without a label, a typed node as ': Type'. An action's
language-given start and done are treated the same way. Re-indexed twins of
one declaration share the about annotations the declaration gathered.

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

* chore(docs): re-record the examples digest in the pilot differential baseline

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

* feat(view): keep words whole in a fitted head, shrinking before breaking one

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

* fix(lower): let a parallel state own a metadata usage in its body

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

* docs(changelog): note the parallel state's metadata member

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

* feat(view): head a stated box above the stated boxes it holds, and name a member below its resolved owner

A stated box that encloses other stated boxes fits its title to the strip
above the topmost of them and sets it there (labelloc=t), so a container's
title is not covered by its members, which keep their stated geometry. A
box the Layout only places is sized to its label and does not move the title.

A node now carries the qualified names its typings resolve to (Node.Typings,
from Model.DeclaredTypes), so a member drawn inside a usage whose written
type differs from the type's canonical name is still headed below it.

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

* feat(view): leave a positioned drawing's unplaced nodes undrawn, or set them in a strip below it on request

A DOT drawing that positions some nodes left the others to neato, which set
them over the placed boxes. They are now omitted with the edges at them,
under a notice, so a migrated diagram shows what its source showed. The new
-render-unplaced strip (Options.Unplaced) packs them in rows below the canvas
or the positioned extent instead, on -render, -render-all, -render-document
and -render-documents alike. Every drawn node is pinned, so the layout header
never names plain neato.

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

* test(docpdf): read the tall figure's first node back by its kind head

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

* fix(view): give a stated box's whole width and height to its fitted label

Graphviz pads a node's label by its default margin of 0.11 by 0.055 in, so
a head fitted to the full stated width could still be drawn past the box's
border. A stated box that carries a label now sets margin=0, so the fit and
the drawing agree; a head filling the width keeps its size, one a point
over it shrinks.

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

* fix(view,migrate): keep a typed port's type outside its symbol and mark every synthesized declaration name

A port with no given name but a type drew nothing beside its square; the type is
now set as its xlabel like a given name. Anonymous parameters, port payloads,
generated subjects, stakeholders, includes and instance slots are declared under
a synthesized name that the SynthesizedName marker did not cover; they are now
marked, and an empty name is never marked.

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>
…emes

* fix(docpdf): name Times, Arial and Courier ahead of the generic print families

The print and pandoc stylesheets asked for bare serif, sans-serif and
monospace, which fontconfig resolves to DejaVu on most Linux machines while
the Times-metric Liberation faces installed beside it go unchosen. The default
body, heading, code and page-number stacks now name the conventional families,
their metric-compatible free equivalents and the generic family last. Sizes,
margins and page size are unchanged; print.css also declares the
opensysml-print-theme layer a theme's print companion fills.

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

* feat(docrender): bundle nasa, ieee and acm themes with print companions

A theme may carry themes/<name>.print.css, laid by the PDF backend over its
print sheet in the opensysml-print-theme layer so the theme's page size,
margins, faces, body size, heading scale and footer reach paper. Themes()
leaves companions out of the public list. nasa, ieee and acm follow the NASA
STI, IEEE Transactions and ACM acmart conventions; print and report gain
companions so their print faces and sizes now print.

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

* docs(doc): list the convention themes and the PDF theme cascade

Usage text, manual page, CLI reference, outputs manual and the backend design
note name every bundled theme, the print-companion cascade order, the sources
and choices behind nasa, ieee and acm, and their limits; changelog fragments
for the themes and the default font stack.

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

* test(doc): pin theme discovery, the print cascade and the PDF faces

Theme discovery lists the seven themes and no companion; each convention
theme's tokens are asserted; a fake-tool test pins default/theme, print sheet,
companion, KaTeX, reader order and that -html-no-default-css drops every
bundled sheet; installed-toolchain tests read /BaseFont, MediaBox and the body
size back from the PDF for the default and each theme.

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

* fix(docrender): set acm tables at 9pt and keep nasa front matter roman without a title page

The acm theme documented 9pt tables but sized only the landscape wide-table
path; an ordinary table stayed at the 10pt body. A --sysml-table-font-size
token now applies to every acm table in HTML and PDF.

The nasa companion reset the page counter on the first main page, which was
the bare title heading when a contents list was asked for without a title
page: the title counted 1, the contents ii and the body continued at 3. The
title heading leading a contents list now shares its front page, and the
article itself is the main page, so running text ahead of the first section
opens the body at 1.

Installed-toolchain tests read the table size back under each convention
theme and the footer sequence back from a nasa report under every
title-page and contents combination.

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

* fix(docrender): count nasa front matter on its own counter and set captions in the convention's face

The nasa companion kept the page counter for the front matter and reset
it on the first main page, so a body opening on a landscape wide page
printed the physical page number and the next portrait page restarted at
1. The cover and front pages now leave the page counter at 0 and count in
roman on a front counter, so the body opens at 1 whichever named page it
starts on. nasa table captions take the sans face like the rest of the
table; acm captions take the text face acmart sets them in.

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>
* fix(symbols): memoize ShortNamed per index generation

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

* test(symbols): treat the short-named cache as unobservable in snapshot comparisons

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>
…ation ends in

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

Copy link
Copy Markdown
Contributor Author

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

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot changed the base branch from develop to main September 24, 2026 14:29
devin-ai-integration Bot and others added 5 commits September 24, 2026 15:06
… the visit budget

RelatedElements, WhereRelated and relationship-derived columns build a
kind's edge table by scanning every workspace declaration, and charged
each one to the query's visit budget, so any model past ~100k
declarations failed every relationship query before traversing. The
scan is now memoized in queryexec.Context.Related, shared across the
queries a document evaluates, and left uncharged; traversal still pays
one visit per element reached.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…n parameterless calls

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…uilt from takes an edit

Co-Authored-By: jason.han <hanhuijun@gmail.com>
* fix(view): label transition triggers by the name their signal or operation ends in

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

* docs(views): trigger labels head their signal by its end name

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

* fix(view): take a trigger's end name from its last segment; keep () on parameterless calls

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>
* docs(examples): record analysis runs in the model and report them in a document

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

* docs(examples): state which recorded runs predate the relay edit

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

* docs(examples): note the sweep's exit status in the analysis-results demo

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

* docs(examples): re-record the pilot-differential baseline for the new example

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

* docs(project): update the differential figures for the new example

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

* docs(examples): build the analysis-results demo on the AnalysisRecords library

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

* docs(project): re-record the differential baseline for the library-based demo

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

* docs(examples): root the analysis-results report at the Records package so recorded runs join it

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

* docs(project): re-record the differential baseline for the Records-rooted demo

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

* docs(project): re-record the differential baseline after merging develop

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>
@HuiJun
HuiJun marked this pull request as ready for review September 24, 2026 16:10
* fix(doc): build relationship edge tables once per model, uncharged to the visit budget

RelatedElements, WhereRelated and relationship-derived columns build a
kind's edge table by scanning every workspace declaration, and charged
each one to the query's visit budget, so any model past ~100k
declarations failed every relationship query before traversing. The
scan is now memoized in queryexec.Context.Related, shared across the
queries a document evaluates, and left uncharged; traversal still pays
one visit per element reached.

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

* fix(doc): rebuild relationship edge tables when the index they were built from takes an edit

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>
devin-ai-integration Bot and others added 6 commits September 24, 2026 18:32
…alking the tree

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
* fix(check): read the ~ operator sites the parser records instead of walking the tree

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

* fix(parser): record nested ~ operators in source order

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

* test(parser): exercise a checkpoint restore over recorded ~ operators

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>
…dation

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit c28ff5e into main Sep 24, 2026
15 checks passed
@HuiJun
HuiJun deleted the release/0.9.0 branch September 24, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant