Skip to content

Fixes #35987: Offer registry relation types with their inverses on native ontologies - #35995

Merged
harshach merged 102 commits into
mainfrom
harshach/ontology-studio/04-native-relations
Oct 29, 2026
Merged

harshach merged 102 commits into
mainfrom
harshach/ontology-studio/04-native-relations

Conversation

@harshach

@harshach harshach commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #35987

Native ontology authors can select registry relationship types and their inverses. Native inverse links remain reciprocal through edits, imports, deletion and restoration, while the picker follows bounded registry pagination.

The published stack targets release 2.1.0. Each linked Shipping issue is In Progress with Product, P1 and Governance metadata.

PR1 #35990, PR2 #35994 and PR3 #35997 are merged, and this PR now targets main. Two chains start at PR4:

PR9, PR11, PR13, PR14 and PR16 are not published yet.

Current assessment for 8f4748f4a5f, recorded 2026-10-29.

Verdict. PASS. Gitar flagged that a failed registry write could leave an orphan or one-way inverse type. One round and three fix-forwards answered it with eight commits, 56bf99b12e1 to 09b4142bcec, and an independent review checked each round. The last review passed 09b4142bcec, with no blocker or major left open from the four reviews. 8f4748f4a5f then merges PR3's landed head 9021493db4a and main's daec19a5ab6, and records PR3's squash 5575a2d4d5e with an ours merge. Neither merge had a conflict. The diff against main has the same patch-id as the reviewed diff against PR3's head fca4419074b. Earlier reviews passed the merge with main's AI-mode restyle at 4868c52ace0 and cf429f94388.

Retrying a failed type creation. When a registry write fails while an author creates a relationship type pair, the next try now finishes the pair. The view remembers the inverse type it registered until the back link is written. On a retry it reloads the registry. It links that inverse back to the type that names it, whatever the retry is called, or reuses it when the primary write failed. It then writes the relation the author drew, once. A retry never patches or reuses a type this view did not register. The error from the failed write still shows once.

Known limits. None of these blocks the merge.

  • The repair runs only when the author opens the type dialog again. Picking a cached type, from the picker or by typing its label, skips it.
  • When two registry types name the remembered inverse, the repair links it back to the first one in registry order.
  • With an approval gate on relationship types, a staged back link or repair does not reach the ontology until the change request is approved and the pair is drawn again. Meanwhile, a retry drawn as the inverse is written one-way. No test stages a registry patch.
  • The view keeps the memory only while it is mounted, and only for the latest inverse. After a reload, or when an inverse create commits on the server but fails on the client, a retry leaves the earlier inverse unlinked and creates a suffixed one, as before this round.
  • The AI-mode case in OntologyConceptInspector.test.tsx repeats PR4's partOf and hasPart fixtures with other IRIs.
  • Restoring one property alone inside a deleted ontology throws EntityNotFoundException and stores nothing when its stored inverse partner is live. Restoring the ontology works. That gap needs a design call and an issue, which is not filed yet.

Test evidence. On 09b4142bcec, TypeScript reports 0 errors and Jest passes 82 of 82 in PR4's 5 UI test files. ESLint reports 0 errors and the one known review-sequential-api-calls warning, Prettier is clean, the Playwright impact map is current, and CI's lint sequence makes no change. The round changed 3 UI files and no Java. The Java gates ran on the earlier merge tree 21999f30ecd. Package and spotless passed, and 465 unit tests in 26 classes passed. The 7 database classes ran on local MySQL 9.3 and PostgreSQL 14, one new database per run. All passed apart from two invocations of OntologyEntityDAOTest.reviewLocksSeeEditsAndArchivalCommittedWhileWaiting, whose rows share one database on the local engines. The Java impact map check passed at 8f4748f4a5f.

CI. Checks at 8f4748f4a5f were still running when this block was written. At cf429f94388, every check passed except maven-collate-ci, which failed with HTTP 422 because the Collate repository has no branch named after this PR's old base. This PR now targets main.

