
# Normative v3 References

These references must be tested against and work before v3 is deemed
ready for release. If there are inconsistencies between these references
and the specification in references_v3_compendium.md they must resolved
by comparison and decision, not simply updated or ignored.

---

## Before and after, from and to
Before and after, and from and to, are applicable to all three datatypes.
They take:
- Item indexes
- Arrival/load/run datetimes
- The identity of csvpath statements
- Fingerprints, as a proxy for the named-file arrival-order index
`:before(...)` and `:to(...)` are a pair, differing only in their reference point inclusivity. Likewise, `:after(...)` and `:from(...)`.

### `:before(...)`
Identifies the lower order items before a reference, exclusive
#### versions before a date
$acme.csvpaths.:before(:date("2026-01-01"))
$acme.files.*.:before(:date("2026-01-01"))
#### versions before an index
$acme.csvpaths.:before(:index(4))
$acme.files.*.:before(:index(4))
#### all runs before an index
$acme.results.:flatten():before(:index(4))

### `:after(...)`
Indicates the higher order items after a reference, exclusive
#### versions after a date
$acme.csvpaths.:after(:date("2026-01-01"))
$acme.files.*.:after(:date("2026-01-01"))
#### versions after an index
$acme.csvpaths.:after(:index(4))
$acme.files.*.:after(:index(4))
#### all runs after an index
$acme.results.:flatten():after(:index(4))

### `:to(...)`
The lower order items before a reference, inclusive
#### versions before a date
$acme.csvpaths.:to(:date("2026-01-01"))
#### versions up to and including an index
$acme.csvpaths.:to(:index(4))

### `:from(...)`
The higher order items after a reference, inclusive
#### versions on or after a date
$acme.csvpaths.:from(:date("2026-01-01"))
#### versions at or after an index
$acme.csvpaths.:from(:index(4))

### Use as range generators
`:above(...)` and `:below(...)` can be passed as an argument to create a predicate against a value that can be selected. The effect is like a less-than or greater-than operator, or a range running from a point to the beginning or end.

#### Select all results with more than 3 errors:
$*.results.:flatten():error_count(:above(3))

#### Two ways of selecting runs without errors
$*.results.:flatten():error_count(:below(1))
$*.results.:flatten():error_count(0)

---

## Function argument string interpolation

Functions that take a string argument can have interpolation strings that plug values from:
- Variables
- Functions

### Form
Interpolation has the form of braces wrapped variables or functions. Literal braces can be escaped by doubling them. E.g.
- `"this is {@day}"` compiles to `"this is Monday"` when `@day` is equal to `Monday`
- `"this is {{a day var goes here}}"` compiles to `"this is {a day var goes here}"`

### Create a dynamic path using a variable
$acme.files.orders/:name("Summary for {@businessunit}.xlsx")

### Create a dynamic path using a function
$acme.files.orders/:name("Summary for {:day_name(:yesterday())}.xlsx")


---

## Date and time functions
Time component functions provide values that can be used in strings and as
arguments to other functions. They are available in all datatypes and have
multiple modes:
- Returning their datetime component based on the `datetime.now()`
- Returning their component based on a date passed as an argument
- Acting as a time anchor as input to a directional or range function
- Acting as a range

The exception being `:date()` which can create a date from a string, but does
not provide the current datetime.

### :year()
$acme.files.orders/:name(:year())/:last()
$acme.files.orders/:from(:year(@the_year)).*

### :month()
$acme.files.orders/:name(:month())/:last()
Evaluated in June yields a path of `orders/06/*`.

### :month_name()
$acme.files.orders/:name(:month_name())/:last()
Evaluated in June yields a path of `orders/June/*`.

### :day()
$acme.files.orders/:name(:day())/:last()
Evaluated on Aug 06 yields a path of `orders/06/*`.

### :day_name()
$acme.files.orders/:name(:day_name())/:last()
Evaluated on a Tuesday yields a path of `orders/Tuesday/*`.

### :hour()
$acme.files.orders/:name(:hour())/:last()
Evaluated at 3am UTC yields a path of `orders/03/*`.

### :hour_24()
$acme.files.orders/:name(:hour_24())/:last()
Evaluated at 3pm UTC yields a path of `orders/15/*`.

### :minute()
$acme.files.orders/:name(:minute())/:last()
Evaluated at 6:15 pm yields a path of `orders/15/*`.

### :second()
$acme.files.orders/:name(:second())/:last()
Evaluated at 6:25:15 pm yields a path of `orders/15/*`.

### :yesterday()
$acme.files.orders/:name(:day_name(:yesterday()))/:last()
Evaluated on a Tuesday yields a path of `orders/Monday/*`.

### :today()
$acme.files.orders/:name(:day_name(:today()))/:last()
Evaluated on a Tuesday yields a path of `orders/Tuesday/*`.

### :date()
$acme.files.orders/:name(:day_name(:date("2026-09-04")))/:last()
Yields a path of `orders/Friday/*`.

### :now()
$acme.files.orders/:name(:minute(:now()))/:last()
Evaluated at 6:15 pm yields a path of `orders/15/*`.


---

## Predicate support functions

### :true()
Get the path+uuid to the manifest of any no-template `acme` runs where
the run method is in `collect_paths()` or `fast_forward_paths()`, the
serial run methods.
$acme.results.:manifest():serial(:true())

Get the path+uuid to the run home dir of any no-template `acme` runs
where the run method is in `collect_paths()` or `fast_forward_paths()`,
the serial run methods.
$acme.results.:serial(:true())

