Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

A Tooling Cookbook

ox check, ox build, ox install, and ox test are the day-to-day commands the previous chapters lean on. The toolchain has more — for moving models between Argon and OWL/OntoUML, for pulling concepts out of curated catalogs, for inspecting the dependency graph, and for browsing what a package actually exports. This chapter is the reference for those.

Each section is a short recipe: what the command does, what it expects, what it emits, and a 1–2-line example you can run against the lease tutorial (or, where the recipe needs a fixture from outside the tutorial, an explicit fixture path).

ox import — bringing a foreign model in

Argon does not assume your starting point is a green-field package. ox import ingests an OntoUML JSON (or OWL-family) artifact and emits a new Argon package with the corresponding concepts, relations, and rules already wired:

$ ox import model.ontouml.json --into ./my_package

The format is auto-detected from the extension and a content-sniff; pass --from ontouml to force it. The emitted directory contains:

  • ox.toml — dual-shape manifest (legacy [project] for ox check / ox test, modern [package] for ox install).
  • README.md — generic scaffold describing layout / build / round-trip, with attribution to the source project’s name.
  • src/main.ar — root-level declarations plus use ufo::* (and any other foundation packages auto-detected against the registry).
  • src/<slug>/mod.ar — one module per OntoUML source package, when the source has nested packages. Each module declares its own classes/relations/generalization-set blocks and use-imports peer modules so cross-module references resolve without fully-qualified paths.

Round-trip identity is preserved via @ontouml-id: doc-comment markers on every emitted declaration and @ontouml-package-id: markers on each mod.ar; no sidecar file is needed.

Two flags are useful in practice:

  • --into <DIR> — target directory. Defaults to a sibling directory named after the foreign artifact’s project name (slugified).
  • --package-name <NAME> — override the emitted package name when the foreign metadata isn’t what you want. Names must match ^[a-z][a-z0-9_-]*$.

The importer prints a one-line summary at the end (wrote package "X" to <dir> (N files, M warnings)) plus a per-code breakdown of any non-fatal XW084x warnings — unmapped stereotypes, name disambiguations, restrictedTo natures preserved as metadata, generalization-set lattice points lowered to partition / disjoint / complete, and so on. ox explain XW0841 (or any code) gives the full reasoning.

Foundation-package detection

If the OntoUML source references packages that the Argon registry already publishes (UFO, COFRIS, CCF, COEX), ox import resolves matching classes against the registry instead of inlining them. The mapping is built-in (UFO → ufo, COFRIS → cofris, etc.); the bridge introspects the local cache (~/.argon/packages/) for each mapped package, drops local declarations whose names appear in the registry’s public surface, and threads use <pkg>::* plus a [dependencies] entry through the emitted package. Cache-miss is a hard error — run ox install <pkg>@<version> first, or pass --no-registry-detect to opt out and inline everything.

Note: OntoUML JSON is the production-tested format today. OWL-family formats (Turtle, RDF/XML, JSON-LD) ride the same translation pipeline (ox-translate) and will be enabled as the surface stabilizes; until then, convert via OntoUML or hand-translate the parts you care about. The Argon roadmap treats round-trippable OWL as a first-class deliverable.

ox export — emitting a foreign model out

The dual of ox import. Run it inside a project directory to translate the project to a foreign format:

$ ox export --format ontouml -o my-model.ontouml.json

--format defaults to ontouml; --output defaults to <package-name>.ontouml.json next to the manifest.

Alongside the emitted file, ox export writes a .drop.toml sidecar listing constructs that have no analog in the target format — refinement types, defeasible rules, standpoints, the bitemporal axes — so a downstream tool that consumes the export can decide whether the loss is acceptable. A round-trip through ox importox export preserves structural identity (class / relation / generalization-set ids on every emitted declaration round-trip via @ontouml-id: markers); whitespace and key order in the emitted JSON may differ from the source, and constructs listed in .drop.toml are dropped by definition.

ox migrate.ol.ar

