spreadsheet-auditor 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spreadsheet_auditor-0.1.0/LICENSE +21 -0
- spreadsheet_auditor-0.1.0/PKG-INFO +332 -0
- spreadsheet_auditor-0.1.0/README.md +265 -0
- spreadsheet_auditor-0.1.0/pyproject.toml +90 -0
- spreadsheet_auditor-0.1.0/setup.cfg +4 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/__init__.py +13 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/__main__.py +8 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/annotate.py +48 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/audit.py +761 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/__init__.py +35 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/base.py +74 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/data_hygiene.py +24 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/finance.py +202 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/formula_integrity.py +91 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/ranges.py +58 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/reconciliation.py +32 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/cli.py +17 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/config_loader.py +132 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/data_hygiene.py +115 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/demo/__init__.py +10 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/demo/demo_bad_budget.xlsx +0 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/dependency_graph.py +55 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/finding.py +136 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/formula_drift.py +128 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/formula_parser.py +110 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/materiality.py +22 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/preflight.py +53 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/py.typed +0 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/range_checks.py +299 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/recalc.py +63 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/reconcile.py +130 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/reference_resolver.py +61 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/report.py +399 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/sarif.py +141 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/suppressions.py +109 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor/workbook_inventory.py +93 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/PKG-INFO +332 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/SOURCES.txt +56 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/dependency_links.txt +1 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/entry_points.txt +2 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/requires.txt +22 -0
- spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/top_level.txt +1 -0
- spreadsheet_auditor-0.1.0/tests/test_checks.py +132 -0
- spreadsheet_auditor-0.1.0/tests/test_checks_registry.py +76 -0
- spreadsheet_auditor-0.1.0/tests/test_cli_ergonomics.py +56 -0
- spreadsheet_auditor-0.1.0/tests/test_confidence_drift.py +63 -0
- spreadsheet_auditor-0.1.0/tests/test_config_schema.py +39 -0
- spreadsheet_auditor-0.1.0/tests/test_corpus.py +65 -0
- spreadsheet_auditor-0.1.0/tests/test_exit_codes.py +69 -0
- spreadsheet_auditor-0.1.0/tests/test_finance_checks.py +98 -0
- spreadsheet_auditor-0.1.0/tests/test_finding_schema.py +80 -0
- spreadsheet_auditor-0.1.0/tests/test_healthcheck.py +46 -0
- spreadsheet_auditor-0.1.0/tests/test_html_output.py +95 -0
- spreadsheet_auditor-0.1.0/tests/test_perf_guardrails.py +78 -0
- spreadsheet_auditor-0.1.0/tests/test_run_metadata.py +78 -0
- spreadsheet_auditor-0.1.0/tests/test_sarif.py +141 -0
- spreadsheet_auditor-0.1.0/tests/test_skill_metadata.py +63 -0
- spreadsheet_auditor-0.1.0/tests/test_suppressions.py +106 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pete Hottelet
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spreadsheet-auditor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Audit existing Excel spreadsheets and financial models for correctness defects: formula errors, broken references, off-by-one ranges, reconciliation failures, circular references, hidden structure, and data-quality risks. Audit-only Agent Skill plus CLI.
|
|
5
|
+
Author: petehottelet
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Pete Hottelet
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/petehottelet/spreadsheet-auditor
|
|
29
|
+
Project-URL: Repository, https://github.com/petehottelet/spreadsheet-auditor
|
|
30
|
+
Project-URL: Issues, https://github.com/petehottelet/spreadsheet-auditor/issues
|
|
31
|
+
Project-URL: Changelog, https://github.com/petehottelet/spreadsheet-auditor/blob/main/CHANGELOG.md
|
|
32
|
+
Keywords: spreadsheet,excel,xlsx,xlsm,audit,auditing,financial-modeling,fpna,reconciliation,formula,data-quality,static-analysis,openpyxl,cli,agent-skill,claude,codex
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: OS Independent
|
|
39
|
+
Classifier: Programming Language :: Python :: 3
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
|
|
43
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
44
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
45
|
+
Classifier: Typing :: Typed
|
|
46
|
+
Requires-Python: >=3.11
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
License-File: LICENSE
|
|
49
|
+
Requires-Dist: openpyxl>=3.1
|
|
50
|
+
Provides-Extra: xml
|
|
51
|
+
Requires-Dist: defusedxml>=0.7; extra == "xml"
|
|
52
|
+
Provides-Extra: graph
|
|
53
|
+
Requires-Dist: networkx>=3.0; extra == "graph"
|
|
54
|
+
Provides-Extra: yaml
|
|
55
|
+
Requires-Dist: PyYAML>=6.0; extra == "yaml"
|
|
56
|
+
Provides-Extra: all
|
|
57
|
+
Requires-Dist: defusedxml>=0.7; extra == "all"
|
|
58
|
+
Requires-Dist: networkx>=3.0; extra == "all"
|
|
59
|
+
Requires-Dist: PyYAML>=6.0; extra == "all"
|
|
60
|
+
Provides-Extra: dev
|
|
61
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
62
|
+
Requires-Dist: jsonschema>=4.0; extra == "dev"
|
|
63
|
+
Requires-Dist: defusedxml>=0.7; extra == "dev"
|
|
64
|
+
Requires-Dist: networkx>=3.0; extra == "dev"
|
|
65
|
+
Requires-Dist: PyYAML>=6.0; extra == "dev"
|
|
66
|
+
Dynamic: license-file
|
|
67
|
+
|
|
68
|
+
<p align="center">
|
|
69
|
+
<img src="project_logo.png" alt="Spreadsheet Auditor logo" width="360">
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
<h1 align="center">Spreadsheet Auditor</h1>
|
|
73
|
+
|
|
74
|
+
<p align="center">
|
|
75
|
+
<strong>Audit existing Excel spreadsheets and financial models for correctness defects — formula errors, broken references, bad ranges, totals that don't reconcile, and data-quality risks.</strong>
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
<p align="center">
|
|
79
|
+
<a href="https://pypi.org/project/spreadsheet-auditor/"><img src="https://img.shields.io/pypi/v/spreadsheet-auditor.svg" alt="PyPI version"></a>
|
|
80
|
+
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="MIT License">
|
|
81
|
+
<img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+">
|
|
82
|
+
<img src="https://img.shields.io/badge/Claude%20%2B%20Codex-Agent%20Skill-orange.svg" alt="Claude + Codex Agent Skill">
|
|
83
|
+
<img src="https://img.shields.io/badge/formats-.xlsx%20%7C%20.xlsm%20%7C%20.csv-lightgrey.svg" alt="Supported formats">
|
|
84
|
+
<img src="https://img.shields.io/badge/output-md%20%7C%20json%20%7C%20html%20%7C%20sarif-blueviolet.svg" alt="Output formats">
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
`spreadsheet-auditor` is a portable [Agent Skill](https://agentskills.io/specification) for **Claude and Codex** (and a standalone command-line toolkit) that answers one question: **"Can I trust this spreadsheet?"**
|
|
90
|
+
|
|
91
|
+
Most spreadsheet tooling helps you *build* workbooks. This one *audits* a workbook you already have — often one you inherited — and returns a severity-ranked report of where it is likely wrong, fragile, or inconsistent. It is deterministic-first: bundled Python checks produce candidate findings with exact cell locations and evidence, so you are not eyeballing cells and guessing.
|
|
92
|
+
|
|
93
|
+
It is intentionally **audit-only**: it reports defects and optional annotations, but never silently rewrites, reformats, or "fixes" your source workbook.
|
|
94
|
+
|
|
95
|
+
> [!TIP]
|
|
96
|
+
> See the auditor in action without installing anything: open
|
|
97
|
+
> [`examples/demo_audit_report.md`](examples/demo_audit_report.md) or
|
|
98
|
+
> [`examples/demo_audit_report.html`](examples/demo_audit_report.html).
|
|
99
|
+
|
|
100
|
+
## Demo (60 seconds)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pip install "spreadsheet-auditor[all]"
|
|
104
|
+
spreadsheet-auditor --demo --summary
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Or against a workbook of your own:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
spreadsheet-auditor path/to/workbook.xlsx \
|
|
111
|
+
--out audit_report.md \
|
|
112
|
+
--json findings.json \
|
|
113
|
+
--annotated audit_annotated.xlsx
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
A complete demo lives in [`examples/`](examples/) with a generator
|
|
117
|
+
([`examples/make_demo.py`](examples/make_demo.py)), the seeded workbook, and
|
|
118
|
+
the resulting report/JSON/HTML/annotated outputs ready to inspect.
|
|
119
|
+
|
|
120
|
+
## Why use it
|
|
121
|
+
|
|
122
|
+
- **Pre-send model review** — de-risk an LBO/DCF/budget model before it
|
|
123
|
+
reaches an investment committee or counterparty.
|
|
124
|
+
- **"Find the error" debugging** — a number looks wrong and you need the
|
|
125
|
+
cell, not a guess.
|
|
126
|
+
- **Inherited-model trust assessment** — you didn't build it; check
|
|
127
|
+
whether it is trustworthy.
|
|
128
|
+
- **CI / batch gating** — fail a pipeline when a committed workbook has
|
|
129
|
+
Critical defects (see
|
|
130
|
+
[`examples/github-actions/`](examples/github-actions/)).
|
|
131
|
+
- **FP&A and month-end close** — catch reconciliation and range mistakes
|
|
132
|
+
in recurring workbooks.
|
|
133
|
+
|
|
134
|
+
## What it detects
|
|
135
|
+
|
|
136
|
+
| Category | Checks |
|
|
137
|
+
|---|---|
|
|
138
|
+
| Formula integrity | live errors (`#REF!`, `#DIV/0!`, `#VALUE!`, `#N/A`, ...), broken/deleted references, references to blank precedents, circular references, formula drift across a row/column, `IFERROR`/`IFNA` error masking |
|
|
139
|
+
| Hardcodes & inputs | numeric literals embedded in formulas, hardcoded plug values inside a formula block |
|
|
140
|
+
| Ranges | aggregate ranges that exclude adjacent data (off-by-one), ranges that include subtotal/total rows, inconsistent aggregate range lengths across peers, hidden rows/columns/sheets inside totals |
|
|
141
|
+
| Reconciliation | stated totals that differ from their components, row totals vs column totals that don't cross-foot |
|
|
142
|
+
| Logic & structure | volatile/fragile functions (`OFFSET`, `INDIRECT`, `NOW`, `RAND`, ...), whole-column references |
|
|
143
|
+
| Data hygiene | numbers stored as text, leading/trailing whitespace in keys/labels, duplicate lookup keys, merged cells inside data ranges |
|
|
144
|
+
| Finance (opt-in HEUR) | balance-sheet balance, sign convention on revenue/expense rows, quarterly period sequencing |
|
|
145
|
+
|
|
146
|
+
Each finding carries a detection mode (`DET` deterministic / `HEUR` heuristic),
|
|
147
|
+
an error-confidence level (`Defect` / `Likely defect` / `Review` / `Info`), a
|
|
148
|
+
severity, evidence, and a suggested fix. Full rule list:
|
|
149
|
+
[`references/check_catalog.md`](references/check_catalog.md).
|
|
150
|
+
|
|
151
|
+
The seeded-defect benchmark is published at
|
|
152
|
+
[`benchmarks/seeded_defects_matrix.md`](benchmarks/seeded_defects_matrix.md);
|
|
153
|
+
methodology at
|
|
154
|
+
[`references/benchmark_methodology.md`](references/benchmark_methodology.md).
|
|
155
|
+
|
|
156
|
+
## Install
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pip install spreadsheet-auditor # core + .xlsx/.xlsm/.csv audit
|
|
160
|
+
pip install "spreadsheet-auditor[all]" # adds defusedxml, networkx, PyYAML
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For local development:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
git clone https://github.com/petehottelet/spreadsheet-auditor.git
|
|
167
|
+
cd spreadsheet-auditor
|
|
168
|
+
pip install -e ".[dev]"
|
|
169
|
+
spreadsheet-auditor --healthcheck
|
|
170
|
+
python -m pytest tests -q
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Releases (signed source archive + Claude/Codex skill zips + SHA-256
|
|
174
|
+
checksums) are published from the
|
|
175
|
+
[Releases page](https://github.com/petehottelet/spreadsheet-auditor/releases).
|
|
176
|
+
|
|
177
|
+
## Run
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Quick look in the terminal
|
|
181
|
+
spreadsheet-auditor model.xlsx
|
|
182
|
+
|
|
183
|
+
# Write artifacts in every supported format
|
|
184
|
+
spreadsheet-auditor model.xlsx \
|
|
185
|
+
--out report.md \
|
|
186
|
+
--json findings.json \
|
|
187
|
+
--annotated annotated.xlsx
|
|
188
|
+
spreadsheet-auditor model.xlsx --format html --out report.html
|
|
189
|
+
spreadsheet-auditor model.xlsx --format sarif --out report.sarif
|
|
190
|
+
|
|
191
|
+
# CI-friendly: one-screen summary + non-zero exit on High-or-worse
|
|
192
|
+
spreadsheet-auditor model.xlsx --summary --fail-on High
|
|
193
|
+
|
|
194
|
+
# Bundled demo for a 60-second tour
|
|
195
|
+
spreadsheet-auditor --demo --summary
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
See `spreadsheet-auditor --help` for the full flag reference, including
|
|
199
|
+
`--strict`, `--show-suppressed`, `--quiet`, `--config`, `--ignore`,
|
|
200
|
+
`--recalc-timeout`, and `--healthcheck --json`.
|
|
201
|
+
|
|
202
|
+
## Outputs
|
|
203
|
+
|
|
204
|
+
- **Markdown report** for human review, grouped by `Confirmed`/`Likely`/`Review`
|
|
205
|
+
buckets so the worst items are easy to triage.
|
|
206
|
+
- **HTML report** for browser review or sharing with non-technical reviewers
|
|
207
|
+
(self-contained, no network).
|
|
208
|
+
- **JSON findings** for reruns, CI, and downstream tooling. Validates against
|
|
209
|
+
[`schemas/findings.schema.json`](schemas/findings.schema.json). Each finding
|
|
210
|
+
carries a stable `fingerprint` for diffing across runs and for fingerprint-
|
|
211
|
+
based suppression.
|
|
212
|
+
- **SARIF 2.1.0** for GitHub code scanning. See
|
|
213
|
+
[`examples/github-actions/code-scanning.yml`](examples/github-actions/code-scanning.yml).
|
|
214
|
+
- **Annotated workbook copy** with comments at finding cells (`--annotated`).
|
|
215
|
+
The source workbook is never modified.
|
|
216
|
+
|
|
217
|
+
## Exit codes
|
|
218
|
+
|
|
219
|
+
| Code | Meaning |
|
|
220
|
+
|---:|---|
|
|
221
|
+
| 0 | Completed; no findings at or above `--fail-on` |
|
|
222
|
+
| 1 | Completed; findings at or above `--fail-on` |
|
|
223
|
+
| 2 | Completed with coverage limitations (only with `--strict` or `--fail-on None`) |
|
|
224
|
+
| 3 | Healthcheck failed: required dependency missing |
|
|
225
|
+
| 4 | Preflight/security failure |
|
|
226
|
+
| 5 | Internal error |
|
|
227
|
+
|
|
228
|
+
Benign limitations (no recalculation engine, missing optional packages) do not
|
|
229
|
+
fail a normal run. Use `--strict` to surface them as exit code `2` in CI.
|
|
230
|
+
|
|
231
|
+
## Agent Skill usage
|
|
232
|
+
|
|
233
|
+
Drop the Claude/Codex zip from the release into your Skills folder, or load it
|
|
234
|
+
directly with [Cursor](https://cursor.com/) Skills. Ask the agent something
|
|
235
|
+
like:
|
|
236
|
+
|
|
237
|
+
> "Audit `Q3_Forecast.xlsx` and tell me what's wrong with it. Write the report
|
|
238
|
+
> to `audit_report.md` and produce an annotated copy."
|
|
239
|
+
|
|
240
|
+
The skill maps the request onto the bundled CLI invocation and surfaces the
|
|
241
|
+
findings inline.
|
|
242
|
+
|
|
243
|
+
## Configuration
|
|
244
|
+
|
|
245
|
+
Optional config file (JSON or YAML) controls scope, materiality, suppression,
|
|
246
|
+
performance limits, and which checks fire. Schema:
|
|
247
|
+
[`schemas/config.schema.json`](schemas/config.schema.json).
|
|
248
|
+
|
|
249
|
+
Example:
|
|
250
|
+
|
|
251
|
+
```yaml
|
|
252
|
+
scope:
|
|
253
|
+
include_sheets: [Budget, Summary]
|
|
254
|
+
headline_outputs: [Summary!C1, Summary!C2]
|
|
255
|
+
materiality:
|
|
256
|
+
absolute: 1000.0
|
|
257
|
+
relative: 0.001
|
|
258
|
+
finance:
|
|
259
|
+
enabled: true # turn on the finance HEUR pack
|
|
260
|
+
limits:
|
|
261
|
+
max_formulas: 50000
|
|
262
|
+
timeout_seconds: 120
|
|
263
|
+
max_reported_findings: 200
|
|
264
|
+
checks:
|
|
265
|
+
IFERROR_MASK: review # warn instead of error
|
|
266
|
+
LITERAL_CONSTANT: off
|
|
267
|
+
suppressions:
|
|
268
|
+
- rule_id: BROKEN_REFERENCE
|
|
269
|
+
range: Imports!A1:A100
|
|
270
|
+
reason: External feed populated at runtime; cells start empty.
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Safety
|
|
274
|
+
|
|
275
|
+
Spreadsheet files are treated as untrusted input. Macros are inventoried but
|
|
276
|
+
never executed, external links are inventoried but never followed,
|
|
277
|
+
recalculation runs headless in an isolated profile, and the original workbook
|
|
278
|
+
is never overwritten. Details in
|
|
279
|
+
[`SECURITY.md`](SECURITY.md) and
|
|
280
|
+
[`references/limitations.md`](references/limitations.md).
|
|
281
|
+
|
|
282
|
+
## Limitations
|
|
283
|
+
|
|
284
|
+
Excel-specific behavior is approximated via LibreOffice. Value-dependent checks
|
|
285
|
+
(`TOTAL_MISMATCH`, `CROSS_FOOT_FAILURE`) require either recalculation
|
|
286
|
+
(LibreOffice/Calc) or cached values written by Excel. Dynamic arrays, data
|
|
287
|
+
tables, Power Query/Data Model, and macros are *inventoried but not executed*.
|
|
288
|
+
Full list:
|
|
289
|
+
[`references/limitations.md`](references/limitations.md).
|
|
290
|
+
|
|
291
|
+
Google Sheets: export to `.xlsx` and audit that. There is no native Sheets API
|
|
292
|
+
integration. See
|
|
293
|
+
[`references/google_sheets.md`](references/google_sheets.md) for a recipe.
|
|
294
|
+
|
|
295
|
+
## FAQ
|
|
296
|
+
|
|
297
|
+
**Does it fix my spreadsheet?** No. It reports defect candidates with
|
|
298
|
+
suggested fixes; applying changes is a separate, explicit step.
|
|
299
|
+
|
|
300
|
+
**Is this an accounting or audit certification?** No. It flags likely defects
|
|
301
|
+
and review items; it does not certify business, accounting, tax, or legal
|
|
302
|
+
correctness.
|
|
303
|
+
|
|
304
|
+
**Does it work without Excel installed?** Yes. It reads workbooks with
|
|
305
|
+
`openpyxl`. LibreOffice is optional and only used to refresh cached values for
|
|
306
|
+
value-dependent checks.
|
|
307
|
+
|
|
308
|
+
**Does it support Google Sheets?** Not directly. Export to `.xlsx` and audit
|
|
309
|
+
that.
|
|
310
|
+
|
|
311
|
+
**How are false positives handled?** Suppress them by `(rule_id, range, reason)`
|
|
312
|
+
or by `fingerprint`. A reason is required; suppressions missing a reason are
|
|
313
|
+
ignored and called out in the report's coverage limitations. Suppressed findings
|
|
314
|
+
stay in the JSON payload (auditable) but are hidden from the report unless
|
|
315
|
+
`--show-suppressed` is passed.
|
|
316
|
+
|
|
317
|
+
## Contributing
|
|
318
|
+
|
|
319
|
+
We welcome new checks, additional test workbooks, and benchmark improvements.
|
|
320
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) and
|
|
321
|
+
[`references/custom_checks.md`](references/custom_checks.md).
|
|
322
|
+
|
|
323
|
+
## License
|
|
324
|
+
|
|
325
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
<sub>Topics: spreadsheet audit, excel auditor, xlsx, xlsm, financial model
|
|
330
|
+
review, formula error checker, reconciliation, cross-foot, range check,
|
|
331
|
+
circular reference detection, data quality, openpyxl, python, CLI, agent
|
|
332
|
+
skill, static analysis, claude, codex, FP&A, financial modeling, fpna.</sub>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="project_logo.png" alt="Spreadsheet Auditor logo" width="360">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Spreadsheet Auditor</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Audit existing Excel spreadsheets and financial models for correctness defects — formula errors, broken references, bad ranges, totals that don't reconcile, and data-quality risks.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://pypi.org/project/spreadsheet-auditor/"><img src="https://img.shields.io/pypi/v/spreadsheet-auditor.svg" alt="PyPI version"></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="MIT License">
|
|
14
|
+
<img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+">
|
|
15
|
+
<img src="https://img.shields.io/badge/Claude%20%2B%20Codex-Agent%20Skill-orange.svg" alt="Claude + Codex Agent Skill">
|
|
16
|
+
<img src="https://img.shields.io/badge/formats-.xlsx%20%7C%20.xlsm%20%7C%20.csv-lightgrey.svg" alt="Supported formats">
|
|
17
|
+
<img src="https://img.shields.io/badge/output-md%20%7C%20json%20%7C%20html%20%7C%20sarif-blueviolet.svg" alt="Output formats">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
`spreadsheet-auditor` is a portable [Agent Skill](https://agentskills.io/specification) for **Claude and Codex** (and a standalone command-line toolkit) that answers one question: **"Can I trust this spreadsheet?"**
|
|
23
|
+
|
|
24
|
+
Most spreadsheet tooling helps you *build* workbooks. This one *audits* a workbook you already have — often one you inherited — and returns a severity-ranked report of where it is likely wrong, fragile, or inconsistent. It is deterministic-first: bundled Python checks produce candidate findings with exact cell locations and evidence, so you are not eyeballing cells and guessing.
|
|
25
|
+
|
|
26
|
+
It is intentionally **audit-only**: it reports defects and optional annotations, but never silently rewrites, reformats, or "fixes" your source workbook.
|
|
27
|
+
|
|
28
|
+
> [!TIP]
|
|
29
|
+
> See the auditor in action without installing anything: open
|
|
30
|
+
> [`examples/demo_audit_report.md`](examples/demo_audit_report.md) or
|
|
31
|
+
> [`examples/demo_audit_report.html`](examples/demo_audit_report.html).
|
|
32
|
+
|
|
33
|
+
## Demo (60 seconds)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install "spreadsheet-auditor[all]"
|
|
37
|
+
spreadsheet-auditor --demo --summary
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or against a workbook of your own:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
spreadsheet-auditor path/to/workbook.xlsx \
|
|
44
|
+
--out audit_report.md \
|
|
45
|
+
--json findings.json \
|
|
46
|
+
--annotated audit_annotated.xlsx
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A complete demo lives in [`examples/`](examples/) with a generator
|
|
50
|
+
([`examples/make_demo.py`](examples/make_demo.py)), the seeded workbook, and
|
|
51
|
+
the resulting report/JSON/HTML/annotated outputs ready to inspect.
|
|
52
|
+
|
|
53
|
+
## Why use it
|
|
54
|
+
|
|
55
|
+
- **Pre-send model review** — de-risk an LBO/DCF/budget model before it
|
|
56
|
+
reaches an investment committee or counterparty.
|
|
57
|
+
- **"Find the error" debugging** — a number looks wrong and you need the
|
|
58
|
+
cell, not a guess.
|
|
59
|
+
- **Inherited-model trust assessment** — you didn't build it; check
|
|
60
|
+
whether it is trustworthy.
|
|
61
|
+
- **CI / batch gating** — fail a pipeline when a committed workbook has
|
|
62
|
+
Critical defects (see
|
|
63
|
+
[`examples/github-actions/`](examples/github-actions/)).
|
|
64
|
+
- **FP&A and month-end close** — catch reconciliation and range mistakes
|
|
65
|
+
in recurring workbooks.
|
|
66
|
+
|
|
67
|
+
## What it detects
|
|
68
|
+
|
|
69
|
+
| Category | Checks |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Formula integrity | live errors (`#REF!`, `#DIV/0!`, `#VALUE!`, `#N/A`, ...), broken/deleted references, references to blank precedents, circular references, formula drift across a row/column, `IFERROR`/`IFNA` error masking |
|
|
72
|
+
| Hardcodes & inputs | numeric literals embedded in formulas, hardcoded plug values inside a formula block |
|
|
73
|
+
| Ranges | aggregate ranges that exclude adjacent data (off-by-one), ranges that include subtotal/total rows, inconsistent aggregate range lengths across peers, hidden rows/columns/sheets inside totals |
|
|
74
|
+
| Reconciliation | stated totals that differ from their components, row totals vs column totals that don't cross-foot |
|
|
75
|
+
| Logic & structure | volatile/fragile functions (`OFFSET`, `INDIRECT`, `NOW`, `RAND`, ...), whole-column references |
|
|
76
|
+
| Data hygiene | numbers stored as text, leading/trailing whitespace in keys/labels, duplicate lookup keys, merged cells inside data ranges |
|
|
77
|
+
| Finance (opt-in HEUR) | balance-sheet balance, sign convention on revenue/expense rows, quarterly period sequencing |
|
|
78
|
+
|
|
79
|
+
Each finding carries a detection mode (`DET` deterministic / `HEUR` heuristic),
|
|
80
|
+
an error-confidence level (`Defect` / `Likely defect` / `Review` / `Info`), a
|
|
81
|
+
severity, evidence, and a suggested fix. Full rule list:
|
|
82
|
+
[`references/check_catalog.md`](references/check_catalog.md).
|
|
83
|
+
|
|
84
|
+
The seeded-defect benchmark is published at
|
|
85
|
+
[`benchmarks/seeded_defects_matrix.md`](benchmarks/seeded_defects_matrix.md);
|
|
86
|
+
methodology at
|
|
87
|
+
[`references/benchmark_methodology.md`](references/benchmark_methodology.md).
|
|
88
|
+
|
|
89
|
+
## Install
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install spreadsheet-auditor # core + .xlsx/.xlsm/.csv audit
|
|
93
|
+
pip install "spreadsheet-auditor[all]" # adds defusedxml, networkx, PyYAML
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
For local development:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git clone https://github.com/petehottelet/spreadsheet-auditor.git
|
|
100
|
+
cd spreadsheet-auditor
|
|
101
|
+
pip install -e ".[dev]"
|
|
102
|
+
spreadsheet-auditor --healthcheck
|
|
103
|
+
python -m pytest tests -q
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Releases (signed source archive + Claude/Codex skill zips + SHA-256
|
|
107
|
+
checksums) are published from the
|
|
108
|
+
[Releases page](https://github.com/petehottelet/spreadsheet-auditor/releases).
|
|
109
|
+
|
|
110
|
+
## Run
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Quick look in the terminal
|
|
114
|
+
spreadsheet-auditor model.xlsx
|
|
115
|
+
|
|
116
|
+
# Write artifacts in every supported format
|
|
117
|
+
spreadsheet-auditor model.xlsx \
|
|
118
|
+
--out report.md \
|
|
119
|
+
--json findings.json \
|
|
120
|
+
--annotated annotated.xlsx
|
|
121
|
+
spreadsheet-auditor model.xlsx --format html --out report.html
|
|
122
|
+
spreadsheet-auditor model.xlsx --format sarif --out report.sarif
|
|
123
|
+
|
|
124
|
+
# CI-friendly: one-screen summary + non-zero exit on High-or-worse
|
|
125
|
+
spreadsheet-auditor model.xlsx --summary --fail-on High
|
|
126
|
+
|
|
127
|
+
# Bundled demo for a 60-second tour
|
|
128
|
+
spreadsheet-auditor --demo --summary
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
See `spreadsheet-auditor --help` for the full flag reference, including
|
|
132
|
+
`--strict`, `--show-suppressed`, `--quiet`, `--config`, `--ignore`,
|
|
133
|
+
`--recalc-timeout`, and `--healthcheck --json`.
|
|
134
|
+
|
|
135
|
+
## Outputs
|
|
136
|
+
|
|
137
|
+
- **Markdown report** for human review, grouped by `Confirmed`/`Likely`/`Review`
|
|
138
|
+
buckets so the worst items are easy to triage.
|
|
139
|
+
- **HTML report** for browser review or sharing with non-technical reviewers
|
|
140
|
+
(self-contained, no network).
|
|
141
|
+
- **JSON findings** for reruns, CI, and downstream tooling. Validates against
|
|
142
|
+
[`schemas/findings.schema.json`](schemas/findings.schema.json). Each finding
|
|
143
|
+
carries a stable `fingerprint` for diffing across runs and for fingerprint-
|
|
144
|
+
based suppression.
|
|
145
|
+
- **SARIF 2.1.0** for GitHub code scanning. See
|
|
146
|
+
[`examples/github-actions/code-scanning.yml`](examples/github-actions/code-scanning.yml).
|
|
147
|
+
- **Annotated workbook copy** with comments at finding cells (`--annotated`).
|
|
148
|
+
The source workbook is never modified.
|
|
149
|
+
|
|
150
|
+
## Exit codes
|
|
151
|
+
|
|
152
|
+
| Code | Meaning |
|
|
153
|
+
|---:|---|
|
|
154
|
+
| 0 | Completed; no findings at or above `--fail-on` |
|
|
155
|
+
| 1 | Completed; findings at or above `--fail-on` |
|
|
156
|
+
| 2 | Completed with coverage limitations (only with `--strict` or `--fail-on None`) |
|
|
157
|
+
| 3 | Healthcheck failed: required dependency missing |
|
|
158
|
+
| 4 | Preflight/security failure |
|
|
159
|
+
| 5 | Internal error |
|
|
160
|
+
|
|
161
|
+
Benign limitations (no recalculation engine, missing optional packages) do not
|
|
162
|
+
fail a normal run. Use `--strict` to surface them as exit code `2` in CI.
|
|
163
|
+
|
|
164
|
+
## Agent Skill usage
|
|
165
|
+
|
|
166
|
+
Drop the Claude/Codex zip from the release into your Skills folder, or load it
|
|
167
|
+
directly with [Cursor](https://cursor.com/) Skills. Ask the agent something
|
|
168
|
+
like:
|
|
169
|
+
|
|
170
|
+
> "Audit `Q3_Forecast.xlsx` and tell me what's wrong with it. Write the report
|
|
171
|
+
> to `audit_report.md` and produce an annotated copy."
|
|
172
|
+
|
|
173
|
+
The skill maps the request onto the bundled CLI invocation and surfaces the
|
|
174
|
+
findings inline.
|
|
175
|
+
|
|
176
|
+
## Configuration
|
|
177
|
+
|
|
178
|
+
Optional config file (JSON or YAML) controls scope, materiality, suppression,
|
|
179
|
+
performance limits, and which checks fire. Schema:
|
|
180
|
+
[`schemas/config.schema.json`](schemas/config.schema.json).
|
|
181
|
+
|
|
182
|
+
Example:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
scope:
|
|
186
|
+
include_sheets: [Budget, Summary]
|
|
187
|
+
headline_outputs: [Summary!C1, Summary!C2]
|
|
188
|
+
materiality:
|
|
189
|
+
absolute: 1000.0
|
|
190
|
+
relative: 0.001
|
|
191
|
+
finance:
|
|
192
|
+
enabled: true # turn on the finance HEUR pack
|
|
193
|
+
limits:
|
|
194
|
+
max_formulas: 50000
|
|
195
|
+
timeout_seconds: 120
|
|
196
|
+
max_reported_findings: 200
|
|
197
|
+
checks:
|
|
198
|
+
IFERROR_MASK: review # warn instead of error
|
|
199
|
+
LITERAL_CONSTANT: off
|
|
200
|
+
suppressions:
|
|
201
|
+
- rule_id: BROKEN_REFERENCE
|
|
202
|
+
range: Imports!A1:A100
|
|
203
|
+
reason: External feed populated at runtime; cells start empty.
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Safety
|
|
207
|
+
|
|
208
|
+
Spreadsheet files are treated as untrusted input. Macros are inventoried but
|
|
209
|
+
never executed, external links are inventoried but never followed,
|
|
210
|
+
recalculation runs headless in an isolated profile, and the original workbook
|
|
211
|
+
is never overwritten. Details in
|
|
212
|
+
[`SECURITY.md`](SECURITY.md) and
|
|
213
|
+
[`references/limitations.md`](references/limitations.md).
|
|
214
|
+
|
|
215
|
+
## Limitations
|
|
216
|
+
|
|
217
|
+
Excel-specific behavior is approximated via LibreOffice. Value-dependent checks
|
|
218
|
+
(`TOTAL_MISMATCH`, `CROSS_FOOT_FAILURE`) require either recalculation
|
|
219
|
+
(LibreOffice/Calc) or cached values written by Excel. Dynamic arrays, data
|
|
220
|
+
tables, Power Query/Data Model, and macros are *inventoried but not executed*.
|
|
221
|
+
Full list:
|
|
222
|
+
[`references/limitations.md`](references/limitations.md).
|
|
223
|
+
|
|
224
|
+
Google Sheets: export to `.xlsx` and audit that. There is no native Sheets API
|
|
225
|
+
integration. See
|
|
226
|
+
[`references/google_sheets.md`](references/google_sheets.md) for a recipe.
|
|
227
|
+
|
|
228
|
+
## FAQ
|
|
229
|
+
|
|
230
|
+
**Does it fix my spreadsheet?** No. It reports defect candidates with
|
|
231
|
+
suggested fixes; applying changes is a separate, explicit step.
|
|
232
|
+
|
|
233
|
+
**Is this an accounting or audit certification?** No. It flags likely defects
|
|
234
|
+
and review items; it does not certify business, accounting, tax, or legal
|
|
235
|
+
correctness.
|
|
236
|
+
|
|
237
|
+
**Does it work without Excel installed?** Yes. It reads workbooks with
|
|
238
|
+
`openpyxl`. LibreOffice is optional and only used to refresh cached values for
|
|
239
|
+
value-dependent checks.
|
|
240
|
+
|
|
241
|
+
**Does it support Google Sheets?** Not directly. Export to `.xlsx` and audit
|
|
242
|
+
that.
|
|
243
|
+
|
|
244
|
+
**How are false positives handled?** Suppress them by `(rule_id, range, reason)`
|
|
245
|
+
or by `fingerprint`. A reason is required; suppressions missing a reason are
|
|
246
|
+
ignored and called out in the report's coverage limitations. Suppressed findings
|
|
247
|
+
stay in the JSON payload (auditable) but are hidden from the report unless
|
|
248
|
+
`--show-suppressed` is passed.
|
|
249
|
+
|
|
250
|
+
## Contributing
|
|
251
|
+
|
|
252
|
+
We welcome new checks, additional test workbooks, and benchmark improvements.
|
|
253
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) and
|
|
254
|
+
[`references/custom_checks.md`](references/custom_checks.md).
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
<sub>Topics: spreadsheet audit, excel auditor, xlsx, xlsm, financial model
|
|
263
|
+
review, formula error checker, reconciliation, cross-foot, range check,
|
|
264
|
+
circular reference detection, data quality, openpyxl, python, CLI, agent
|
|
265
|
+
skill, static analysis, claude, codex, FP&A, financial modeling, fpna.</sub>
|