### :false()
Get the path+uuid to the run home dir of any no-template `acme` runs
where the run method is in `collect_by_line()` or
`fast_forward_by_line()`, the breadth-first run methods.
$acme.results.:serial(:false())

### :none()
Provides the `None` value for use in metadata predicates. Find all the
`acme` run results with 0-level templates that are still in progress.
$acme.results.*:completed(:none())

### :not_none()
Select the name home paths+uuid of all named-files that have an arrival
activation set.
$*.files.:on_arrival(:not_none())

### :empty()
Empty and none are for the most part synonymous. In a few cases there are distinctions. A field that defaulted to an empty list matches `:empty()` not `:none()`. A JSON file that serialized None as null does not match `:empty()`. A key that is not present matches `:none()`, but not `:empty()`.

| Function | Matches |
|----------|---------|
| `:empty()` | `''`, `[]`, `{}` |
| `:none()`  | `''`, `null`, No such field |

Find the name homes where `status` doesn't exist in the manifest entry (indicating a successful registration) and there was no template.
$*.files.:status(:none()):template(:empty())

### :not_empty()
Get a list of all templates used in registrations
$*.files.:template(:not_empty())

---

## Narrowing predicate forms and pointer selection in `results` files

The following references return the path+uuid on `query()`.

#### `resolve()` to the content of file
`$acme.results.:last().:errors()`

#### `resolve()` to all errors that have idchains
`$acme.results.:last().:errors(:idchain(:not_none()))`

#### `resolves()` to all errors with matching idchains
`$acme.results.:last().:errors(:idchain("add[0]"))`

#### `resolve()` to contents, iff idchain exists in file
`$acme.results.:last().:errors():idchain(:not_none())`

#### `resolve()` to contents, iff idchain matching exists in file
`$acme.results.:last().:errors():idchain("add[0]")`

---

## The field accessor functional taxonomy
Field accessor functions are assigned one of 5 functional groups:
  - `uuid`: :uuid(), :run_uuid(), :named_file_uuid(), :named_paths_uuid()
  - `name`: :named_paths_name(), :named_results_name(), :named_file_name()
  - `fingerprint`: :fingerprint(), :named_file_fingerprint()
  - `type`: :type()
  - Everything else

The values found by functions in the same functional group can be compared in reference expressions.

A function that represents a unique identifier field may:
- Retrieve the value when used without an argument
- Select an entity when its value matches the function's argument

### UUIDs

#### Return the UUID of the named-file used in the run:
$acme.results.:first():named_file_uuid()

#### Return the UUID of the named-paths group version used in the run:
$acme.results.:first():named_paths_uuid()

#### Select a registered version of an `acme` file by its UUID:
$acme.files.:uuid("ab37-fef3...")

### Names

#### Select named-files registrations for `orders` that failed
$*.files.:status("Registration failed"):named_file_name("orders")

#### Select the first run for each template for runs having the
named-file name `orders`:
$*.results.:groups():named_file_name("orders"):first()

### Fingerprint

#### Select a named-file version by fingerprint
$acme.files.:fingerprint("4fd50acf4b5da0c2bcb8cb6c66a753a27c62280d0848824a6224647a5650ff3a")

#### Select all runs that used a specific version of a named-file
$*.results.:flatten():named_file_fingerprint("4fd50acf4b5da0c2bcb8cb6c66a753a27c62280d0848824a6224647a5650ff3a")

#### Two ways of retrieving all `acme` fingerprints
$acme.files.:flatten():fingerprint()
$*.files.:fingerprint():named_file_name("acme")

### Type

#### Select all `acme` named-file versions by type
$acme.files.:flatten():type("xlsx")

---

## Pointers

A function can point to a certain item to the exclusion of other items. Examples include:
- `:index(4)`  - the 5th item in an ordered set
- `:last()` - the last item in an ordered set
- `:errors()` - the `errors.json` file created by every run

### One pointer per reference context
Two pointers can not cohabitate the same reference in the same context, such as a `name_one`. For e.g. the following are not legal:
- $acme.files.:index(3):last()  - cannot specify the 4th item and the last item at the same time, even if the last item is 4th.
- $acme.results.orders:last().header_checks:manifest():errors() - cannot point to the manifest file and the errors file at the same time.

---

## Functions in `root_major`

Root major holds the named-entity name. It can take for the following:
- A static name string, as defined in the grammar
- `*` - the only wildcard allowed
- `:regex(...)` - a standard regex identifying a set of names
- `:name(...)` - a name that may include variable interpolation or be the string form of a variable
- `:choice(...) - a pipe-delimited sequence of matching names

#### The set of all file homes of the acme named-file
$acme.files.:flatten()

#### The set of all file homes for all named-files
$*.files.:flatten()

#### The set of all file homes for all named-files starting with `B`
$:regex(/^B/).files.:flatten()

#### File homes matching `EMEA orders` given a variable `@where` equals `EMEA`
$:name("{@where} orders").files.:flatten()

#### The set of all file homes for the orders, invoices, and shipments named-files
$:choice("orders|invoices|shipments").files.:flatten()

---

## Definition files
Named-paths and named-files have definition.json files to hold configuration
information. There is one unversioned definition.json in each named-entity
within those datatypes. To get configuration for any group its own
`definition.json` file must be read.

#### Point to a named-file's definition file
$acme.files.:definition()

#### Two equivalent ways to get arrival activation information
$acme.files.:definition():on_arrival()
$acme.files.:on_arrival()

#### Query-only when multiple definitions selected
In keeping with the limitation that references can only retrieve the contents
of a single file at a time, querying across named-entities for path+uuid is
possible, but then resolving the reference would raise an exception. This
reference is not legal:
$*.files.:definition()

---

### One grouping wildcard per `name_one` path
For `files` and `results` the `name_one` path can have at most one grouping
wildcard.
#### The following are illegal:
- $acme.files.:all()/:all()
- $acme.files.:groups()/:all()
- $acme.files.:groups()/:groups()

#### `*/:flatten()`
Note that `$acme.files.*/:flatten() offers a subtle distinction over `:flatten()`:
- `$acme.files.:flatten()` - all `acme` file homes
- `$acme.files.*/:flatten()` - all `acme` file homes that have a template (a 1-level template)

