79 lines
3.1 KiB
Markdown
79 lines
3.1 KiB
Markdown
|
|
# 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)
|