Skip to main content

Workpaper Review Gate

+----------------------------------------------------------------------+
|                        Workpaper Review Gate                         |
+----------------------------------------------------------------------+
|     Stop incomplete workpapers reaching manager review               |
+----------------------------------+-----------------------------------+
| DR  what it gives you            | CR  what it needs                 |
+----------------------------------+-----------------------------------+
| READY / NOT_READY / BLOCKED      | a pack directory of artefacts     |
| cover sheet for the reviewer     | a self-review JSON from the prep  |
| repeat-finding flags             | -                                 |
+----------------------------------+-----------------------------------+

tests PyPI Python 3.10+ License: MIT

Browser evaluation · Reproduce locally · Quick demo · Release notes

The maintained source is under packages/review-ready-gate in the Accounting Review Pipeline. The review-ready-gate distribution, review-ready command and reviewready import remain compatibility identifiers.

A local, review-first readiness gate for Australian public-practice packs. You point it at a folder of workpapers from a junior, an offshore team, or an AI agent. It tells you whether that folder is allowed to enter manager review.

A public evaluation pack reproduces the v0.1.5 manager-review result on fabricated BAS fixtures. It is a local review aid, not an approval system.

Fabricated proof

Pack Result What the gate reports
examples/bas-ready READY No configured findings. A human still decides whether the pack may proceed.
examples/bas-not-ready NOT_READY Missing GST control export, incomplete self-review and a blocking open item.

Open the manager-facing browser evaluation or reproduce the versioned evaluation pack from the fabricated fixtures.

It is the missing upstream step in this stack:

Incomplete pack
      |
      v
review-ready-gate      <-- maintained monorepo package
      |
      |  READY
      v
Manager review (judgement, risk, client impact)
      |
      v
Monthly Close Controls / payday-super-checker / other engines

Monthly Close Controls answers 'what material exceptions exist on these trial balances?'. This tool answers a prior question: 'is the pack even allowed onto the review desk?' A file can have material variances and still be READY, because the variances are documented. A file with a missing GST control export is NOT_READY even if the numbers look tidy.

It does not connect to Xero, store OAuth tokens, write journals, lodge BAS, lock a period, call an LLM, or claim that a file is correct.

Why this exists

Preparation got cheaper. Review did not. Software, offshore capacity, and AI all increase the number of files that hit the review desk. The scarce resource in a firm is the manager who can actually sign.

Missing tie-outs, open questions in email, an unbalanced trial balance and unresolved findings from last period send a pack back for more preparation. This gate checks for those gaps before the pack reaches the manager.

Quick demo

The repository contains fabricated data only. Do not commit client workpapers.

For optional supporting documents, the synthetic document intake example preserves original bytes, proposed fields and human corrections. It adds document checks to an existing pack without replacing its trial balance or changing the readiness output schema.

For the manager-facing, reproducible BAS evaluation, see the manager review gate evaluation pack. The missing evidence evaluation shows what the gate does when a month-end source is absent, empty, for the wrong period, or edited after the gate ran, including a balanced pack that reaches READY without its bank reconciliation.

examples/ is the assault course: every move the tool has, run against fabricated data, with nothing at stake. Learn the flags here before pointing it at a real pack.

python -m pip install -e ".[dev]"

review-ready gate \
  --profile bas \
  --pack examples/bas-ready \
  --output ../../../review-ready-demo/bas-ready

The ready demo exits 0 and writes 3 files:

  • readiness-summary.md: cover sheet a manager reads top to bottom
  • findings.csv: one row per finding, for Excel or Power BI
  • readiness-pack.json: structured evidence, source hashes, and any supplied acknowledgement
review-ready gate \
  --profile bas \
  --pack examples/bas-not-ready \
  --output ../../../review-ready-demo/bas-not-ready

The not-ready demo exits 2. The GST control export is missing, the preparer has not certified the pack, a blocking open item is still OPEN, and the same missing artefact was OPEN on the prior pack, so it is flagged as a repeat.

review-ready view --pack-dir ../../../review-ready-demo/bas-ready

--output points outside this checkout, and it has to: the command refuses an output directory inside a version-control checkout, exiting 1 without creating anything. A readiness pack names a client's file, its workpaper references and every finding standing between it and manager review, and inside a checkout it is one git add -A away from a history that every clone copies. A .gitignore entry is a convention the next commit can waive, and it does nothing about the copy sitting in the working tree meanwhile. A checkout is any directory at or above the output holding .git, .hg, .svn or .bzr, because the harm is the pack going under version control and every one of those copies a committed pack to each clone. A directory inside the work tree named by GIT_WORK_TREE counts too, since Git can hold its metadata elsewhere and leave a tracked tree carrying no marker to find. A work tree selected some other way, by --work-tree on another process's git invocation or by core.worktree in a repository this command never opens, cannot be discovered from here: the check is a backstop for the location you chose, not a proof that a directory is untracked. An output the command cannot examine, such as one behind a symbolic-link loop or an unreadable parent, is refused on the same grounds rather than assumed safe. The refusal applies to writing only: review-ready view still opens a pack wherever it already is.