#### `:flatten()/*`
Note, however, `$acme.files.:flatten()/*` is illegal because it is essentially
contradictory. It says flatten all the layers as wildcards, except one last layer
that is a wildcard. Because there is no functional difference between the last and
the preceding layers it is not possible say if `:flatten()` or `:flatten()/*` was
applied, so the combination is impractical and for clarity it is illegal.

#### `:groups()/*`
In contrast to `:flatten()/*`, `:groups()/*` is legal. It says group in all names
except wildcard the last one. Where there are not multiple levels, the `*` controls.

Given the following name homes, each with 10 versions (not shown, named
<version-number-N>.csv where N is the arrival index):
<named_files>/acme/jan.csv
<named_files>/acme/feb.csv
<named_files>/acme/invoices/jan/invoice1.csv
<named_files>/acme/invoices/jan/invoice2.csv
<named_files>/acme/shipments/jan/week1.csv
<named_files>/acme/shipments/jan/week2.csv
<named_files>/acme/shipments/feb/week1.csv
<named_files>/acme/shipments/feb/week2.csv

- $acme.files.:groups()/*.:last() returns:
<named_files>/acme/feb.csv/<version-number-10>.csv
<named_files>/acme/invoices/jan/invoice2.csv/<version-number-10>.csv
<named_files>/acme/shipments/jan/week2.csv/<version-number-10>.csv
<named_files>/acme/shipments/feb/week2.csv/<version-number-10>.csv

#### Other `files` and `results` paths wildcarding
The following are illustrative for both the templated datatypes, `files` and `results`:
- `$acme.files.:flatten()/*` - illegal, cannot flatten all layers and then have another wildcard layer
- `$acme.files.:flatten()/:all()` - legal, can flatten all layers except one last grouping layer
- `$acme.files.*/:groups()` - legal, can wildcard one layer then group all other layers

Note that the following unlikely references are legal and equivalent:
- `$acme.files.*/:all()/*`
- `$acme.files.*/*/*`

### Groups and flatten occur in `name_one` only
#### The following are illegal:
- $acme.csvpaths.:all().:flatten()
- $acme.results.:last().:groups():manifest()

### Limitations on wild cards in `name_three`
- Only `*` and `:all()` may be used in `name_three`
- At most one wildcard may be used in `name_three`
- `:all()` devolves to being the equivalent of `*`

#### The following are equivalent:
- $acme.files.:name("orders.csv").*
- $acme.files.:name("orders.csv").:all()

#### The following are equivalent:
- $acme.results.:last().:all()
- $acme.results.:last().*

#### The following are equivalent:
- $acme.csvpaths.:last().:all()
- $acme.csvpaths.:last().*

#### The following are illegal:
- $acme.files.*.:all():all()
- $acme.results.:last().*:all()

---

### Log files

Note that `:log()` is a reference to a single log file that contains log output from all runs and other Framework activities. References v3 provides access to this resource at `name_one` to enable references users to access a high value source, despite the fact that the log file lives in a scope separate from every other aspect of references.

#### Get log file for current CsvPath Framework project
The following are functionally identical:
$acme.files.:log()
$acme.csvpaths.:log()
$acme.results.:log()

---

## The Results Datatype
Notes
- A "1-level template" means a template like :1/:run_dir where the run is 1 path
segment below a particular named-result home directory. A "non-template run dir"
means a run dir that is a direct child of the named-result home.
- Some constructions may simply be less efficient equivalents to others.
For example `:from(:index(-3))` is identical to `:from(-3)`. In this case, both
`:from()` and `:index()` need to exist for different requirements, and while we
wouldn't suggest combining them together in this inefficient way, it wouldn't be
technically prevented.

### Finding the "last" run or runs of a type of information:

### Last run from every named-results group with no template
$*.results.:last()

#### A run with no template
$alpha.results.:last()

#### A run with no template, same as without the wildcard
$alpha.results.*:last()

#### A run with no template, same as with wildcard
$alpha.results.:all():last()

#### Last run with any depth template
$alpha.results.:flatten():last()

#### A run from all templates starting `beta`
$alpha.results.beta/:flatten():last()

#### Last run of all runs w/1-level template starting `beta/`
$alpha.results.beta/:all():last()
Note that :all() does not group by :run_dir so this is better written
as `$alpha.results.beta/*`

#### A run of all 1-level templates starting `beta/`
$alpha.results.beta/*:last()

#### A manifest entry of the most recent run with no template
$alpha.results.:manifest():last()

#### A manifest entry of the most recent run, period, across every named-result
$*.results.:manifest():last()

#### Runs for every template and non-template run dir
$alpha.results.:groups():last()

---

### Find runs by relative time

#### Find errors in any named-result run since close of business yesterday
$*.results.:flatten():from(:yesterday(:hour(18))).*:errors()

### Find errors from yesterday at a specific idchain of a csvpath with the `purchases` identity
$acme.results.:flatten():yesterday().purchases:errors(:idchain("customer[0]id[0]"))

### What errors yesterday from a csvpath with the `purchases` identity matched a customer
$acme.results.:flatten():yesterday().purchases:errors(:message(/customer: 319/))

### Two equivalent ways to find csvpaths generating more than 10 errors yesterday
$acme.results.:flatten():yesterday().*:errors(:count(:above(10)))
$acme.results.:flatten():yesterday().:errors(:count(:above(10)))

---

### use of :all()
#### The single last run of those with 0-level templates (a.k.a. no template)
$alpha.results.:all():last()

#### The single last run of those with templates equivalent to or matching `test/one/:run_dir`
$alpha.results.test/one/:all():last()

#### The set of last runs for each group of runs with 3-level templates
where the first level is `test` and the third level is `one`, grouped by
the values of the 2nd template level
$alpha.results.test/:all()/one:last()

#### All csvpaths for all runs having no template
$alpha.results.:all().:all()

#### Find all csvpath instance manifests for all runs with no template.
$alpha.results.:all().:manifest()

#### Manifest of the first of all alpha results
$alpha.results.:flatten():first():manifest()

#### Manifest of last statement of first alpha results
$alpha.results.:flatten():first().:last():manifest()

#### Error count of all statements of first alpha results
$alpha.results.:flatten():first().:all():error_count()

#### Error counts for all statements of the 5th 0-level alpha results
$alpha.results.:all():index(5).:all():error_count()

---

### Run directories must be represented in `name_one`

#### Error: there is no run dir called `beta`. No exception, but never returns results.
$acme.results.beta

#### Corrected
$acme.results.beta/*

---

### Templates and path segment names

#### Two ways to get every run having a 0-level template
$alpha.results.:all()
$alpha.results.*

#### First run with template `customers/2025/:run_dir`
$acme.results.customers/2025/:first()

#### `invoices` csvpath instance path in 1st run having a 1-level template `customers/:run_dir`
$acme.results.customers/*:first().invoices

#### `invoices` in 1st run w/2-level template ending `2025/:run_dir`
$acme.results.*/2025/:first().invoices

