# Path C — `kind = 'NclTransform` Phase B per ADR-030 — **declarable today, executive backend deferred**. A declarative NCL data-transform spec (target file + JSONPath selector + operation + value expression) that needs no Rust handler. Awaits an interpreter backend in `ontoref-daemon` once the expressive-power trigger fires (≥3 real ops proven expressible in this shape). ## Files | File | Purpose | | --- | --- | | [`rename_ontology_node.ncl`](rename_ontology_node.ncl) | Catalog declaration with `kind = 'NclTransform` and a fully-populated `body` | ## What the `body` declares | Field | Value | Meaning | | --- | --- | --- | | `target` | `.ontology/core.ncl` | NCL file to mutate (relative to project root) | | `selector` | `$.nodes[?(@.id == $inputs.node_id)].name` | JSONPath into the exported value, with `$inputs.` substitution | | `operation` | `'Set` | Replace the selected location (`'Set` \| `'Append` \| `'Remove` \| `'Merge`) | | `value_expr` | `$inputs.new_name` | NCL expression evaluated in op context, supplying the new value | ## Today's runtime behaviour Dispatching against a stock daemon returns: ``` HTTP/1.1 501 Not Implemented { "error": "missing_executive_backend", "kind": "NclTransform", "op_id": "rename_ontology_node", "hint": "awaits ADR-030 trigger — expressive-power proof for >=3 real ops" } ``` This is intentional per ADR-034 constraint `non-rust-kinds-declarable-not-executable-without-flag`. The op is a first-class catalog entry; cross-project consumers can read its contract via ADR-028 content-addressed catalog ontologies. ## When the executive backend lands The interpreter will: 1. Load `target` via `nickel export`. 2. Apply the `operation` at every match of `selector`, substituting `$inputs.*` with the actual op invocation inputs and computing `value_expr` in the op's context. 3. Re-canonicalise and write back. 4. Run the post-validators. 5. Sign the canonical state delta as the witness. The host runtime synthesises the ondaod context for the `evaluate_ondaod` pre-validator BEFORE invoking the transform — that is the structural guarantee the ADR-034 Hard constraint `non-rust-kinds-require-ondaod-pre` enforces at typecheck time. ## When NOT to use - The op needs cryptographic operations (signing, hashing beyond blake3-canonical) → use Path A `'Rust`. - The op spans multiple files or coordinates effects across non-NCL artifacts (oplog, blobs, registry mutations) → use Path A `'Rust`. - The op needs control-flow (branches, loops, conditionals beyond a single JSONPath transform) → use Path A `'Rust`. `'NclTransform` is for the trivial CRUD subset — set a name, append to an array, remove an entry, merge a record. That subset is empirically ~80% of catalog ops once a substrate matures; the trigger is whether real-world experience confirms that ratio. ## References - [ADR-034 — Catalog extensibility beyond Rust](../../../.ontoref/adrs/adr-034-catalog-extensibility-beyond-rust.ncl) - [ADR-030 mechanism #5 — InterpretedNclOps](../../../.ontoref/adrs/adr-030-catalog-discovery-cross-project.ncl) - [`schema-future.ncl::NclTransformBody`](../schema-future.ncl)