Still owed. None of these has run yet. Run each IT on -Pmysql-elasticsearch and then -Ppostgres-opensearch, and confirm a Tests run: line.

  • PR4's own ITs IndependentOntologyInverseIT and IndependentOntologyAxiomIT.
  • TaskResourceIT and the task ITs listed on PR1, which this head carries.
  • PR1's review-list ITs IndependentOntologyApprovalIT, IndependentOntologyPublicationIT and IndependentOntologyReleaseIT, and WorkflowDefinitionResourceIT in the global-state lane.
  • The full openmetadata-service unit suite and every merge-queue IT the planner selects against main, with the cache-tests and postgres-opensearch lanes.
  • Playwright OntologyNativeRelations.spec.ts and OntologyNativeStudio.spec.ts against a live stack. They drive classic mode.
  • The two invocations of OntologyEntityDAOTest.reviewLocksSeeEditsAndArchivalCommittedWhileWaiting under Testcontainers.
  • Changed-class coverage, which needs the ITs above.
  • The plan's live and performance lanes for this PR.

AI mode. main's Ontology Studio AI-mode restyle #36433 now gates new screens on AI mode. AI mode lacks none of PR4's controls. The inverse label, the relation type dialog, the registry-backed picker with its create option and the permission-denied toast all render in code both modes share.

Not verified yet. This PR is verified only when its unit, live and performance boxes in the plan are all checked. The operator lands the stack.

Earlier description and verification records

These records preserve the earlier design notes, test results and attachments. Earlier statements about the current head or readiness apply to their recorded revisions. The integration assessment above supersedes those statements.

Fixes #35987

Describe your changes

Native Ontology Studio now offers shared registry relationship types alongside the ontology's own object properties. Selecting Part Of reuses or creates native properties by exact predicate IRI, stores a restriction on the source concept, and shows Has Part on the target's incoming relation. Subclass Of keeps its native hierarchy behavior; annotation properties stay out of the picker.

Inverse links remain reciprocal through edits, imports, deletion, and restoration. New inverse claims release displaced partners. Restoring a self-inverse property preserves its link; restoring a missing partner drops the stale link. Both soft and hard deletion attribute partner cleanup to the deleting user inside the retained transaction. Registry types without an inverse create one native property without inventing a partner.

The picker loads all registry pages within a documented bound, shows inverse labels across page boundaries, and rejects invalid pagination instead of displaying an incomplete catalog. Administrators can create custom registry pairs in the dialog; authors without relationship-type Create permission can use existing types.

Design: ADR:2026-10-21-native-relations-instantiate-registry-relationship-types.

Validation

Current source snapshot: 213ae3115fdf740d405d7cecd338a6f343743c52.

  • Backend reactor build passed across 16 modules, including compilation of the new storage and API tests. Normal commit hooks passed.
  • 532 UI tests passed in 71 suites. Changed UI line coverage: native relation utility 100%, picker 98.41%, concept inspector 98.01%, graph view 90.86%. A subsequent focused run passed all 12 relation utility tests, including the new no-inverse contract assertion.
  • Full TypeScript diagnostics were compared against exact base ba6d06c88bd931b5854bfe003a288be3c9dee255 with identical dependencies, generated models, and external fixtures. Both compilations exit 2 with the same 562 diagnostics; normalized full messages and multiplicity have zero additions or removals.
  • Fresh API proof passed against the rebuilt Docker backend: reciprocal set/clear, self-inverse restoration, protected soft-deleted IRIs, source-only restrictions, OWL inverse export, one-sided import normalization, competing claims, and rejected-delete rollback. A separate RED-to-GREEN proof verifies that another user's hard delete credits that deleter on the surviving partner.
  • The focused Playwright flow passed against Vite on port 3640 and the rebuilt backend on port 8640. It covers registry groups, own object properties, Part Of reuse and incoming labels, Subclass Of, custom type creation, and a DataSteward with explicit native-author permissions but no registry Create permission.
  • Java impact ownership, UI formatting/lint, i18n generation, and decision-record checks passed. Harness warnings are retained in the local receipts.

Remaining verification

This is a published implementation snapshot; the following gates remain open under the shared test coordinator:

  • Re-run the current focused Java storage slice and changed-class coverage. The previous 159-test run passed before the deletion-actor fix; its outer repository coverage was 89.04%. Added metadata and rollback cases are compiled but not yet executed.
  • Run the current 14-case inverse API suite on both MySQL/Elasticsearch and PostgreSQL/OpenSearch. Earlier 12-case results do not cover this final unit.
  • Run the full affected Java selection and the 31-spec affected Playwright selection, including the required repeat/parallel stability checks.
  • Upload the reviewed screenshots and 37-second H.264 recording. The local artifacts are complete, but the available browser is signed out of GitHub; no hosted media URL is claimed.
  • Complete the independent review and performance verdict.