#### `invoices` in 1st run w/3-level template ending `2025/:run_dir`
$acme.results.*/*/2025/:first().invoices

#### `invoices` in 1st run w/2-level template starting with `M` and ending `2025/:run_dir`
$acme.results.:name(/^M.*/)/2025/:first().invoices

#### `invoices` from 1st run w/template ending `2025/:run_dir`, beginning with `acme`, `star`, or `general`
$acme.results.:choice("acme|star|general")/2025/:first().invoices

#### `invoices` from 1st run w/2-level template ending with `2025/:run_dir` w/source data CSV
$acme.results.*/2025/:first():type("csv").invoices

#### Two ways to get manifest of first run with 1-level template `customers/:run_dir`
$acme.results.customers/:manifest():first()
$acme.results.customers/:first():manifest()

---

### `vars.json`, `data.json`, `meta.json`, `errors.json`, `printouts.txt` and `unmatched.json`

### the data.csv output of the `invoices` csvpath statement in the first run with a 2-level template `customers/2025/:run_dir`
$acme.results.customers/2025/:first().invoices:data()

#### the vars.json output of the `invoices` csvpath statement in the first run with a 2-level template `customers/2025/:run_dir`
$acme.results.customers/2025/:first().invoices:vars()

#### the meta.json output of the `invoices` csvpath statement in the first run with a 2-level template `customers/2025/:run_dir`
$acme.results.customers/2025/:first().invoices:meta()

#### unmatched.csv output of the 3rd through last csvpath statements in the first run with a 2-level template `customers/2025/:run_dir`. calling `resolve()` on finder will error.
$acme.results.customers/2025/:first().:from(2):unmatched()

#### unmatched.csv output of the 3rd through last csvpath statements in the first run with a 2-level template `customers/2026/:run_dir`, where the current year == 2026
$acme.results.customers/:name(:year())/:first().:from(2):unmatched()

#### unmatched.csv output of the 3rd through last csvpath statements in the first run with a 1-level template `customers/:run_dir` where the date of arrival was 2025-01-01
$acme.results.customers/:date("2025-01-01"):first().:from(2):unmatched()

#### unmatched.csv output of the 3rd through last csvpath statements in each run with a 1-level template `customers/:run_dir` where the date of arrival was 2025-01-01 or newer
$acme.results.customers/:from(:date("2025-01-01")).:from(2):unmatched()

#### unmatched.csv of the 3rd through last statements in last three runs with template `customers/:run_dir`
$acme.results.customers/:from(:index(-3)).:from(2):unmatched()

#### errors file from the header_checks statement of a 0-length template run of `alpha`
$alpha.results.2026-01-01_01-01-01.header_checks:errors()

#### Two ways to get all errors files from no-template alpha runs with header_checks statements
$alpha.results.*.header_checks:errors()
$alpha.results.:all().header_checks:errors()

