Skip to main content

CollationDelta: two string relations joined by a delta

CollationDelta

Detect string ordering and equality changes before a runtime upgrade.

PyPI Python requirement Runtime dependencies License

CollationDelta records a comparator's results for your string corpus, saves a portable capture, and compares captures offline. Capture a baseline in one runtime and the same corpus and requested profile in another. The original runtimes are needed only to create the captures.

It reports equality merges, equality splits, and order reversals as individual pair witnesses. Equality means compare(a, b) == 0; it does not mean matching bytes or SQL equality. A runtime version change alone is not drift.

The Python CLI has no runtime dependencies. The included Node and optional native Chromium adapters implement the same strict intl.collator.v1 contract. Custom executable adapters can record an application's own comparator.

Install

CollationDelta 0.2 requires Python 3.10+ on Linux or macOS. Node is needed for Node capture; browser capture also requires an explicitly installed Chromium runtime and optional Playwright toolchain. Windows adapter execution is unsupported.

From source

git clone https://github.com/0then0/collationdelta.git
cd collationdelta
uv sync --locked --python 3.10
uv run --locked collationdelta --help

To install a local wheel:

uv build
uv venv /tmp/collationdelta-install --python 3.10
uv pip install --python /tmp/collationdelta-install/bin/python \
  dist/collationdelta-0.2.0-py3-none-any.whl
/tmp/collationdelta-install/bin/collationdelta --version

Published releases

pip install collationdelta==0.2.0
collationdelta --version

Version 0.2.0 includes Node capture, optional native browser capture and Python 3.10 support. The older 0.1.0 release requires Python 3.12+ and includes Node capture only.

Capture and compare

Node is required for this example. Run it from the source checkout:

adapter="$(uv run --locked collationdelta node-adapter)"
uv run --locked collationdelta capture \
  --corpus examples/corpus.json --profile examples/profile.json \
  --output /tmp/baseline.json -- node "$adapter"
uv run --locked collationdelta capture \
  --corpus examples/corpus.json --profile examples/profile.json \
  --output /tmp/current.json -- node "$adapter"
uv run --locked collationdelta compare /tmp/baseline.json /tmp/current.json \
  --json-output /tmp/report.json

Using the same runtime twice gives a control capture. To check an upgrade, run the first capture in the old environment and the second in the new environment. Offline comparison needs only Python and the two capture files.

For native browser capture, see the browser guide. collationdelta browser-adapter prints the bundled browser adapter path. Browser installation and executable selection are explicit; capture never downloads a browser.

Inputs

Corpus JSON assigns a stable ID to each exact string:

{
  "version": 1,
  "entries": [
    { "id": "rupee", "value": "₨" },
    { "id": "letters", "value": "Rs" },
    { "id": "zero", "value": "0" }
  ]
}

A requested profile identifies the comparator contract and configuration:

{
  "version": 1,
  "contract": "intl.collator.v1",
  "locale": "en",
  "options": { "sensitivity": "base" }
}

IDs must be unique and nonempty. Duplicate values under different IDs are allowed. Strings are preserved exactly: no trimming, case folding, normalization, or removal of controls. Empty strings, U+0000, newlines, combining marks and supplementary characters are supported. Invalid UTF-8 and unpaired surrogates are rejected.

Each capture requests all n² ordered comparisons, including the diagonal, for 1–256 entries. There is no sampling. JSON files are limited to 32 MiB; long strings can reach file or transport limits before the entry limit.

The reference adapters fix localeMatcher to lookup. They support sensitivity, numeric, caseFirst, ignorePunctuation, usage, and collation. Locale canonicalization and supported lookup negotiation are allowed. Explicit options and recognized co, kn, kf extensions must resolve, with explicit options taking precedence. An unsupported locale or ignored explicit request returns unsupported, a reason, any known resolved settings, and no comparisons.

See the protocol specification for option values, schemas and custom adapters.

Results and exit codes

