joey.hersh

systems / store-close-reconciliation

Store-close reconciliation

Deterministic accounting, AI extraction, human exception review

Put fuzzy work in a box with sharp edges.

Period
June – September 2026
My role
Architect and implementation lead at Guadalupe Automation, with a partner running the client relationship. Built with coding agents I directed and reviewed.
State
Pilot delivered to a multi-store retailer. Engagement re-scoped around a client-reviewed source of truth in September 2026.
  • 15Deterministic parsersbank, POS, commission, discount, cash count
  • 295 / 315June closereconciled, zero open amount differences, per the August acceptance review
  • 857Tests passing94 database-backed tests run in CI
  • Python
  • Postgres
  • Windmill
  • Docker
  • pydantic
an isometric shop counter with a cash drawer open, a stack of receipts, and a ledger book, a thin conveyor of tiny rectangles feeding a funnel
Fifteen deterministic parsers; the model reads receipts and never writes a row.
store-close.flow: architecture flowunstructuredDocument intakefiles · email · POS syncfiles · email · POS syncClassify and routefour lanesfour lanesDeterministic parsers15 structured sources15 structured sourcesModel laneclosed schemas · scanned evidenceclosed schemas · scanned…Extraction reviewevery model proposalevery model proposalReconciliationdeposits · tolerances · periodsdeposits · tolerances · p…Audit statelineage · runs · breakslineage · runs · breaksRole-gated approvalletters · accounting exportletters · accounting expo…Reports and exports

Diagram nodes, in flow order: Document intake (files · email · POS sync); Classify and route (four lanes); Deterministic parsers (15 structured sources); Model lane (closed schemas · scanned evidence); Extraction review (every model proposal); Reconciliation (deposits · tolerances · periods); Audit state (lineage · runs · breaks); Role-gated approval (letters · accounting export); Reports and exports.

deterministic code model judgment human durable state tool / API

The problem

A multi-store retailer closing the books every day by hand: card batches, deposits, invoices, credits, employee certificates, commissions, discounts. The failure mode of automating this badly is obvious. If the machine is wrong about money and nobody notices, you've built a liability.

The boundary I drew

Everything structured is deterministic. Fifteen parsers handle bank statements, point-of-sale exports, accounting-system packets, and the commission, discount, gift-certificate, employee-credit, and cash-count workbooks. Reconciliation, period logic, deposit matching, tolerances, and exports are plain Python with tests.

The model gets one lane. It reads scanned close packets, deposit slips, physical card vouchers, and inbound email, against a closed set of eight schemas. It proposes fields. It never writes an accounting row. Every proposal is forced into a review queue regardless of its confidence, and if the response is malformed it degrades to "needs review" instead of guessing. Card numbers are scrubbed from every prompt and every response before anything is persisted, and the system fails closed if it can't prove the scrub ran.

Two approval gates are role-locked in code: a sales manager for customer letters, an accounting manager for the accounting-system export. A schema test enforces that there is no foreign-key path by which an unreviewed extraction can feed an approved output. That test is the design.

What happened

The first acceptance review surfaced one genuine discrepancy at a store plus thirty-two items that needed a human look, mostly daily-cut differences and deposits in transit. After the August feedback round the June close stood at 315 checks, 295 reconciled, zero open amount differences, and twenty normal-course items. Daily store reports were a capability the client didn't have before.

Scope grew past the plan: the dashboard expanded while the store-manager reports were the actual product. In September we reset the engagement around one client-reviewed source of truth, with the accounting-system import re-test and baseline sign-off as the next milestones.

What I took from it

I changed how I run discovery. I now start every engagement by writing the success test with the client before I write anything else, and I treat "the client asked for a feature" as a requirement to capture, not a ticket to build.

Store-close reconciliation, in twenty-five seconds

Store-close reconciliation for a multi-store retailer: fifteen deterministic parsers, one model lane that can only propose, a review queue for every proposal, and two approval gates locked in code. June close: 295 of 315 checks, zero open amount differences.