Repository navigation
Releases
OntoBoard 1.135.0 (2026-11-06)
OntoBoard 1.135.0 - host smoke receipt
When Widoco or Konclude is not installed, Documentation... and Reason with Konclude... now offer
to download it, checked against the SHA-256 OntoBoard was built with, or to use a copy downloaded
by hand. See WHAT THIS RELEASE ADDS.
Produced on Windows 11 Pro (10.0.26100), with tools/smoke.ps1 and -Dontoboard.selftest=true, the
verdict read from what Protege logged. Protege 5.6.9 is the maintainer's own install, with
ontoboard-1.134.2.jar moved out of plugins and this jar the only ontoboard-*.jar in it; Protege
5.5.0 is a throwaway copy of the install, the same way. Each run was given pizzabfo-edit.owl
from a fresh clone of the pizza-bfo test project (a26ac31).
2026-11-06 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx2G PASS check 10/10 test 12/12
2026-11-06 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx500M PASS check 10/10
2026-11-06 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx2G PASS check 10/10 test 12/12
The -Xmx500M run is what Protege.exe gives a user who double-clicks it. The 5.5.0 run finished
loading pizza-bfo, its seven imports resolved from disk; the two 5.6.9 runs were stopped at their
verdicts before it had.
The tenth check is new: "downloads can use TLS" builds a TLS context and opens the operating
system's certificate store, which is what Download... needs, inside Protege's own OSGi container -
the bundle imports javax.net.ssl as optional, so only the host can say whether it is wired. It
passed on both: TLS from SunJSSE (TLSv1.3, TLSv1.2) on 5.6.9 and (TLSv1, TLSv1.1, TLSv1.2) on
5.5.0, Windows trust store 93 roots on each.
The jar: sha256 4569ad304f073a15..., built by mvn -o clean package from the working tree this
release was committed from. The unit suite in that build, on Java 11: 2,806 tests, 0 failures,
0 errors, 3 skipped - PinchZoomTest, as before; BundleConfigurationTest, the manifest check, which
a clean build reaches before the jar exists (run against this jar afterwards, its 18 tests
passed); and KoncludeTest's executable-bit test, which needs a file system with one and runs on
CI's Linux job. The new and changed test classes also passed on Java 25, which CI uses.
Eight NullPointerExceptions were logged, four in each -Xmx2G run, all in Protege's own
OWLCellRenderer; none from OntoBoard.
Beyond the smoke, both downloads were run for real through the classes the Download... button
calls - Download.fetch over HttpsOpener, KoncludeInstall.install, and the start probe Reason
with Konclude... uses - from a harness, into empty folders, with each host's own Java:
JRE 11.0.25 (5.6.9) Widoco 40,858,575 bytes = pin Konclude zip = pin, unpacked, starts
JRE 1.8.0_121 (5.5.0) Widoco = pin Konclude zip = pin, unpacked, starts
On 1.8.0_121 the JRE's own trust store refuses GitHub's certificate ("PKIX path building
failed", measured); both downloads succeeded through the fallback to Windows' certificate store.
WHAT THIS RELEASE ADDS
- When Widoco or Konclude is missing - or Konclude is there and will not start - a dialog comes
before the action's own form, with four ways on. Download... saves the release OntoBoard was
built against into a folder you choose, keeps it only if its length and SHA-256 match (pinned
in the plugin: GitHub publishes no digest for these assets), unpacks Konclude with the
libraries it needs beside it, makes it executable off Windows, and fills in and remembers the
path; Cancel closes the connection at once. Copy link and Open release page are for a browser
download, after which Choose file... takes the jar, the Konclude zip (unpacked for you) or the
program itself. A file with the release's exact name and another hash is refused. - Nothing half-written ever has the release's name: bytes go to .part and are renamed only
once checked, and every other way out deletes the part file. A jar under the release's name but
not its length - a browser download stopped part-way, or still running - is no longer taken
for an installed Widoco. - HTTPS only, at most five redirects, none leaving HTTPS. Certificate checking is never switched
off: after a certificate-path failure the download is tried again against the operating
system's store (Windows' own, or a Linux system Java store), and otherwise says so. - The dialog names what else is needed: Java 11 for Widoco on a Java 8 Protege, with where to get
it; Microsoft's Visual C++ runtime for Konclude on Windows when it is missing (all four
libraries the release imports, read from its binaries); Rosetta 2 on Apple silicon. Konclude's
"did not start" message names the missing runtime too, and Widoco's Java-too-old message says
where to get a newer one.
WHAT THIS RECEIPT DOES NOT COVER
- The dialog itself was not clicked through. It appears only when a tool is missing, and no smoke
run drives Protege by hand; the download, the checks, the unpacking and the start probe were
run for real through the same classes, and everything the dialog says or decides is tested
without a screen. - The Linux and macOS paths - the Linux trust store fallback, the executable bit, the Rosetta and
quarantine advice - are covered by unit tests only, the executable bit on CI's Linux job. - An independent review of the change found three problems, fixed before this build: the runtime
check missed the two "_1" libraries Qt imports; Cancel did not close a stalled connection and
was then reported as a failure; and a chosen zip was unpacked before its program was looked for.
A fourth finding, a cut-short jar taken for Widoco, was fixed with them. Nine smaller points
were left for later.
OntoBoard 1.134.2 (2026-11-05)
OntoBoard 1.134.2 - host smoke receipt
A patch for one defect, found when the two example projects ran their QC workflow on GitHub for
the first time: a project that passed Build... inside Protege failed make test on GitHub, in its
SPARQL checks. See FIXED.
Produced on Windows 11 Pro (10.0.26100), with tools/smoke.ps1 and -Dontoboard.selftest=true, the
verdict read from what Protege logged. Protege 5.6.9 is the maintainer's own install, with
ontoboard-1.134.1.jar moved out of plugins and this jar the only ontoboard-*.jar in it; Protege
5.5.0 is a throwaway copy of the install, the same way. Each run was given pizzabfo-edit.owl
from a fresh clone of the pizza-bfo test project (7ff2db9) carrying the Makefile this release
generates.
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx2G PASS check 9/9 test 12/12
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx500M PASS check 9/9
2026-11-05 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx2G PASS check 9/9 test 12/12
The -Xmx500M run is what Protege.exe gives a user who double-clicks it. The two -Xmx2G runs
finished loading pizza-bfo, its seven imports resolved from disk; the -Xmx500M run was stopped at
its self-check verdict, before the ontology had finished loading.
The jar: sha256 c5ff870e9a520df3..., built by mvn -o clean package from the working tree this
release was committed from. The unit suite in that build, on Java 11: 2,762 tests, 0 failures,
0 errors, 2 skipped - PinchZoomTest, as before, and BundleConfigurationTest, the manifest check,
which a clean build reaches before the jar exists; run against this jar afterwards, its 18 tests
passed. The three test classes this release changes - OdkScaffoldTest, RegressionPinsTest and
PatternIndexTest - also passed on Java 25, which CI uses.
The first attempt at that build stopped in its clean step, unable to delete a directory under
target/; the next attempt, a few minutes later, ran through.
Eight NullPointerExceptions were logged, four in each -Xmx2G run, all in Protege's own
OWLCellRenderer; none from OntoBoard.
The self-test's in-process build scaffolds a project of its own, so it runs this release's
Makefile but not make or ROBOT, which is where the defect was. The fix was checked there: with
ROBOT 1.9.8, the version the generated QC workflow installs, on fresh clones of both example
projects, running make test's recipes as the Makefile states them - through a short script
standing in for make, which this machine does not have: it reads the variables and recipes from
the Makefile and runs them in order, stopping at the first failure, as make does.
pizza Makefile as committed FAIL in sparql_test check_labels: 4 violations
pizza Makefile from 1.134.2 PASS reason, report, sparql_test, validate_profile
pizza-bfo Makefile as committed FAIL in sparql_test cq5: 4 violations
pizza-bfo Makefile from 1.134.2 PASS reason, report, sparql_test, validate_profile
InProcessTargets.whyNotEligible, which Build... asks, refuses both Makefiles as committed and
accepts both from 1.134.2.
FIXED IN 1.134.2
- A project that passed Build... in Protege failed its QC workflow on GitHub. Found when the two
example projects ran QC on GitHub for the first time. ROBOT 1.9.8 failed pizza's check_labels
on four pattern classes - Concept, Object, Price and Currency - and pizza-bfo's cq5 on the four
relations a baking must have, has participant to occupies temporal region. Each label those
checks look for is in an import. Build... inside Protege had passed the same checks, because it
queries the ontology with its imports merged; the generated Makefile's sparql_test ran robot
verify on the edit file alone, which sees nothing its imports say. The target now merges the
imports first, as validate_profile already did, and both projects pass make test under the
same ROBOT. A project created before 1.134.2 gets the new Makefile from Project > Update
project files...; until then Build... says the Makefile is not the one OntoBoard generates, and
names that menu item.
ALSO IN THIS RELEASE
- PatternIndexTest failed CI on main once 1.134.1 was merged, with nothing in the repository
wrong: an import of a pattern's import did not load over the network, and the test called the
shipped pattern index stale. It now looks for unloaded imports through the whole imports
closure, and rebuilds the index once more before calling a row stale. - The documentation site: the two examples link to their ontologies' documentation pages, and
each example ends with how to make that page with Build and release > Documentation....
OntoBoard 1.134.1 (2026-11-05)
OntoBoard 1.134.1 - host smoke receipt
A patch for one defect in 1.134.0, found by the maintainer in Protege 5.6.9 on the day 1.134.0
was released: a sheet narrower than the window was cut off part of the way across. See FIXED.
Produced on Windows 11 Pro (10.0.26100), with tools/smoke.ps1 and -Dontoboard.selftest=true, the
verdict read from what Protege logged. Protege 5.6.9 is the maintainer's own install, with
ontoboard-1.134.0.jar moved out of plugins and this jar the only ontoboard-*.jar in it; Protege
5.5.0 is a throwaway copy of the install, the same way. Each run was given pizzabfo-edit.owl
from a fresh clone of the pizza-bfo test project (7ff2db9).
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx2G PASS check 9/9 test 12/12
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx500M PASS check 9/9
2026-11-05 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx2G PASS check 9/9 test 12/12
The -Xmx500M run is what Protege.exe gives a user who double-clicks it. Both 5.6.9 runs finished
loading pizza-bfo, its seven imports resolved from disk; the 5.5.0 run was stopped at its
self-test verdict, before the ontology had finished loading.
The jar: sha256 4aecee8d733cd86d..., built by mvn -o clean package from the working tree this
release was committed from. The unit suite in that build, on Java 11: 2,761 tests, 0 failures,
0 errors, 2 skipped - PinchZoomTest, as before, and BundleConfigurationTest, the manifest check,
which a clean build reaches before the jar exists; run against this jar afterwards, its 18 tests
passed. The new SheetGridWidthTest also passed on Java 25, which CI uses.
One full build before that failed in CanvasGestureInteractionTest, a test that drives the board
in a real window when a display is present; run alone twice it passed both times, and the next
full build passed. Nothing on the board changed in this release.
Eight NullPointerExceptions were logged, four on each host, all in Protege's own OWLCellRenderer
building the class hierarchy view; none from OntoBoard.
The self-test builds the sheet editor's view on both hosts (Window > Tabs > OntoBoard Sheets:
SheetEditorView built without throwing, and closed again), but nothing here looks at a pixel.
The fix below is covered by SheetGridWidthTest, which lays out the grid the view builds in a
2,000 px window, and by an offscreen render of pizza-bfo's 04_baker_roles through the same code:
all four columns, the header rows exactly as wide as the rows beneath. Seeing it in Protege's
own window is still to be done.
FIXED IN 1.134.1
- A sheet narrower than the window was cut off part of the way across. Reported from Protege
5.6.9 with 1.134.0 on pizza-bfo's four-column sheets: the two header rows ran across the whole
tab, while the rows beneath them stopped inside the second column, the rest grey - Name and
Role of could not be seen. The panel above the grid was a plain JPanel, which its viewport
stretches to the tab's width; the header-row table in it shares the grid's columns and spread
that width across them, while the grid, which does not resize its columns, stayed as wide as
they had asked to be - and drew them clipped at its own edge. The panel is now a Scrollable
that keeps its own width, so both tables lay the columns out alike, at the widths their
contents asked for. SheetGridWidthTest: 480 px of grid under 1,945 px of columns before, all
four columns after.
ALSO IN THIS RELEASE
- The documentation site: a shorter homepage with two examples to try - a pizza ontology, and a
BFO pizza ontology with a knowledge graph - and a page of the ontologies made with OntoBoard.
The Honest accounting section of the menu is now About: limitations, what was fixed, and the
comparison with other tools.
OntoBoard 1.134.0 (2026-11-05)
OntoBoard 1.134.0 - host smoke receipt
Produced on Windows 11 Pro (10.0.26100), with tools/smoke.ps1 and -Dontoboard.selftest=true, the
verdict read from what Protege logged. Protege 5.6.9 is the maintainer's own install, with
ontoboard-1.133.1.jar moved out of plugins and this jar the only ontoboard-*.jar in it; Protege
5.5.0 is a throwaway copy of the install, the same way. Every run opened pizzabfo-edit.owl from
a fresh clone of the pizza-bfo test project (7ff2db9): its seven imports resolved from disk, and
the clone's git status was clean afterwards - nothing written beside the ontology.
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx2G PASS check 9/9 test 12/12
2026-11-05 Protege 5.6.9 OWL API 4.5.29 JRE 11.0.25+9 -Xmx500M PASS check 9/9
2026-11-05 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx2G PASS check 9/9 test 12/12
The -Xmx500M run is what Protege.exe gives a user who double-clicks it.
The jar: sha256 20eeabb337646f70..., built by mvn -o clean package from the tree of 69ee3a7,
the commit that brought this receipt; the commits after it change the citation metadata and
one test (below), not the plugin. The unit suite in that build, on Java 11: 2,757 tests,
0 failures, 0 errors, 2
skipped - PinchZoomTest, as before, and BundleConfigurationTest, the manifest check, which a clean
build reaches before the jar exists; run against this jar afterwards, its 18 tests passed.
CompiledClassesTest passed, so no class in it was written by another compiler.
The four NullPointerExceptions logged on 5.5.0 are Protege's own OWLCellRenderer building the
class hierarchy view, as before; none on 5.6.9. Two other plugins of that 5.5.0 install,
cellfie 2.2.4 and swrltab 2.1.3, failed to install there; not ours.
The self-test builds the sheet editor's view on both hosts (Window > Tabs > OntoBoard Sheets:
SheetEditorView built without throwing, and closed again) - the view this release changed most.
WHAT THIS RECEIPT DOES NOT COVER
Nothing here looks at a pixel or presses a button in the sheet editor, the board or a dialog: the
self-test constructs the two tabs and drives nine read-only menu items. What the sheet editor now
does - the folder it opens from each kind of file, following the active ontology, keeping unsaved
edits - is covered by 29 unit tests and was checked headless on pizza-bfo's real files, not
clicked through in Protege. The Release... and Template... fixes below are covered by unit tests,
not driven in the host.
CI on the release branch failed first, on Linux and on Windows, in one test, and had failed
since CI moved to Java 25 (09a8123): BuildsWithNothingInstalledTest installed a SecurityManager
to refuse every exec, and from Java 24 none can be installed (JEP 486). The plugin was not at
fault; the test could not run. It now keeps the SecurityManager where Java still allows one and
otherwise records the build with Java Flight Recorder's jdk.ProcessStart event, after showing
the recorder a start it must see. Checked on Java 11, 17 and 25 - and on 25 it fails, naming
the program, when one is started during the build. No plugin code changed.
FIXED IN 1.134.0 (each in docs/fixed.md, with how it was found)
- The sheet editor said "No templates yet" over nine templates one folder away. Opened from
pizza-bfo's edit file it looked only in src/templates; its sheets are in kg/templates. It now
tries four places in a fixed order - templates/ beside the file (src/templates instead, for an
ODK edit file), then the project's src/templates, kg/templates and templates/ - with the
project root found at most four levels up. It follows the active ontology, never replaces
unsaved edits or a folder chosen by hand, creates nothing, and its toolbar names the folder.
Check sheets... starts with that folder filled in, and Template...'s Browse opens in it. - Every row of a sheet failed with "could not interpret" when its ID prefix (kg:) was not
declared, and nothing said why: Template... now names the prefix, and the declared one that
would settle it. - Every row of a built graph "names 2 different things" in Check sheets... and the sheet
editor's marks: a CURIE was compared with the IRI it expands to. - ID ranges... offered a block under a name nothing mints with. The board, the sheet editor and
the dialog now use one function for the editor's name. - Template... recorded the person running it as the author of other people's terms, with
provenance recording on: a class only an import declares, rdfs:label, a datatype. A term is new
now only when neither the ontology nor anything it imports has it. - Release... proposed 0.1.1 over a published 1.0.0, from an owl:versionInfo a release never
updates, and would have released it, or 1.0.0 again over the published copy. It proposes the
version after the newest release now, and refuses a semantic version at or below it. - Record who edits terms... offered FOLLOW_THE_ONTOLOGY, ALWAYS and NEVER. Words now.
- Documentation... showed Widoco's ERROR lines over a page it had written: each known line is
explained once.
DOCUMENTATION
- docs/limitations.md audited claim by claim against the source: what a user meets in 1.134.0
is there, the retired web application is not. - Internal material is no longer in the repository: the evaluation plan, the user-study
material, the paper-claims audit, the expert-evaluation triage, and the design specs and plans
of docs/superpowers/. Earlier versions remain in the history.
OntoBoard 1.133.1 (2026-11-02)
OntoBoard 1.133.1 - host smoke receipt
Produced on macOS 15.8.1 (Intel x86_64) as 1.133.0's was: a throwaway copy of each install, the
jar under test as the only ontoboard-*.jar in its plugins, -Dontoboard.selftest=true, and the
verdict read from what Protege logged - Protege stopped only once its own startup had finished
as well.
2026-11-02 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx2G PASS check 9/9 test 12/12
2026-11-02 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx2G PASS check 9/9 test 12/12
The jar: sha256 9a14b0b1d03bb51b..., built by javac from a clean export of commit ee27dad
(mvn clean package), not from the working tree's target/. The unit suite: 2,679 tests, 0
failures, 28 skipped - one of them the manifest check, which a clean build reaches before the jar
exists; run against this jar afterwards, it passed.
The four NullPointerExceptions logged on each host are Protege's own OWLCellRenderer, as before.
WHY THERE IS NO 1.133.0 RELEASE
1.133.0 was committed, pushed and tagged (v1.133.0, 5d1d9b3), and the release workflow failed in
its Test step - mvn -B clean test, run on the tagged commit before anything is packaged,
because the jar a user downloads has to be the jar that was tested. Nobody can download 1.133.0.
The tag stays, as v1.122.0's did.
Two failures, neither visible on the Mac 1.133.0's receipt was produced on, and neither said by
the run to anyone not signed in to GitHub, whose page showed "Process completed with exit code
1". The tests now print an annotation for each failure under GitHub Actions (GitHubAnnotations),
which is how both were found.
-
Windows, failing on every push since d607d05: seven tests whose assertions passed, and then
JUnit could not remove their temporary folders, because a Turtle file was still open. The OWL
API leaves a handle on a file whenever it has to guess the format and a parser fails before
one succeeds - measured with lsof: one handle on a Turtle file read by File or through an
address mapped to it, none when the format is named or the file is RDF/XML. Windows will not
delete, rename or replace an open file, so this held a user's file as well as a test's.
OntologySource.loadFile now reads a file the way PatternIndex already did - through a stream it
closes, under a stand-in document IRI - and OntologySource.load uses it for any address that
resolves to a local file. OntologySourceTest counts the handles on Linux and macOS. -
Linux, intermittently since b2c386a: the second conversion of the same history wrote a
different release file from the first - <terms:date rdf:datatype="...#string"> once and
terms:date the next. "x" and "x"^^xsd:string are one literal, equal to the OWL API too, and
its data factory, shared by every manager in a process, caches annotations and hands back
whichever form it holds until a background eviction drops it. On a CI runner the cache
sometimes cleared between the two conversions; on the Mac it never did. The conversion now
writes every ontology with explicit xsd:string removed, so a converted repository is the same
bytes whatever the cache did.
CI on ee27dad: the Test step passed on Linux and on Windows, and both Windows smoke runs passed.
Also driven in Protege 5.6.9, on this jar, by a probe pressing the real buttons:
- Turn an ontology into an ODK repository: NFDIcore 3.0.5 from a file, with 3.0.4 and 3.0.3 read
from GitHub. The nine steps ticked in order in 15.9 s; three releases and tags v3.0.3, v3.0.4,
v3.0.5; build passing; no warnings. - The OntoBoard menu as Protege built it: 45 items in seven submenus, with 13 separators - the
same tree, line for line, as 1.133.0's. - An ontology opened and closed without touching the board, twice: no .ontoboard.json beside it.
- The board, opened with nothing saved: pizza (86 terms, 5 frames) and MWO 3.0.2 (660 terms, 21
frames) - no two boxes overlap, and no line passes through a frame neither of its ends is in
(0 of 146, 0 of 982). The pizza board the same in Protege 5.5.0, focused as well as opened.
The MWO run's focused-board step did not finish: the machine was swapping, starved by four
Protege 5.5.0 instances that earlier self-test runs had left running - the run script had
stopped a subshell rather than Protege, and now stops Protege - and the run was ended by hand. - Run self-test, then the workspace closed: Protege names no listener as never removed.
Windows: CI runs the unit tests and the self-test in Protege's Windows downloads on every push.
WHAT THIS RELEASE ADDS (over 1.132.0, the last release before it)
- Project > Turn an ontology into an ODK repository...: an ontology in any format, or a web
address, with its earlier versions; each earlier version a release, a commit dated as it says
and a tag; imports turned into modules of the terms used; built, tested, released, recorded in
git, and the commands that push it to GitHub. Every step shown as it runs, with Stop. - The board frames a design pattern merged into the ontology, found by its terms: the pizza
ontology as one file shows 3 patterns, NFDIcore 14, MWO 19. Arrange > Outline finds them again
on a board saved before. - The OntoBoard menu grouped by job, in the order the guide works: Project, Reuse, Terms,
Spreadsheets | Check and test, Build and release, Share | Record who edits terms..., Check
requirements..., Run self-test. ROBOT, Notes and Knowledge graph are gone as menus;
Provenance... is Record who edits terms...; each entry is in one place.
FIXED
- A file OntoBoard read was held open on Windows until the garbage collector ran, when the OWL
API had to guess its format - see above. - A converted repository was not always the same bytes twice - see above.
- Opening an ontology left .ontoboard.json beside it, and that file froze the outline:
a board is now written from its first change only. - A long row of pattern frames reached over the property sections, so lines from the outline into
a pattern crossed them: the frames are folded into rows, and the sections start right of them. - Messages and documentation pages named menu places that had moved, about 15 of them before the
regrouping (ROBOT > Template..., Project > Pull request...). A test now follows every path,
submenu by submenu, in the plugin's messages and on the pages. - The build's report said "imported terms" for other ontologies' terms merged into the file.
- Run self-test left every view it built registered with Protege: it took the tabs it opened off
the screen and never disposed them, so each run added listeners that stayed until Protege
closed - 72 named when one workspace closed. The tabs are now closed as Protege's own close
button closes one, and a tab check that fails names what was thrown. - A jar could carry a class VS Code's Eclipse compiler had written for code javac rejects - its
method replaced by a throw of "Unresolved compilation problem" - which Maven tested and packaged
because it was newer than its source. The suite now fails on such a class (CompiledClassesTest),
and this jar was built from a clean export of the commit.
NOT DONE (on the roadmap in docs/limitations.md): Check this ontology without a project; greying
out entries that cannot run yet; help for each project configuration key; base/full/simple
release artefacts; History for properties and individuals; Obsolete offering to move children;
bring to front and send to back.
OntoBoard 1.128.0 (2026-10-29)
OntoBoard 1.128.0 - host smoke receipt
Produced by tools/smoke.ps1 -SelfTest.
2026-10-25 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx500M PASS check 9/9 test 11/11
2026-10-25 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx500M PASS check 9/9 test 11/11
THE FOUR THINGS 1.127.0 ADMITTED IT HAD NOT FINISHED
Its receipt listed them under "what is still not true". All four are done here, and the list of
what remains is shorter and different.
- A PATTERN THAT WAS NEVER A PATTERN IS GONE
contentops is removed, and the library is 162 patterns rather than 163. Its description was the
text of the ODP wiki's INDEX page - "Below you find the currently proposed Content OPs (CPs). New
proposals of CPs are very welcome. Please post a..." - so the harvest had turned a category
listing into a library entry, and the ontology it was given was the SAN file belonging to
actuation-actuator-effect, byte for byte.
Removing a pattern is not deleting a directory. It moved seven count assertions, the measured
class total (1,556 to 1,520 - the 36 classes it contributed were actuation-actuator-effect's
counted a second time) and the duplicate count (10 to 9). Each now carries the reason in a
comment rather than only a new number.
AND IT CLOSED A DEBT THIS REPOSITORY HAD LOGGED AGAINST ITSELF. docs/compared-with-ontoeditor.md
asked somebody to "pick one number, state the definition, fix all of them": the count was 163 in
some files and 159 in six others. It is 162 bundled, 152 distinct, everywhere - README, docs/index,
the library page, compared-with, persistent-identifiers, requirements-status, odk-workflow - and
that item is marked done.
- THE REASONER'S VERDICT IS NOW INSIDE PROTEGE, NOT ONLY ON THE WEB
The four findings were measured, written to patterns/soundness.tsv and published on the pattern
pages - and the pages are the one place a curator working inside Protege is not looking. Select
one of the flagged patterns in ROBOT > Pattern library... and the chooser says so in red, with
the reason, BEFORE the import. Importing a pattern whose class cannot have an instance makes the
user's own ontology unsatisfiable, and the first they would otherwise hear of it is their own
reasoner refusing to classify something that looks unrelated.
A pattern a reasoner is happy with says nothing. A box on all 162 is a box nobody reads, and it
would make the three that matter harder to notice rather than easier.
READ, NOT COMPUTED: the verdicts come from the table PatternSoundnessTest generates and checks on
every build. Running a reasoner over 162 patterns to open a dialog would take twenty seconds and
answer a question already answered. Absence is not a finding either - a contributed pattern from
the user's own folder has no row and gets no claim made about it.
MY OWN TEST PASSED VACUOUSLY FIRST, AND THAT IS THE INTERESTING PART. It asserted
forPattern("actingfor").isClean(), which is true when the table is MISSING, because an unknown
pattern is reported clean by design. The table WAS missing: patterns/soundness.tsv was not in the
pom's resource include list, so nothing was bundled, every verdict came back unknown, and the
test went green. Only the three assertions naming a specific finding failed. The test now asserts
that a flagged pattern is flagged, so it can tell "checked and fine" from "never read".
- EVERY PATTERN THAT CAN ANSWER A QUESTION NOW SAYS WHICH
161 of the 162 patterns carry competency questions, up from 123. The one that does not is
template-instance, and that is correct rather than outstanding: it declares no classes and no
properties, so there is nothing a question could be about - verified, not assumed.
The questions were derived from each pattern's own axioms and then put to a second pass told to
REFUTE anything the pattern cannot answer, which corrected 17 of the first 22 and rewrote most of
the rest. Every one records competency_questions_source, saying it was derived here and that the
upstream submission states none, so nobody comparing a page with the portal finds questions the
portal never published.
This matters more than documentation: since 1.127.0 the library's search reads the competency
questions, so a pattern without them is close to unfindable by the question it answers.
- THE EXAMPLES SHOW A DOMAIN INSTEAD OF SHOWING THEIR OWN CLASS NAMES
ALL 160 EXAMPLES IN THE LIBRARY ARE CURATED. None carries the generator's "replace the generic
names with real ones" header any more, which is an instruction that had stood unread on 119 of
them. The two patterns without an example will not get one: template-instance declares no classes
or properties, and every example of spatial-graph-adapter-sga is inconsistent because the pattern
is.
A generated example was correct in shape and taught nothing: every individual named after its
class and labelled "an Attribute", "a Type", "the whole". What is there now is a domain:
actingfor Matteo Sanvitale, a shipping officer, acting for CEMA s.r.l. - the pattern's own
stated scenario, with the company acting only through a person
countingas Searle's own case: at a faculty board meeting, a raised hand counts as a vote
controlflow the scope screening of a journal submission, with the case task branching into
exactly the two deliberation tasks its cardinality restriction requires
mwo-value- the lattice parameter of nickel, with its measured value and unit
specification
eep the 2024 energy audit of a Karlsruhe school against DIN V 18599
TWO GATES, INDEPENDENT OF EACH OTHER, PASS ON ALL OF THEM:
- tools/check-pattern-examples.py: every class and property used is one the PATTERN declares,
and every object-property assertion respects its rdfs:domain and rdfs:range. This is the
check that catches a property used backwards. - PatternSoundnessTest: each example MERGED with its pattern is consistent under HermiT. Merged,
because no example imports its pattern - they reuse its IRIs by prefix - so an example read
on its own cannot contradict anything.
THREE THINGS THE CURATION FOUND, rather than only improved:
- aquaticresourceobservation asserted the plain string "a value" against a property whose
declared range is xsd:int, on both of its year properties. They are typed literals now. - climaticzone held an untyped string where its pattern declares xsd:gYear.
- eventcore's generated example was three individuals with NO EDGES AT ALL, because the pattern
declares neither rdfs:domain nor rdfs:range and the generator could derive no shape from it.
That one was extended rather than renamed, which is why its axiom count moves from 9 to 37.
ONE I HAD TO CORRECT BY HAND: the agent curating aquaticresources left out the canOccurIn link -
the relation the pattern is actually about - reasoning that adding a triple would disagree with
the count in patterns/soundness.tsv. That file is generated; protecting it is backwards. The
example now shows both of the pattern's relations.
A PROCESS MISTAKE OF MINE, RECORDED BECAUSE IT COST REAL WORK
The first curation run was given a list of pattern ids I TYPED FROM MEMORY instead of reading the
file I had just written them to. 48 of the 119 ids do not exist - bfo-continuant-parthood,
pmdco-sample-and-specimen, nfdi-publication-and-citation and 45 more - so roughly 40% of that
run went looking for directories that were never there, while 58 real generic examples were not
assigned to anybody. The agents behaved correctly throughout: they invented nothing for a missing
id, and they declined to overwrite the eight examples that were already curated. The second run
was given the list read from disk.
TESTS
2,530 Java, 0 failures, 1 skipped, from mvn clean package on the shipped tree.
74 JavaScript, 0 failures - unchanged, because this release touches no JavaScript.
Both hosts read the library as part of the self-check: "162 patterns indexed, and
actingfor parsed to 2 classes, 2 properties" - so the index and the removal of a
pattern from it are things a running Protege agrees with.
ReasonerVerdictTest 8 new - the shipped table is on the classpath, outside OWL 2 DL is not
called inconsistent, an unsatisfiable class is named with its
consequence, a pattern with no row says nothing, the parser skips a
short row, the wording agrees with the number of classes, and the
warning reaches the chooser's HTML for a flagged pattern and not for a
clean one
Counts that moved with contentops, each with its reason in the test: PatternLibraryTest (the
bundled collection, the group totals, the empty and null queries, the class total, the duplicate
count), PatternOrderTest, ContributedPatternsTest.
WHAT IS STILL NOT TRUE
- A contradiction that arises only against DUL or BFO is still not caught, because imports are
deliberately not resolved - five of the cited servers no longer answer. Every pattern page
says how many ontologies it imports, so a reader can see how much its verdict leaves out. - 49 patterns have no scenario text. The competency questions now cover 161 of 162, which is
the field that matters for finding one. - Nobody has seen the curated examples rendered as graphs. The strict mkdocs build passes and
both gates pass, which proves the links resolve and the RDF is sound - not that any particular
diagram reads well. - The ODP portal still does not answer over HTTPS, and five pattern IRIs point at a server that
no longer answers at all. Each page offers an archived copy for that reason. - No Zenodo DOI, no w3id PURL, not in Protege's plugin registry, the paper audited and not
rewritten, .xlsx read-only, no contact address or ORCID in CITATION.cff.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
OntoBoard 1.127.0 (2026-10-24)
OntoBoard 1.127.0 - host smoke receipt
Produced by tools/smoke.ps1 -SelfTest.
2026-10-24 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx500M PASS check 9/9 test 11/11
2026-10-24 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx500M PASS check 9/9 test 11/11
THE PATTERN LIBRARY HAS NOW BEEN PUT TO A REASONER
163 patterns have shipped as something other people should build ontologies out of, and until
this release nothing had ever asked a reasoner whether any of it holds together. PatternSoundness
reasons over every pattern and every example with HermiT on each build, in 22 seconds, and
commits its verdicts to patterns/soundness.tsv. A test fails when that file and the patterns
disagree, which is what lets each pattern's page quote what a reasoner says without the claim
drifting away from the truth.
159 OF THE 163 ARE CONSISTENT with no unsatisfiable class, and their examples are consistent with
them. Four are not, and each page says so with the reason:
roledependentnames outside OWL 2 DL: assumesAgentRole sits in a cyclic property
hierarchy, which breaks the regularity restriction. HermiT refuses
the ontology rather than answering about it.
winstonpartwhole outside OWL 2 DL: the non-simple property po-feature appears in an
asymmetric object property axiom.
spatial-graph-adapter-sga Attribute and ContextualizedRelation are unsatisfiable: two
properties declare BOTH as rdfs:domain, which OWL reads as their
intersection, and the pattern then declares the two disjoint.
template-instance consistent, but declares no classes or properties at all, so no
example can be built for it.
BEING OUTSIDE OWL 2 DL IS NOT THE SAME AS BEING INCONSISTENT, and the pages do not conflate them.
One is a contradiction; the other is a question no DL reasoner can be asked. A test asserts that
each exception is described in a curator's words rather than as a Java exception class.
THE CHECK NOTHING HAD EVER RUN
NOT ONE OF THE 163 EXAMPLES DECLARES owl:imports OF ITS PATTERN. Every one reuses the pattern's
IRIs by prefix, so an example loaded on its own is a document of undeclared names - it cannot
contradict anything, and "the example parses" was all anybody had ever established. Merging the
two is what turns that into "the example is a model of the pattern", and it found a real defect:
the generated example for spatial-graph-adapter-sga asserted an individual into two classes its
pattern declares disjoint. That example has been withdrawn, because every example of that
pattern is inconsistent.
THE GENERATOR THAT PRODUCED IT IS FIXED, not just its output. tools/make-pattern-examples.py
asserted EVERY rdfs:domain of a property, which is correct OWL - several domain axioms are a
conjunction - but it never checked whether those classes were declared disjoint. It now reads
owl:disjointWith and owl:AllDisjointClasses, refuses to write an example for a pattern whose
property has an empty domain, and says which property and which pair of classes.
IMPORTS ARE DELIBERATELY NOT RESOLVED WHEN REASONING. 101 patterns declare them; among the
targets are five on a server that stopped answering, two unresolvable file:/schemas/ URIs, and a
portal whose HTTPS endpoint does not complete a TLS handshake. Resolving them would make the gate
depend on the weather - the same pattern verified today and unverified tomorrow - and a pattern
that passed only because its import failed to download would be indistinguishable from one that
passed on its own merits. The cost is stated on every page: the "Brings in" row says how much was
left out of that pattern's own check.
TWO PATTERNS PROTEGE COULD NOT LOAD AT ALL
actuation-actuator-effect and contentops share one byte-identical pattern.ttl, and NO OWL API
PARSER WOULD READ IT - all eighteen were tried. The cause was one malformed literal:
owl:versionInfo 2.0.0 ;
which is not a valid Turtle literal. It tokenises as 2.0, then a statement-ending dot, then a
bare 0 - "Encountered 0 at line 120". rdflib accepts it leniently, inventing a triple
whose subject is the literal 0, which is why the file looked fine to every tool except the one
that matters. The .owl sibling carried the same defect as an invalid xsd:decimal. Both are fixed,
both patterns now parse, and both are HermiT-clean.
SOURCES THAT CAN ACTUALLY BE CHECKED
MEASURED: ontologydesignpatterns.org, which publishes 123 of these patterns, does not complete a
TLS handshake from here - so every stored https:// URL to it is dead - and over plain http:// its
wiki redirects a submission page to its front page. The ontology files themselves still serve
over http. The Internet Archive holds the submission pages.
So each pattern page now carries a "Check it yourself" line with the published source, AN
ARCHIVED COPY, and the ontology file, and says in a note why the archive link is there. A
citation nobody can follow is not a citation. The URLs were in metadata.json all along and no
page had ever rendered one.
WHAT EACH PAGE NOW TELLS SOMEBODY DECIDING
A "Should you use this one?" table, built only from measurements:
Size classes, properties and axioms - a four-term pattern is a shape to copy, a
forty-term one is a commitment
Brings in how many ontologies it imports, because adopting it adopts those too
Reasoning what HermiT says, quoted from the committed verdicts
Duplicate of when the library lists the same pattern twice, which it does for five pairs
Plus two new guides: docs/choosing-a-pattern.md (search by the question you want answered, let
the open ontology suggest patterns, what the recommender's two signals are and why both are
needed, what is and is not checked) and docs/contributing-a-pattern.md (the folder route, which
needs no rebuild, and the issue route with the review criteria published in advance as runnable
robot commands). .github/ISSUE_TEMPLATE/pattern-submission.yml is the form.
SEARCH NOW FINDS A PATTERN BY THE QUESTION IT ANSWERS
PatternLibrary.matching read the id, name, description, category and domain - and NOT the
competency questions, which are the one field written in the words a curator actually types.
"working for which organization" found nothing, while actingfor, whose coversRequirements says
almost exactly that, sat in the list under a name nobody would guess. The questions are searched
now, and 123 of the 163 patterns carry them.
AND 36 PAGES HAD BEEN SHOWING THEM AS ONE RUN-ON BULLET. The page generator split the field on a
bar; measured, 36 metadata files separate questions with a SEMICOLON and not one uses a bar. Both
are accepted now.
22 PATTERNS GAINED COMPETENCY QUESTIONS, derived from their own axioms and then checked against
them by a second pass told to refute anything the pattern cannot answer - which corrected 17 of
the 22. Each carries competency_questions_source recording that they were derived here and that
the upstream submission states none, so nobody mistakes them for the portal's own wording. Four
pages whose description was empty after heading-stripping now show those questions instead of
nothing.
WHAT IS HONESTLY INCOMPLETE: 17 of the 40 patterns without questions still have none. Questions
were derived for them, but the session hit its usage limit before the checking pass could reach
them, and an unchecked question about what a pattern answers is not worth publishing. They are
named in the list below.
A TRAP WORTH RECORDING FOR WHOEVER TOUCHES THE REASONER
DECLARING A HermiT DEPENDENCY BREAKS THIS AUDIT. robot-core already brings
org.semanticweb.hermit:1.4.5.456, which is the build compatible with the OWL API 4.5.9 this
project pins to match the Protege 5.5.0 host. Every newer build on Maven Central is compiled
against an OWL API whose OWLOntologyID.getDefaultDocumentIRI() returns java.util.Optional, where
4.5.9 returns Guava's - so clausification dies with NoSuchMethodError. A direct dependency also
sorts AHEAD of robot-core on the classpath, so adding one silently replaces the working reasoner
with a broken one. It cost an hour to find, twice: the first measurement run worked only because
the explicit jar was appended LAST and robot's won. Take HermiT from robot-core and do not pin
it. The test's javadoc says so.
No dependency was added for any of this: org.semanticweb.hermit-1.4.5.456.jar is already bundled
inside the plugin jar by robot-core, byte-identical to the copy 1.126.0 shipped. Which also means
HermiT is available to the plugin at RUNTIME, not only to its tests - the pattern dialog could
say what a reasoner thinks of a pattern before somebody imports it, and does not yet.
TESTS
2,522 Java, 0 failures, 1 skipped, from mvn clean package on the shipped tree.
74 JavaScript, 0 failures - unchanged, because this release touches no JavaScript.
The pattern library is read on both hosts as part of the self-check: "163 patterns
indexed, and actingfor parsed to 2 classes, 2 properties" - so the index this
release rewrote is one a running Protege can still read.
PatternSoundnessTest 4 new - every pattern and example holds together or is a named
exception, the committed verdicts match what a reasoner says, each
exception is described in a curator's words, and outside-OWL-2-DL is
kept distinct from inconsistent
PatternLibraryTest +1 - a pattern is found by the question it answers, and every word of a
query still has to match
Regenerating patterns/index.tsv is a command now rather than a Java method name in a comment:
mvn -o test -Dtest=PatternIndexTest -Dontoboard.writeIndex=true. It is deliberately not
automatic - a rebuild on a day when a cited server is unreachable writes a SMALLER t...
OntoBoard 1.126.0 (2026-10-24)
OntoBoard 1.126.0 - host smoke receipt
Produced by tools/smoke.ps1 -SelfTest.
2026-10-24 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx500M PASS check 9/9 test 11/11
2026-10-24 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx500M PASS check 9/9 test 11/11
Both hosts report "OntoBoard 1.126.0 resolved and started", so the version that ran is the
version in pom.xml rather than a stale bundle out of Felix's cache.
A REFUSED COMMIT NOW SAYS WHAT THE DISAGREEMENT IS
docs/conflicts.md item 5 - "a read-only conflict report, best value per unit of work" - is done,
for git conflicts. Since 1.123.0 a commit on a conflicted tree has been refused, which stopped
the plugin recording conflict markers into an ontology and reporting success. What it left the
user with was a list of filenames and no way to find out what the two sides disagreed about,
because the one file they can open - the working copy - is the one version that is no longer an
ontology.
Both the refusal and "Show me what has changed" now carry lines like:
src/ontology/mwo-edit.owl: 1 term changed on both sides, differently, out of 1 and 1. Each
needs somebody to choose.
Both sides relabelled Material, differently: this branch has "Material Entity", the other
branch has "Material Thing".
It reports; it does not resolve. Which of two definitions of a class is right is not a tool's
decision, and there is still no three-way merge here to offer.
AGREEMENT IS REPORTED APART FROM DISAGREEMENT. Two people who made the SAME edit have not
conflicted, even though git says they have. Counting those as decisions would teach a curator to
skim the report, and the next one they skim will be real.
THE ESTIMATE'S PREMISE WAS WRONG, IN A USEFUL DIRECTION
Item 5 was listed as blocked behind items 6 and 7 - applicable diff objects, and a base version
per session - on the grounds that naming a disagreement needs a common ancestor and real change
objects rather than rendered strings.
For a GIT conflict git has kept a common ancestor all along: stage 1 IS the common version, and
no session, lock, vector clock or version counter was needed to obtain it. Rendered strings turn
out to be enough to NAME a disagreement; they are only insufficient to RESOLVE one. The thing
that genuinely needs a base version is the live collaboration path, which has none - and that is
item 7, still open.
MEASURED, NOT REASONED: SEVEN REAL CONFLICTED REPOSITORIES
Each shape was created with real git and run through the shipped function with the real process
runner - not a fake, and not a reimplementation of the production path:
UU content clash on one term stages 1 2 3 names the term and both labels
DU deleted here, changed there stages 1 3 "this branch no longer has this file ..."
AA created on both sides stages 2 3 "both branches created this file
independently - 2 axioms here, 2 there ..."
UU markers committed in one side stages 1 2 3 "... this branch will not parse ..."
UU path with a space in it stages 1 2 3 reported at all, which it was not before
AU renamed differently on both stage 2 only "only this branch has this file, and there is
UA stage 3 only no common version of it"
DD the old name of that rename stage 1 only "neither branch has this file any more"
DD deleted on both sides NEVER ARRIVES git resolves it silently and the file is
absent from the status entirely
A German umlaut in a path was confirmed by accident: a refuter checking finding 5 left
src/ontology/Begriffsübersicht.ttl conflicted in one of these repositories, and the shipped
code reads it correctly through git's per-byte octal escaping.
And the measurement that justifies the whole feature: on the conflicted repository all three
stages parse cleanly as ontologies and THE MERGED WORKING COPY DOES NOT PARSE AT ALL - "Content
is not allowed in prolog", because git has written <<<<<<< into it. A side-by-side text view of
a conflicted .owl is a view of something that has stopped being an ontology, which is why this
compares git's three stages instead of the file on disk.
A BUG THE MEASUREMENTS FOUND IN MY OWN FIRST VERSION
The first version inferred the shape of the conflict from which versions the OWL API could read:
no stage 2 meant "this branch deleted it". That is wrong exactly when git HAS the stage and it
will not parse - a file somebody committed with conflict markers still in it, which is the thing
docs/conflicts.md says happens today. It reported a broken file as a deletion, confidently, and
a user's next move after reading that would have been the wrong one.
Fixed by asking git which stages it kept (git ls-files -u) and reporting a parse failure as a
parse failure. Proven on a real repository with markers committed into stage 2, and guarded by
ConflictReviewTest.aStageThatWillNotParseIsNotReportedAsADeletion.
TWO MORE THINGS THE MEASUREMENTS CORRECTED:
- The OWL API's Turtle parser is LENIENT. A file with a missing period and an undeclared prefix
still parsed - into an ontology missing the class the broken line carried - so the report
said "this branch removed Material", which is a true statement about the ontology that file
actually describes. Genuinely unparseable stages are rarer than assumed; committed conflict
markers are the realistic cause. - Delete/delete does not produce a DD status from a plain merge. GitRepo.isUnmerged admits DD,
so the path is reachable and is covered, but it took a real merge to learn that the ordinary
case never reaches it.
NINE DEFECTS AN ADVERSARIAL REVIEW FOUND IN THIS RELEASE, BEFORE IT SHIPPED
Four reviewers read the change along different dimensions and raised 16 findings; each was then
handed to refuters told to DISPROVE it. The ones below survived, were reproduced against real git
or measured directly, and are fixed here. The review cost about 2.5 million tokens across 30
agents and was worth it: eight of these were wrong output a user would have acted on.
-
A RENAME ON BOTH SIDES WAS REPORTED AS A DELETION. The one-sided branches tested for a missing
stage 2 or 3 BEFORE asking whether git kept an ancestor. MEASURED on git 2.38.1: ours renames
a.ttl to b.ttl, theirs to c.ttl, and the merge leavesDD a.ttl,AU b.ttl,UA c.ttl-
single-stage sets. The report said "the other branch no longer has b.ttl" about a path that
branch never had. A curator restoring it loses one of the two renames. Worse, it is the same
confident lie that asking git for the stage list was added to prevent. No test could reach it:
a single-stage set needs a null ancestor AND a null side, and no case passed both. -
AN UNREACHABLE IMPORT MADE A READABLE FILE "UNPARSEABLE", IN 13.6 SECONDS. Each stage was
loaded through a default-configured manager, which fetches owl:imports. MEASURED: an ontology
importing two unreachable IRIs threw UnloadableImportException after 13.6s - per stage, three
stages per file. An ODK edit file imports its modules by IRI, so this was the ordinary case,
not a corner. The guarded configuration answers in 2.5s with the ontology intact, and nothing
is lost because only each version's OWN axioms are compared. -
TWO INDEPENDENT ADDITIONS OF ONE TERM WERE CALLED AGREEMENT. ReleaseDiff records an ADDED
change with the term's rdfs:label as its only value, so two people who each introduced the
same IRI with the same label were reported as agreeing while their definitions, parents and
restrictions went uncompared. -
A SECOND CHANGE TO A TERM COULD HIDE A DISAGREEMENT ABOUT IT. Only the last change per term
was kept, so two sides that each relabelled Material differently AND moved it under the same
parent reduced to one identical MOVED entry per side, compared equal, and were announced as
agreement - with the label disagreement absent from the report altogether. -
A CONFLICTED PATH WITH A SPACE IN IT GOT NO REPORT AT ALL.
git status --porcelainquotes
such a path - MEASURED:UU "src/my ontology.owl"- and the quotes were kept, so the path
ended in"rather than.owl, the file was judged not an ontology, and nothing was said.
Non-ASCII paths are octal-escaped per BYTE, so they are now gathered and decoded as the UTF-8
they are rather than one escape at a time. -
DURING A REBASE THE TWO SIDES WERE NAMED BACKWARDS. In a merge, stage 2 is this branch; in a
rebase, cherry-pick or revert it is what is already on the new base and stage 3 is the change
being replayed. MEASURED: duringgit rebasethe status still prints UU and says nothing.
Telling a curator their own edit is "the other branch" invites them to discard their own work.
MERGE_HEAD is asked for once per report, and the sides are named neutrally when it is absent. -
"NOTHING DISAGREES" WAS SAID ABOUT A FILE GIT HAD JUST REFUSED. MEASURED on a real conflict
where both sides edited only the ontology's own rdfs:label: "Both sides changed 0 and 0 terms,
and nothing they both touched disagrees" - while the commit was being refused, which invites
the reader to conclude the refusal is a bug. The report now says plainly that it compares
terms and not ontology-level annotations, comments or synonyms. -
AN EMPTIED VERSION WAS CALLED UNREADABLE. git exits 0 with no output for an empty blob, which
was read as a parse failure rather than as the empty ontology it is. -
LinkageError escaped the soft-failure guarantee, which is the throwable this codebase
documents as the realistic one when a class the host was expected to provide is absent.
WHAT THE REVIEW DID NOT COVER: the workflow verified at most four findings per dimension, so
three of the sixteen were never put to a refuter. Of the rest, four were judged hous...
OntoBoard 1.125.0 (2026-10-24)
OntoBoard 1.125.0 - host smoke receipt
Produced by tools/smoke.ps1 -SelfTest.
2026-10-24 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx500M PASS check 9/9 test 11/11
2026-10-24 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx500M PASS check 9/9 test 11/11
FOUR THINGS THE COLLABORATION LAYER SAID IT DID AND DID NOT
docs/conflicts.md was written for 1.123.0 by reading the code rather than the comments, and it
found that the one mitigation this plugin offers against two people editing the same term had
never worked. Three of the four items below are from that list; the fourth came out of fixing
the first.
-
THE EDITING CLAIM HAD NEVER FIRED, IN ANY RELEASE. CollabSession.editedTerm took the
operation's id and required an http(s) prefix - but OntologyOperation.local mints a
UUID.randomUUID(), so the test failed every single time and noteEdited was called with null on
every publish. The advisory badge a peer shows for "somebody is editing this" has never
appeared. It had NO TEST, which is how it stayed dead through sixteen releases of the collab
package.THE OBVIOUS FIX WOULD HAVE BEEN WRONG. data["iri"] holds the subject for a class, an
individual and an annotation - and the PROPERTY for a property edge, and the literal
"rdf:type" for a class assertion. Reading it blind claims the wrong term on two of the five
shapes, and a claim on the wrong term is worse than no claim: it tells a colleague that nobody
is editing the class they are about to edit. So Outbound carries a subjectIri that each
mapping sets for itself, and an edge sets none - it names a relation rather than a term. -
A CONFLICTED PULL REQUEST NOW SAYS SO. gh was never asked for
mergeable, so the first
anybody heard of a conflict was the red box on the pull request page. For an .owl that is the
wrong place to deal with it: a file full of conflict markers does not parse, so GitHub's web
editor cannot resolve one. The listing marks it and says where to resolve it instead. -
A VIEWER TOKEN IS READ-ONLY. role was parsed in bridge.mjs and discarded - the file's own
comment said so - so anyone who could connect could write and a read-only reviewer could not
be expressed at all. The bridge refuses a write from a viewer, TELLS THE SENDER WHY rather
than letting the change vanish, and still delivers everything others write. mint-token.mjs's
help no longer says the role is unenforced. -
A CHANGE THAT CANNOT BE APPLIED IS REPORTED. It was an INFO line and nothing else, so a
colleague's edit that this plugin could not read left the two copies out of step with nobody
aware of it: the sender saw their change published, the receiver saw nothing, and a log file
is not somewhere a curator looks. The receiver is told now, with a running count.THE SENDER IS STILL NOT TOLD. That needs a NACK, and the protocol has no message for one -
bridge.mjs's envelope list is hello, welcome, op, presence, peers, error. Half of the item is
delivered and the receipt says which half.
TESTS
2,482 Java in a clean copy of the repository, 0 failures, 1 skipped. 74 JavaScript, 0 failures.
OperationMapperTest 4 new - a class, a subclass edit and an annotation each claim the right
term, and a property edge claims nothing
CollabSessionTest 3 new - an unapplicable change is reported, the count rises, an ordinary
change says nothing
PullRequestTest 3 new - a conflicting PR is recognised, output without the field is not
read as a conflict, and the command asks for it
bridge-interop 3 new - a viewer cannot write, is told why, and still receives
TWO TESTS I HAD TO CORRECT, both because the code was right:
- A label on a term that is neither a declared class nor a declared individual is unmappable,
so there is no operation to carry a subject. The test declares the class first. - An invented operation TYPE cannot be used to exercise the skipped path: OntologyOperation
refuses one at construction, deliberately. The realistic case is a real type with a field
missing, which is what a peer on a different version sends.
WHAT IS STILL NOT TRUE
- Resolution is still last-writer-wins by arrival. No version check, no vector clocks, no
three-way merge, no common ancestor anywhere in the live path. - The sender of a dropped operation is still not told.
- Nobody has seen the editing badge, the viewer refusal or the PR conflict marker in a running
Protege. They are measured through the session, the bridge and the parser. - AxiomDiff and ReleaseDiff still return rendered strings rather than applicable changes, so
nothing can resolve a conflict even when it can describe one. docs/conflicts.md items 5-7. - Everything 1.124.0 listed as outstanding still is: no Zenodo DOI, no w3id PURL, not in
Protege's plugin registry, the paper audited and not rewritten, .xlsx read-only, 39 thin
patterns, no contact address or ORCID in CITATION.cff.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
OntoBoard 1.124.0 (2026-10-24)
OntoBoard 1.124.0 - host smoke receipt
Produced by tools/smoke.ps1 -SelfTest.
2026-10-24 Protege 5.6.9 OWL API 4.5.29 JRE Temurin 11.0.25 -Xmx500M PASS check 9/9 test 11/11
2026-10-24 Protege 5.5.0 OWL API 4.5.9 JRE 1.8.0_121 -Xmx500M PASS check 9/9 test 11/11
EVERYTHING THE ONTOLOGY SAYS IS NOW ON THE BOARD
Six axiom types reached 1.123.1 as hover text, which on a diagram means invisible: a class could
be constrained six ways and look unconstrained. Measured on MWO 3.0.1, every one of them now
draws.
DisjointClasses 15 axioms -> 29 lines dashed red, no arrowheads, one per pair
InverseObjectProperties 38 -> 38 lines dashed, arrowheads both ends
Property characteristics 25 -> a label suffix
SubPropertyChainOf 3 -> a chain node with numbered links
ObjectPropertyAssertion 5 -> an arrow between two individuals
HasKey 0 here, 1 on DUL -> an arrow labelled "key"
MWO 3.0.1 whole board 524 nodes / 489 edges at 1.122.1
553 / 652 at 1.123.0 (class expressions)
556 / 730 now
DUL (patterns/eep) 196 / 374 -> 207 / 475
WHY EACH IS THE SHAPE IT IS
- DISJOINTNESS HAS NO DIRECTION, so no arrowhead at either end; an arrow would have a reader
looking for one. Pairwise rather than through a hub, because an n-ary DisjointClasses means
every pair is disjoint and a hub node would be a term the ontology does not contain. One line
per pair in a fixed order, so an axiom stated from both sides does not draw two lines on top
of each other. - A CHARACTERISTIC IS A FACT ABOUT ONE PROPERTY. Transitive has no second term for an arrow to
reach, so an edge would misstate the arity. It rides on the property's label, where it is
visible at a glance and costs no edges. - A CHAIN HAS THREE TERMS AND AN ORDER, so no two-ended shape fits. It reuses the node that
already stands for "something the ontology says that is not a term" - the one anonymous class
expressions get - with the links numbered so the order survives. - EVERY ONE OBEYS THE OPT-IN RULE: both ends must already be on the board. That is what stops
disjointness from filling a taxonomy with red lines, and it is why the 38 inverse pairs appear
only on a board where somebody has put the properties themselves.
AND ONE THING DELIBERATELY NOT DRAWN. SWRL rules - 4 on MWO. A rule is a horn clause over
variables; any node-and-edge shape for it would be an invented notation, and a picture that
misleads is worse than a gap that is written down. Protege's own rule tab shows them.
TERMS NO LONGER LAND ON TOP OF EACH OTHER
Reported: overlapping nodes. The cause was not the arrange algorithms - it was that
SchemaGraph.render placed every unpositioned node by a counter stepping right from (40,40) that
never looked at the stored positions. On a board anybody had arranged, the first saved node is
usually near the origin, so a newly added term went exactly on top of it. Worse, it is not a
once-per-term problem: every derived node the projection mints - a datatype, a class expression,
a property chain - arrives unpositioned on EVERY render.
CanvasPlacement.freeSlot searches a lattice for the first slot that touches nothing already
placed, claims it before the next node is asked for, and wraps after ten columns so thirty new
terms form a block instead of a line four thousand pixels long. Deterministic: the same board
gives the same arrangement every time, which matters because a render follows every edit
anywhere in Protege and a board that reshuffled itself would be unusable.
Six tests, including the one that matters - twenty-five nodes placed in sequence, every pair
checked for overlap.
TESTS
2,472 in a clean copy of the repository, 0 failures, 1 skipped.
RemainingAxiomsTest 9 new - one per relation, each also asserting the opt-in rule
CanvasPlacementTest 6 new - including determinism and the no-overlap sweep
CanvasLegendTest 14 - the completeness guard forced both new edge kinds to be
documented in this commit; it has no catch-all, which is the point
DotExportTest 11 - one DOT style per edge kind
WHAT IS STILL NOT TRUE
- Nobody has seen the new relations in a running Protege. They are measured through the
projection and the host smoke reaches only "SchemaCanvasView built without throwing". - A board with every term of MWO on it now carries 730 edges. That is readable at a fitted
zoom and dense at 100%; no edge bundling or filtering has been attempted. - An expression or chain node still has no saved position, so it is laid out afresh on every
render - now into free space rather than onto another node, but not in the same place twice
if the board around it changed. - Collaboration still has no concurrency control, and the advisory editing claim still never
fires - docs/conflicts.md has the ranked list. - Everything 1.123.1 listed as outstanding still is: no Zenodo DOI, no w3id PURL, not in
Protege's plugin registry, the paper audited and not rewritten, .xlsx read-only, 39 thin
patterns, no contact address or ORCID in CITATION.cff.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com