Validate a delivery¶
Available in: Python · Node · CLI · Browser
Run the numbered AGS Format Rules over a transfer file and get a verdict —
in-process from Python or Node, in SQL from DuckDB, at the shell with
lat, or drag-and-drop in the browser.
import laterite
# Validate a file. read(...).validate() returns the Ags4File (so it chains);
# the Report is on the .report property.
ags = laterite.read("examples/sample_site.ags").validate()
r = ags.report
print(
f"is_valid={r.is_valid} count={r.count} "
f"dict_version={r.dict_version!r} resolution={r.resolution!r}"
)
assert r.is_valid is True
assert r.count == 0
assert r.dict_version == "4.1.1" # auto-selected from TRAN_AGS
read(path).validate() runs the rule engine and returns the
Ags4File, so it chains; the verdict rides on .report.
is_valid and count are the headline. dict_version and resolution
tell you which edition the rules came from — both read straight off the
file: the edition is taken from TRAN_AGS, and resolution='exact' means
that edition was matched on the nose (otherwise laterite falls back to the
nearest dictionary it ships). You never pass an edition.
Because .validate() hands the file back, keep going on the same handle —
query it, slice a group, or emit it — without re-reading from disk.
import { validate } from "laterite";
import assert from "node:assert/strict";
// Validate a file. The Report carries the verdict plus which edition the rules
// came from — read straight off the file's TRAN_AGS; you never pass an edition.
const report = validate("examples/sample_site.ags");
console.log(
`isValid=${report.isValid} count=${report.count} ` +
`dictVersion=${report.dictVersion} resolution=${report.resolution}`,
);
assert.equal(report.isValid, true);
assert.equal(report.count, 0);
assert.equal(report.dictVersion, "4.1.1"); // auto-selected from TRAN_AGS
assert.equal(report.resolution, "exact");
Same engine, camelCase verbs: the free validate() returns a Report
whose isValid / count / dictVersion / resolution mirror the Python
properties one-for-one, and report.toJson() is byte-identical to
lat validate --json, so a Node service and a CI gate can share downstream
tooling. For the chaining style, read(path).validate() returns the
Ags4File with the verdict on .report — exactly the
Python shape.
The laterite_ags4 DuckDB extension is a read-only reader — it has no
validate function. Run the numbered rules with the lat
CLI or the laterite library (the Python/Node tabs
above); the extension then reads the file and can consume an
externally-minted .ags.idx (from lat certify) for fast single-group
reads. See the DuckDB function reference.
A clean file prints one line and exits 0:
A file with problems prints a count line, then a findings table — one row
per violation — and exits 1. File-level findings (a missing group) carry
no line, shown as -:
delivery.ags: 4 finding(s)
┌──────┬──────┬───────┬──────────────────────────────────────────────────────┐
│ Rule ┆ Line ┆ Group ┆ Description │
╞══════╪══════╪═══════╪══════════════════════════════════════════════════════╡
│ 14 ┆ - ┆ TRAN ┆ TRAN group not found. │
├╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 15 ┆ - ┆ UNIT ┆ UNIT group not found. │
├╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 17 ┆ - ┆ TYPE ┆ TYPE group not found. │
├╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 4 ┆ 5 ┆ PROJ ┆ DATA row field count does not match the HEADING row. │
└──────┴──────┴───────┴──────────────────────────────────────────────────────┘
Add --json for machine-readable findings keyed by rule. The exit code is
unchanged — 0 for an empty findings, 1 when it's populated — so a CI
gate can branch without parsing stdout:
{
"file": "delivery.ags",
"findings": {
"AGS Format Rule 14": [
{
"line": null,
"group": "TRAN",
"desc": "TRAN group not found."
}
],
"AGS Format Rule 15": [
{
"line": null,
"group": "UNIT",
"desc": "UNIT group not found."
}
],
"AGS Format Rule 17": [
{
"line": null,
"group": "TYPE",
"desc": "TYPE group not found."
}
],
"AGS Format Rule 4": [
{
"line": 5,
"group": "PROJ",
"desc": "DATA row field count does not match the HEADING row."
}
]
}
}
Open the web app and drag your file into the Validate pane. The same numbered-rules engine runs compiled to WebAssembly, entirely client-side — your file never leaves your machine, which makes it safe for confidential ground-investigation data. Findings arrive grouped by rule with the resolved edition and severity tiers, and you can carry the same file straight into the Fix or Explore panes.
Every validating door runs the same rule engine and picks the dictionary
edition from the file's TRAN_AGS — the Python/Node report and the CLI's
--json carry identical findings. Reach for the CLI in a build gate (exit 1
fails the build); reach for .validate() when you want to keep working with
the parsed file in the same process.
See also: lat CLI · Certify a file