Use exit code 0 only for READY, 2 for NOT_READY or BLOCKED, and 1 for a malformed file, an invalid command, an --output path inside a version-control checkout, or an --output path that cannot be written.

To run the gate on a schedule in CI, copy examples/github-actions-readiness-check.yml into .github/workflows/. It runs against a repo-stored synthetic pack, fails the job when the pack is BLOCKED, and reports NOT_READY for a human. A READY result is still not an approval.

What gets gated

Profile Required artefacts Extra controls
bas trial balance, activity statement, GST control GL, open items, self-review 1A less 1B ties to GST control movement
month_end current TB, prior TB, open items, self-review optional bank rec; prior date earlier; same tenant
year_end current TB, prior TB, tie-out matrix, open items, self-review no UNSUPPORTED statement lines

Optional in every profile: prior_findings.csv. An OPEN prior finding that is still present is marked repeat.

A READY status means no configured control tripped, and only the controls that ran can trip. Every optional slot with no usable input is therefore listed under 'Controls not run' in the pack JSON and the summary, and counted in the summary's scope block: a month_end pack with no bank_rec.csv in it is READY with the bank reconciliation control not run, which is a different claim from READY with every control run. An optional file that exists but holds no bytes is a finding as well, because an empty file is not evidence; its digest is still recorded, so a reviewer can see which bytes the finding is about.

Filenames inside the pack directory are fixed. Header-only CSV schemas live under schemas/, together with the JSON Schema for self_review.json.

Self-review

self_review.json is part of the pack, not a courtesy. Exact keys, exact assertion names, JSON booleans only:

{
  "preparer_initials": "AB",
  "prepared_on": "2026-04-10",
  "engagement_type": "bas",
  "period_end": "2026-03-31",
  "assertions": {
    "pack_complete": true,
    "tie_outs_done": true,
    "open_items_listed": true,
    "variances_explained": true,
    "self_reviewed": true
  }
}

engagement_type must match --profile. prepared_on must not be earlier than period_end. Any assertion that is not true is NOT_READY. The assertions are necessary, not sufficient: a preparer who ticks pack_complete while the GST control file is missing still gets MISSING_ARTEFACT. The JSON Schema is schemas/self_review.json.

Open items

ItemID,Severity,Owner,DueDate,Status,Description,Resolution

Severity is BLOCKING, EXPLAIN, or TRIVIAL. Status is OPEN or CLEARED. A BLOCKING item that is still OPEN with no resolution blocks the gate. A CLEARED item with no resolution text also fails: cleared means someone wrote down what happened.

Trial balance

The 10-column canonical CSV from xero-trial-balance-export:

ReportDate,Tenant,Section,AccountID,AccountName,AccountCode,Debit,Credit,YTDDebit,YTDCredit

One tenant, one report date, unique Tenant+AccountID. Movement debit must equal movement credit, and YTD debit must equal YTD credit, or the pack is BLOCKED.

BAS tie-out

If both the activity statement and the GST control GL are present:

  • labels 1A and 1B are required
  • 1A - 1B is compared with GST-control sum(Credit) - sum(Debit)
  • a difference beyond --tieout-tolerance (default $0.01) is NOT_READY

This is a cash-style control-account tie-out on the files you supply. It is not a lodgement, not a cash-versus-accruals bridge, and not a substitute for the bas-preparation skill.

Human acknowledgement

Optional --review-note JSON:

{
  "reviewer_initials": "RD",
  "reviewed_on": "2026-04-12",
  "comment": "Reviewed fabricated demo findings only; no client file was approved by this example."
}

reviewed_on must not be earlier than period_end. An acknowledgement is evidence of a human action only. It never changes NOT_READY or BLOCKED to READY.

Viewing an existing pack

review-ready view is the read-only half of the gate: it loads a generated pack, proves the 3 files still agree with each other, and prints the cover sheet. It never writes, renames or deletes anything, and it cannot change what the engine computed.

review-ready view --pack-dir outputs/bas-ready