#### Two equivalent ways to get errors files from no-template alpha runs with header_checks statements that were run on 1/1/2026
$alpha.results.:regex("2026-01-01_").header_checks:errors()
$alpha.results.:from("2026-01-01").before("2026-01-02").:header_checks:errors()

#### Get an errors file using a regex in `name_one`. And a similar regex in `files` for comparison.
$alpha.results.orders/:regex("202[6789]")/EMEA:last().header_checks:errors()
$alpha.files.orders/:regex("202[6789]")/EMEA.:last()


#### Get the path and/or contents of the default printouts file, `printouts.txt`
$acme.results.:flatten():last().:printouts()

---

### Arbitrary files from printouts and Parquet

#### `report.txt` (a print-mode printout file) within the `invoices` csvpath statement in the first run with a 2-level template starting with the value of @myname and ending in `2025/:run_dir`
$acme.results.:name(@myname)/2025/:first().invoices:file("report.txt")

#### `report.txt` (a print-mode printout file) within the `invoices` csvpath statement in the first run with a 2-level template ending in `2025/:run_dir`
$acme.results.*/2025/:first().invoices:file("report.txt")

#### all parquet files output of all of the csvpath statements in the last three runs with a 1-level template `customers/:run_dir`
$acme.results.customers/:from(:index(-3)).*:type("parquet")

#### Get a printouts file named for its stream
Given the csvpath
`~ print-mode:separate ~$[*][ print("hello world", "greetings")]`, get
the resulting `greetings.txt` printouts. The following two references
are equivalent:
$acme.results.:flatten():last().:printouts("greetings")
$acme.results.:flatten():last().:file("greetings.txt")


---

### Global archive ledger

#### Manifest path+uuid for very run across every named-results group
$*.results.:manifest()

### Error: incorrect ways to find the last item in the global ledger
$*.results.:last():manifest()
$*.results.:manifest():last()

Note that when we have information available without using a manifest we
must get it that way. Practically all cases are covered by
non-through-manifest means. Explicit uses of :manifest() should be used
only to find the path to the file or retrieve the full contents of the
manifest file or entry.

#### Two ways to get the moment a csvpath statement within a named-paths group
begins to run. The first by archive ledger manifest, the second by direct
access. Note that these two references are not functionally identical. Due to
variable run times, threading races, etc. the second reference time could be
earlier than the time found by the first reference.
$*.results.:manifest():last():time()
$*.results.:flatten():last().:last():time()

#### Two ways to get the UUID of the first known run. First by archive
manifest, second by direct access. Unlike the above references focused on the
last activity, these two references are functionally identical.
$*.results.:manifest():first():run_uuid()
$*.results.:flatten():first():uuid()

#### Two ways to get the run dir of a run containing a csvpath instance
with a certain UUID. First by archive ledger manifest, second by direct
access.
$*.results.:manifest():uuid("a381..."):run_home()
$*.results.:flatten():having(:uuid("a381...")):run_home()

#### Two ways to get the last instance run yesterday. Note that these may
not return the same identity due to timing effects and the difference in
what last tracks in `name_one` (i.e. run start time) vs. in the global
manifest (i.e. instance start times within runs).
$*.results.:manifest():yesterday():last():identity()
$*.results.:yesterday():last().:last():identity()

#### Two ways to find all the instances in runs with the named_paths group
`orders` that happened yesterday. Note that the first finds the start times
of instances within runs whereas the second finds the start times of runs.
This difference means that the resulting lists of instances are not
guaranteed to match.
$*.results.:manifest():named_paths_name("orders"):yesterday()
$orders.results.:flatten():yesterday().*

#### Two ways to find all the instances in runs with the named_file
`orders` that happened yesterday. As with other time based references of
this type, the difference between the tracking the run time vs. the
instance start time within the run makes this pair of reference return
result that are not always going to be the same.
$*.results.:manifest():named_file_name("orders"):yesterday()
$*.results.:flatten():yesterday():named_file_name("orders").*

#### Archives can provide a kind of multi-project namespacing, in that
projects can use the same archive name with different internal paths or
different archive names with the potential for identical internal paths.
The archive name. archive path, `named_files_root`, and
`named_paths_root` values will be entirely consistent for all references
because references are context-bounded to an archive.
$*.results.:manifest():archive_name()

#### Two ways of finding the template used by a run
$*.results.:manifest():run_uuid("789a..."):template()
$*.results.:flatten():run_uuid("789a..."):template()

---

### Run manifest field accessors

#### All pull field values from the run manifest
$widgets.results.:first():serial()
$widgets.results.:first():all_valid()
$widgets.results.:first():all_completed()
$widgets.results.:first():status()
$widgets.results.:first():method()
$widgets.results.:first():host()
$widgets.results.:first():username()
$widgets.results.:first():time_completed()
$widgets.results.:first():manifest_path()
$widgets.results.:first():named_paths_name()
$widgets.results.:first():named_results_name()
$widgets.results.:first():named_file_name()
$widgets.results.:first():run_uuid()

#### this use of `:uuid()` gives the same result as `:run_uuid()`
$widgets.results.:first():uuid()

