spreadsheet-guard
A standalone, read-only preservation gate for .xlsx and .xlsm files.
Compare an original workbook with a candidate produced by an agent, script, or
library. spreadsheet-guard audits OOXML structure, formulas, cached values, and
feature relationships without modifying either input. It emits deterministic
JSON and automation-friendly exit codes.
- MIT licensed
- No proprietary runtime or service dependency
- Local files only
- Fail-closed on invalid or incomplete evidence
Install and audit
Requires Python 3.11 or newer.
pip install spreadsheet-guard
spreadsheet-guard before.xlsx after.xlsx --output preservation-report.json
The command writes the complete report to preservation-report.json and a
one-line summary to stdout:
{"report": "preservation-report.json", "schema_version": 1, "status": "passed"}
| Status | Exit code | Meaning |
|---|---|---|
passed |
0 | Every configured preservation dimension passed. |
failed |
1 | At least one configured dimension found a regression. |
unassessed |
1 | Required evidence was unavailable or a dimension was disabled. |
error |
2 | Inputs, policy, or execution were invalid. |
Run the checked-in proof
From a clone of this repository, these commands target bash or zsh and use repo-relative paths:
uv sync
uv run spreadsheet-guard \
examples/formula-integrity/before.xlsx \
examples/formula-integrity/after-intact.xlsx \
--output /tmp/spreadsheet-guard-passed.json
uv run spreadsheet-guard \
examples/formula-integrity/before.xlsx \
examples/formula-integrity/after-formula-damaged.xlsx \
--output /tmp/spreadsheet-guard-failed.json
The first command exits 0 with passed. The second exits 1 with failed
because SUM(A1:A2) changed to SUM(A1:A1). The frozen reports are checked in
at:
This compact proof demonstrates the packaged engine and report contract. It does not establish universal Excel compatibility or business-output correctness.
What it checks
The default policy requires all five dimensions to remain unchanged:
- Macro inventory
- External-link inventory
- Worksheet inventory and names
- Formula integrity
- OOXML package integrity
Package integrity checks part relationships, XML parseability, cached formula values, and semantic fingerprints for workbook features such as charts, defined names, data validation, conditional formatting, drawings, external links, and pivot-related metadata.
The strict default also reports intentional formula or structural changes. The caller must compare each finding with the intended edit.
Custom policy
Pass --policy policy.json to replace the strict default:
spreadsheet-guard before.xlsx after.xlsx \
--output preservation-report.json \
--policy policy.json
{
"macro_inventory": {"mode": "unchanged"},
"external_link_inventory": {"mode": "unchanged"},
"worksheet_inventory": {
"mode": "unchanged",
"expected_names": ["Inputs", "Model", "Outputs"]
},
"formula_integrity": {"mode": "unchanged"},
"package_integrity": {"mode": "unchanged"}
}
A custom policy should enumerate all five dimensions when a passed result is
required. A dimension set to null is reported as unassessed.
Python API
from pathlib import Path
from spreadsheet_guard import guard_workbooks
outcome = guard_workbooks(
Path("before.xlsx"),
Path("after.xlsx"),
Path("preservation-report.json"),
)
print(outcome.status)
Limits
- The Guard evaluates preservation. It does not determine whether formulas, assumptions, or business logic are correct.
- The Guard is read-only. It reports findings and does not repair either workbook.
- Inputs are limited to OOXML
.xlsxand.xlsmworkbooks. - A clean report applies only to the configured dimensions and the supplied before-and-after pair.
Write with a commit gate
WolfXL applies policy before a workbook
write, runs independent verification, and commits only accepted candidates.
spreadsheet-guard is the free, read-only audit surface.
License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spreadsheet_guard-0.1.0.tar.gz.
File metadata
- Download URL: spreadsheet_guard-0.1.0.tar.gz
- Upload date:
- Size: 67.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
577103e9ef4946d021e17fd457646d12318a50574048eca4fc1ac1a05fa4f6e4
|
|
| MD5 |
c6a140fa80178270ce48ed39a209b725
|
|
| BLAKE2b-256 |
bdbbdc69aac93941746342d2ef7ddb0a805bdd1b89d075647141a5b42e6069bb
|
File details
Details for the file spreadsheet_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: spreadsheet_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef952b474827356d381a1f9e3ddb724f950229ebd7ddd3204940b100ea83e47f
|
|
| MD5 |
42c091c5c52b8dce7876180edae4c3f5
|
|
| BLAKE2b-256 |
00dba2d8b201466dc9ab2d39483bb9adf85bfe451fd1e44cfc4655796a77d97f
|