A LinkML schema repository: the Biolink data model (entities, associations, predicates) plus all derived artifacts (Python, JSON-Schema, OWL, SHACL, ShEx, Protobuf, JSON-LD, prefix map).
- Uses
uv(neverpip).uv syncinstalls;uv run <cmd>runs things.Makefiletargets wrapuv runfor you. linkmlandlinkml-runtimeare pinned to==1.11.1inpyproject.toml. Do not bump casually, and never downgrade — generation output depends on the exact version, andpush-main-regenerate-artifactsauto-commits whatever the pinned version produces. A mismatch silently rewrites every artifact underproject/andsrc/biolink_model/datamodel/(including semantic changes such aspredicateenums collapsing toLiteral[...]) whilemake teststill passes.- The pin lives in three places that must move together:
dependencies(linkml-runtime), thescriptsextra (linkml), and thedevdependency-group (linkml). The dev-group pin is not redundant —linkmlis not a core dependency, so without ituv syncresolveslinkmlby backtracking offlinkml-runtime, which is nondeterministic. - Python
>=3.10(CI matrix: 3.10–3.13). Default branch ismaster.
- Edit the root files:
biolink-model.yaml(hyphenated) andattributes.yaml. The schema doesimports: [linkml:types, attributes], soattributes.yamlmust sit next to it. - Never edit the copies at
src/biolink_model/schema/biolink_model.yaml+src/biolink_model/schema/attributes.yaml. The build regenerates them by copying the root files in (note the hyphen→underscore rename). - Never edit anything under
project/,docs/, orsrc/biolink_model/datamodel/(e.g.model.py) — all derived. Thepush-main-regenerate-artifactsworkflow re-derivesproject/*andsrc/*on push tomaster.
The build copies the root schema because about.yaml → source_schema_path is src/biolink_model/schema/biolink_model.yaml (read via utils/get-value.sh), so every generate/test/lint target first does that cp.
make help # list targets
make test # full local check = gen-project + pytest + linkml-lint + codespell
make gen-project # regenerate all project/ artifacts + Python datamodel
make lint # linkml-lint only (auto-copies schema first)
make test-python # pytest only (auto-copies schema first)
make testdoc # build docs + local mkdocs server
- Running
pytestdirectly will test a stale schema unless you first copy the root yaml in. Prefermake test-python/make lint/make test— they copy automatically. make tests(plural) andtox.iniare stale/broken (typobiolink_model.yamlO; tox targets py38/39). Ignore them; usemake test.- yamllint is not part of
make test. CI runs it separately:uv run yamllint -c .yamllint-config biolink-model.yaml(line-length max 200, enforced on PRs). - A single test:
uv run pytest tests/test_data.py(aftercp biolink-model.yaml src/biolink_model/schema/biolink_model.yaml). Main schema class for examples isEntity.
PRs run (pr-verify-pull-request, pr-codespell, pr-validate-biolink-yaml, pr-check-dependencies):
make test + codespell + yamllint biolink-model.yaml. The dependency check rebuilds uv.lock from scratch, so keep version ranges sane in pyproject.toml.
- Add meaningful
description:to every class/slot/enum/type. - For polymorphic classes, mark the discriminator slot
type_designator: true. - Map to existing standards where appropriate (e.g.
dcterms, OBO ontologies). - Never guess OBO/ontology term IDs. Look them up via the OLS API first.
- linkml-lint runs with
.linkmllint.yamlwhich disablesstandard_naming,canonical_prefixes, andrecommended— so those won't block, but don't rely on them catching issues.
This file is the single source of truth. CLAUDE.md and .github/copilot-instructions.md are symlinks to it, so edit only AGENTS.md.
There is no justfile in this repo — earlier copies of these instructions said "justfile" where they meant Makefile.