#### Instance scope field accessors -- $widgets, one run, statement identity `company_names`
$widgets.results.:first().company_names:uuid()
$widgets.results.:first().company_names:run_uuid()
$widgets.results.:first().company_names:valid()
$widgets.results.:first().company_names:completed()
$widgets.results.:first().company_names:files_complete()
$widgets.results.:first().company_names:serial()
$widgets.results.:first().company_names:identity()
$widgets.results.:first().company_names:actual_data_file()
$widgets.results.:first().company_names:origin_data_file()
$widgets.results.:first().company_names:fingerprints()
$widgets.results.:first().company_names:source_mode_preceding()
$widgets.results.:first().company_names:preceding_instance_identity()
$widgets.results.:first().company_names:manifest_path()
$widgets.results.:first().company_names:named_file_name()

---
### All in name three and name one

#### All in name_three. One result per statement in last run. If run has 3 statements, finds 3 results.
$acme.results.:last().:all():uuid()

---

### Directions and ranges

#### Two ways to get last three runs with template `customers`
$acme.results.customers:from(:index(-3))
$acme.results.customers:from(-3)

#### the 2nd through 4th runs with template `customers`
$acme.results.customers:from(1):to(3)

#### Two ways to range on a date
$acme.results.customers:from(:date("2025-01-01"))
$acme.results.customers:from("2025-01-01")

#### runs between 2025-01-01 and 2025-01-31, both dates inclusive
$acme.results.customers:from(:date("2025-01-01")):to(:date("2025-01-31"))

#### mixing index-mode and date-mode bounds in the same range is possible
$alpha.results.*:from(2):to(:date("2026-01-10_8-00-00"))
Note that the instruction is to find a range of results, identify the 3rd result in the range, collect from 3rd through the last result that happened before Jan 10 at 8am.

#### Two ways to find the remaining items from a pointer
$acme.results.customers:from(-3):last()
$acme.results.customers:from(-3)


#### A pointer alongside a range selects within the range
$acme.results.customers:from(-6):to(-2):last()
Note that the pointer picks from items found by the range, not the larger set of items the range draws from.

#### 3rd->last csvpath instances in first run with template `customers/2025/:run_dir`
$acme.results.customers/2025/:first().:from(2)

#### the 2nd-through-4th statement (0-based, inclusive)
$acme.results.customers/2025/:first().:from(1):to(3)

#### Two ways to get an unmatched.csv; one using a range narrowed to exactly one statement.
$acme.results.customers/2025/:first().:from(2):to(2):unmatched()
$acme.results.customers/2025/:first().:index(2):unmatched()
Note no exception on `resolve()` because the reference retrieves exactly 1 file.

---

## The Files Datatype

### File homes

#### all no template file homes in `alpha`
$alpha.files.*
Note that file homes have paths but not UUID. On `query()` this reference
gives a list of path+None.

#### Two ways to get all file homes for `alpha`
$alpha.files.:groups()
$alpha.files.:flatten()

Note that `:groups()`'s grouping behavior and `:flatten()`'s flattening behavior only matter if we have potentially multiple children of each group or potential group to pick from. In these cases we don't have child items because the reference stops at `name_one`; i.e. the file home. While `:groups()` may make grouping happen, because we don't use the groups, we don't see them, and therefore they effectively don't exist.

#### The file home for `orders.csv`
$alpha.files.:name("orders.csv")
Note that the file home directory name will have a `.`. Because
references use `.` as part of their structure the file home's `.` must be
handled. References v3 uses the `:name()` function to effectively escape
`.` in names.

Note that file homes have paths but not UUID. On `query()` this reference
gives a path+None. Unlike `FileManager`, references do not default to the
most recent registration in any way.

---
### Referencing Excel files

References can point to Excel files (xlsx) and their worksheets. A reference
to an Excel file that doesn't have a `name_two` value is a reference to
the default worksheet within the files workbook.

#### Point to an xlsx file home
$acme.files.orders/:name("west coast.xlsx")

#### Point to an xlsx file home with a specific reference to a worksheet.
$acme.files.orders/:name("west coast.xlsx")#march
Note that the reference result returned on `query()` is the typical path+uuid
plus the name_two value

---

### Versions

#### Two ways to get every version of a file home
$alpha.files.:name("orders.csv").*
$alpha.files.:name("orders.csv").:all()

#### Get the first version of `alpha` registered file `orders.csv`
$alpha.files.:name("orders.csv").:first()

Note that file homes do not have UUID but since both references point
to the first version, both return a path+uuid

---

### Versions by indexes

$alpha.files.:name("orders.csv").:last()
$alpha.files.:name("orders.csv").:first()
$alpha.files.:name("orders.csv").:index(1)


---

### Selecting versions by ordinal or date

#### Find the first version registered yesterday
$acme.files.*.:yesterday():first()
Note that `:yesterday()` is dynamic shorthand for a datetime

#### Find the last `acme` version created after the 4th of July home. Note
$acme.files.:flatten():after(:date("{:year()}-07-04_23:59:59")).:last()

Note that the `name_three` pointer provides the actual version file
path+uuid and, on `resolve()` bytes.

Note that dates construct using their earliest moment forcing us to specify the
last moment of the 4th in order for `:after()` to actually mean after. A
slightly simpler approach would have been to use
`:from(:date("{:year()}-07-05"))`.

#### Find version by wrapping index
$alpha.files.:name("orders.csv").:from(:index(-3))

#### Select the 3rd and 4th versions
$alpha.files.:name("orders.csv").:after(1):to(3)

#### Select the last three versions
$alpha.files.:name("orders.csv").:from(-3):last()

#### Select versions on or after a moment
$alpha.files.:name("orders.csv").:from(:date("2026-01-01"))

#### Select versions from one moment up to and including another
$alpha.files.:name("orders.csv").:from("2026-01-01"):to("2026-01-31")