Before displaying anything it fails closed on: a missing artefact; JSON that is not valid UTF-8, not valid JSON, or carries unknown, missing or duplicated top-level members; a threshold or nested source digest that no longer parses as the writer rendered it; a readiness-summary.md whose overall status, source-evidence digests or review-boundary statement disagree with the JSON (including a second, conflicting status line); and a findings.csv whose header, row count or any cell disagrees with the JSON findings, honouring the writer's formula-injection guard exactly. On success the sheet ends with the SHA-256 of each artefact's exact bytes, so the displayed evidence can itself be archived. Exit code is 0 when a pack was verified and shown, 1 when verification failed.

Design

  • Exact Decimal arithmetic for money, never binary floating point. The gate fixes its own 28-digit context, ignoring the caller's, and refuses a pack whose trial-balance totals would round instead of comparing them inexactly.
  • Schema, duplicate-key, date, and numeric gates fail closed: a malformed file is exit 1 and writes no pack.
  • Missing or empty required artefacts are findings, not crashes, so the cover sheet can tell the preparer what to send back.
  • Source SHA-256 digests travel with the pack. Each digest is taken from the same immutable byte snapshot the loader parsed.
  • Spreadsheet-facing finding text whose first non-whitespace character is =, +, - or @ is prefixed with an apostrophe.
  • The 3 pack files are staged beside their destinations and moved into place only once all 3 have been written. A failed run does not leave 2 runs mixed together.
  • No wall-clock timestamps in the pack.

Data boundary

  • Use a separate, access-controlled working directory for client source files and outputs.
  • A generated pack cannot be written into a version-control checkout at all. write_review_pack walks up from the resolved --output directory and refuses if any level holds .git, .hg, .svn or .bzr, before it creates anything; a .git file counts as well as a directory, so a worktree and a submodule are checkouts too. A level it cannot examine is refused rather than read as an absence. The library enforces this too, so a caller that bypasses the CLI does not bypass the rule.
  • Keep this checkout limited to fabricated fixtures. Its .gitignore blocks CSVs outside examples/ and schemas/, and blocks all 3 generated pack files by name. That stays as a second line: it catches a pack copied in by hand, which no guard on the writer can see.
  • Do not use this as tax, financial, audit, or legal advice.

Development

Use the locked toolchain. python -m pytest is not what CI runs.

uv lock --check
uv sync --locked --all-extras
uv run --locked --extra dev pytest
uv run ruff check reviewready tests
uv run mypy reviewready
uv build

The test suite covers schema gates, the 3 fabricated engagement packs, empty and incomplete artefacts, GST and bank-rec breaks, unsupported tie-outs, acknowledgement parsing, deterministic pack generation, fail-closed pack viewing, and the command-line exit contract.

Continuous integration verifies the committed uv.lock, runs the test suite on Python 3.10, 3.12, 3.13 and 3.14, then builds and smoke-tests the wheel with the fabricated demo. CodeQL scans the Python source, and Dependabot is configured to propose updates for uv dependencies and pinned GitHub Actions. See CONTRIBUTING.md for the local verification and data-handling requirements. To cut a release, follow RELEASING.md. Do not tag until you intend to publish.

MIT licensed. Boundary statement: DISCLAIMER.md.

Metadata

Release files for review-ready-gate 0.1.8

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

Source distribution (sdist)

Source distribution for review-ready-gate 0.1.8
File Size Uploaded
review_ready_gate-0.1.8.tar.gz 141.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for review-ready-gate 0.1.8
File Interpreter ABI Platform
review_ready_gate-0.1.8-py3-none-any.whl Python 3 none any Details

Total release size: 186.1 kB

Release files / review_ready_gate-0.1.8.tar.gz

Download URL review_ready_gate-0.1.8.tar.gz
Size 141.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0ff7bdda6cc68c32059be8016e275a2ee199e4df0b45a5c64303a722a150e396
BLAKE2b-256 checksum
How to use checksums
ea7ddc4503cb8114e0f689ef16deb5dc46c02058f1f21ca86f302cdf327cebd8
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 Sep 26, 2026.

Transparency log

Release files / review_ready_gate-0.1.8-py3-none-any.whl

Download URL review_ready_gate-0.1.8-py3-none-any.whl
Size 45.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cb08b06e6ba4add0084956f651e14a68b6e0e8423881478da817be5aa35881dd
BLAKE2b-256 checksum
How to use checksums
3178e8e761701fef7b89b33129260f5c81798f1dc94837a15a0deacb0bb4f587
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 Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

0.1.10

2 release files

0.1.9

2 release files

This release

0.1.8 This release

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.3

2 release files

0.1.1

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