ontolith 1.0.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.
Files changed (226) hide show
  1. ontolith-1.0.0/.github/workflows/ci.yml +221 -0
  2. ontolith-1.0.0/.github/workflows/security.yml +86 -0
  3. ontolith-1.0.0/.gitignore +51 -0
  4. ontolith-1.0.0/.pre-commit-config.yaml +24 -0
  5. ontolith-1.0.0/CHANGELOG.md +1756 -0
  6. ontolith-1.0.0/CLAUDE.md +490 -0
  7. ontolith-1.0.0/CODE_OF_CONDUCT.md +26 -0
  8. ontolith-1.0.0/CONTRIBUTING.md +295 -0
  9. ontolith-1.0.0/LICENSE +201 -0
  10. ontolith-1.0.0/PKG-INFO +137 -0
  11. ontolith-1.0.0/README.md +60 -0
  12. ontolith-1.0.0/SECURITY.md +36 -0
  13. ontolith-1.0.0/conformance/__init__.py +0 -0
  14. ontolith-1.0.0/conformance/conftest.py +112 -0
  15. ontolith-1.0.0/conformance/test_accountable_owner.py +250 -0
  16. ontolith-1.0.0/conformance/test_admin_audit_trail.py +220 -0
  17. ontolith-1.0.0/conformance/test_append_only.py +142 -0
  18. ontolith-1.0.0/conformance/test_append_only_properties.py +189 -0
  19. ontolith-1.0.0/conformance/test_assertion_audit_log.py +228 -0
  20. ontolith-1.0.0/conformance/test_audit_table_immutability.py +486 -0
  21. ontolith-1.0.0/conformance/test_basic_assertion.py +108 -0
  22. ontolith-1.0.0/conformance/test_bitemporal.py +1089 -0
  23. ontolith-1.0.0/conformance/test_composite_policy.py +274 -0
  24. ontolith-1.0.0/conformance/test_confidence_threshold_policy.py +122 -0
  25. ontolith-1.0.0/conformance/test_confidence_trust_filters.py +988 -0
  26. ontolith-1.0.0/conformance/test_conflict.py +1825 -0
  27. ontolith-1.0.0/conformance/test_conflict_routing_properties.py +247 -0
  28. ontolith-1.0.0/conformance/test_contradiction_resolution.py +1775 -0
  29. ontolith-1.0.0/conformance/test_include_flagged_history.py +331 -0
  30. ontolith-1.0.0/conformance/test_plugin_contract.py +204 -0
  31. ontolith-1.0.0/conformance/test_policy_injection.py +126 -0
  32. ontolith-1.0.0/conformance/test_proposal_policy.py +159 -0
  33. ontolith-1.0.0/conformance/test_proposal_workflow.py +364 -0
  34. ontolith-1.0.0/conformance/test_require_review_by_role_policy.py +128 -0
  35. ontolith-1.0.0/conformance/test_require_review_for_ai_policy.py +188 -0
  36. ontolith-1.0.0/conformance/test_review_workflow.py +1487 -0
  37. ontolith-1.0.0/conformance/test_source_quorum_policy.py +347 -0
  38. ontolith-1.0.0/conformance/test_source_required_policy.py +114 -0
  39. ontolith-1.0.0/conformance/test_trust_delegation.py +465 -0
  40. ontolith-1.0.0/conformance/test_trust_delegation_properties.py +97 -0
  41. ontolith-1.0.0/conformance/test_vector_search.py +93 -0
  42. ontolith-1.0.0/conformance/test_where_lookup_operators.py +202 -0
  43. ontolith-1.0.0/conftest.py +19 -0
  44. ontolith-1.0.0/docs/Ontolith_Implementation_Plan.md +376 -0
  45. ontolith-1.0.0/docs/Ontolith_PRD.md +391 -0
  46. ontolith-1.0.0/docs/Ontolith_SPEC.md +688 -0
  47. ontolith-1.0.0/docs/Ontolith_UseCases_and_Interfaces.md +236 -0
  48. ontolith-1.0.0/docs/adr/ADR-0001-storage-default.md +215 -0
  49. ontolith-1.0.0/docs/adr/ADR-0002-schema-definition.md +101 -0
  50. ontolith-1.0.0/docs/adr/ADR-0003-agent-identity.md +95 -0
  51. ontolith-1.0.0/docs/adr/ADR-0004-confidence-semantics.md +94 -0
  52. ontolith-1.0.0/docs/adr/ADR-0005-conflict-model.md +104 -0
  53. ontolith-1.0.0/docs/adr/ADR-0006-licensing-and-business.md +110 -0
  54. ontolith-1.0.0/docs/adr/ADR-0007-interop-priority.md +94 -0
  55. ontolith-1.0.0/docs/adr/ADR-0008-mcp-surface.md +180 -0
  56. ontolith-1.0.0/docs/adr/ADR-0009-trust-level-range.md +124 -0
  57. ontolith-1.0.0/docs/adr/ADR-0010-sqlite-transaction-model.md +166 -0
  58. ontolith-1.0.0/docs/adr/ADR-0011-provenance-fk-enforcement.md +108 -0
  59. ontolith-1.0.0/docs/adr/ADR-0012-class-dsl-compiler.md +74 -0
  60. ontolith-1.0.0/docs/adr/ADR-0013-linkml-dialect-coverage.md +109 -0
  61. ontolith-1.0.0/docs/adr/ADR-0014-mcp-authentication.md +338 -0
  62. ontolith-1.0.0/docs/adr/ADR-0015-plugin-capability-isolation.md +212 -0
  63. ontolith-1.0.0/docs/adr/ADR-0016-duckdb-second-backend.md +95 -0
  64. ontolith-1.0.0/docs/adr/ADR-0017-cardinality-conflict-semantics.md +74 -0
  65. ontolith-1.0.0/docs/adr/ADR-0018-policy-strategy-injection.md +71 -0
  66. ontolith-1.0.0/docs/adr/ADR-0019-public-api-stability-policy.md +267 -0
  67. ontolith-1.0.0/docs/adr/ADR-0020-hybrid-retrieval-storage-layer.md +263 -0
  68. ontolith-1.0.0/docs/adr/ADR-0021-rest-interface.md +201 -0
  69. ontolith-1.0.0/docs/adr/ADR-0022-rest-write-review-admin.md +513 -0
  70. ontolith-1.0.0/docs/adr/ADR-0023-multi-target-supersession-audit-trail.md +174 -0
  71. ontolith-1.0.0/docs/adr/ADR-0024-as-of-schema-resolution.md +113 -0
  72. ontolith-1.0.0/docs/adr/ADR-0025-policy-kb-parameter-and-source-quorum.md +186 -0
  73. ontolith-1.0.0/docs/adr/ADR-0026-security-ci-hardening.md +209 -0
  74. ontolith-1.0.0/docs/adr/ADR-0027-defer-relation-traversal-and-lookup-operators.md +138 -0
  75. ontolith-1.0.0/docs/adr/ADR-0028-value-type-enforcement-required-deferred.md +102 -0
  76. ontolith-1.0.0/docs/adr/ADR-0029-validator-invocation.md +89 -0
  77. ontolith-1.0.0/docs/adr/ADR-0030-retract-contradiction-capability-floor.md +85 -0
  78. ontolith-1.0.0/docs/adr/ADR-0031-retracted-terminal-for-winner-selection.md +81 -0
  79. ontolith-1.0.0/docs/adr/ADR-0032-duckdb-concurrency-lock.md +64 -0
  80. ontolith-1.0.0/docs/adr/ADR-0033-trust-at-least-delegation-attenuation.md +55 -0
  81. ontolith-1.0.0/docs/adr/ADR-0034-cli-schema-migrate.md +49 -0
  82. ontolith-1.0.0/docs/adr/ADR-0035-flag-contradiction-eligible-winner.md +65 -0
  83. ontolith-1.0.0/docs/adr/ADR-0036-rdf-owl-bridge.md +80 -0
  84. ontolith-1.0.0/docs/adr/ADR-0037-graphql-interface.md +482 -0
  85. ontolith-1.0.0/docs/adr/ADR-0038-admin-capability-gating.md +190 -0
  86. ontolith-1.0.0/docs/adr/ADR-0039-retract-interface-exposure.md +53 -0
  87. ontolith-1.0.0/docs/adr/ADR-0040-composite-policy-strategy.md +67 -0
  88. ontolith-1.0.0/docs/adr/ADR-0041-audit-table-immutability-triggers.md +106 -0
  89. ontolith-1.0.0/docs/adr/ADR-0042-admin-action-audit-trail.md +99 -0
  90. ontolith-1.0.0/docs/adr/ADR-0043-mcp-query-hybrid-retrieval-params.md +72 -0
  91. ontolith-1.0.0/docs/adr/ADR-0044-observability-scope.md +251 -0
  92. ontolith-1.0.0/docs/adr/ADR-0045-confidence-source-role-policy-strategies.md +233 -0
  93. ontolith-1.0.0/docs/adr/ADR-0046-proposal-reviewers-and-assign-action.md +241 -0
  94. ontolith-1.0.0/docs/adr/ADR-0047-provenance-on-ontology-not-entity.md +144 -0
  95. ontolith-1.0.0/docs/adr/ADR-0048-include-flagged-history-query-opt-ins.md +230 -0
  96. ontolith-1.0.0/docs/adr/ADR-0049-retraction-aware-as-of.md +208 -0
  97. ontolith-1.0.0/docs/adr/ADR-0050-time-varying-many-supersedes-hint.md +228 -0
  98. ontolith-1.0.0/docs/adr/ADR-0051-plugin-process-isolation.md +826 -0
  99. ontolith-1.0.0/docs/adr/ADR-0052-storage-format-migrations.md +481 -0
  100. ontolith-1.0.0/docs/adr/README.md +101 -0
  101. ontolith-1.0.0/docs/known-issues.md +2414 -0
  102. ontolith-1.0.0/examples/quickstart.py +213 -0
  103. ontolith-1.0.0/pyproject.toml +307 -0
  104. ontolith-1.0.0/src/ontolith/__init__.py +47 -0
  105. ontolith-1.0.0/src/ontolith/core/__init__.py +80 -0
  106. ontolith-1.0.0/src/ontolith/core/assertion.py +132 -0
  107. ontolith-1.0.0/src/ontolith/core/clock.py +116 -0
  108. ontolith-1.0.0/src/ontolith/core/embedder.py +141 -0
  109. ontolith-1.0.0/src/ontolith/core/entity.py +34 -0
  110. ontolith-1.0.0/src/ontolith/core/errors.py +159 -0
  111. ontolith-1.0.0/src/ontolith/core/ids.py +146 -0
  112. ontolith-1.0.0/src/ontolith/core/namespace.py +30 -0
  113. ontolith-1.0.0/src/ontolith/core/observability.py +216 -0
  114. ontolith-1.0.0/src/ontolith/govern/__init__.py +66 -0
  115. ontolith-1.0.0/src/ontolith/govern/conflict.py +234 -0
  116. ontolith-1.0.0/src/ontolith/govern/contradiction.py +112 -0
  117. ontolith-1.0.0/src/ontolith/govern/policy.py +886 -0
  118. ontolith-1.0.0/src/ontolith/govern/proposal.py +114 -0
  119. ontolith-1.0.0/src/ontolith/govern/provenance.py +44 -0
  120. ontolith-1.0.0/src/ontolith/identity/__init__.py +45 -0
  121. ontolith-1.0.0/src/ontolith/identity/admin_event.py +57 -0
  122. ontolith-1.0.0/src/ontolith/identity/credential.py +44 -0
  123. ontolith-1.0.0/src/ontolith/identity/ports.py +33 -0
  124. ontolith-1.0.0/src/ontolith/identity/principal.py +67 -0
  125. ontolith-1.0.0/src/ontolith/identity/token_auth.py +52 -0
  126. ontolith-1.0.0/src/ontolith/interfaces/__init__.py +0 -0
  127. ontolith-1.0.0/src/ontolith/interfaces/cli.py +1135 -0
  128. ontolith-1.0.0/src/ontolith/interfaces/graphql.py +1203 -0
  129. ontolith-1.0.0/src/ontolith/interfaces/mcp.py +1046 -0
  130. ontolith-1.0.0/src/ontolith/interfaces/rest.py +1407 -0
  131. ontolith-1.0.0/src/ontolith/observe/__init__.py +0 -0
  132. ontolith-1.0.0/src/ontolith/ontology.py +3614 -0
  133. ontolith-1.0.0/src/ontolith/plugins/__init__.py +40 -0
  134. ontolith-1.0.0/src/ontolith/plugins/manifest.py +79 -0
  135. ontolith-1.0.0/src/ontolith/plugins/ports.py +148 -0
  136. ontolith-1.0.0/src/ontolith/plugins/reference/__init__.py +33 -0
  137. ontolith-1.0.0/src/ontolith/plugins/reference/csv_importer.py +159 -0
  138. ontolith-1.0.0/src/ontolith/plugins/reference/json_exporter.py +56 -0
  139. ontolith-1.0.0/src/ontolith/plugins/reference/rdf_exporter.py +172 -0
  140. ontolith-1.0.0/src/ontolith/plugins/reference/required_fields_validator.py +103 -0
  141. ontolith-1.0.0/src/ontolith/plugins/registry.py +476 -0
  142. ontolith-1.0.0/src/ontolith/plugins/sandbox/__init__.py +18 -0
  143. ontolith-1.0.0/src/ontolith/plugins/sandbox/enforcement.py +417 -0
  144. ontolith-1.0.0/src/ontolith/plugins/sandbox/protocol.py +151 -0
  145. ontolith-1.0.0/src/ontolith/plugins/sandbox/remote_view.py +175 -0
  146. ontolith-1.0.0/src/ontolith/plugins/sandbox/runner.py +769 -0
  147. ontolith-1.0.0/src/ontolith/plugins/sandbox/wire.py +369 -0
  148. ontolith-1.0.0/src/ontolith/plugins/views.py +150 -0
  149. ontolith-1.0.0/src/ontolith/py.typed +0 -0
  150. ontolith-1.0.0/src/ontolith/query/__init__.py +9 -0
  151. ontolith-1.0.0/src/ontolith/query/builder.py +578 -0
  152. ontolith-1.0.0/src/ontolith/schema/__init__.py +58 -0
  153. ontolith-1.0.0/src/ontolith/schema/dsl.py +425 -0
  154. ontolith-1.0.0/src/ontolith/schema/ir.py +228 -0
  155. ontolith-1.0.0/src/ontolith/schema/linkml.py +367 -0
  156. ontolith-1.0.0/src/ontolith/schema/rdf.py +245 -0
  157. ontolith-1.0.0/src/ontolith/store/__init__.py +5 -0
  158. ontolith-1.0.0/src/ontolith/store/base.py +926 -0
  159. ontolith-1.0.0/src/ontolith/store/duckdb/__init__.py +11 -0
  160. ontolith-1.0.0/src/ontolith/store/duckdb/backend.py +2279 -0
  161. ontolith-1.0.0/src/ontolith/store/duckdb/migrations.py +430 -0
  162. ontolith-1.0.0/src/ontolith/store/migrations.py +72 -0
  163. ontolith-1.0.0/src/ontolith/store/sqlite/__init__.py +9 -0
  164. ontolith-1.0.0/src/ontolith/store/sqlite/backend.py +2549 -0
  165. ontolith-1.0.0/src/ontolith/store/sqlite/migrations.py +462 -0
  166. ontolith-1.0.0/tests/__init__.py +0 -0
  167. ontolith-1.0.0/tests/benchmarks/__init__.py +0 -0
  168. ontolith-1.0.0/tests/benchmarks/conftest.py +78 -0
  169. ontolith-1.0.0/tests/benchmarks/test_hybrid_query.py +449 -0
  170. ontolith-1.0.0/tests/benchmarks/test_traversal.py +378 -0
  171. ontolith-1.0.0/tests/contract/__init__.py +0 -0
  172. ontolith-1.0.0/tests/fixtures/plugins/__init__.py +6 -0
  173. ontolith-1.0.0/tests/fixtures/plugins/broken_bad_manifest.py +5 -0
  174. ontolith-1.0.0/tests/fixtures/plugins/broken_no_manifest.py +5 -0
  175. ontolith-1.0.0/tests/fixtures/plugins/broken_raises_on_init.py +10 -0
  176. ontolith-1.0.0/tests/fixtures/plugins/trivial_importer.py +15 -0
  177. ontolith-1.0.0/tests/fixtures/plugins/trivial_importer_filesystem_only.py +17 -0
  178. ontolith-1.0.0/tests/fixtures/plugins/trivial_importer_network_and_filesystem.py +16 -0
  179. ontolith-1.0.0/tests/fixtures/plugins/trivial_importer_network_only.py +17 -0
  180. ontolith-1.0.0/tests/fixtures/plugins/trivial_reasoner_default_caps.py +11 -0
  181. ontolith-1.0.0/tests/fixtures/plugins/trivial_validator.py +20 -0
  182. ontolith-1.0.0/tests/golden/__init__.py +0 -0
  183. ontolith-1.0.0/tests/golden/test_classes_ir_yaml_roundtrip.py +32 -0
  184. ontolith-1.0.0/tests/golden/test_schema_yaml_roundtrip.py +144 -0
  185. ontolith-1.0.0/tests/integration/__init__.py +0 -0
  186. ontolith-1.0.0/tests/property/__init__.py +0 -0
  187. ontolith-1.0.0/tests/property/test_embedder_properties.py +44 -0
  188. ontolith-1.0.0/tests/unit/__init__.py +0 -0
  189. ontolith-1.0.0/tests/unit/test_cli.py +2655 -0
  190. ontolith-1.0.0/tests/unit/test_contradiction.py +66 -0
  191. ontolith-1.0.0/tests/unit/test_core.py +175 -0
  192. ontolith-1.0.0/tests/unit/test_cross_interface_error_codes.py +311 -0
  193. ontolith-1.0.0/tests/unit/test_duckdb_backend.py +2542 -0
  194. ontolith-1.0.0/tests/unit/test_embedder.py +72 -0
  195. ontolith-1.0.0/tests/unit/test_govern.py +1071 -0
  196. ontolith-1.0.0/tests/unit/test_graphql.py +2024 -0
  197. ontolith-1.0.0/tests/unit/test_identity.py +224 -0
  198. ontolith-1.0.0/tests/unit/test_mcp_server.py +2480 -0
  199. ontolith-1.0.0/tests/unit/test_models.py +202 -0
  200. ontolith-1.0.0/tests/unit/test_observability.py +177 -0
  201. ontolith-1.0.0/tests/unit/test_ontology.py +1353 -0
  202. ontolith-1.0.0/tests/unit/test_ontology_validators.py +490 -0
  203. ontolith-1.0.0/tests/unit/test_plugin_isolation_conformance.py +103 -0
  204. ontolith-1.0.0/tests/unit/test_plugin_manifest.py +61 -0
  205. ontolith-1.0.0/tests/unit/test_plugin_registry.py +617 -0
  206. ontolith-1.0.0/tests/unit/test_plugin_sandbox.py +1288 -0
  207. ontolith-1.0.0/tests/unit/test_plugin_views.py +142 -0
  208. ontolith-1.0.0/tests/unit/test_principal.py +154 -0
  209. ontolith-1.0.0/tests/unit/test_principal_trust_immutability_invariant.py +40 -0
  210. ontolith-1.0.0/tests/unit/test_public_api_surface.py +298 -0
  211. ontolith-1.0.0/tests/unit/test_query.py +1153 -0
  212. ontolith-1.0.0/tests/unit/test_reference_csv_importer.py +206 -0
  213. ontolith-1.0.0/tests/unit/test_reference_json_exporter.py +84 -0
  214. ontolith-1.0.0/tests/unit/test_reference_plugins_registration.py +143 -0
  215. ontolith-1.0.0/tests/unit/test_reference_rdf_exporter.py +259 -0
  216. ontolith-1.0.0/tests/unit/test_reference_required_fields_validator.py +173 -0
  217. ontolith-1.0.0/tests/unit/test_rest.py +2537 -0
  218. ontolith-1.0.0/tests/unit/test_retract_contradiction_capability_floor.py +215 -0
  219. ontolith-1.0.0/tests/unit/test_schema_codegen.py +152 -0
  220. ontolith-1.0.0/tests/unit/test_schema_dsl.py +174 -0
  221. ontolith-1.0.0/tests/unit/test_schema_ir.py +358 -0
  222. ontolith-1.0.0/tests/unit/test_schema_linkml.py +549 -0
  223. ontolith-1.0.0/tests/unit/test_schema_rdf.py +388 -0
  224. ontolith-1.0.0/tests/unit/test_sqlite_backend.py +2604 -0
  225. ontolith-1.0.0/tests/unit/test_storage_migrations.py +1202 -0
  226. ontolith-1.0.0/uv.lock +2852 -0
