ADR-0019 — OBO Write-Back via fastobo¶
Status¶
Accepted — implemented in v0.12.0 (read path v0.11, write-back v0.12)
Context¶
OntoCore indexes OBO Format 1.4 (.obo) for biomedical workflows. v0.7 shipped read-only OBO support with a minimal line parser. v1.0 Protégé parity requires reliable read/write, rich metadata (synonyms, definitions, xrefs), and patch-based editing consistent with Turtle write-back (ADR-0006).
The canonical Rust stack for OBO is fastobo + fastobo-owl per OBO_ROBOT_SPEC.md.
Decision (original)¶
v0.11¶
- Read path: Replace the minimal OBO line parser with
fastobo::from_str→ existingParsedOntology/ catalog model. Surface synonyms, definitions, and property values in catalog annotations and entity detail. - Write-back: Document patch schema; defer OBO inspector editing and disk serialize to v0.12.
- Boundaries: Turtle patches (
ontocore-owl::patch) own Turtle write-back. OBO patches use a separate op namespace inontocore-obo.
v1.0 (remaining)¶
- Optional
fastobo-validatorin CI /ontocore validate - Richer OBO metadata round-trip parity with Protégé / ROBOT
Current implementation (v0.12)¶
ontocore-obocrate applies OBO patch ops to.obofiles on disk- Entity Inspector and
ontocore/applyAxiomPatchdispatch by file extension (.ttlvs.obo) - CLI:
ontocore patch path/to/terms.obo patches.json - Documented ops: patch-reference.md · OBO authoring
OBO patch op schema¶
JSON array; each object has "op" (snake_case). Term subject is always an OBO id (e.g. GO:0008150) or resolved IRI.
op |
Required fields | Description |
|---|---|---|
set_name |
term_id, value |
Replace name clause |
add_synonym |
term_id, value, scope |
Add synonym (EXACT, RELATED, BROAD, NARROW) |
remove_synonym |
term_id, value |
Remove matching synonym |
add_def |
term_id, value |
Add or replace def |
remove_def |
term_id |
Remove definition |
add_xref |
term_id, xref |
Add xref (DB:ID or structured) |
remove_xref |
term_id, xref |
Remove xref |
set_namespace |
term_id, namespace |
Set term namespace |
set_deprecated |
term_id, value |
Set is_obsolete |
add_is_a |
term_id, parent_id |
Add is_a parent |
remove_is_a |
term_id, parent_id |
Remove is_a parent |
Example:
[
{
"op": "add_synonym",
"term_id": "EX:001",
"value": "example term",
"scope": "EXACT"
},
{
"op": "add_def",
"term_id": "EX:001",
"value": "An example class."
}
]
Turtle vs OBO write-back¶
| Concern | Turtle | OBO |
|---|---|---|
| Patch crate | ontocore-owl |
ontocore-obo |
| LSP apply | ontocore/applyAxiomPatch on .ttl |
Same method, .obo dispatch |
| Subject key | entity_iri |
term_id |
| Manchester | Yes | No (structural OBO clauses) |
| Imports | owl:imports patch ops |
N/A (separate ontology files) |
Consequences¶
Positive:
- Single canonical OBO parser (
fastobo) reduces drift from Protégé / ROBOT - Patch schema documented before implementation; shipped in v0.12
- Biomedical workflows can edit OBO in VS Code without Protégé
Negative:
- Two patch vocabularies (Turtle vs OBO ops) — unified LSP envelope only
- Full Protégé OBO feature parity (all xref types, logical definitions) remains v1.0 work