Skip to content
langacorpPublic

About

Measure whether the copies that should be identical still are. Divergence is a fact; choosing the right version is a decision AEGIS leaves to a person.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Repository files navigation

samecheck

self-test DOI

Measure whether the copies that should be identical still are — and never say which one is right.

The defect it was born from

2026-08-27. Two measurements on the same day, in the same estate:

One configuration file existed in 29 copies, in 4 distinct versions, under 3 different naming conventions. Nobody knew that until it was counted.

Separately, one of our own components — a plugin running on dozens of client sites we operate — was found in 6 distinct contents and declared only 3 version numbers — including one install that claimed the same version as the majority while differing from it, and one that carried the highest version number while having lost five files the others had.

Both findings share a shape: the declared version number does not identify the content. It is a declared value, not a measured one. Anything that trusts it is counting wrong, and no completeness check will notice, because the field is full.

What it does

For every copy it builds a manifest — sha256 per file, relative path — and reduces it to one fingerprint: sha256 over the sorted digest-and-path lines.

Sorting is not cosmetic. os.walk does not guarantee an order, and without a stable one two identical copies produce two different fingerprints; the tool would report divergence everywhere and mean nothing by it.

Then it:

  • groups by content, never by name and never by declared version;
  • compares the declared version against the measured content, and names the contradiction when the same claimed version covers different contents. A tool that only groups by content sees those as two ordinary variants rather than as a lie;
  • shows the three-set difference between groups: only in A, only in B, and in both but different. The third set is the one that distinguishes a superset from a divergent branch. Without it, a copy with two extra files looks like a newer version even when it has lost five others.

What it will not do

It will not tell you which copy is the correct one, and it will not align anything.

Choosing is a decision. A tool that decides quietly will one day overwrite the copy that had the thing nobody else had — the translation, the local fix, the field that was only ever set in one place.

Coverage is always declared

Every run states how many copies were measured out of how many declared, how many files were read, which copies were missing, which files and directories could not be read, and what was excluded.

A directory that cannot be listed, and a symlink to a directory, are not entered. Both are named in the coverage, because every file inside them is left out of the comparison. A FIFO or device is not read and is counted as unreadable.

If an include filter was used, the run says so — divergence outside the filter was not measured. Measured divergence is a lower bound, never an upper one. A partial coverage can call two things identical when they are not, and it always errs in the same direction.

A run that measured nothing prints NOTHING WAS MEASURED. This is not a pass. and exits 2. That includes a run where the copies exist but no file was read in any of them — an include that matches nothing, for example. Equal empty manifests are not evidence that the copies are the same.

Install

None needed. Python 3.9+, standard library only. The single file runs as it is:

curl -O https://raw.githubusercontent.com/langacorp/samecheck/main/samecheck.py
python3 samecheck.py --selftest

Or install it from git, which puts a samecheck command on the path. It is not published on PyPI.

pipx install git+https://github.com/langacorp/samecheck
pip install git+https://github.com/langacorp/samecheck
samecheck --selftest

Prove it before you trust it

python3 samecheck.py --selftest

Five directions, all asserted, any one failing fails the test:

  1. must fire on copies that differ — one by a changed file, one by an added file
  2. must stay silent on identical copies, including when one has a node_modules the other lacks
  3. must name the contradiction — same declared version, different content
  4. must not look like a pass when nothing was measured
  5. the fingerprint must not depend on file order — the same manifest fed in reverse must produce the same fingerprint

The unit tests in tests/ check each part on its own, in both directions:

python3 -m unittest discover -s tests -v

Use

python3 samecheck.py /srv/site-a/plugin /srv/site-b/plugin /srv/site-c/plugin
python3 samecheck.py -c copies.json --json

copies.example.json:

{
  "copies": [
    "/srv/site-a/wp-content/plugins/example",
    "/srv/site-b/wp-content/plugins/example"
  ],
  "exclude": ["node_modules", ".git", "cache"],
  "include": "\\.php$",
  "declared_version": {
    "file": "example.php",
    "pattern": "Version:\\s*([0-9.]+)"
  }
}

declared_version is optional; without it the tool groups by content only and cannot name contradictions. Its pattern needs one capture group.

--exclude and --include on the command line also apply next to a config: --exclude adds to its list, --include replaces its filter. An exclude with a slash, such as vendor/bin, matches that run of directories at any depth.

A copy can be a single file. Its name is not part of the fingerprint, so the same content kept as config.php and config-old.php is one content.

Exit codes: 0 one content · 1 divergence found · 2 nothing was measured, or the config or a regex could not be used. The same codes apply with --json.

Limits, stated

  • It compares files on disk. Database rows, registered cron jobs and licence state are not files, are not measured, and can make two copies with the same fingerprint behave differently.
  • Two files can be functionally equivalent and byte-different — a timestamp in a header, different line endings. Those are reported as divergence, because they are, and deciding they do not matter is a decision.
  • --include makes a run faster and the answer smaller. It never makes it safer.

The other tools

Each came out of a defect measured on our own estate. Each one is standalone and depends on none of the others.

  • realroute — checks that a route really exists, by content and not by status code.
  • leakform — finds secrets in a git repository by shape, across every ref.
  • provenreal — compares what a system claims with what can be measured, from independent sources.
  • countdrift — finds numbers written by hand that no longer match their source.
  • kemproof — attests that an ML-KEM-768 key exchange really happened. It does not encrypt anything.

The set is kept on the organisation profile. It is not written here as a count, because a number typed by hand is the thing countdrift exists to find.

Where this comes from

LANGA runs an ecosystem of digital services on its own infrastructure. This tool came out of a defect we hit while running them: the same component installed in many places, quietly no longer the same. Those places are:

  • LANGA — the ecosystem
  • Drive In — marketing packages for local business
  • LANGA Tools — WordPress toolkit for developers
  • eFruit — food marketplace for local producers

See How we work.


License

MIT. See LICENSE.


Built and maintained by LANGA.

About

Measure whether the copies that should be identical still are. Divergence is a fact; choosing the right version is a decision AEGIS leaves to a person.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages