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.
Files changed (58) hide show
  1. spreadsheet_auditor-0.1.0/LICENSE +21 -0
  2. spreadsheet_auditor-0.1.0/PKG-INFO +332 -0
  3. spreadsheet_auditor-0.1.0/README.md +265 -0
  4. spreadsheet_auditor-0.1.0/pyproject.toml +90 -0
  5. spreadsheet_auditor-0.1.0/setup.cfg +4 -0
  6. spreadsheet_auditor-0.1.0/spreadsheet_auditor/__init__.py +13 -0
  7. spreadsheet_auditor-0.1.0/spreadsheet_auditor/__main__.py +8 -0
  8. spreadsheet_auditor-0.1.0/spreadsheet_auditor/annotate.py +48 -0
  9. spreadsheet_auditor-0.1.0/spreadsheet_auditor/audit.py +761 -0
  10. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/__init__.py +35 -0
  11. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/base.py +74 -0
  12. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/data_hygiene.py +24 -0
  13. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/finance.py +202 -0
  14. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/formula_integrity.py +91 -0
  15. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/ranges.py +58 -0
  16. spreadsheet_auditor-0.1.0/spreadsheet_auditor/checks/reconciliation.py +32 -0
  17. spreadsheet_auditor-0.1.0/spreadsheet_auditor/cli.py +17 -0
  18. spreadsheet_auditor-0.1.0/spreadsheet_auditor/config_loader.py +132 -0
  19. spreadsheet_auditor-0.1.0/spreadsheet_auditor/data_hygiene.py +115 -0
  20. spreadsheet_auditor-0.1.0/spreadsheet_auditor/demo/__init__.py +10 -0
  21. spreadsheet_auditor-0.1.0/spreadsheet_auditor/demo/demo_bad_budget.xlsx +0 -0
  22. spreadsheet_auditor-0.1.0/spreadsheet_auditor/dependency_graph.py +55 -0
  23. spreadsheet_auditor-0.1.0/spreadsheet_auditor/finding.py +136 -0
  24. spreadsheet_auditor-0.1.0/spreadsheet_auditor/formula_drift.py +128 -0
  25. spreadsheet_auditor-0.1.0/spreadsheet_auditor/formula_parser.py +110 -0
  26. spreadsheet_auditor-0.1.0/spreadsheet_auditor/materiality.py +22 -0
  27. spreadsheet_auditor-0.1.0/spreadsheet_auditor/preflight.py +53 -0
  28. spreadsheet_auditor-0.1.0/spreadsheet_auditor/py.typed +0 -0
  29. spreadsheet_auditor-0.1.0/spreadsheet_auditor/range_checks.py +299 -0
  30. spreadsheet_auditor-0.1.0/spreadsheet_auditor/recalc.py +63 -0
  31. spreadsheet_auditor-0.1.0/spreadsheet_auditor/reconcile.py +130 -0
  32. spreadsheet_auditor-0.1.0/spreadsheet_auditor/reference_resolver.py +61 -0
  33. spreadsheet_auditor-0.1.0/spreadsheet_auditor/report.py +399 -0
  34. spreadsheet_auditor-0.1.0/spreadsheet_auditor/sarif.py +141 -0
  35. spreadsheet_auditor-0.1.0/spreadsheet_auditor/suppressions.py +109 -0
  36. spreadsheet_auditor-0.1.0/spreadsheet_auditor/workbook_inventory.py +93 -0
  37. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/PKG-INFO +332 -0
  38. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/SOURCES.txt +56 -0
  39. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/dependency_links.txt +1 -0
  40. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/entry_points.txt +2 -0
  41. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/requires.txt +22 -0
  42. spreadsheet_auditor-0.1.0/spreadsheet_auditor.egg-info/top_level.txt +1 -0
  43. spreadsheet_auditor-0.1.0/tests/test_checks.py +132 -0
  44. spreadsheet_auditor-0.1.0/tests/test_checks_registry.py +76 -0
  45. spreadsheet_auditor-0.1.0/tests/test_cli_ergonomics.py +56 -0
  46. spreadsheet_auditor-0.1.0/tests/test_confidence_drift.py +63 -0
  47. spreadsheet_auditor-0.1.0/tests/test_config_schema.py +39 -0
  48. spreadsheet_auditor-0.1.0/tests/test_corpus.py +65 -0
  49. spreadsheet_auditor-0.1.0/tests/test_exit_codes.py +69 -0
  50. spreadsheet_auditor-0.1.0/tests/test_finance_checks.py +98 -0
  51. spreadsheet_auditor-0.1.0/tests/test_finding_schema.py +80 -0
  52. spreadsheet_auditor-0.1.0/tests/test_healthcheck.py +46 -0
  53. spreadsheet_auditor-0.1.0/tests/test_html_output.py +95 -0
  54. spreadsheet_auditor-0.1.0/tests/test_perf_guardrails.py +78 -0
  55. spreadsheet_auditor-0.1.0/tests/test_run_metadata.py +78 -0
  56. spreadsheet_auditor-0.1.0/tests/test_sarif.py +141 -0
  57. spreadsheet_auditor-0.1.0/tests/test_skill_metadata.py +63 -0
  58. 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 &mdash; 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 &mdash; often one you inherited &mdash; 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** &mdash; de-risk an LBO/DCF/budget model before it
123
+ reaches an investment committee or counterparty.
124
+ - **"Find the error" debugging** &mdash; a number looks wrong and you need the
125
+ cell, not a guess.
126
+ - **Inherited-model trust assessment** &mdash; you didn't build it; check
127
+ whether it is trustworthy.
128
+ - **CI / batch gating** &mdash; 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** &mdash; 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 &mdash; 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 &mdash; often one you inherited &mdash; 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** &mdash; de-risk an LBO/DCF/budget model before it
56
+ reaches an investment committee or counterparty.
57
+ - **"Find the error" debugging** &mdash; a number looks wrong and you need the
58
+ cell, not a guess.
59
+ - **Inherited-model trust assessment** &mdash; you didn't build it; check
60
+ whether it is trustworthy.
61
+ - **CI / batch gating** &mdash; 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** &mdash; 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>