Human reports show status, coverage and pair witnesses with IDs, escaped original strings, Unicode code points and old/new signs. Findings appear once per unordered pair. --limit N limits displayed findings only; full JSON evidence remains available. compare --format json prints a deterministic report, and --json-output FILE saves it.

  • 0: complete CAPTURED or STABLE; informational commands.
  • 1: complete DRIFT with one or more findings.
  • 2: INCOMPLETE or DRIFT_INCOMPLETE. Valid partial or unsupported capture evidence is saved with this code.
  • 3: ERROR: invalid or incompatible inputs, corrupt digests, contradictory relations, malformed protocol, launch/crash/timeout or output-limit failure. Capture leaves an existing destination untouched.

Unknown comparisons are never treated as equality. Incomplete evidence can retain a finding when either direction of the pair was successfully observed on each side; this does not increase completed coverage or justify STABLE.

Saved runtime examples

The Node upgrade case compares official Node 18.20.8 and 24.21.0 binaries. It records an equality merge for ₨ / Rs and an order reversal for ₨ / 0, with repeated captures and offline reports. An unchanged sorted snapshot hides the equality change; a small deduplication example shows its application consequence.

The Node/browser case uses eight Icelandic names, Node 24.21.0 and Google Chrome for Testing 156.0.8078.4 on macOS arm64. Both support en and return STABLE on this corpus. Node supports is; this browser reports no supported lookup match and known resolved locale en-US. Strict offline comparison returns INCOMPLETE, zero findings. Fallback relations are not substituted for missing strict observations.

These are finite comparison experiments, not production incidents or evidence about every browser distribution. Newer builds may legitimately change locale support.

Evidence and guarantees

Captures embed the original corpus, requested profile, effective settings, runtime and adapter metadata, relation signs, explicit failures, coverage, invocation details, limits, diagnostics and a SHA-256 digest. Loading revalidates the digest, schema, coverage and finite-order consistency.

Compatible captures must have identical ID/value mappings and requested profiles, including locale spelling. Entry order may differ. Effective settings may differ and are reported for interpretation. Validation rejects nonzero self comparisons, nonzero comparisons of identical strings, contradictory reciprocals/equality and strict-order cycles. Partial validation checks only known constraints.

Transport bounds time and stdout/stderr output. The POSIX supervisor terminates the adapter process group on completion and failure. Capture files are written through a temporary file and atomically replaced after validation and serialization succeed.

A digest detects content alteration; it is not a signature or runtime authentication. Version labels and user agents are observations or adapter claims. Preserve executable provenance separately when it matters. Captures may include sensitive strings and argv.

Scope

Stability on a finite corpus says nothing about all Unicode strings. Drift means a change from the selected baseline, not a specification violation. CollationDelta does not implement UCA, supply locale data, repair sorting, validate database indexes, or establish SQL UNIQUE/GROUP BY behavior.

Unicode Conformance tests against Unicode/CLDR specifications. CollationDelta uses your saved comparator baseline. glibc-unicode-sorting studies sorting changes through PostgreSQL over large datasets. CollationDelta uses a bounded user corpus and explicit equality/order witnesses.

Development

uv sync --locked --python 3.10
uv run --locked ruff check .
uv run --locked ruff format --check .
uv run --locked pytest
uv build

See testing and environments for browser integration, supported-runtime coverage and packaging checks. See the changelog and release guide for release maintenance. The project uses the Apache-2.0 license.

Metadata

Release files for collationdelta 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for collationdelta 0.2.0
File Size Uploaded
collationdelta-0.2.0.tar.gz 89.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for collationdelta 0.2.0
File Interpreter ABI Platform
collationdelta-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 115.0 kB

Release files / collationdelta-0.2.0.tar.gz

Download URL collationdelta-0.2.0.tar.gz
Size 89.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6f850774ea9a314ecda7804d2ea0560fff020228e32b0321320e2ad34b7cf2a2
BLAKE2b-256 checksum
How to use checksums
e9d28f692bf4f90cc5f497f7ebad3120728aa1c8bc665c0affb6dcd2f56acfce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / collationdelta-0.2.0-py3-none-any.whl

Download URL collationdelta-0.2.0-py3-none-any.whl
Size 25.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bcb4b5155929ef5e43b59e9a410b57121cfe8af947537a8d27ce326cffdafaed
BLAKE2b-256 checksum
How to use checksums
260ea496540d8896765cdb3f625f01774dcb086380eedbd644406032dc09cb09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page