Type of change

  • Feature

Checklist

  • Self-review against REVIEW.md
  • Unit, current-artifact API, and focused Playwright evidence recorded
  • Full affected Java and Playwright gates
  • Final backend changed-class coverage
  • Screen recording uploaded
  • Independent verdict

Summary by Gitar

  • Review rules:
    • Approval rule freezes reviewers and approvalRule while a release is in review
  • Publication status:
    • Ontologies expose derived publicationStatus from active and latest releases
  • Definition status:
    • Concepts and properties derive Draft, In Review, or Approved from release membership
  • Class model:
    • Concepts gain abstract, definitionSource, deprecated, and replacedBy fields
    • Properties enforce at least two enumValues and support replacedBy
  • Working diff:
    • Added concept-grouped working diff pages with deprecation change type

This will update automatically on new commits.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge as part of the reviewed stack, with the fresh-registry permission concern addressed by PR #35991.

Summary

Native ontologies now offer registry relationship types and their inverse labels alongside their own object properties.

  • Native ontology authors can build relations from shared registry types.
  • Native property inverse links stay reciprocal through edits and lifecycle changes.
  • Incoming relations use their inverse label when the ontology declares one.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Choose a relationship type] --> B[Plan native writes]
  B --> C[Create missing properties or link existing ones]
  C --> D[Server settles reciprocal inverse links]
  D --> E[Validate final changes]
  E --> F[Save source restriction]
  F --> G[Refresh ontology model]
  G --> H[Show inverse label on incoming relation]
Loading

Reviews (21) · Last reviewed commit: "Merge class model fixes into native rela..." · Reviewed by Greptile

First unit of #35983. The enum carries the Any or All reviewer rule that
later commits put on the ontology, freeze into the review target, and
turn into the review task's approval threshold.
…ionship types

Decision record for the native relation picker: registry types become native
object properties matched by exact predicate IRI, inverses stay reciprocal on
write, and the create option is gated on the relationshipType permission.
@harshach harshach added safe to test Add this label to run secure Github workflows on PRs backend labels Oct 22, 2026
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

harshach and others added 14 commits October 22, 2026 08:16
Adds the fields to the concept and property schemas, the create
requests, the release payload allowlist, and the RDF catalog vocabulary.
Adds the DEPRECATED change type, the REPLACED_BY reference role, and the
concept-grouped rows of the working diff. Regenerates the TypeScript
types.
The IT states the contract before the implementation: setting, creating with,
repointing, clearing, deleting and restoring an object property's inverse keeps
both sides reciprocal; a one-directional import normalizes on apply and is
reused by exact IRI; the release export carries owl:inverseOf both ways.
Concepts and properties now carry deprecation and replacement, and
concepts carry abstract and a definition source:

- A replacement must name another definition of the same kind in the
  same ontology. It is indexed as a REPLACED_BY reference, so deleting
  a replacement target is refused like any other dangling reference.
- An enumeration needs at least two allowed values. One-value
  enumerations stored before this rule stay editable until their values
  change.
- Release projection writes om:abstract, dct:source, owl:deprecated,
  and dct:isReplacedBy, and native import reads them back.
- Release and working diffs classify a member whose deprecated flag
  turned true as DEPRECATED.
- GET /ontologies/{id}/working/diff?groupBy=concept returns the working
  changes grouped by the concept they define, with parent labels and a
  property count, paged by group under its own revision-bound cursor.
…sion

IndependentOntologyClassModelIT covers the field round trips, the
enumeration minimum and its legacy carve-out, replacedBy integrity, the
DEPRECATED diff row, and grouped diff paging with the 412 cursor rule.
NativeOntologyMemoryIT adds a class-create change set and its rollback.
Existing ITs that stored one-value enumerations now use two values.
Adds the fields to the concept and property schemas, the create
requests, the release payload allowlist, and the RDF catalog vocabulary.
Adds the DEPRECATED change type, the REPLACED_BY reference role, and the
concept-grouped rows of the working diff. Regenerates the TypeScript
types.
Concepts and properties now carry deprecation and replacement, and
concepts carry abstract and a definition source:

