Skip to content

Ontology Studio: complete the v7 prototype flows - #36868

Merged
harshach merged 330 commits into
mainfrom
harshach/ontology-studio/v7-completion
Nov 6, 2026
Merged

harshach merged 330 commits into
mainfrom
harshach/ontology-studio/v7-completion

Conversation

@harshach

@harshach harshach commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Describe your changes:

Ontology Studio gains the flows in the v7 clickable prototype. With no reviewers, an editor publishes directly. With reviewers, the author requests review from the publish dialog, stays in Studio, and sees the decision. Ontology writes require edit rights, and seeded roles grant authoring and reviewing.

The PR lands as units. Each unit is one merge commit with its own unit tests and Playwright cases, so the history reads unit by unit.

Landed units:

  • G19. The RDF projection is built once on first start instead of waiting for the weekly run.

  • G1. Ontology writes, release capture, and activation require edit rights on the ontology. Listed reviewers vote on their assigned review.

  • G14. Large ontologies render: the layout folds crowded ranks to the viewport's shape and fits on load, so 400 concepts show at once. Above 500 concepts the graph shows the neighbourhood of the selected concept. The graph, Find, and Tree work from the keyboard.

  • G9. The create ontology dialog follows the prototype: owners, reviewers at creation, and a collapsed Advanced section with ID, IRI, namespace, and layer. It validates before submit, and names that differ only in digits get distinct prefixes. Picker rows offer Settings and Delete, with search and concept counts.

  • G2. Two built-in roles, OntologyAuthor and OntologyReviewer. DataSteward gets both policies on new installs, and an idempotent v210 data migration attaches them on upgrade without touching the admin's other DataSteward policies.

  • G4. Saving a release with no changes returns the existing Draft instead of minting another, an ontology has at most one open review (a second request gets 409 naming the open one), and the suggested version is computed from the active release. The Releases tab hides older Drafts that never went to review.

  • G3. Studio shows only the actions the user's rights allow. Edit, Publish, and Connect are hidden without edit rights, both modes share one empty state, a user without Create reads which role to ask for, and disabled release controls say why. When the catalog has more ontologies than All ontologies can draw as one graph, it shows one message pointing to the ontology menu instead of a list of buttons.

  • G10. One New concept drawer serves the toolbar, the canvas, the empty state, and the Term tab. It validates the name, label, and IRI before any write, supports Create & add another, and shows Undo on create and delete. In All ontologies, Add Concept opens the drawer with a required Ontology field instead of doing nothing until a separate selector is used.

  • G5. With no reviewers configured, activating a sealed Draft publishes it directly for a caller with edit rights. In one transaction under the ontology lock, the release becomes Approved with approvalBasis of NO_REVIEWERS_CONFIGURED, gets an APPROVED event with no voters, and activates. With reviewers, activation still returns 409. Release events now include the review request.

  • G12. The server detects disjointness clashes. POST /ontologyAxioms/validate returns a DISJOINT_CLASH warning that names both concepts, and release capture refuses a draft whose subclass closure puts a concept under two disjoint classes.

  • G15. Users without edit rights read the active release, not the working draft. A Draft/Published switch on the version chip lets an author compare the two, and Edit is offered only on Draft. Mode, view, and version live in the URL, so reload, Back, and shared links reopen the same view. A user who owns one concept can enter Edit from that concept. Graph, Tree, and Ontology views work in View and Edit, and a read-only Overview tab shows counts, owners, reviewers, version, and namespace. The health card can be minimized per user.

  • G11. In Edit mode, a double-click on empty canvas opens the New concept drawer and places the node at the click. Relationships connect by click or by a drag from the node's handle, and self-loops, duplicates, and subclass cycles are refused before any write. Relationship rows have edit and delete, and an edge click opens its detail. Deleting a concept lists its children, relationships, rules, and bindings from a new GET /v1/ontologyConcepts/{id}/deleteImpact, removes the references with it, and offers Undo. In All ontologies, changing the drawer's Ontology field keeps the typed fields and clears only the parents. When a new concept's name belongs to a deleted concept, the drawer says so and offers Restore instead of failing with a bare 409.

  • G20. Two recursive hard deletes of large ontologies no longer deadlock. EntityDAO.deleteByIds pins the primary-key range with a MySQL index hint, so a delete locks only its own rows even when table statistics are stale. PostgreSQL reads the hint as a comment. The scope menu gives each row an accessible name that separates the label from its count. A link to a concept with no ontology in it opens that concept's inspector even when the catalog has too many ontologies to draw as one graph.

  • G6. The publish dialog offers one primary action per state. With no reviewers it is Publish vX.Y.Z, and adding a reviewer flips it to Request review without a reload. Capture release is now Save as release draft. After a request the author stays in Studio and sees who was asked, can withdraw the request, and reads the approval or rejection in the dialog, the Studio banner, and the Inbox. Rollback is labelled with both versions and asks for confirmation. The release in force shows no activation actions.

  • G1b and G1c. Creating and submitting a glossary-scope change set, requesting an AI domain draft for a glossary, and moving a deleted term's children each require EditAll, the same right as the other ontology write paths.

  • G16. The query results header names the scope, <ontology> · v1.0.0 or <ontology> · draft. Editors can query the working draft with POST /v1/ontologies/{id}/sparql?scope=draft, which requires edit rights. Errors read as a title and a hint, ASK shows true or false, and results show a row count, the run time, Copy, and CSV. All ontologies explains the query choice with counts, saved queries gain Find and Duplicate, and the builder shows its SPARQL on request.

  • G13. Rules open in a quick form that reads as a sentence: a subject that must have, can never also be, or is the same as another concept, with counts and properties, a live preview, and the server's reasons. The advanced form is one switch away, and the switch refuses in one sentence when it would lose detail. Pickers search concepts by label and accept a pasted IRI. A mapping can point to a concept in any ontology the user can read. GET /v1/ontologies/{id}/working/validation validates the whole draft, the graph marks clashing concepts and edges, a panel lists the conflicts to resolve, and the relationship picker warns before it adds a disjointness clash.

  • G7, part 1. The Changes tab names each concept by its label, not its IRI tail, and filters All, Added, Changed, and Removed with counts and a search. The dialog suggests the version and says why: a removal suggests a major version, an addition a minor one, and a first release v0.1.0. Opening the dialog validates the working draft, so errors show before a release is saved. Logical consistency reads Not applicable when the server has no materialized inference. Counts read per kind, such as 4 changes · 2 concepts · 1 property, and the version chip shows Draft once.

  • G17. Data mode shows one concept at a time, picked from a searchable list, with its assets and their bound columns. An asset opens a panel inside Studio, with Open asset as a separate button. A concept with no assets says so and offers Link Asset to editors. The link picker filters by type and service and suggests assets with reasons. Unlink names what becomes unbound, asks to confirm, and offers Undo. A table page lists the concepts the table and its columns are bound to, from a new GET /v1/ontologyConcepts/boundTo/{assetType}/{assetId} that leaves out concepts the reader cannot view.

  • G7b. The review shows each changed field with its before and after value instead of a JSON block. Review tasks are titled Review <ontology> v<version>. The Studio banner names the ontology, the version, and who the review waits on, and All ontologies lists one line per open review. When a draft has more than 1,000 changes, the change list says its counts cover the first 1,000.

  • G18. The import preview lists each concept, property, relationship, and rule as New, Update, Already exists, Duplicate, or Skipped, grouped with checkboxes, and imports only the ticked items. Preview and apply run the same datatype check, so an unsupported range fails the preview with its reason. SKOS exports import again. The export dialog exports the current draft or any release, and the Releases row adds SKOS and CSV. Installed and imported ontologies get readable names and https IRIs, and a clash the import would create shows on its item with both concepts named.

  • G18c. A partial import stays consistent. Unticking a new concept also unticks the relationships and rules that use it and says so, and the server refuses an apply whose operations need a concept the change set leaves out, naming both. CSV exports label a concept by its name when it has no display name.

  • G7d. GET /v1/ontologies/reviews takes an ontologyId filter, so the Studio banner finds the selected ontology's review however many reviews are open. A review whose only reviewer was removed reads no reviewer assigned instead of ready to publish.

  • G8. Each Releases row shows the version, its status, the author, the date, per-kind counts such as 2 concepts · 1 property, and Published without review or who approved or rejected it, with search, status filters, and paging. Compare versions lists the concepts added, changed, and removed between two releases. Release events read one per line, with the reason for a rejection.

  • P1a and P1d. One rule for reading the working draft. Every read of draft content needs EditAll on the ontology, and release reads keep view access. The rule covers draft SPARQL, the working diff, validation, export, references, the concept, property, and axiom lists, and change sets. The change-set list takes ontology or ontologyId, and a viewer's memory review panel shows an empty queue instead of an error. Reading a single definition by id or name stays open to any viewer, for deep links and the concept panel, as docs/decisions/2026-11-03-ontology-working-draft-reads-require-edit-rights.md records.

  • P1e. A concept owner without ontology rights edits their concept's draft wording, read by id, while the graph shows the release.

  • P1f. A second selection in the tree opens that concept.

  • P1g. When the concept panel resizes the canvas, the graph republishes its node positions, so the connection handles stay on their nodes.

  • P1b. OntologyStudioFlows.spec.ts drives every Studio interaction in the prototype, in AI and classic mode where both offer it.

  • R1. Server fixes from the PR review. Patches that move or copy a field run the same content check as other patches, and axiom patches run it too. A table page lists every visible concept binding, however many hidden ones come first. Activation refuses a version that a published release already holds (409), and capture skips published versions when it suggests one.

  • R2. UI fixes from the PR review. A display name that yields no ID asks for one. A failed pack review shows an error with Retry and holds Install. Clash highlights follow the subclass path to each disjoint ancestor. A change list cut off at its first page suggests no version and asks the author to pick one. The review compares structured values and shows ids when two values read the same. The scope menu and the query picker show 20 ontologies at a time with Show more, request counts only for the rows on screen, and fall back to the active release's counts when the draft is not readable.

  • R3 and R4. Decision records for the first RDF index run and the graph limits, and amendments that bring the onto-IRI, reviewers, imports, and roles records in line with the code. Flow 2 asserts exact prefixes, and an IT shows that a DataSteward edits ontology content but not glossary scope.

  • R5 and R6. The approval-notice IT asserts the exact summary. The review-filter IT requests its oldest and newest reviews alone, so the result no longer depends on thread order. The table-page Data mode case waits for the column drawer before it closes it.

  • R7. When a reviewer rejects with no reason and the reason comes from their latest task comment, that reason now reaches the recorded decision, the vote, the release event, and the author's notice.

  • R8. The RDF ontology declares the release's approvalBasis as a stored predicate, so RdfOntologyContractTest accepts what the release writer emits.

  • R9 and R9b. Draft apply reads the classes an imported axiom or property names from the operation itself, not from the optional requiresConceptIris. It checks them with the importer's own class rule (OntologyClassHierarchy.classPositions). A client that drops a dependency from a partial import gets 400, while SKOS classes, annotation-property domains and assertion individuals pass as they do at preview. The asset concept links response has no cap on links.

  • R10 and R10b. Linked concepts on a table page open the Studio with that concept selected. Concept live data tells a loading or failed bindings read apart from an unbound concept, and a failed read offers Retry.

  • R11. Draft apply also checks every concept an operation declares in requiresConceptIris, so a partial import cannot keep a restriction or an assertion on an individual it dropped.

  • R12. The new-class panel shows an error and keeps Create disabled when a SKOS concept has parents, equivalent or disjoint classes, or properties, whichever was chosen first. The class pickers offer only OWL classes. The asset picker shows "already linked" once.

  • R14 and R16. Playwright picks an ontology by typing its name, so a pick works when the list holds more than 100 ontologies and only the rows in view are rendered. A form sign-in in Playwright returns only after the app has used its post-login redirect, so a page opened right after sign-in is not sent to the home page.

  • R15. A list of concepts, properties, axioms or change sets that names no ontology also checks EditAll on the ontology of every row it returns, and refuses the whole page on one refusal (ADR v3). R18 checks each distinct glossary scope of an unscoped change-set list once, from the rows already loaded. The datatype picker offers only OWL 2 datatypes.

  • R17. parseSchemas.js takes the named $RefParser export of @apidevtools/json-schema-ref-parser 14, which main's chore(deps): bump @apidevtools/json-schema-ref-parser from 9.1.2 to 14.1.1 in /openmetadata-ui/src/main/resources/ui #37063 bumped, so the TypeScript Type Generation job runs again. The regenerated ingestion schemas differ only in shorter $ref pointers, and each one resolves to the same schema as before.

