ontolint 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ontolint-0.1.0/LICENSE +202 -0
- ontolint-0.1.0/PKG-INFO +456 -0
- ontolint-0.1.0/README.md +429 -0
- ontolint-0.1.0/pyproject.toml +178 -0
- ontolint-0.1.0/pyproject.toml.orig +175 -0
- ontolint-0.1.0/src/ontolint/__init__.py +7 -0
- ontolint-0.1.0/src/ontolint/__main__.py +8 -0
- ontolint-0.1.0/src/ontolint/_version.py +15 -0
- ontolint-0.1.0/src/ontolint/adapters/__init__.py +1 -0
- ontolint-0.1.0/src/ontolint/adapters/robot.py +72 -0
- ontolint-0.1.0/src/ontolint/adapters/shacl.py +147 -0
- ontolint-0.1.0/src/ontolint/catalogue.py +77 -0
- ontolint-0.1.0/src/ontolint/cli.py +302 -0
- ontolint-0.1.0/src/ontolint/context.py +127 -0
- ontolint-0.1.0/src/ontolint/data/rule_catalogue.csv +308 -0
- ontolint-0.1.0/src/ontolint/engine.py +157 -0
- ontolint-0.1.0/src/ontolint/github.py +27 -0
- ontolint-0.1.0/src/ontolint/graph/__init__.py +5 -0
- ontolint-0.1.0/src/ontolint/graph/algorithms.py +198 -0
- ontolint-0.1.0/src/ontolint/linter.py +96 -0
- ontolint-0.1.0/src/ontolint/loader.py +385 -0
- ontolint-0.1.0/src/ontolint/models.py +115 -0
- ontolint-0.1.0/src/ontolint/ontolint.py +34 -0
- ontolint-0.1.0/src/ontolint/ownership.py +159 -0
- ontolint-0.1.0/src/ontolint/paths.py +89 -0
- ontolint-0.1.0/src/ontolint/policy.py +202 -0
- ontolint-0.1.0/src/ontolint/profiles.py +68 -0
- ontolint-0.1.0/src/ontolint/py.typed +1 -0
- ontolint-0.1.0/src/ontolint/reporting.py +306 -0
- ontolint-0.1.0/src/ontolint/rule_info.py +139 -0
- ontolint-0.1.0/src/ontolint/rules/__init__.py +5 -0
- ontolint-0.1.0/src/ontolint/rules/alignment.py +428 -0
- ontolint-0.1.0/src/ontolint/rules/builtin.py +156 -0
- ontolint-0.1.0/src/ontolint/rules/class_heuristics.py +195 -0
- ontolint-0.1.0/src/ontolint/rules/classes.py +297 -0
- ontolint-0.1.0/src/ontolint/rules/external.py +58 -0
- ontolint-0.1.0/src/ontolint/rules/governance.py +137 -0
- ontolint-0.1.0/src/ontolint/rules/governance_metadata.py +300 -0
- ontolint-0.1.0/src/ontolint/rules/hierarchy_quality.py +370 -0
- ontolint-0.1.0/src/ontolint/rules/identifiers.py +89 -0
- ontolint-0.1.0/src/ontolint/rules/iri_lexical_extras.py +157 -0
- ontolint-0.1.0/src/ontolint/rules/iri_quality.py +193 -0
- ontolint-0.1.0/src/ontolint/rules/lexical.py +279 -0
- ontolint-0.1.0/src/ontolint/rules/lexical_quality.py +291 -0
- ontolint-0.1.0/src/ontolint/rules/metadata.py +111 -0
- ontolint-0.1.0/src/ontolint/rules/metrics.py +396 -0
- ontolint-0.1.0/src/ontolint/rules/obo.py +423 -0
- ontolint-0.1.0/src/ontolint/rules/owl.py +415 -0
- ontolint-0.1.0/src/ontolint/rules/owl_axioms.py +478 -0
- ontolint-0.1.0/src/ontolint/rules/owl_expressions.py +491 -0
- ontolint-0.1.0/src/ontolint/rules/registry.py +69 -0
- ontolint-0.1.0/src/ontolint/rules/runtime.py +95 -0
- ontolint-0.1.0/src/ontolint/rules/safe_loader.py +56 -0
- ontolint-0.1.0/src/ontolint/rules/safety.py +253 -0
- ontolint-0.1.0/src/ontolint/rules/shacl_authoring.py +393 -0
- ontolint-0.1.0/src/ontolint/rules/shacl_quality.py +273 -0
- ontolint-0.1.0/src/ontolint/rules/shapes.py +151 -0
- ontolint-0.1.0/src/ontolint/rules/skos.py +158 -0
- ontolint-0.1.0/src/ontolint/rules/skos_integrity.py +388 -0
- ontolint-0.1.0/src/ontolint/rules/specs.py +17 -0
- ontolint-0.1.0/src/ontolint/rules/support.py +136 -0
- ontolint-0.1.0/src/ontolint/selection.py +94 -0
ontolint-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
ontolint-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ontolint
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Offline ontology-quality linter for RDF, OWL, SKOS, and SHACL graphs
|
|
5
|
+
Keywords: linter,ontology,owl,rdf,shacl,skos
|
|
6
|
+
Author: Arnaud Gelas
|
|
7
|
+
Author-email: Arnaud Gelas <arnaudgelas+ontolint@gmail.com>
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
17
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: pyshacl>=0.40.2
|
|
20
|
+
Requires-Dist: rdflib>=7.6.0
|
|
21
|
+
Requires-Python: >=3.13
|
|
22
|
+
Project-URL: Homepage, https://github.com/arnaudgelas/ontolint
|
|
23
|
+
Project-URL: Source, https://github.com/arnaudgelas/ontolint
|
|
24
|
+
Project-URL: Issues, https://github.com/arnaudgelas/ontolint/issues
|
|
25
|
+
Project-URL: Documentation, https://github.com/arnaudgelas/ontolint/blob/main/docs/rules.md
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img src="https://raw.githubusercontent.com/arnaudgelas/ontolint/main/logo.png" alt="ontolint logo" width="240">
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
# ontolint
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<a href="https://github.com/arnaudgelas/ontolint/actions/workflows/ci.yml"><img alt="CI status" src="https://github.com/arnaudgelas/ontolint/actions/workflows/ci.yml/badge.svg?branch=main"></a>
|
|
36
|
+
<a href="https://github.com/arnaudgelas/ontolint/actions/workflows/validation.yml"><img alt="Validation status (ROBOT image and mutation testing)" src="https://github.com/arnaudgelas/ontolint/actions/workflows/validation.yml/badge.svg?branch=main"></a>
|
|
37
|
+
<a href="https://github.com/arnaudgelas/ontolint/commits/main"><img alt="Last commit" src="https://img.shields.io/github/last-commit/arnaudgelas/ontolint"></a>
|
|
38
|
+
<a href="https://github.com/arnaudgelas/ontolint/issues"><img alt="Open issues" src="https://img.shields.io/github/issues/arnaudgelas/ontolint"></a>
|
|
39
|
+
</p>
|
|
40
|
+
<p align="center">
|
|
41
|
+
<a href="https://www.python.org/"><img alt="Python 3.13+" src="https://img.shields.io/badge/python-3.13%2B-3776AB?logo=python&logoColor=white"></a>
|
|
42
|
+
<a href="https://github.com/arnaudgelas/ontolint/blob/main/LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/license-Apache--2.0-blue"></a>
|
|
43
|
+
<a href="https://github.com/arnaudgelas/ontolint/blob/main/docs/rules.md"><img alt="Rules implemented: 228 of 307" src="https://img.shields.io/badge/rules-228%2F307_implemented-brightgreen"></a>
|
|
44
|
+
<img alt="Offline first" src="https://img.shields.io/badge/mode-offline--first-informational">
|
|
45
|
+
<img alt="Formats: RDF, OWL, SKOS, SHACL" src="https://img.shields.io/badge/formats-RDF%20%C2%B7%20OWL%20%C2%B7%20SKOS%20%C2%B7%20SHACL-6f42c1">
|
|
46
|
+
</p>
|
|
47
|
+
<p align="center">
|
|
48
|
+
<a href="https://docs.astral.sh/ruff/"><img alt="Code style and lint: Ruff" src="https://img.shields.io/badge/lint%20%26%20format-ruff-D7FF64?logo=ruff&logoColor=black"></a>
|
|
49
|
+
<img alt="Types: pyright strict and mypy" src="https://img.shields.io/badge/types-pyright%20strict%20%2B%20mypy-2a6db2">
|
|
50
|
+
<img alt="Coverage gate: at least 95 percent" src="https://img.shields.io/badge/coverage%20gate-%E2%89%A595%25-brightgreen">
|
|
51
|
+
<a href="https://github.com/arnaudgelas/ontolint/blob/main/docs/mutation-policy.md"><img alt="Mutation gate: at least 85 percent" src="https://img.shields.io/badge/mutation%20gate-%E2%89%A585%25-brightgreen"></a>
|
|
52
|
+
<a href="https://docs.astral.sh/uv/"><img alt="Managed with uv" src="https://img.shields.io/badge/managed%20with-uv-DE5FE9"></a>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
`ontolint` is an offline ontology-quality linter for RDF graphs. It provides
|
|
56
|
+
graph-local checks for RDF/OWL, SKOS, lexical quality, class hierarchies, and
|
|
57
|
+
optional SHACL validation. It is a practical review aid—not a substitute for
|
|
58
|
+
OWL 2 DL validation, a reasoner, or expert ontology review.
|
|
59
|
+
|
|
60
|
+
## What it checks
|
|
61
|
+
|
|
62
|
+
228 of the 307 catalogue rules are implemented; the rest are planned. The
|
|
63
|
+
[rule reference](https://github.com/arnaudgelas/ontolint/blob/main/docs/rules.md) documents each one with an example.
|
|
64
|
+
|
|
65
|
+
- 217 Python graph checks for metadata, identifiers, IRIs, labels and lexical
|
|
66
|
+
quality, class hierarchies, OWL axioms and class expressions, SKOS, SHACL
|
|
67
|
+
shape quality, governance, ontology metrics, mapping quality, input-safety
|
|
68
|
+
hygiene and, opt-in, OBO Foundry conventions.
|
|
69
|
+
- `INPUT001` for RDF parsing failures.
|
|
70
|
+
- `SHACL001` for optional pySHACL validation results.
|
|
71
|
+
- `TOOL001` for configuration and execution failures.
|
|
72
|
+
- `SEM001` for opt-in ROBOT OWL-profile validation failures.
|
|
73
|
+
- `SEC001`, `SEC002`, `SEC006`, `SEC009`, `SEC010`, `SEC011` and `SEC013` for
|
|
74
|
+
unsafe inputs, rejected by the loader before linting (see below).
|
|
75
|
+
|
|
76
|
+
Each finding includes a rule identifier, severity, focus, message, suggested
|
|
77
|
+
remediation, and confidence level. Rules are policy-oriented: a finding is not
|
|
78
|
+
automatically a logical inconsistency.
|
|
79
|
+
|
|
80
|
+
## Requirements and installation
|
|
81
|
+
|
|
82
|
+
Python 3.13 or later is required. ontolint installs a command named `ontolint`.
|
|
83
|
+
|
|
84
|
+
Install it as a standalone tool, isolated from your other Python packages:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# uv (recommended)
|
|
88
|
+
uv tool install git+https://github.com/arnaudgelas/ontolint
|
|
89
|
+
|
|
90
|
+
# or pipx
|
|
91
|
+
pipx install git+https://github.com/arnaudgelas/ontolint
|
|
92
|
+
|
|
93
|
+
# or into the current environment
|
|
94
|
+
python -m pip install git+https://github.com/arnaudgelas/ontolint
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Run it once without installing it:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
uvx --from git+https://github.com/arnaudgelas/ontolint ontolint ontology.ttl
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
From a clone of the repository, `uv tool install .` installs the checkout and
|
|
104
|
+
`uv tool install --editable .` keeps it linked to your working copy. Check the
|
|
105
|
+
installation with:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
ontolint --version
|
|
109
|
+
ontolint --help
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`python -m ontolint` works as well. Docker is needed only for `--owl-profile`.
|
|
113
|
+
|
|
114
|
+
### Development setup
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
uv sync --group dev
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
In a development checkout run the command through uv, for example
|
|
121
|
+
`uv run ontolint ontology.ttl`. For a standard `pip` environment, install the
|
|
122
|
+
package and its test tools:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
python -m pip install -e .
|
|
126
|
+
python -m pip install pytest hypothesis pytest-gremlins pytest-xdist
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Run the linter
|
|
130
|
+
|
|
131
|
+
Use the library directly when integrating ontolint into Python applications:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from rdflib import Graph
|
|
135
|
+
from ontolint import Linter
|
|
136
|
+
|
|
137
|
+
graph = Graph().parse("ontology.ttl")
|
|
138
|
+
findings = Linter(graph, base="https://example.org/ont#").run()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The command-line interface is a thin wrapper around the same Python library
|
|
142
|
+
(in a development checkout, prefix the commands with `uv run`):
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Text report
|
|
146
|
+
ontolint ontology.ttl \
|
|
147
|
+
--base 'https://example.org/ont#'
|
|
148
|
+
|
|
149
|
+
# JSON report written to a file
|
|
150
|
+
ontolint ontology.ttl \
|
|
151
|
+
--base 'https://example.org/ont#' \
|
|
152
|
+
--format json --output report.json
|
|
153
|
+
|
|
154
|
+
# Fail a CI job for warning- or error-level findings
|
|
155
|
+
ontolint ontology.ttl --fail-on warning
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Supported report formats are `text`, `json`, and `sarif`.
|
|
159
|
+
|
|
160
|
+
| Exit code | Meaning |
|
|
161
|
+
| --- | --- |
|
|
162
|
+
| `0` | No finding meets the configured `--fail-on` threshold. |
|
|
163
|
+
| `1` | At least one finding meets the threshold. |
|
|
164
|
+
| `2` | Tool failure: unreadable input or configuration, an unknown rule selector, a usage error, or a requested rule that `failed` or is `unsupported` (for example `--owl-profile` without Docker). |
|
|
165
|
+
|
|
166
|
+
Exit `2` outranks `1`: when a requested backend did not deliver a verdict the run cannot
|
|
167
|
+
pass, even with `--fail-on never`. The report is still written so you can see why. Rules that
|
|
168
|
+
are `skipped` (no shapes supplied, no OWL profile requested, ignored) never change the exit code.
|
|
169
|
+
|
|
170
|
+
### Discovering rules
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
ontolint --version
|
|
174
|
+
ontolint --list-rules # table
|
|
175
|
+
ontolint --list-rules --format json # machine-readable
|
|
176
|
+
ontolint --explain SHQ001 # title, severity, fix, backend, scope, requirements
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`--list-rules` shows the catalogue *status* of every rule: `implemented` (can be selected and
|
|
180
|
+
run) or `proposed` (planned only; it has no severity or scope, cannot be selected and never
|
|
181
|
+
runs). This is different from the per-run *execution status* below. `--explain` on an unknown
|
|
182
|
+
identifier exits `2`.
|
|
183
|
+
|
|
184
|
+
### Selecting rules and profiles
|
|
185
|
+
|
|
186
|
+
`--select` and `--ignore` take rule identifiers (`ONT001`) or family prefixes (`ONT`),
|
|
187
|
+
case-insensitively, comma-separated and/or repeated. Unknown selectors, empty entries
|
|
188
|
+
(`ONT,`) and proposed-only rules are errors (exit `2`), so a typo never becomes an empty run.
|
|
189
|
+
|
|
190
|
+
`--profile` picks a bundle of defaults:
|
|
191
|
+
|
|
192
|
+
| Profile | Rules | Severity overrides | Default `--fail-on` |
|
|
193
|
+
| --- | --- | --- | --- |
|
|
194
|
+
| `minimal` | `ONT`, `IRI`, `DATA`, `SKOS`, `SHACL`, `SEM` (structural integrity) | none | `error` |
|
|
195
|
+
| `recommended` | all (same as no profile) | none | `error` |
|
|
196
|
+
| `ci` | all | none | `warning` |
|
|
197
|
+
| `strict` | all | `ONT003` becomes `error` | `info` (any finding fails) |
|
|
198
|
+
| `obo` | all, plus the opt-in `OBO` family | none | `warning` |
|
|
199
|
+
|
|
200
|
+
**Opt-in rule families.** The `OBO` family encodes OBO Foundry conventions, so it
|
|
201
|
+
never runs by default: it is excluded from running without a profile and from
|
|
202
|
+
`recommended`, `ci`, `strict` and `minimal`. Enable it with `--profile obo`,
|
|
203
|
+
`--select OBO` or `--select OBO003`. `--list-rules` and `--explain` mark these
|
|
204
|
+
rules as opt-in. An explicit `--select` replaces a profile's selection, so
|
|
205
|
+
`--profile obo --select LEX` runs only `LEX`.
|
|
206
|
+
|
|
207
|
+
Precedence when options combine:
|
|
208
|
+
|
|
209
|
+
1. The rule set is `--select` if given, else the profile's rules, else all rules. `--select`
|
|
210
|
+
*replaces* the profile's selection.
|
|
211
|
+
2. Ignores always win over selection: `--ignore`, the profile's ignores and the policy file's
|
|
212
|
+
`ignored_rules` are unioned and removed. Policy `ignored_rules` remain exact identifiers.
|
|
213
|
+
3. Severity overrides: profile first, then the policy file's `severity_overrides` (policy wins).
|
|
214
|
+
4. `--fail-on`: the command line, else the profile's value, else `error`.
|
|
215
|
+
|
|
216
|
+
Other policy values (base, languages, thresholds) behave as before: explicit CLI options beat
|
|
217
|
+
the policy file.
|
|
218
|
+
|
|
219
|
+
### Rule execution status
|
|
220
|
+
|
|
221
|
+
JSON and SARIF always say what happened to every selected rule, so "no findings" can never be
|
|
222
|
+
confused with "not checked": `executed`, `skipped` (not applicable or ignored, with the
|
|
223
|
+
reason), `unsupported` (backend unavailable, e.g. no `pyshacl` or Docker) or `failed`
|
|
224
|
+
(the rule or backend raised). Rules that were deselected by `--select`/profile are simply
|
|
225
|
+
absent. Text output stays unchanged unless a rule was ignored, unsupported or failed, in which
|
|
226
|
+
case a `Rule execution:` block is appended.
|
|
227
|
+
|
|
228
|
+
* JSON keeps `summary` and `findings` and adds `schema_version` (currently `1`), a `path` on
|
|
229
|
+
each finding, `rules` (id, family, title, effective and default severity, category, backend,
|
|
230
|
+
scope, requirements, suggestion), `execution_summary` and per-file `files[].executions`.
|
|
231
|
+
* SARIF 2.1.0 adds `tool.driver.rules` (name, short/full description, help,
|
|
232
|
+
`defaultConfiguration.level`, category/backend/scope properties), `ruleIndex` and an
|
|
233
|
+
`artifactLocation` on every result, and a run `invocation`. Skipped, unsupported and failed
|
|
234
|
+
rules are `toolExecutionNotifications` (levels `note`, `warning`, `error`);
|
|
235
|
+
`executionSuccessful` is `false` when any rule failed or is unsupported.
|
|
236
|
+
* Findings carry no line/column yet. The report model has an optional location slot that SARIF
|
|
237
|
+
will turn into a `region` once rules can supply real positions.
|
|
238
|
+
|
|
239
|
+
### Several files
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
ontolint ontologies/*.ttl --format sarif --output findings.sarif
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
* Globbing is the shell's job (on Windows `cmd`/PowerShell pass the pattern through; use a
|
|
246
|
+
shell that expands it or list the files). Directories are rejected with an error rather than
|
|
247
|
+
walked.
|
|
248
|
+
* Each file is linted independently with the same options and its own report; results are
|
|
249
|
+
aggregated. Files are ordered by report path regardless of argument order, and duplicates
|
|
250
|
+
(`./a.ttl`, a symlink, another spelling on a case-insensitive file system) collapse into one.
|
|
251
|
+
If any file cannot be parsed, every parse failure is reported and the run exits `2` before
|
|
252
|
+
linting. `--shapes` and `--owl-profile` apply to every file; ROBOT runs once per file.
|
|
253
|
+
* Report paths (JSON `path`, SARIF `artifactLocation.uri`, fingerprints) are POSIX-style:
|
|
254
|
+
relative to the working directory when the file is beneath it (`onto/a.ttl`), otherwise
|
|
255
|
+
absolute (`file:///C:/x/a.ttl` in SARIF), with backslashes converted. Run from a stable
|
|
256
|
+
directory such as the repository root so baselines and SARIF paths are portable.
|
|
257
|
+
* Fingerprints: a single-file run hashes `(rule, focus, message)` exactly as before, so existing
|
|
258
|
+
baselines keep working. A multi-file run also hashes the report path so identical findings in
|
|
259
|
+
two files stay distinct; a baseline written from one file therefore does not carry over to a
|
|
260
|
+
multi-file run. Write multi-file baselines from multi-file runs.
|
|
261
|
+
|
|
262
|
+
### GitHub annotations
|
|
263
|
+
|
|
264
|
+
`--format github` is not available yet. Workflow-command annotations need a file *and a line*,
|
|
265
|
+
and findings carry no source locations. The escaping helpers (`%`, CR, LF and, for properties,
|
|
266
|
+
`:` and `,`) already exist in `ontolint.github`; the formatter is gated on location support.
|
|
267
|
+
|
|
268
|
+
### Optional SHACL validation
|
|
269
|
+
|
|
270
|
+
Pass a shapes graph with `--shapes` to enable pySHACL validation:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
ontolint ontology.ttl --shapes shapes.ttl
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The integration uses `meta_shacl=True` and `advanced=True`. Newer SHACL draft
|
|
277
|
+
features are not guaranteed to be supported.
|
|
278
|
+
|
|
279
|
+
### OWL profile validation with ROBOT in Docker
|
|
280
|
+
|
|
281
|
+
Build the minimal project image once. Its final stage contains only the ROBOT
|
|
282
|
+
JAR and a non-root Java runtime:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
docker build --tag ontolint-robot:1.9.11 docker/robot
|
|
286
|
+
ontolint ontology.ttl --owl-profile DL
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The profile run mounts the ontology directory read-only, disables container
|
|
290
|
+
networking, drops Linux capabilities, and applies CPU, memory, process, and
|
|
291
|
+
timeout limits. The image build verifies the ROBOT JAR against a pinned
|
|
292
|
+
SHA-256. Supply a digest-pinned image with `--robot-image` in CI.
|
|
293
|
+
|
|
294
|
+
## Policy and baselines
|
|
295
|
+
|
|
296
|
+
A JSON policy can supply a base IRI, label-language requirements, thresholds,
|
|
297
|
+
ignored rules, and severity overrides.
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
{
|
|
301
|
+
"base": "https://example.org/ont#",
|
|
302
|
+
"languages": ["en"],
|
|
303
|
+
"depth_limit": 10,
|
|
304
|
+
"inheritance_limit": 5,
|
|
305
|
+
"soup_limit": 15,
|
|
306
|
+
"ignored_rules": ["CLS002"],
|
|
307
|
+
"severity_overrides": {"ONT003": "error", "OWL005": "info"}
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Emit SARIF using a policy
|
|
313
|
+
ontolint ontology.ttl \
|
|
314
|
+
--config policy.json --format sarif --output findings.sarif
|
|
315
|
+
|
|
316
|
+
# Record accepted findings, then report only newly introduced ones
|
|
317
|
+
ontolint ontology.ttl --write-baseline baseline.json
|
|
318
|
+
ontolint ontology.ttl \
|
|
319
|
+
--baseline baseline.json --fail-on warning
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Baselines compare stable hashes of `(rule, focus, message)` (plus the report path for multi-file runs). They are useful for
|
|
323
|
+
incremental adoption, but are not semantic version comparisons.
|
|
324
|
+
|
|
325
|
+
## Development and quality checks
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
# Unit and property-based tests
|
|
329
|
+
uv run pytest -q
|
|
330
|
+
|
|
331
|
+
# Run tests in parallel
|
|
332
|
+
uv run pytest -q -n auto
|
|
333
|
+
|
|
334
|
+
# Mutation testing (opt-in)
|
|
335
|
+
uv run pytest -m 'not slow' --gremlins --no-cov --gremlin-parallel --gremlin-cache
|
|
336
|
+
|
|
337
|
+
# Lint the project
|
|
338
|
+
uv run ruff check .
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Hypothesis tests generate RDF class hierarchies and verify that the linter's
|
|
342
|
+
cycle diagnostics agree with an independent reachability oracle. Mutation
|
|
343
|
+
testing is configured to target `src/ontolint/ontolint.py`.
|
|
344
|
+
|
|
345
|
+
### CI workflows
|
|
346
|
+
|
|
347
|
+
`.github/workflows/ci.yml` runs the fast PR checks (Ruff, mypy, pyright,
|
|
348
|
+
`pip-audit`, tests with coverage, package build). All actions are pinned to
|
|
349
|
+
commit SHAs and the uv version is pinned; Renovate keeps both current.
|
|
350
|
+
|
|
351
|
+
`.github/workflows/validation.yml` runs weekly and on manual dispatch:
|
|
352
|
+
|
|
353
|
+
- ROBOT Docker image build and smoke test (also on pull requests that touch
|
|
354
|
+
`docker/` and carry the `validation` label). Logs are uploaded as artifacts.
|
|
355
|
+
- Mutation testing with the command above plus JSON/HTML reports, followed by
|
|
356
|
+
`.github/scripts/mutation_gate.py`, which enforces the per-operator and
|
|
357
|
+
overall thresholds. Reports are uploaded as artifacts.
|
|
358
|
+
|
|
359
|
+
The operators, thresholds, scope, waiver process and blocking/advisory rules
|
|
360
|
+
are defined in [docs/mutation-policy.md](https://github.com/arnaudgelas/ontolint/blob/main/docs/mutation-policy.md).
|
|
361
|
+
|
|
362
|
+
## Rule reference
|
|
363
|
+
|
|
364
|
+
[docs/rules.md](https://github.com/arnaudgelas/ontolint/blob/main/docs/rules.md) documents every rule with its severity, fix, a flagged
|
|
365
|
+
example, a clean example and the reported message. Rules that are not
|
|
366
|
+
implemented yet are listed as TODO. The file is generated; regenerate it with
|
|
367
|
+
`uv run python tests/rule_docs_generator.py`.
|
|
368
|
+
|
|
369
|
+
## Interpretation principles
|
|
370
|
+
|
|
371
|
+
1. RDF syntax validity and OWL logical consistency are different properties.
|
|
372
|
+
2. SHACL validation does not establish ontology-design quality.
|
|
373
|
+
3. Multiple RDFS domains or ranges are conjunctive, not alternative choices.
|
|
374
|
+
4. Under OWL's open-world assumption, missing evidence is not falsehood.
|
|
375
|
+
5. A subclass cycle is a review warning, not automatically an inconsistency.
|
|
376
|
+
6. `owl:allValuesFrom` does not imply the existence of a value.
|
|
377
|
+
7. A SKOS `broader` cycle is informational; it is not universally prohibited.
|
|
378
|
+
8. The linter does not fetch URLs or resolve `owl:imports` automatically.
|
|
379
|
+
9. Semantic OWL axioms are never auto-fixed because intent cannot be inferred
|
|
380
|
+
reliably.
|
|
381
|
+
|
|
382
|
+
## Scope and limitations
|
|
383
|
+
|
|
384
|
+
- Term-level rules only judge terms the file owns. With `--base` the base decides (a base such as
|
|
385
|
+
`http://purl.obolibrary.org/obo/RO_` is a plain prefix; a warning is printed when it selects no declared
|
|
386
|
+
term). Without it the owned namespaces are derived from the `owl:Ontology` IRI(s) (the IRI, the IRI
|
|
387
|
+
without `#`/`/`/`.owl`, and for OBO ontologies the `.../obo/<NAME>_` ID space); RDF/RDFS/OWL/XSD terms
|
|
388
|
+
are never owned, and if no declared term matches, every declared term is treated as owned.
|
|
389
|
+
- Definitions are read from `rdfs:comment`, `skos:definition`, `dcterms:description`, `dc:description`,
|
|
390
|
+
`obo:IAO_0000115`, `obo:IAO_0000600` and `prov:definition`; labels from `rdfs:label` and `skos:prefLabel`.
|
|
391
|
+
Add more with the policy lists `extra_definition_predicates` and `extra_label_predicates` (absolute IRIs).
|
|
392
|
+
- With `--shapes`, the SHACL step first checks the shapes graph and reports SHACL001 as failed with
|
|
393
|
+
`ShapesRejected` when pySHACL would crash or stall on it: an IRI that rdflib cannot serialise (such as
|
|
394
|
+
`{`, `}`, `|`, `^`, a space or a quote), a cyclic `rdf:list`, a list cell with several `rdf:rest` values,
|
|
395
|
+
a list shared by several lists, a list longer than 400 items, or lists whose squared lengths sum above
|
|
396
|
+
160000 (pySHACL's meta-validation re-walks each list for every internal result). The data graph is not
|
|
397
|
+
refused up front: odd IRIs, large enumerations and malformed lists are accepted, and if pySHACL fails on
|
|
398
|
+
one anyway the failure is reported as `ShapesRejected` with the underlying error.
|
|
399
|
+
- Class-hierarchy analysis uses asserted `rdfs:subClassOf` statements; it does
|
|
400
|
+
not calculate entailments or inspect an import closure.
|
|
401
|
+
- `CLS002` can be noisy for TBox-only ontologies and is often disabled in that
|
|
402
|
+
profile.
|
|
403
|
+
- Shape coverage (`SHQ006`) checks direct instances and direct class targets
|
|
404
|
+
only.
|
|
405
|
+
- Strongly connected components are calculated recursively, which can reach
|
|
406
|
+
Python's recursion limit on unusually large graphs.
|
|
407
|
+
- SARIF output does not yet include source line or column locations.
|
|
408
|
+
|
|
409
|
+
## Related tools and sources
|
|
410
|
+
|
|
411
|
+
- [RDFLib](https://rdflib.readthedocs.io/)
|
|
412
|
+
- [pySHACL](https://github.com/RDFLib/pySHACL)
|
|
413
|
+
- [W3C SHACL Recommendation](https://www.w3.org/TR/shacl/)
|
|
414
|
+
- [W3C SKOS Reference](https://www.w3.org/TR/skos-reference/)
|
|
415
|
+
- [OOPS! pitfall catalogue](https://oops.linkeddata.es/catalogue.jsp)
|
|
416
|
+
- [OntoSniff](https://ise-fizkarlsruhe.github.io/ontoink/ontosniff/)
|
|
417
|
+
- [ROBOT](https://robot.obolibrary.org/)
|
|
418
|
+
- [OBO Foundry principles](https://obofoundry.org/principles/fp-000-summary.html)
|
|
419
|
+
|
|
420
|
+
The `data/` directory contains crosswalks to the OOPS! and OntoSniff catalogues.
|
|
421
|
+
Those mappings are traceability aids, not claims of identical behavior.
|
|
422
|
+
|
|
423
|
+
## Input safety
|
|
424
|
+
|
|
425
|
+
Ontologies are untrusted input, so the loader is deliberately strict:
|
|
426
|
+
|
|
427
|
+
- Parsing runs with the network disabled. Any socket or DNS attempt is blocked
|
|
428
|
+
and reported (`SEC013`); a JSON-LD file with an external `@context` is
|
|
429
|
+
refused (`SEC006`). `owl:imports` is never fetched.
|
|
430
|
+
- Inputs larger than `--max-input-bytes` (default 64 MiB) or holding more than
|
|
431
|
+
`--max-triples` triples (default 5,000,000) are rejected (`SEC001`, `SEC002`).
|
|
432
|
+
Both can also be set in the `--config` policy file.
|
|
433
|
+
- RDF/XML with external entities or nested entity expansion is refused
|
|
434
|
+
(`SEC010`), compressed files are refused (`SEC011`), and relative paths that
|
|
435
|
+
escape the working directory or symlinks that leave it are refused (`SEC009`).
|
|
436
|
+
- Rejected inputs are reported as `SECxxx: ...` on stderr with exit code `2`,
|
|
437
|
+
like a parse failure. Post-parse hygiene checks (`SEC004`, `SEC005`,
|
|
438
|
+
`SEC008`, `SEC012`, `SEC014`) are ordinary findings.
|
|
439
|
+
|
|
440
|
+
## Roadmap
|
|
441
|
+
|
|
442
|
+
[`data/rule_catalogue.csv`](https://github.com/arnaudgelas/ontolint/blob/main/data/rule_catalogue.csv) is the machine-readable
|
|
443
|
+
catalogue. It records 307 entries: 228 executable diagnostics and 79 proposed
|
|
444
|
+
candidates. The additional entry beyond the original roadmap is `TOOL001`, an
|
|
445
|
+
operational diagnostic for the linter itself. The 18 `OPS` entries of the
|
|
446
|
+
original roadmap describe command-line and report features, not checks on an
|
|
447
|
+
ontology; they moved to [docs/cli-features.md](https://github.com/arnaudgelas/ontolint/blob/main/docs/cli-features.md).
|
|
448
|
+
|
|
449
|
+
The next major areas are comprehensive rule fixtures and false-positive cases,
|
|
450
|
+
OWLAPI/ROBOT and reasoner adapters, safe import-closure support, richer SHACL
|
|
451
|
+
authoring checks, ontology-diff regression testing, and opt-in publishing/FAIR
|
|
452
|
+
checks.
|
|
453
|
+
|
|
454
|
+
## License
|
|
455
|
+
|
|
456
|
+
Licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/arnaudgelas/ontolint/blob/main/LICENSE).
|