Skip to main content

Path conventions

rule-line uses two different kinds of path, and they are not the same thing. One addresses a position inside a ruleset document; the other addresses a step's position inside the step tree. Keeping them distinct is deliberate.

Diagnostic location dot-path

A diagnostic location points at a position inside the ruleset document — it is what a diagnostic's path field carries so an editor can jump to the exact field that produced the problem.

It is built from dots and bracketed indices:

  • A field name that looks like a plain identifier is joined with a dot: steps[2].formula locates the formula field of the third step.
  • An array position is a bracketed integer: steps[2] is the third step.
  • A segment containing a dot, a bracket, or a quote is bracket-quoted using JSON string escaping, so it round-trips unambiguously: input["odd.key"] locates the field literally named odd.key, and a field name that itself contains a quote is escaped the way JSON escapes it, for example input["he said \"hi\""].

Worked examples

LocationReads as
steps[2].formulathe formula field of the third step
input["odd.key"]the input field literally named odd.key
input["he said \"hi\""]the input field literally named he said "hi"

Why the escape set exists

Fixed DSL keys — steps, formula, type, and the rest — can never contain a dot, so for them a plain dotted path is always unambiguous. But a tenant's own input-schema field names are arbitrary strings and can contain a dot, a bracket or a quote. Bracket-quoting exactly those segments is what keeps input["odd.key"] from being misread as an input object with an odd field and a key sub-field. The forward slash / is deliberately not part of the escape set — see below.

Step path

A step path addresses a step's position in the tree. Unlike a location, it is derived from tree position rather than authored, and it is never written back into the ruleset document — it exists only in the trace, where it must stay fixed after the fact.

Step-path segments are slugs joined with a forward slash:

  • checkout/items/validate-total — the validate-total step, nested inside the items step, inside the checkout step.
  • Inside a foreach, a runtime occurrence gains a bracketed iteration index on the iterating segment: invoice/positions[3]/compute-vat addresses the compute-vat step as it ran on the fourth ([3]) iteration of the positions loop.

Worked examples

Step pathReads as
checkout/items/validate-totala structural path — the step's fixed position, no iteration
invoice/positions[3]/compute-vata runtime occurrence — the step as it ran on iteration [3] of the positions foreach

Why / was chosen

The slash was chosen precisely so a step reference can never be mistaken for a field traversal: a dot-path never uses / as a separator, so a step path embeds cleanly inside a dot-path location without any escaping. JSON string escaping does not escape / either, so this falls out of the encoding rather than needing a special case.

Derived step paths are never stored in the ruleset document. A structural path is recomputed from tree position whenever it is needed; a runtime occurrence path is recorded only in the trace of an actual run.