The operations catalog is FROZEN as a destination — no new operation is authored there — and its retirement is bound to a Rust reconciliation that has not happened

Superseded

ontoref
ADR-024 built the operations layer, ADR-026 gave it three validation planes, ADR-030 and ADR-034

Context

ADR-024 built the operations layer, ADR-026 gave it three validation planes, ADR-030 and ADR-034 opened it beyond Rust with four `kind`s. The howto `qa:ontoref-catalog-extension-howto` is Verified and NORMATIVE: it walks an author through declaring an operation, implementing the Rust handler, registering it in the ops module index and validating it. Everything about that surface is coherent. The problem is not its design.

MEASURED 2026-08-14.

· THE HTTP DISPATCH ROUTE IS THE DAEMON. `POST /ops` (`ontoref-daemon/src/api.rs:420`, `ops_surface.rs:23`) is how a catalogued operation runs over the network. [CORRECTED 2026-08-31 — see amendment: this bullet originally read «THE ONLY DISPATCH ROUTE IS THE DAEMON […] There is no CLI path and no in-process path for a consumer», and both of those exist. `main.rs:303-311` declares `--invoke-op`, and `:577-613` dispatches IN PROCESS via `ops_surface::dispatch_op_request` with no server. The clause was already false when it was written on 2026-08-14.]

· THE DAEMON IS NOT RUNNING, AND THE PROJECT'S OWN FSM SAYS SO. `operational-mode` is `current: local`, `desired: daemon`. So 15 declarations under `.ontoref/catalog/operations/` and the 11 Rust modules in `ontoref-ops/src/ops/` are not «unused by choice». They are UNREACHABLE in the workflow this project actually runs, and have been for as long as the dimension has been unmet.

· NO CONSUMER HAS EVER FILLED IT. Walking the 12 registered projects: 10 of 11 carry `.ontoref/catalog/` materialised and EMPTY — 0 operations, 0 validators; the eleventh does not carry the directory at all. The protocol projects a skeleton and nothing fills it.

· THE DECLARED SURFACE EXCEEDS THE BUILT ONE, BY DESIGN AND BY DRIFT. Of ADR-034's four kinds, `'NclTransform` and `'Wasm` answer HTTP 501 deliberately, awaiting an ADR-030 trigger — that part is honest. What is not accounted for: `ontoref-ontology/src/layout.rs` still carries a legacy `catalog` fallback (`:81`, `:231`) alongside the current section, and nobody has reconciled the Rust surface against the layout changes that have landed since.

· THE COUPLING IS REAL AND MULTI-CRATE. `catalog_dir` is a first-class layout section (`layout.rs:47,65,201,222`); `ontoref-derive`'s `#[onto_operation]` pairs an id 1:1 with `catalog/operations/<id>.ncl` and the coherence check is a runtime concern (O6); `validation/criteria_validators.rs:257` walks `catalog/validators`; `daemon/memory.rs:212` resolves the same. Removing the catalog is not a data migration.

WHAT PROMPTED THE QUESTION. The routed-operation envelope (ADR-089, ADR-092) gives an operation a place to declare where it comes from and what it feeds. The operator's reading is that the future projects to biops rather than to catalogued operations, because an operation is ONE occupant of that envelope — which also wraps sensors, work orders, SOWs and witnesses, each keeping its own predicate (bl-036: the envelope is shared, the probe is not).

Decision

The operations catalog is FROZEN AS A DESTINATION. No new operation and no new validator is authored under `catalog/operations/` or `catalog/validators/` in this project. Anything new is declared as a routed operation.

The catalog STAYS IN PLACE, dormant and unmodified. No crate is touched by this decision, no directory is removed, and nothing already declared there stops working — including in consumer projects that carry the empty skeleton.

ITS RETIREMENT IS BOUND TO A RECONCILIATION THAT HAS NOT HAPPENED, and that reconciliation is named here so the freeze cannot become permanent by forgetting. Minimum known scope: `ontoref-ontology/src/layout.rs` (the catalog section and its legacy fallback), `ontoref-derive::onto_operation`, `ontoref-ops/{registry,dispatch,ops/}`, `validation/criteria_validators.rs`, `daemon/memory.rs`. Its outcome decides whether the catalog is retired, absorbed into the routed-operation model, or kept as a historical kind — and THAT decision carries its own ADR and its own migration, because removing `catalog/` from ten consumers is a consumer-visible layout change.

`qa:ontoref-catalog-extension-howto` stays Verified and MUST record the freeze. A normative howto that walks an author into a frozen surface is worse than no howto: it is an instruction the project no longer means.

WHAT THIS DECISION IS NOT. It is not a judgement that the operations layer was wrong, and it is not a deprecation. A deprecation announces removal; this announces that authoring stops while the question of removal is unanswered — and the honest reason is that nobody has looked at the Rust side since the layout moved.

Constraints

  • Soft No operation is authored under catalog/operations beyond those present when this ADR was accepted.
  • Hard The normative catalog-extension howto states that the surface is frozen, so the instruction a reader meets matches the decision.
  • Soft This ADR does not retire the catalog; any removal carries its own ADR and its own migration.

Alternatives considered

  • Retire the catalog now and migrate its declarations to routed operations.rejected: It is a multi-crate Rust change (layout section and legacy fallback, the derive macro's id pairing, the ops registry and dispatch, the criteria validators, the daemon memory reader) plus a migration for ten consumers — to replace dormant code with a model that has five occupants and no dispatch path of its own. Destroying what exists for what is not yet is the inversion of the operator's own «an undeveloped potential is an obstacle» reading.
  • Change nothing and keep authoring operations there.rejected: Every addition couples one more thing to `POST /ops` on a daemon the FSM records as not running, and enlarges what the reconciliation must move. The 10 empty consumer skeletons are the measured shape of declarations nobody can run.
  • Freeze informally — stop authoring there without an ADR.rejected: The instruction that reaches people is `qa:ontoref-catalog-extension-howto`, which is Verified and normative and says the opposite. An unwritten freeze is contradicted by a governed surface on first consultation, and the contradiction resolves in favour of whichever the reader met first.
  • Mark the catalog Deprecated.rejected: Deprecation announces removal. Nobody has established that the catalog should be removed — the reconciliation may well conclude it is absorbed or kept as a historical kind. Announcing a removal that has not been decided would be the derived-criterion pattern (adr-049) applied to a lifecycle.

Anti-patterns

  • A normative howto walking authors into a surface nothing can reach — A capability's design is coherent and its instructions are Verified, but the path that would execute it is unavailable — a service not run, a backend not built, a flag never enabled. The howto keeps recruiting authors because nothing connects the instruction to the availability of the runtime. The tell is a step-by-step guide whose final step cannot be performed on the machine the reader is on.
  • Stopping work on a surface without naming what would resume it — Authoring stops on a surface, correctly, but nothing records what would end the pause or who owns it. The freeze becomes a removal nobody decided, and the surface rots in place while every reader assumes someone else is handling it. Distinguishable from deprecation only by the absence of an announcement.

Related ADRs

ADR-024 · ADR-026 · ADR-029 · ADR-030 · ADR-034 · ADR-089 · ADR-092

Was this useful? Rate it
Got something to add? Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
· reads

We use cookies to help this site function, understand service usage, and support marketing efforts. Cookie Policy for more info.