---

### Templates

#### every registration with no template
$alpha.files.*
Note this returns:
- named_files/alpha/one.csv
- named_files/alpha/two.csv
- named_files/alpha/three.csv
But not:
- named_files/alpha/updated/one.csv

#### The last registration in any no-template `alpha` file home
$alpha.files.*.:last()

#### The last registration for every no-template `alpha` file home
$alpha.files.:all().:last()

#### The first registration for every no-template `alpha` file home
$alpha.files.:all().:first()

### List all `alpha` no-template file homes
$alpha.files.:all()

### List all `alpha` file homes
$alpha.files.:flatten()

#### The last registration of all registrations in any `alpha` file home
$alpha.files.:flatten().:last()

#### The first registration of all registrations in any `alpha` file home
$alpha.files.:flatten().:first()

#### The last registration of all registrations in any file home ending in `orders.csv`
$alpha.files.:flatten()/:name("orders.csv").:last()
Note that this result will includes no-template registrations of `orders.csv`, i.e. when `flatten()` is applied to 0 levels between top of the path and the last level.

#### The first registration of all registrations where the template begins `2025` and the file home ends in `orders.csv` with any number of template levels in between.
$alpha.files.2025/:flatten()/:name("orders.csv").:first()

#### find all the orders.csv file homes registered using any or no template
$alpha.files.:flatten()/:name("orders.csv")

#### The last registration for every file home
$alpha.files.:groups().:last()

#### The first registration for every file home
$alpha.files.:groups().:first()

### The version's own manifest entry, either order
$alpha.files.:name("orders.csv").:last():manifest()
$alpha.files.:name("orders.csv").:manifest():last()

---

### Definition.json

#### Retrieving the `alpha` named-file's definition.json contents
$alpha.files.:definition()
Note that there is always 1 definition.json is per named-file

#### Getting the on_arrival value
$alpha.files.:on_arrival()

#### Getting the sftp sources object as a whole
$alpha.files.:sources()

#### Getting the source value component identifing an sftp server
$alpha.files.:source_address("local_server")

---

### Manifests

#### Retrieve the `alpha` manifest path and content
$alpha.files.:manifest()

#### Retrieving the full manifest entry of the last no-template registration
$alpha.files.:manifest():last()

Note that we require references to use the field accessor, ranges, pointers, dates, etc. without going through the named-file's manifest, unless there is some corner case where the manifest is the only recourse. However, we allow retrieving the full contents of the manifest or manifest entry.

#### Retrieve the named-file datatype's arrivals ledger
$*.files.:manifest()

#### Ordinal indexing into the global ledger disallowed, instead use references like:
$*.files.:flatten():last()
$*.files.:flatten().:last()

#### grouping file homes across all named-files to find all last registrations
$*.files.:groups().:last()



### Use field accessors on one matched version
$alpha.files.:name("orders.csv").:last():uuid()
$alpha.files.:name("orders.csv").:last():time()
$alpha.files.:name("orders.csv").:last():fingerprint()
$alpha.files.:name("orders.csv").:last():origin()
$alpha.files.:name("west coast.xlsx").:last():mark()
Note that this retrieves the worksheet mark of an already-matched version.
Selecting a specific worksheet to query in the first place still goes
through `name_two` (`#worksheet`).

### Find a named-file registered version by fingerprint.
$alpha.files.:fingerprint("a711df7d2846e8ba46125d3f7adb7aea0ede50eb20a6550fca2358628a05425b")

Note that this returns the first matching registered fingerprint. Multiple
versions may have the same fingerprint if registered under different file homes.

Note that we use the `:fingerprint()` accessor as a query predicate by passing in
a match value.

Note that the `:fingerprint()` function is in scope in `name_one` and `name_three`.

### Get the README.md for a named-file, if existent
$acme.files.:readme()

Note that `:readme()` is a file accessor that has no relationship to the
`name_one` file home path, and that there is only one README.md per named-file.
Therefore, you cannot combine a path with the `:readme()` function in
`name_one`.



---

## The Csvpaths Datatype


### Version pointers
Note that these return path+uuid, where path is always the same `group.csvpaths`.
Each can be used to resolve the full content of `group.csvpaths` for that
version.

#### The last version of `acme`
$acme.csvpaths.:last()

#### The first version of `acme`
$acme.csvpaths.:first()

#### The 2nd version of `acme`
$acme.csvpaths.:index(1)

#### The `acme` versions from the -3 position to the last version
$acme.csvpaths.:from(-3)

#### Selecting the `acme` versions from 2nd to 4th, then keeping only the 4th
$acme.csvpaths.:from(1):to(3):last()


---

## All versions

#### Two ways to get all versions
$acme.csvpaths.:all()
$acme.csvpaths.*

#### All versions of all named-paths groups
$*.csvpaths.*

---

### UUIDs

#### Find `acme` version by UUID; the most specific reference possible
$acme.csvpaths.:uuid("45ad7aa7-fe08-4f18-8b1b-e2d11675bf36")

---

#### Collect the my_validations statement, if present, from every `acme` version
$acme.csvpaths.:all().my_validations

#### Redundant but permitted
$acme.csvpaths.:all():last().my_validations

Note that the correct way to write this is
$acme.csvpaths.:last().my_validations

#### For all named-paths groups, find `my_validations` in any named-paths group's last version
$*.csvpaths.:last().my_validations