The legacy .ol source extension is being retired (OW0813 warns at every .ol it parses). ox migrate walks the project tree, renames files, edits the manifest, and rewrites .gitignore / .gitattributes patterns:

$ ox migrate --from ol --dry-run     # preview the plan, mutate nothing
$ ox migrate --from ol               # apply the rename
$ ox migrate --from ol --rewrite-docs  # also rewrite `.ol` mentions inside doc comments

The migration is git-aware: inside a git working tree it uses git mv so history follows the rename; outside, it falls back to std::fs::rename. It is atomic — if any step fails, no files are renamed. It is idempotent — running it on an already-migrated tree prints “nothing to migrate” and exits.

Exit codes are stable: 0 success, 1 I/O / manifest / git error, 2 conflict (a .ar file would clobber an existing .ar). CI scripts can branch on the code without parsing the human output.

ox catalog — pinned ontology catalogs

A catalog is a curated collection of ontology entries — pins of UFO, BFO, OntoUML libraries, internal vocabulary packages — that downstream projects can browse and selectively pull from. The pin lives in ox.toml under [catalog]:

[catalog]
url = "git@github.com:sharpe-dev/argon-catalog.git"
sha = "a8f3e2c1b4..."

The pinned SHA is authoritative; every catalog operation reads from it. ox catalog exposes four subcommands:

$ ox catalog list                    # every entry in the catalog
$ ox catalog show <entry>            # full manifest of one entry
$ ox catalog update                  # fetch catalog HEAD; rewrite [catalog].sha
$ ox catalog sources                 # print the pinned URL + SHA

--format human (the default) prints box-drawing tables; --format json emits machine-readable output for scripts.

Exit codes for ox catalog: 0 success, 2 entry not found, 3 version mismatch, 4 dependency cycle, 5 source-parse error, 6 auth failed, 7 lock mismatch.

ox yank — pulling concepts from a catalog into your source

Catalogs store complete ontologies. Often you want one piece — Contract from legal-kb, the Person shape from ufo. ox yank materializes named concepts into src/yanked/:

$ ox yank legal-kb::Contract                          # one concept + its parents
$ ox yank legal-kb::{Contract, Party, Obligation}     # several at once
$ ox yank legal-kb::Contract --no-deps                # just the concept; supply parents yourself
$ ox yank legal-kb::Contract --include-all            # the entry's entire translation
$ ox yank --verify                                    # re-yank everything and diff against disk

The yanked source lands at src/yanked/<entry>_<ConceptName>.ar (or a multi-concept variant). Each yank also appends a row to ox.yank.toml — the yank ledger — recording the catalog URL, SHA, entry, version, source IRIs, timestamp, and a Blake3 content hash. The ledger is what makes yanks reproducible.

--verify re-runs every recorded yank against the pinned SHA and reports any divergence. Run it in CI to catch upstream drift you have not yet pulled.

The default mode includes the transitive parent closure: if you yank Contract, you also get every concept Contract : ParentX : ParentY : ... references along its supertype chain. --no-deps opts out — useful when those parents already live in your project. --include-all opts way in — useful when you want a faithful copy of the upstream entry.

ox tree and ox why — inspecting the dependency graph

Cargo-shaped twin commands for understanding what your project depends on, and why.

$ ox tree
lease-tutorial v0.1.0 (./)

$ ox tree --depth 2
lease-tutorial v0.1.0 (./)
├── ufo v0.2.1
│   └── coex v0.2.1
└── cofris v0.2.1
    └── ccf v0.2.1

ox tree reads ox.lock (no network) and prints a DFS box-tree of transitive dependencies. --depth N truncates; --depth 0 is just the root.

ox why answers “why is this package in my graph?”:

$ ox why coex
coex v0.2.1
  ← ufo v0.2.1
  ← lease-tutorial v0.1.0 (./)

It walks reverse edges from the named package back to the project root, printing every distinct path. If the package is orphaned (lockfile stale; cleaned up by ox install), the output says so.

Both commands are read-only. They will not refresh the lockfile, fetch from the registry, or hit the network.

ox show — schema introspection