The branch also carries UI checkstyle fixes for every file it touches (C1), and five merges of current main (M1, which moves the UI to Vite 8.3.5, M2, M3, which adopts main's ButtonUtility icon buttons and its id-based reviewer match in DefaultAuthorizer, M4, which adopts main's autoComplete="off" on the Studio search inputs, and M5, which orders main's task field-path migration before OntologyRolesMigration in v210).

Type of change:

  • New feature

High-level design:

  • Direct publish is decided inside activation, with the ontology row locked. A sealed Draft with an empty reviewer list publishes for a caller with edit rights. The server records why no review happened. With reviewers, activation returns 409.
  • Two seeded roles, OntologyAuthor and OntologyReviewer, are attached to DataSteward on new installs and by an idempotent migration on upgrade.
  • The publish dialog maps release stage, reviewers, and the caller's rights to one primary and one secondary action.
  • Decision records under docs/decisions/ cover each durable choice.

Tests:

Tests are grouped by kind, then by area. A count in parentheses is the number of cases at this head. Java classes carry a count only when this PR adds them.

Java unit tests.

  • Edit rights and roles. DefaultAuthorizerTest, OntologyResourceAccessTest (6), OntologyEditLockResourceTest, OntologyAiResourceTest, OntologyImpactServiceTest, and OntologyOwnerInheritanceTest (4).
  • Releases and publish. OntologyReleaseReuseTest (7), OntologyReleasePublicationTest, OntologyReleaseComparisonTest, OntologyReleaseRepositoryTest, and OntologyDecisionNoticeTest (4).
  • Release storage. OntologyReleaseCaptureTest, OntologyReleaseActivationTest, OntologyPublicationStorageTest, OntologyActiveGraphStorageTest, OntologyDerivedStatusStorageTest, OntologyReleaseComparisonStorageTest, and OntologyReleaseReviewListTest run each case for MySQL and PostgreSQL.
  • Validation. OntologyStructureValidatorTest covers clashes through the subclass closure, the clash count, and deletion impact. OntologyReleaseValidationTest and OntologyChangePreflightTest cover capture and partial imports.
  • Import and export. NativeOntologyImportItemsTest (15), NativeOntologyCsvCodecTest, NativeOntologyRdfImporterTest, and RdfGraphSerializerTest.
  • Query and RDF. OntologyDraftQueryTest (4), RdfInitialIndexRunTest (5), and RdfProjectionStateResolverTest.

Java integration tests.

  • Edit rights and roles. IndependentOntologyAuthorizationIT holds the role, operation, and status matrix, including the draft paths, working-draft validation, and a DataSteward who edits ontology content but not glossary scope. IndependentOntologyDraftReadIT (2) and OntologyChangeSetIT cover the working-draft read rule, change sets included. OntologyImpactIT covers moving a deleted term's children, and its new case fails on the old check. OntologyEditLockResourceIT, OntologyRolesIT (7), and OntologyRolesMigrationIT (1, the step run twice).
  • Releases, review, and publish. IndependentOntologyApprovalIT, IndependentOntologyActivationIT, IndependentOntologyReleaseIT, IndependentOntologyPublicationIT, IndependentOntologyStatusIT, IndependentOntologyReleaseDiffIT, IndependentOntologyReviewNoticeIT (6), IndependentOntologyReviewFilterIT (3), and IndependentOntologyReleaseKindCountsIT (2).
  • Validation. IndependentOntologyAxiomIT and IndependentOntologyReleaseValidationIT.
  • Concepts and data. IndependentOntologyConceptDeleteImpactIT (2) and OntologyConceptBindingsIT, which lists every visible link of an asset whose hidden bindings fill the first 100 rows.
  • Hard delete. OntologyConcurrentHardDeleteIT (1) purges two 400-concept ontologies at once for three rounds and asserts that the InnoDB deadlock counter does not move. It passed three runs in a row. With the shared delete change, TableResourceIT passed on MySQL and OntologyConceptResourceIT on MySQL and PostgreSQL.
  • Import and export. NativeOntologyImportReviewIT (8), NativeOntologyPartialImportIT (4, one drops requiresConceptIris and gets 400), NativeOntologyPartialImportPropertyIT (2), IndependentOntologyReleaseExportFormatsIT (a SKOS export imports again), and IndependentOntologyUrnIriExportIT (2).
  • Query and RDF. OntologyDraftQueryIT (4) and RdfFirstIndexRunIT (2).
  • Final run. Every Ontology IT class ran in the parallel lane on the final server code: 992 tests, 2 failures. One was OntologyConcurrentHardDeleteIT, which asserts on the global deadlock counter. CI runs it alone in the global-state lane, and it passes there. The other was IndependentOntologyReviewNoticeIT, whose approval case still expected the release slug. A sequential rerun also found a race in how IndependentOntologyReviewFilterIT picked its oldest review. R5 fixed both tests. Then IndependentOntologyReviewNoticeIT passed 5 of 5, and IndependentOntologyReviewFilterIT passed three runs in a row and once in the global-state lane.

Jest.

  • Permissions. OntologyEmptyState, OntologyHealthPanel, and OntologyExplorerPage, which covers the role matrix, the over-limit message, and glossary Edit only for users the lease accepts.
  • Create and picker. OntologyCreateDialog, OntologyCreateForm, OntologyCreateForm.utils, OntologyStudioScopeMenu, and OntologyStudioScopeMenu.counts (3), which runs the real count hook over 45 ontologies.
  • Draft reads. OntologyMemoryReviewPanel and useOntologyChangeSetApply.
  • Graph. studioGraphLayout, studioFocusedGraph, studioViewport, conceptSearch, OntologyStudio.utils, OntologyGraphView, and useOntologyGraph.studio.
  • Authoring. OntologyNewClassPanel, OntologyNewClassPanel.utils, OntologyConceptEditor, OntologyConceptInspector, OntologyConceptDeleteDialog, OntologyConceptLiveData, OntologyAuthoringWorkspace, OntologyAllOntologiesConceptDrawer, OntologyRelationCheck.utils, PortOverlay, useOntologyGraphEdit, useOntologyEditLease, and OntologyNativeChangeSet.utils.
  • Published view and URL state. OntologyStudioUrlState.utils, OntologyVersionChip, useOntologyStudioModel, and OntologyExplorerPage.integration.
  • Rules. OntologyAxiomEditor, OntologyAxiomQuickRule.utils, OntologyIriInput, OntologyPropertyEditor, OntologyRelationClash.utils, RelationshipTypePicker, OntologyStudioModel.utils, and conflictHighlight.
  • Query. OntologyStudioQueryConsole, OntologyQueryResults, OntologyQueryResults.utils, OntologyQueryError.utils, OntologyQueryPicker, OntologyQueryPicker.counts (3), and OntologyVisualQueryBuilder.
  • Data mode. OntologyNativeDataMode, OntologyDataGraph, OntologyDataAssetPicker, OntologyDataConceptPick.utils, OntologyBindingSuggestion.utils, OntologyAssetSuggestion.utils, OntologyConceptAssets, OntologyColumnBindingEditor, TableLinkedConcepts, and TableDetailsPageV1.
  • Publish and review. OntologyPublicationModal, OntologyReleasePanel, OntologyReleasePanel.stages, OntologyReleasePanel.utils, OntologyExplorerPage.publication, useOntologyPublication, useOntologyPublication.utils, OntologyReleaseChanges.utils, OntologyReleaseHistory, OntologyReleaseCompare, OntologyReleaseReviewers, OntologyReviewPanel, OntologyReviewBanner, OntologyReviewRelease.utils, OntologyTasksDrawer, and OntologyTaskDetail.
  • Import and export. OntologyNativeImportPanel, useOntologyIdentitySource, OntologyReleaseExportModal, OntologyNativePackReview, and OntologyLibrary.native.

Playwright.

  • Permissions and roles. OntologyStudioPermissions.spec.ts (12), OntologyRoles.spec.ts (1), and OntologyRbacRdf.spec.ts (7), which includes a steward without EditAll who is offered no glossary Edit tab.
  • Prototype flows. OntologyStudioFlows.spec.ts (20) runs ten flows in AI and classic mode: create from the picker and the empty state, name and prefix rules, adding concepts three ways, the unsaved-edit guard, direct publish, review and approval, rejection and withdrawal, per-role actions, rollback and compare, and keyboard reach in the tree and the graph.
  • Create, picker, and shell. OntologyNativeStudio.spec.ts (18), OntologyFirstRun.spec.ts (5), and OntologyNativeTreeShell.spec.ts (2).
  • Large graphs. OntologyLargeGraph.spec.ts (19) covers 400 visible nodes, Find, Tab order, Tree arrow keys, 1024 px, and dark mode.
  • Authoring. OntologyConceptDrawer.spec.ts (20, in AI and classic mode), OntologyNativeRelations.spec.ts (9), OntologyNativeAuthoring.spec.ts (2), and OntologyNativeOperations.spec.ts (4).
  • Rules and validation. OntologyRules.spec.ts (14) covers quick rules, the advanced form, clashes on the graph, Validate all, and mappings across ontologies. OntologyAuthoringSafety.spec.ts (3).
  • Published view. OntologyPublishedView.spec.ts (10).
  • Query. OntologyQueryScope.spec.ts (11) covers draft and published scope, errors, ASK, Copy and CSV, saved queries, and the builder. OntologyQueryRdf.spec.ts (5) and OntologyDataExploreRdf.spec.ts (1).
  • Data mode. OntologyNativeDataMode.spec.ts (11), which follows a table's linked concept back into the Studio, and OntologyNativeLiveData.spec.ts (2), which fails the bindings read and recovers with Retry.
  • Publish, review, and releases. OntologyReview.spec.ts (26) covers each publish dialog state, the author's Inbox, and release history and compare. OntologyReviewChanges.spec.ts (13) covers the change list, the suggested version, field-level changes, task names, and the banner.
  • Import and export. OntologyNativeImportReview.spec.ts (23), OntologyNativeImport.spec.ts (5), and OntologyNativeExport.spec.ts (2, including RDF/XML for a bare urn IRI).
  • Final run. On the final server code (9d0e83f1354), every non-RDF Ontology spec ran on chromium with 2 workers, and all 287 tests passed. The Ontology RDF project passed 39 of 42, and the other 3 are test.fixme cases for tabs the Studio removed. Earlier runs on this branch hit two test-only races, both fixed: an ontology picker with more than 100 entries renders only the rows in view (R14), and a page opened within a second of a form sign-in was sent to the home page (R16).
  • Performance. On Published, the first graph node appears at a median of 1,771 ms, against 2,120 ms on Draft (10 interleaved runs each). Dragging a connection holds frame time at p95 10.1 ms (limit 50 ms). Typing in the rule preview holds p95 at 22.8 ms (limit 100 ms). From Run to rendered rows, a query takes a median of 836 ms and p95 of 1,009 ms.

Python.

  • test_ontology_iris.py asserts that a structure violation round-trips conceptIds and defaults it to an empty list. The file passes 23 cases.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Nov 2, 2026
…e all, and the quick rule form in the safety spec (G13)
Copilot AI balanced review requested due to automatic review settings November 5, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 1063 → 1063
- 0 added, 0 removed, 3 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/ontologyStudio.ts
  openmetadata-ui/src/main/resources/ui/src/generated/entity/data/glossaryTerm.ts
  openmetadata-ui/src/main/resources/ui/src/generated/entity/data/table.ts

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

Copilot AI balanced review requested due to automatic review settings November 5, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

⚠️ UI Checkstyle passed — lint findings in changed files

🔍 ESLint findings in this PR's files — 0 error(s), 28 warning(s)

Errors block the build. Warnings do not yet — they are rules whose backlog is still
being worked down, listed so this PR does not add to it. See docs/ui-code-quality-gate.md.

0 error(s), 28 warning(s) across 14 changed file(s).

Count Rule
11 react-hooks/exhaustive-deps
9 openmetadata-imports/no-api-calls-in-iteration
7 openmetadata-imports/review-sequential-api-calls
1 openmetadata-imports/no-cross-page-imports
All findings
Location Rule Message
🟡 src/components/OntologyExplorer/OntologyGraphG6.tsx:300:7 react-hooks/exhaustive-deps React Hook useImperativeHandle has an unnecessary dependency: 'explorationMode'. Either exclude it or remove the dependency array.
🟡 src/components/OntologyExplorer/hooks/useOntologyGraph.ts:1728:5 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 'DATA_MODE_ASSET_TYPES'. Either include it or remove the dependency array.
🟡 src/components/OntologyExplorer/hooks/useOntologyGraph.ts:2341:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'containerRef', 'glossaryColorMap', 'graphData', 'inputNodes.length', 'positionAssetNodes', 'positionCircularNode
🟡 src/components/OntologyExplorer/hooks/useOntologyGraph.ts:2604:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'containerRef' and 'suppressEdgeCheck'. Either include them or remove the dependency array.
🟡 src/components/governance/ontology/OntologyAuthoringWorkspace/OntologyConceptDeleteDialog.tsx:85:13 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/components/governance/ontology/OntologyAuthoringWorkspace/OntologyConceptDeleteDialog.tsx:88:5 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/components/governance/ontology/OntologyAuthoringWorkspace/OntologyConceptDeleteDialog.tsx:91:27 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/components/governance/ontology/OntologyAuthoringWorkspace/OntologyConceptDeleteDialog.tsx:100:7 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/components/governance/ontology/OntologyAuthoringWorkspace/OntologyConceptDeleteDialog.tsx:100:13 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/components/governance/ontology/OntologyConceptEditor/useReadableConceptOptions.ts:47:32 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/components/governance/ontology/OntologyGraphView/OntologyGraphView.tsx:804:9 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/components/governance/ontology/OntologyNewClassPanel/OntologyNewClassPanel.tsx:461:19 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/components/governance/ontology/OntologyReleaseExportModal/OntologyNativeImportPanel.utils.ts:520:21 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/components/governance/ontology/OntologyTasksDrawer/OntologyTasksDrawer.tsx:131:22 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/hooks/governance/ontology/useOntologyChangeSetApply.ts:205:30 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/hooks/governance/ontology/useOntologyChangeSetApply.ts:379:9 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/hooks/governance/ontology/useOntologyPublication.ts:515:22 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/hooks/governance/ontology/useOntologyPublication.utils.ts:461:28 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:120:1 openmetadata-imports/no-cross-page-imports Page features must not import another page feature. Move shared code to components, hooks, interfaces, or pure utilities.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:210:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 't'. Either include it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:434:6 react-hooks/exhaustive-deps React Hook useMemo has an unnecessary dependency: 'tableDetails.tags'. Either exclude it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:448:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'setDqLineageData'. Either include it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:602:6 react-hooks/exhaustive-deps React Hook useMemo has missing dependencies: 'customizedPage?.tabs' and 'feedCount'. Either include them or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:813:6 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'navigate'. Either include it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:828:5 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'navigate'. Either include it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx:895:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'fetchActivityCount' and 'fetchTaskCounts'. Either include them or remove the dependency array.
🟡 src/rest/ontologyAPI.ts:139:28 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/utils/governance/ontology/OntologyRelationClash.utils.ts:50:28 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.

Fix locally (fast - only checks files changed in this branch):

make ui-checkstyle-changed

Copilot AI balanced review requested due to automatic review settings November 5, 2026 22:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Copilot AI balanced review requested due to automatic review settings November 5, 2026 22:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@gitar-bot

gitar-bot Bot commented Nov 6, 2026

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

🔴 High risk · New ontology edit-right and review/publish controls govern draft access and activation; a permission error could expose drafts or publish changes without intended approval.

Completes the Ontology Studio v7 prototype flows, including direct publish without reviewers, review requests with edit-rights gating, seeded OntologyAuthor and OntologyReviewer roles with a v210 migration, and the graph, create, release, query, data-mode, and import/export updates. Ten resolved findings this session covered the move/copy EditAll bypass, missing decision records, the DataSteward role conflict, partial-import preflight gaps, a duplicate UI note, and an N+1 change-set fetch. No open findings remain.

✅ 10 closed
✅ Bug: Create failures other than name errors now show a generic toast

📄 openmetadata-ui/src/main/resources/ui/src/components/governance/ontology/OntologyCreateDialog/OntologyCreateDialog.tsx:192-203
Before this commit, the catch block passed the Axios error to showErrorToast, which displays the server's message. Now only errors that ontologyCreateErrorKey recognises (409, must match, size must be between) get a specific message. Every other server refusal shows server.unexpected-error. That includes the 403 that G1 now returns to users without create rights, and the 400 for a relative or invalid IRI or namespace typed into the new Advanced fields. The user loses the reason the request failed. Fall back to the Axios error when no known key matches.

✅ Security: Content-patch guard ignores from of move/copy, so EditAll is bypassed

📄 openmetadata-service/src/main/java/org/openmetadata/service/resources/ontology/OntologyResourceAccess.java:43-48 📄 openmetadata-service/src/main/java/org/openmetadata/service/resources/ontology/OntologyConceptResource.java:227-228
touchesContent only looks at each operation's path. A patch like [{"op":"move","from":"/description","path":"/displayName"}] deletes the description, and a move/copy out of /tags changes the tags the same way, yet the guard sees only /displayName. The base patchInternal check then maps the operation to EditDisplayName through JsonPatchUtils.getMetadataOperation, which also reads path only. A DataSteward, which the new ADR says can no longer change a concept or ontology description, can still remove or overwrite it without EditAll. To fix this, treat an operation as a content edit when either its path or its from starts with a content field, or require EditAll whenever JsonPatchUtils.readsFromAnotherPath(patch) is true. Also add a move case to OntologyResourceAccessTest.

✅ Quality: G19 first-start RDF index run has no decision record

📄 openmetadata-service/src/main/java/org/openmetadata/service/apps/bundles/rdf/RdfInitialIndexRun.java:29-43 📄 openmetadata-service/src/main/java/org/openmetadata/service/resources/apps/AppResource.java:180
The PR description states a new rule: "The RDF projection is built once on first start instead of waiting for the weekly run." The new ADR covers only G1 authorization. No file in docs/decisions/ says that startup queues an on-demand RdfIndexApp run. No record says that any existing run record, of any status, is the idempotency key. And none says that this enqueue must run after the app row is persisted, because OmAppJobListener loads the app by name. That ordering spans AppResource.loadDefaultApplications and the job listener, so it can't be seen from a single file. The repo squash-merges, so the description never reaches git log. The record would state: "When RDF is enabled and RdfIndexApp has no run record, server startup queues one on-demand run triggered by system:rdf-initial-index. That run is queued after the app entity is persisted. Any existing run record means nothing is queued, and a failed enqueue falls back to the weekly schedule."

✅ Quality: Studio graph node limit (500/120/2 hops) has no decision record

📄 openmetadata-ui/src/main/resources/ui/src/components/OntologyExplorer/OntologyExplorer.constants.ts:592-596 📄 openmetadata-ui/src/main/resources/ui/src/components/OntologyExplorer/utils/studioFocusedGraph.ts:32-44 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/OntologyLargeGraph.spec.ts:29-30
This commit adds three limits that were judgment calls: STUDIO_GRAPH_NODE_LIMIT = 500, STUDIO_FOCUS_NODE_CAP = 120 and STUDIO_FOCUS_DEPTH = 2. Together they change what Studio shows. Above 500 concepts the canvas draws nothing until a concept is selected or found, and after that it draws at most 120 concepts within two hops of the seeds. Under the repo's decision-record rules, a new limit or cap that was a judgment call needs a record. None of the files in docs/decisions/ covers it. The closest one, 2026-10-24-ontology-studio-bounds-tree-windows-and-count-workers, only bounds Tree windows at 2,048.

The record would say roughly: "Above 500 concepts the Studio graph draws no canvas until a concept is selected or found. It then draws at most 120 concepts within two hops of the selection and the top Find matches, and points users to Tree for the full ontology." This comes from the constants comment: "Past this many concepts the Studio graph draws a neighbourhood instead of the whole ontology: Fit would shrink every label below legibility." The Playwright spec also hard-codes NODE_LIMIT = 500 and toBeLessThanOrEqual(120), so the record should list both specs as its guard.

✅ Quality: New prefix/ID derivation contradicts Accepted onto-IRI ADR

📄 openmetadata-ui/src/main/resources/ui/src/components/governance/ontology/OntologyCreateForm/OntologyCreateForm.utils.ts:81-95 📄 openmetadata-ui/src/main/resources/ui/src/components/governance/ontology/OntologyCreateForm/OntologyCreateForm.utils.ts:122-127 📄 openmetadata-ui/src/main/resources/ui/src/components/governance/ontology/OntologyCreateForm/OntologyCreateForm.utils.ts:187-201 📄 openmetadata-ui/src/main/resources/ui/src/components/governance/ontology/OntologyCreateForm/OntologyCreateForm.utils.ts:248-260
docs/decisions/2026-10-30-studio-created-ontologies-take-onto-iris.md is Accepted. It says digits are dropped from the default prefix ("Digits, spaces, punctuation and accented letters are dropped"), that the user overrides only the prefix, which is checked against ^[A-Za-z0-9_][A-Za-z0-9._-]*$, and that the ontology name is what the user types. This commit changes all three. derivePrefix now keeps [a-z0-9] and adds 2, 3, … when the prefix is taken. The dialog accepts any absolute IRI and namespace in place of a prefix. The ontology name is now deriveOntologyId(displayName), kebab-cased. OntologyCreateDialog.test.tsx, which the record names as its guard, has been rewritten to match the new behaviour. Per the decision-record rules, add a record that supersedes this one and set the old record's Status to name it. The new record would say something like: "The default prefix is the first 8 lowercase letters and digits of the display name, with the smallest integer ≥2 appended while the namespace is taken; the ontology name is the kebab-cased display name; Advanced lets the user replace the ID, IRI and namespace with any absolute IRI." This is the PR description's "names that differ only in digits get distinct prefixes".

...and 5 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

sonarqubecloud Bot commented Nov 6, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.1 backend safe to test Add this label to run secure Github workflows on PRs

Projects

Status: Done ✅

Development

Successfully merging this pull request may close these issues.

2 participants