Note that `*` mimics grouping; therefore, this delivers a list or 0
or more, not a single item


---

### Having

#### Find last version containing `my_validations` for all named-paths groups
$*.csvpaths.:having("my_validations"):index(-1)

Note that `*` mimics grouping; therefore, this delivers a list or 0
or more, not a single item

#### Finding `my_validations` across versions with `*` implied
$acme.csvpaths.:having("my_validations")

#### Collects the last three versions of `acme` if they have a
`my_validations` statement
$acme.csvpaths.:having("my_validations"):from(-3)


---

### ':from()' and ':to()' and ':before()' and ':after()' as instance ranges

#### Select the 3rd through last statements from the last version of `acme`
$acme.csvpaths.:last().:from(:index(2))

#### Selecting the `acme` versions loaded within January 2026. Not that
`:date("2026-01-31")` expands to the very first moment of the 31st, so
this reference effectively misses one day.
$acme.csvpaths.:from(:date("2026-01-01")):to(:date("2026-01-31"))

---

### Identities

In `name_three`, the directional/range functions can work on identities:
- `:index()` or bare int
- `:name()` with a string, int, or variable equaling the statement identity

A csvpath statement within a group has an identity that is:
- The index of the statement within the group
- A name assigned by the writer using a metadata field (`id`, `Id, `ID`,
`name`, `Name`, or `NAME`) in the statement's leading comment

The index of a statement is always meaningful, regardless of it it is named.
And the index is also used as the name, if another name is not assigned by
the writer.

#### Indexes are csvpath identities and are always available even when an
explicit string overrides the default index-as-identity
$acme.csvpaths.:last().:from(1):to(3)

#### Select sequential statements
$acme.csvpaths.:last().:from("header checks"):to("validation summary")
Note this uses the index of `header checks` and the index of
`validation summary`. The range is inclusive, from the last version of
`acme`.

Note that if the names given do not match, the reference returns no results,
no error is thrown, and no partial results given.

#### Select statements from the last version of `acme` before `header checks`
$acme.csvpaths.:last().:before("header checks")

Note that if `header checks` is not found the reference returns nothing, but
does not error. Also note that if `header checks` is the first statement, the
reference simply doesn't match and returns nothing; it doesn't error, and
doesn't wrap the index.

#### Three ways to get the csvpath statement with identity `company_names` and index 0
$acme.csvpaths.:last().company_names
$acme.csvpaths.:last().0
$acme.csvpaths.:last().:index(0)

Note that the middle reference uses `0` as the identity. While logically and grammatically this `0` is not the index, practically speaking, it doesn't matter.

---

#### The version's own manifest entry, either order
$acme.csvpaths.:last():manifest()
$acme.csvpaths.:manifest():last()

#### definition.json and its sub-objects
$acme.csvpaths.:definition()
$acme.csvpaths.:scripts()
$acme.csvpaths.:webhooks()
$acme.csvpaths.:transfers()
$acme.csvpaths.:destinations()

#### Global group loads ledger including every named-paths group
$*.csvpaths.:manifest()

#### Ordinal indexing into the global ledger, either order works
$*.csvpaths.:last():manifest()
$*.csvpaths.:manifest():last()

#### Find the last loaded version of every named-paths group
$*.csvpaths.:last()

#### Find every version from every group
$*.csvpaths.:all()

#### Field accessors on one matched version
$acme.csvpaths.:last():uuid()
$acme.csvpaths.:last():time()
$acme.csvpaths.:last():fingerprint()
$acme.csvpaths.:last():origin()
$acme.csvpaths.:last():manifest_path()
$acme.csvpaths.:last():named_paths_name()
$acme.csvpaths.:last():named_paths_identities()
$acme.csvpaths.:last():named_paths_count()

#### The path and contents of the `acme` manifest
$acme.csvpaths.:manifest()

#### Get `acme`'s `README.md`, if existent
$acme.csvpaths.:readme()

Note that `:readme()` is a file accessor that has no relationship to the
`name_one` version selection. There is only one README.md per named-paths
group. Therefore, you cannot combine version selection with the `:readme()`
function in `name_one`.

---

### Named-paths group `definition.json` files

Definition.json files holding named-paths group configuration work as
described above with the `files` data type, where they are also found.

There are two caveats, also referenced above, but primarily implementation
details of named-paths groups `definition.json` files that will change
in due time but have meaning for functions today:

1. Named-paths groups `definition.json` files may include configuration
details for a point in time for groups other than the group that contains
and owns the `definition.json` file. This is due to the ability to create
multiple named-paths groups from a single file. The capability may go
away and/or the persistence of the foreign group(s) may end. Regardless,
named-paths groups only derrive their configuration from their own
`definition.json` file and functions and other code may only apply the
configuration of the specific named-paths group from the group's own
file when acting. No other cross-group configuration access or usage is
permitted, regardless of what legacy content may continue to exist in the
group's `definition.json` file.

2. In at least one case there is a structure in named-paths group
`definition.json` files that is currently under-powered and on the roadmap
for extension, in a way that changes how a specific set of its functions'
arguments are handled as noted below.

#### Case of a name parameter not being supported: `definition.json` may not
support multiple sets (all, valid, invalid, error) of named webhooks. If only
one unnamed set is supported, the functions accessing fields work without a
string argument name. It is likely that named sets of webhooks will be
supported in the foreseeable future, as it is a current roadmap item.
$acme.csvpaths.:webhooks_on_complete_invalid()