- A replacement must name another definition of the same kind in the
  same ontology. It is indexed as a REPLACED_BY reference, so deleting
  a replacement target is refused like any other dangling reference.
- An enumeration needs at least two allowed values. One-value
  enumerations stored before this rule stay editable until their values
  change.
- Release projection writes om:abstract, dct:source, owl:deprecated,
  and dct:isReplacedBy, and native import reads them back.
- Release and working diffs classify a member whose deprecated flag
  turned true as DEPRECATED.
- GET /ontologies/{id}/working/diff?groupBy=concept returns the working
  changes grouped by the concept they define, with parent labels and a
  property count, paged by group under its own revision-bound cursor.
…sion

IndependentOntologyClassModelIT covers the field round trips, the
enumeration minimum and its legacy carve-out, replacedBy integrity, the
DEPRECATED diff row, and grouped diff paging with the 412 cursor rule.
NativeOntologyMemoryIT adds a class-create change set and its rollback.
Existing ITs that stored one-value enumerations now use two values.
OntologyWorkingState runs registered finalizers at the outermost
mutation's exit, before validation. OntologyPropertyRepository registers
one that settles inverse links over the affected neighbourhood: the side
that states a link decides it, the latest statement wins, and a partner
no longer pointed back at is released. Partners are written through the
updater so they version, index and validate like any edit. The RDF
importer reads owl:inverseOf as symmetric, so a one-directional file
describes both sides and a re-import changes nothing.
IndependentOntologyAxiomIT drops its indirect inverse variant, which
relied on one-sided inverse chains.
@harshach
harshach requested a review from a team as a code owner October 23, 2026 01:04
@harshach
harshach requested a review from IceS2 October 23, 2026 01:04
An ontology carries an approvalRule, AnyReviewer by default or
AllReviewers. prepareReview freezes the rule into the task's review
target and leaves the requester's and the author's own user entries out
of the assignees. The rule reaches the workflow as the start variable
approvalMode=allAssignees, which CreateTask turns into the task's
approvalThreshold, so the shared counters stay unchanged.

Each counted vote is recorded on the task in reviewVotes with its
comment; the deciding vote is recorded in the decision transaction with
any voter whose record was lost. Reviewers and the approval rule are
locked with 409 while a release of the ontology is in review.

GET /v1/ontologyReleases/{id}/review and
GET /v1/ontologies/reviews?view=assigned|created|pending read a review
from the task's recorded votes.

Amends ADR:2026-10-14-ontology-reviews-bind-workflow-tasks-to-revisions
as v13.
The list loads the releases of all listed tasks in one batched read.
The list test now asserts that exactly one statement reads release rows
and that it covers both releases, so a read per task fails it. Resolving
each task's about reads only the names of its release, so the assertion
does not count that lookup.
Adds a gray badge for deprecated changes to main's AI-mode change list, as StatusBadge.constant.ts colours a deprecated status.
An incoming relation whose property has an inverse now reads the inverse label in both the classic and the AI panel, because the label logic moved into main's shared renderRelationRow. The relation type dialog renders in both modes, so a new relation type can be created from AI mode too. A new AI-mode test covers the inverse label.
Main moved 26 commits before PR1 landed. The merge had no conflicts.
PR1 landed on main as 5f2b733. This branch already holds PR1's final code, so the merge keeps the tree.
The type dialog registers the inverse, then the primary, then patches the
inverse to name the primary. These cases fail one of the later writes once
and retry the same draft through the dialog. A retry after a failed primary
write must reuse the inverse already registered, and a retry after a failed
back link must patch the inverse to name the primary. Either way the
registry ends with one reciprocal pair and no suffixed duplicate.
PR2's branch brings main through 7843a02 and records PR1's squash merge 5f2b733. The merge had no conflicts.
The type dialog registers the inverse, then the primary, then patches the
inverse to name the primary. When the primary write failed, a retry
registered a second inverse with a numeric suffix and left the first one
unlinked. When the back link failed, a retry found the primary and returned
it, so the pair stayed one-way.