ox show prints the schema contents the elaborator built up. Useful for confirming what a package actually exports, or for piping into a script:

$ ox show concepts                                   # every concept the package elaborates
$ ox show concepts --filter rigidity=rigid           # filter by metatype-axis values
$ ox show concepts --filter qname=lease --limit 10   # substring match + cap rows
$ ox show standpoints --lattice                      # standpoint DAG, not the table
$ ox show queries --format json                      # machine-readable

Eight kinds are valid: concepts, relations, properties, standpoints, queries, mutations, computes. --filter KEY=VALUE is repeatable (multiple filters are AND’d; substring match on the column). --sort COL lexicographically sorts ASC by the named column. --limit N truncates after filtering.

--lattice is special: with standpoints, it emits the parent-child DAG instead of the table. With any other kind, it errors.

Both human (default) and json output formats are supported; the JSON shape is stable across patch releases.

ox stats — what’s in the project

A one-shot summary, useful for post-elaboration diffs and for talking-points in design reviews:

$ ox stats
project: lease-tutorial
modules: 11
total lines: 287
concepts: 6
roles: 2
properties: 19
rules: 2
constraints: 2
enums: 0
individuals: 0
queries: 3
computations: 1
standpoints:
  default

Output goes to stderr (so it composes with redirects); the format is intentionally human-shaped — there is no --format json because ox show already covers the machine-readable case.

A typical session

Pulling these together, a realistic UFO-team workflow:

# import the OntoUML model the team has been editing
$ ox import lease-domain.ontouml.json --into ./lease

$ cd lease
$ ox check
$ ox stats
$ ox show concepts --filter rigidity=rigid

# pull supplementary concepts from the curated catalog
$ ox catalog list
$ ox yank ufo::Relator
$ ox yank legal-kb::{Contract, Obligation}
$ ox check

# write a derive rule, run a query, mutate
$ ox query active_leases
$ ox mutate sign_lease --principal alice-001

# emit a snapshot for a downstream tool
$ ox export --format ontouml -o lease-derived.ontouml.json

# inspect the dependency graph before publishing
$ ox tree
$ ox why coex

Every command in that session is read-only against the model, except mutate (which appends to the bitemporal log) and import/yank (which write to the source tree).

Reference workspaces in the catalog

Each ox subcommand in this chapter has a dedicated workspace family in _catalog/:

  • _catalog/cli-ox-import/{ontouml-json,ontouml-with-package-name,xw0841,xw0843,negative-missing-file}/ — the ox import recipes plus the two most common XW084x warnings.
  • _catalog/cli-ox-export/{ontouml,with-drop-sidecar,format-json,negative-no-package,round-trip-stable}/ox export including the round-trip-stability variant exercising structural-identity preservation.
  • _catalog/cli-ox-migrate/{dot-ol,dot-ol-dry-run,with-rewrite-docs,already-migrated,exit-code-2}/ox migrate across the relevant exit-code branches.
  • _catalog/cli-ox-catalog/{list,show,update,sources,negative-missing-sha}/ox catalog subcommands.
  • _catalog/cli-ox-yank/{single,multi,no-deps,include-all,verify-drift}/ox yank recipes plus the CI-friendly --verify mode.
  • _catalog/cli-ox-tree/{minimal,depth-2,negative-stale-lock,via-workspace,via-publish-graph}/ and cli-ox-why/{direct,transitive,orphan,negative-not-installed,via-workspace}/.
  • _catalog/cli-ox-show/{concepts,relations,standpoints-lattice,with-filter,with-limit}/.
  • _catalog/cli-ox-stats/{minimal,multi-module,with-tests,with-mutations,via-workspace}/.

Read these as worked test fixtures — every command in this chapter has a reproducer in version control.

What’s elsewhere

Chapter 4.3 covers ox check, ox build, ox explain, the LSP, and the editor extension — the day-to-day surface. Chapter 4.2 covers ox install, ox update, ox audit, and ox publish — the lockfile and registry side. The commands in this chapter sit alongside both: model-shaped operations that don’t fit cleanly in either bucket but that you’ll use as the project grows.