ontoref-code/examples/catalog-extension/03-ncl-transform/README.md

79 lines
3.1 KiB
Markdown
Raw Permalink Normal View History

# 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.<field>` 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)