schematron 0.16.1

Schematron: pure Rust implementation of ISO/IEC 19757-3 rule-based XML validation, with its own XML parser, XPath 1.0 engine, XPath 2.0 and 3.0 subsets, schema linting, and SVRL reporting. By SixArm.com.
Documentation
# CLAUDE.md

Instructions for Claude Code in this repository.

**The instructions are in [`AGENTS.md`](AGENTS.md). Read that file.**

This file is deliberately a pointer, not a copy. Agent instructions split
across two files drift apart, and the drift is invisible until an agent acts
on the stale half. `AGENTS.md` is the single source of truth; everything below
is Claude-specific mechanics that do not belong there.

## Quick orientation

- **What this is** — a pure Rust ISO/IEC 19757-3 Schematron validator. No C,
  no XSLT, no FFI, no `unsafe`.
- **Where the truth lives** — [`spec/`]spec/ is normative. Code and spec
  disagreeing is a defect in one of them.
- **The gate** — the four commands in [`AGENTS.md`]AGENTS.md#the-commands-that-gate-a-change
  must pass before any change is done. `cargo test --lib` is the fast loop
  while iterating (see [`agents/testing.md`]agents/testing.md for the full
  layer-by-layer breakdown, including fuzzing and benchmarks); run the full
  gate before declaring done, not just the fast loop.

## Working notes

Mechanics specific to running this crate from *this* machine/session — not
duplicated from `AGENTS.md` or `agents/testing.md`, which cover what to run
and why:

- **The crate root is `schematron/`, not the repository root.** The repository
  holds the crate and the website as peers, so run `cargo` from here. Anything
  that reads the crate root at compile time — `env!("CARGO_MANIFEST_DIR")`, which
  five of the test files use — bakes in the path it was built with, and cargo
  does not rebuild on a directory move. A `target/` from before the move makes
  those tests look for `spec/` and `examples/` at the old path and fail with
  exit code 3 and empty output. `cargo clean` is the fix, not a source change.
- **`cargo clippy --fix` refuses on a dirty tree**, so commit or stash first
  rather than reaching for `--allow-dirty`; the point of the refusal is that
  the rewrite is otherwise unreviewable.
- **The MSRV toolchain `1.96` is installed.** If a bump is needed,
  `rustup toolchain install <version> --profile minimal` first, then actually
  run the tests on it.

## Things that look like bugs and are not

Do not "fix" a surprising XPath 1.0 semantic without reading
[`agents/invariants.md`](agents/invariants.md) first — existential node-set
comparison, NaN-yielding conversions, the empty-node-set-versus-boolean case,
and `sum()`'s positive zero are all correct, deliberate, and tested. This list
is deliberately not copied here; a second copy is exactly the kind of drift
this file's opening paragraph warns about.

## Before claiming a change is done

Do not report success on a partial run. If a gate fails for a reason unrelated
to the change, say so explicitly rather than describing the work as complete.
New behaviour needs a test that fails without the change — verify that, do not
assume it.