The view now remembers the inverse it registered until the back link is
written. On a retry, the planner names the draft's inverse after that type
and reuses it, or, when the primary is already registered and names it, the
view patches the back link. No other type is patched, and the error from
the failed write is still shown.

A rollback would need the Delete right on relationship types, which the
dialog does not check, and the registry's soft delete keeps the name taken,
so the retry's create would conflict.
PR2 landed on main as 8c01d4c, a squash of ae01b93 with the same tree.
This merge records the squash so that main is an ancestor of this branch. The
tree does not change.
A new case puts another author's unlinked "approves" in the registry and
creates "approved by" with the inverse "approves". The view registers
"approves2" and links only that type back, so it never claims a type it
did not register.

The case where the back link failed now also checks that the retry
writes the relation once and that only the first failure is reported.
After the back link of "approved by" fails, the author retries with the
label "signed off by" and the same inverse "approves". The new case
expects the retry to link "approves" back to "approvedBy" and to give
"signedOffBy" its own inverse, "approves2", so no type is the inverse of
two primaries. It fails until the view finishes the earlier pair before
it plans the retry.
When the back link fails, the primary names the inverse but the inverse
names nothing. A retry under a new label reused that inverse for the new
primary, so the inverse ended up named by two primaries.

Before it plans a retry, the view now links the inverse it registered
back to the type that already names it, whatever the retry is called,
and then plans the draft with no reuse, so the new primary gets its own
inverse. The inverse is reused only while nothing names it, after a
failed primary write. Only the inverse this view registered is patched.
Two cases in OntologyGraphView.test.tsx pin behavior the view already has.
A retry whose back-link repair fails keeps the remembered inverse, so a
later retry links it back. A retry drawn from the other end, under the
inverse's own label, still links the earlier pair back.
Base automatically changed from harshach/ontology-studio/03-class-model to main October 29, 2026 21:40
After the back link of "approved by" fails, the author draws the
relation from the other end and types "approves". The case already
checks that the retry links the earlier pair back. It now also checks
the relation the retry writes: the property "approvedBy" first, then
"approves" naming it as its inverse, and one axiom on "approves". That
is what a first draw of "approves" writes. It fails until the view
looks the label up in the registry as the repair left it, because the
retry still writes "approves" with no inverse.
When the back link of "approved by" fails and the author retries by
drawing "approves", the view links the pair back in the registry. It
then looked the label up in the list it loaded before that repair,
where "approves" names no inverse. So the retry wrote the property
"approves" with no inverse and never declared "approvedBy". A first
draw of "approves" writes both properties, linked.

finishUnlinkedPair now returns the registry with the patched inverse in
place of the stale entry, and the view looks the label up and plans the
draft in that list. The retry now writes "approvedBy", then "approves"
naming it, then one axiom, as a first draw does. The view still patches
only the inverse it registered, keeps it when the repair fails, and
reports the failed write once.
PR3's landed head 9021493 brings main through 8c01d4c and records PR2's
squash merge. The merge had no conflicts.
Main moved to daec19a before PR3 landed. The merge had no conflicts.
PR3 landed on main as 5575a2d, a squash of 9021493 merged with daec19a.
This merge records the squash so that main is an ancestor of this branch. The
tree does not change.
@gitar-bot

gitar-bot Bot commented Oct 29, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 6 closed / 6 findings

🔴 High risk · Reciprocal inverse-link writes across ontology edits, imports, deletion, and restoration could leave stored property relationships inconsistent or remove links unexpectedly.

Native ontology authors can now pick shared registry relationship types and their inverses, with inverse links kept reciprocal through edits, imports, deletion and restoration. Six issues were resolved this session, including one-sided inverse pairs, reuse of soft-deleted IRIs, restore dropping dangling inverses, review-list task loading, and orphaned registry types on failed pair creation. No open findings remain.

✅ 6 closed
✅ Edge Case: Reciprocal-inverse rule skips retargeting, so pairs can stay one-sided