@@ -0,0 +1,221 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ # Least privilege (security review finding, M4 Workstream 7): none of this
10
+ # workflow's jobs write to the repo, comment on PRs, or otherwise need more
11
+ # than read access — checkout, running tests/lint/benchmarks, and uploading
12
+ # to codecov.io (no token; codecov-action doesn't need repo write access to
13
+ # do that) all only need contents: read. security.yml already scopes itself
14
+ # the same way, for the same reason.
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ quality:
20
+ name: Code Quality
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ matrix:
24
+ python-version: ["3.11", "3.12", "3.13"]
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ # Full history so the griffe-diff step below can resolve the PR's
30
+ # base ref (KI-020) — same reason commitlint's checkout does this.
31
+ fetch-depth: 0
32
+
33
+ - name: Install uv
34
+ uses: astral-sh/setup-uv@v3
35
+ with:
36
+ enable-cache: true
37
+
38
+ - name: Set up Python ${{ matrix.python-version }}
39
+ run: uv python install ${{ matrix.python-version }}
40
+
41
+ - name: Install dependencies
42
+ run: uv sync --all-extras
43
+
44
+ - name: Format check
45
+ run: uv run ruff format --check
46
+
47
+ - name: Lint
48
+ run: uv run ruff check
49
+
50
+ - name: Type check
51
+ run: uv run mypy --strict src conformance/conftest.py
52
+
53
+ - name: Dependency rule check
54
+ run: uv run lint-imports
55
+
56
+ - name: Docstring coverage
57
+ run: uv run interrogate src/ontolith -c pyproject.toml
58
+
59
+ - name: Public API surface diff (KI-020)
60
+ if: matrix.python-version == '3.12'
61
+ # Blocking as of the 1.0 tag (Implementation Plan §5's "warn pre-1.0,
62
+ # block post-1.0"). This is NOT a required status check in the repo's
63
+ # branch ruleset (checked directly: only deletion, non_fast_forward,
64
+ # pull_request, code_quality, and code_scanning rules exist — no
65
+ # required_status_checks rule) — "blocking" here means a visible red
66
+ # CI failure a reviewer sees and must knowingly merge past, the same
67
+ # as any other job in this workflow, not a structural merge block.
68
+ #
69
+ # Griffe checks a module's `__all__` members if it has one, else its
70
+ # non-underscore/non-imported names — NOT "every non-underscore
71
+ # module-level function" (an earlier version of this comment claimed
72
+ # that; wrong, see below). A pure addition to `__all__` exits 0
73
+ # (confirmed). But it does NOT follow that only a genuine breaking
74
+ # change exits 1 — a still-earlier draft claimed that too, also
75
+ # wrong: griffe's breakage detector (`find_breaking_changes`) flags
76
+ # a public attribute's value TEXT changing even when semantically
77
+ # identical (confirmed: reordering `frozenset({"entity",
78
+ # "assertion"})` to `frozenset({"assertion", "entity"})` in
79
+ # store/base.py — same set, exit 1, "Attribute value was changed"),
80
+ # and a signature change on any name actually listed in its own
81
+ # module's `__all__` (or re-exported via another module's `__all__`
82
+ # — griffe follows the alias), even one this project's own ADR-0019
83
+ # doesn't consider part of the 13-package public surface (confirmed:
84
+ # adding a required parameter to plugins/sandbox/wire.py's
85
+ # restricted_loads, listed in that module's own `__all__` but not
86
+ # ADR-0019's — exit 1). A signature change on a name NOT listed in
87
+ # its own (or any re-exporting) module's `__all__` does NOT trip it
88
+ # (confirmed: same edit on cli.py's db_status, absent from cli.py's
89
+ # own `__all__ = ["app"]` and never re-exported — exit 0) — nothing
90
+ # catches this case, which is intended: `ontolith.interfaces.cli` is
91
+ # deliberately outside ADR-0019's SDK surface, and
92
+ # `test_public_api_surface.py`'s own docstring says plainly it does
93
+ # NOT catch signature-level changes at all, only export
94
+ # additions/removals/renames within the 13 packages it pins.
95
+ # Removing something from `__all__` alone, with the import kept,
96
+ # also doesn't trip this step (confirmed: exit 0) — for one of the
97
+ # 13 ADR-0019-pinned packages, `test_public_api_surface.py`'s own
98
+ # pinned `_EXPECTED` dict catches that instead; for `wire.py` or any
99
+ # other unpinned module, nothing catches it, same as the
100
+ # signature-change case above. Expect this gate to occasionally flag
101
+ # a cosmetic or internal-but-`__all__`-listed change as a false
102
+ # positive; that's a known, accepted cost of blocking it, not a bug
103
+ # in this workflow.
104
+ # Compares against the PR's base commit; on a push-to-main run (no
105
+ # PR context) compares against HEAD itself, i.e. a no-op — the
106
+ # meaningful comparison already happened during the PR's own run.
107
+ env:
108
+ BASE_REF: ${{ github.event.pull_request.base.sha || 'HEAD' }}
109
+ run: uv run python -m griffe check ontolith -s src -a "$BASE_REF" -f github
110
+
111
+ commitlint:
112
+ name: Commit message format
113
+ runs-on: ubuntu-latest
114
+ if: github.event_name == 'pull_request'
115
+
116
+ steps:
117
+ - uses: actions/checkout@v4
118
+ with:
119
+ fetch-depth: 0
120
+
121
+ - name: Validate Conventional Commits format
122
+ env:
123
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
124
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
125
+ run: |
126
+ pattern='^(feat|fix|docs|test|refactor|chore|perf|ci)(\([a-zA-Z0-9_-]+\))?: .+'
127
+ failed=0
128
+ while IFS= read -r line; do
129
+ sha="${line%% *}"
130
+ subject="${line#* }"
131
+ if [[ ! "$subject" =~ $pattern ]]; then
132
+ echo "::error::Commit $sha does not follow Conventional Commits: $subject"
133
+ failed=1
134
+ fi
135
+ done < <(git log --no-merges --format='%H %s' "$BASE_SHA..$HEAD_SHA")
136
+ exit $failed
137
+
138
+ test:
139
+ name: Tests
140
+ runs-on: ${{ matrix.os }}
141
+ strategy:
142
+ matrix:
143
+ os: [ubuntu-latest, macos-latest, windows-latest]
144
+ python-version: ["3.11", "3.12", "3.13"]
145
+
146
+ steps:
147
+ - uses: actions/checkout@v4
148
+
149
+ - name: Install libseccomp (Linux only — ADR-0051 plugin sandbox enforcement)
150
+ if: matrix.os == 'ubuntu-latest'
151
+ run: sudo apt-get update && sudo apt-get install -y libseccomp2
152
+
153
+ - name: Install uv
154
+ uses: astral-sh/setup-uv@v3
155
+ with:
156
+ enable-cache: true
157
+
158
+ - name: Set up Python ${{ matrix.python-version }}
159
+ run: uv python install ${{ matrix.python-version }}
160
+
161
+ - name: Install dependencies
162
+ run: uv sync --all-extras
163
+
164
+ - name: Run tests + conformance (combined coverage)
165
+ env:
166
+ HYPOTHESIS_PROFILE: ci
167
+ # Folded scalar (`>-`), not a `\`-continued literal block: this step
168
+ # runs on windows-latest too, whose default shell is PowerShell, which
169
+ # doesn't treat a trailing backslash as a line continuation and fails
170
+ # to parse the command (`Missing expression after unary operator
171
+ # '--'`). A folded scalar collapses to one line, valid in every shell.
172
+ run: >-
173
+ uv run pytest tests/ conformance/
174
+ --cov=src/ontolith --cov-report=xml --cov-report=term
175
+ --cov-fail-under=90
176
+
177
+ - name: Upload coverage
178
+ if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
179
+ uses: codecov/codecov-action@v4
180
+ with:
181
+ files: ./coverage.xml
182
+ fail_ci_if_error: false
183
+
184
+ - name: Run quickstart example
185
+ if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
186
+ run: uv run python examples/quickstart.py
187
+
188
+ benchmarks:
189
+ # M4 Workstream 1 exit gate: the 5 SPEC §9 budget rows are enforced as
190
+ # hard per-test ceilings inside tests/benchmarks/ itself (see
191
+ # tests/benchmarks/conftest.py's assert_within_budget) — this job is
192
+ # blocking (no continue-on-error, runs on every PR, not just pushes to
193
+ # main) precisely because those assertions, not this job definition,
194
+ # are what fails a genuine regression.
195
+ name: Benchmarks (§9 budgets)
196
+ runs-on: ubuntu-latest
197
+
198
+ steps:
199
+ - uses: actions/checkout@v4
200
+
201
+ - name: Install uv
202
+ uses: astral-sh/setup-uv@v3
203
+ with:
204
+ enable-cache: true
205
+
206
+ - name: Set up Python
207
+ run: uv python install 3.12
208
+
209
+ - name: Install dependencies
210
+ run: uv sync --all-extras
211
+
212
+ - name: Run benchmarks
213
+ run: uv run pytest tests/benchmarks/ --benchmark-only --benchmark-json=benchmark-results.json -q
214
+
215
+ - name: Upload benchmark results
216
+ if: always()
217
+ uses: actions/upload-artifact@v4
218
+ with:
219
+ name: benchmark-results
220
+ path: benchmark-results.json
221
+ overwrite: true
@@ -0,0 +1,86 @@
1
+ name: Security
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ schedule:
7
+ # Weekly, independent of PR activity — catches newly-disclosed CVEs in
8
+ # already-merged dependencies (Implementation Plan §7.1).
9
+ - cron: "0 6 * * 1"
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ # pip-audit, bandit, and SBOM generation share one checkout + `uv sync`
16
+ # instead of three, to cut per-PR Actions-minute usage on this repo's
17
+ # private-repo minute allotment (this workflow otherwise roughly doubles
18
+ # security.yml's total runner time for no benefit — none of the three
19
+ # steps depend on each other's output, they're just sharing setup cost).
20
+ scan:
21
+ name: Dependency + static security scan
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v3
29
+ with:
30
+ enable-cache: true
31
+
32
+ - name: Set up Python
33
+ run: uv python install 3.12
34
+
35
+ - name: Install dependencies
36
+ run: uv sync --all-extras
37
+
38
+ - name: Run pip-audit
39
+ run: uv run pip-audit
40
+
41
+ # `if: always()` below: these three steps are otherwise independent of
42
+ # pip-audit's outcome, but without it a pip-audit failure silently
43
+ # skips bandit/SBOM for the rest of the job (a real incident — a
44
+ # newly-disclosed transitive-dependency CVE masked two genuine bandit
45
+ # findings for a full PR before anyone noticed bandit hadn't actually
46
+ # run). The job still fails overall if any step fails; this only
47
+ # ensures every step gets a chance to report its own result.
48
+ - name: Run bandit
49
+ if: always()
50
+ run: uv run bandit -r src/ontolith -c pyproject.toml
51
+
52
+ - name: Generate SBOM
53
+ if: always()
54
+ run: uv run cyclonedx-py environment --pyproject pyproject.toml -o sbom.json
55
+
56
+ - name: Upload SBOM
57
+ if: always()
58
+ uses: actions/upload-artifact@v4
59
+ with:
60
+ name: sbom
61
+ path: sbom.json
62
+
63
+ gitleaks:
64
+ name: Secret scanning (gitleaks)
65
+ runs-on: ubuntu-latest
66
+
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+ with:
70
+ fetch-depth: 0
71
+
72
+ - name: Run gitleaks
73
+ uses: gitleaks/gitleaks-action@v3
74
+ env:
75
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76
+ # This repo is private under a personal account (not an
77
+ # organization) — gitleaks-action's license requirement is gated
78
+ # on org vs. personal account, not public vs. private repo
79
+ # visibility, so no GITLEAKS_LICENSE is needed here. That would
80
+ # change if this repo ever moved under an organization.
81
+ #
82
+ # PR comments disabled so this job only needs the default
83
+ # read-only GITHUB_TOKEN (workflow permissions: contents: read,
84
+ # above) rather than pull-requests: write — findings still surface
85
+ # via the job's own log/summary output.
86
+ GITLEAKS_ENABLE_COMMENTS: false
@@ -0,0 +1,51 @@
1
+ # Claude Code configuration (maintainer-only)
2
+ .claude/
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+ *.so
9
+ .Python
10
+ build/
11
+ develop-eggs/
12
+ dist/
13
+ downloads/
14
+ eggs/
15
+ .eggs/
16
+ lib/
17
+ lib64/
18
+ parts/
19
+ sdist/
20
+ var/
21
+ wheels/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+
26
+ # Virtual environments
27
+ venv/
28
+ ENV/
29
+ env/
30
+
31
+ # Testing
32
+ .pytest_cache/
33
+ .coverage
34
+ htmlcov/
35
+ .hypothesis/
36
+
37
+ # IDEs
38
+ .vscode/
39
+ .idea/
40
+ *.swp
41
+ *.swo
42
+ *~
43
+
44
+ # OS
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # Project specific
49
+ *.db
50
+ *.sqlite
51
+ *.sqlite3
@@ -0,0 +1,24 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-merge-conflict
10
+
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.2.2
13
+ hooks:
14
+ - id: ruff
15
+ args: [--fix]
16
+ - id: ruff-format
17
+
18
+ - repo: https://github.com/pre-commit/mirrors-mypy
19
+ rev: v1.8.0
20
+ hooks:
21
+ - id: mypy
22
+ args: [--strict, --ignore-missing-imports]
23
+ additional_dependencies: [pydantic>=2.0, python-ulid>=2.0]
24
+ files: ^(src/|conformance/conftest\.py$)