📄 docs/decisions/2026-10-21-native-relations-instantiate-registry-relationship-types.md:19 📄 docs/decisions/2026-10-21-native-relations-instantiate-registry-relationship-types.md:15
OntologyProperty.inverse holds one value (ontologyProperty.json:126). The record covers setting an inverse and clearing or deleting one side, but not moving an inverse to a different property. Example: P↔Q exists and someone sets P.inverse = R. Following the rule as written, R.inverse becomes P, but Q.inverse is still P. If R already pointed at some S, then S.inverse is still R. Either way the pairs end up one-sided, which is exactly what this record says it prevents. This can happen through the picker's "reused by IRI" path (line 15) whenever an existing property such as an imported skos:broader already has a different inverse. It can also happen through a one-direction import statement, which the record normalizes. Since implementers will check code against this record, it should state the retarget behaviour.

✅ Edge Case: Reuse-by-IRI ignores soft-deleted properties that still hold the IRI

📄 docs/decisions/2026-10-21-native-relations-instantiate-registry-relationship-types.md:15
ADR:2026-10-14-ontology-definitions-have-independent-entity-storage makes property IRIs unique within an ontology, and soft-deleted definitions count toward that uniqueness. This record reuses a property only when the ontology "already has" one with the registry predicate, and otherwise creates a new one. Suppose an author picks hasPart, later deletes the native …/hasPart property, then picks hasPart again. Creating a new property with that IRI breaks the unique (ontologyId, iriHash) index, so the picker's instantiate step fails. The record should say whether a soft-deleted match is restored (PUT restore already keeps the IRI) or reported to the author.

✅ Quality: SETTLE_PASSES=8 finalizer budget is an unrecorded judgment call

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyWorkingState.java:26 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyWorkingState.java:64-78
OntologyWorkingState.settle() adds a retry budget: finalizers run again until a pass adds no change, and after 8 passes the write fails with IllegalStateException (a 500, not a 400). The value 8 is a judgment call, and the finalizer order it depends on (finalizers run before requireValid, ontologies in sorted UUID order, each key registered once per outermost mutation) can't be seen from any single repository. None of the records in docs/decisions/ states it, and the new ADR covers reciprocity but not how it is reached. Add a sentence to ADR:2026-10-21-native-relations-instantiate-registry-relationship-types (or a new record) such as: "Pre-validation finalizers run at the end of the outermost ontology mutation, before validation, until a pass records no new change; a mutation that has not settled after 8 passes is rejected." Cite it from the constant.

✅ Quality: Restore silently drops a dangling inverse; the ADR says it is refused

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyPropertyRepository.java:87-93 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyPropertyRepository.java:208-214 📄 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IndependentOntologyInverseIT.java:157-169
The Accepted record says "An inverse IRI that names no live object property is still refused." reconcileInverses makes an exception for restore. When a revived property's inverse dangles, the code calls links.link(iri, null) and clears the link without telling anyone, and the new test restoringAPropertyWhosePartnerIsGoneDropsTheLink locks that in. The record states neither this exception nor the rule that a new claim takes an occupied partner and releases its previous holder (claimingAnOccupiedPartnerMovesIt). Either refuse the restore, or amend the record's Decision with: "Restoring a property whose inverse no longer names a live object property clears that inverse instead of refusing the restore."

✅ Performance: listReviews loads a task for every open review on each page request

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyReleaseRepository.java:237-251 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/OntologyReleaseRepository.java:296-306
listReviews scans every In Review release across all ontologies in batches of 1000. For each release the caller can view, it calls reader(...), which runs tasks.get(..., "assignees,reviewers,createdBy") before reader.matches(view) can filter it out (OntologyReleaseRepository.java:255-270, 296-306). That makes every page request O(open reviews) task loads, each with relationship lookups, no matter what limit or after asks for, and later pages repeat the whole scan. Suggested fix: bulk-load the tasks for each batch with one tasks.get(uriInfo, ids, fields, include) call (the setFieldsInBulk path) before building readers. Alternatively, pre-filter on the task's assignee and creator relationships in SQL so only matching reviews get hydrated.

...and 1 more closed from earlier reviews

Verification

Rules No rules evaluated

Functional validation Not enabled

Set up

Auto-approval Not enabled

Set up

For more verification details, comment gitar display:verbose.

Options

Display: compact → Showing compact verification results.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@sonarqubecloud

Copy link
Copy Markdown

@harshach
harshach merged commit 92d4e43 into main Oct 29, 2026
72 checks passed
@harshach
harshach deleted the harshach/ontology-studio/04-native-relations branch October 29, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ontology Studio: offer registry relation types with their inverses on native ontologies

2 participants