EOFY document chasing for accounting firms

A chase letter that never lies
by asking for what it already has.

Docket reads a filename, decides what it can safely conclude, and leaves the rest open rather than guessing. What it cannot place stays unplaced โ€” it is never marked satisfied on no evidence, and the CRM is never told a client was chased until a real letter exists.

Filename-first The free tier reads the name before any model is asked
Refuses to guess Unclassified stays unclassified, never satisfied on no evidence
Never asks twice A satisfied requirement never reappears on the letter
Record after, not before "Chased" is written only once a real letter exists

The blind spot

A wrong record looks finished. A blank one gets checked.

Most document-chasing automation is built to always produce an answer. The failure mode is not that it is slow -- it is that a confident wrong answer stops the next person from looking.

A guess dressed as a decision

A classifier that must always answer will place an unreadable filename somewhere. A client stops being chased for a document nobody actually confirmed they sent -- and nothing anywhere reports the gap.

Asking twice erodes trust

A chase letter that re-asks for a document already on file reads as carelessness to the one person -- the client -- whose patience the whole exercise depends on.

A wrong CRM record stops the follow-up

If "chased" is written the moment a job starts rather than after the letter actually sends, a refused draft leaves the CRM asserting a contact that never happened -- and nobody follows up, because the record already says it is done.

How it works

Four steps, each one able to say "I don't know"

Every step either produces a real answer or an honest refusal. Nothing in between -- there is no step that outputs a plausible guess.

  1. 01

    Classify

    Filename rules answer first, for free. Only what they cannot read is sent to a model -- and what the model also cannot place stays unplaced, not guessed.

    docket/classify_rules.py docket/classify_model.py
  2. 02

    Compare

    Each required document type is checked against what this client actually sent, in the right financial year. Satisfaction is a lookup, never an inference.

    docket/requirements.py docket/rules.py
  3. 03

    Draft

    The chase letter is built only from what is still missing. A draft naming an already-satisfied document, or stating a figure, is refused rather than sent.

    docket/letter.py
  4. 04

    Record

    The CRM is marked "chased" only once that exact letter exists. A refused draft leaves the record exactly as it was -- a blank that gets checked, not a lie that looks finished.

    docket/crm.py

Try it

Same filename, two systems, different outcome

Pick a real filename from Docket's own test corpus. Compare what a classifier forced to always answer would do against what Docket actually does.

client C0142 ยท one document at a time

Forced to always answer A classifier with no "I don't know"

Bank statement

The name states what it is. Filed as a bank statement.

confidence not applicable -- rules matched

Requirement Satisfied

Docket Tier 1 rules, then tier 2 only on the residue

Bank statement

Same result -- the filename genuinely says what it is. Tier 1 handled it for free.

docket.classify_filename() -> ('bank_statement', 'Westpac')

Requirement Satisfied

What this changes on the client's chase letter

Still missing contract, invoice, payslip, receipt
Letter asks for the bank statement again? No
CRM state Chased FY2026 -- once the letter exists

Both classifications above were run for real against Docket's code on 2026-09-19, one fictional client, no live model call. The letter and CRM panels reflect the outcome of that same run.

The rules

Satisfaction is a lookup, never an inference

Three rules decide whether a document counts, and every one of them has a plain-English statement a partner can check without reading code.

SEASON-001 -- a document belongs to one year

A document uploaded outside the financial year being checked does not satisfy that year's requirement. Last year's bank statement is a real document that still leaves this year's requirement open.

EXCLUDE-001 -- the firm's own paper never counts

A document the firm generated -- a tax notice, a remittance advice -- never appears on a client's list of things to send. Asking a client for a document the firm wrote is the mistake this rule exists to prevent.

MATCH-001 -- met only by a classified document

A requirement is met only by a document of exactly that type, sent by the client, inside the year. An unclassified document -- Docket does not know what it is -- satisfies nothing.

Client C0142 -- what FY2026 requires

One real run
Requirement status for client C0142, financial year 2026
Requirement Status
Bank statement Satisfied
Payslip Missing
Invoice Missing
Receipt Missing
Contract Missing
Scan0001.pdf Unclassified -- counted, not guessed

Only the bank statement is satisfied. The letter this client receives asks for the other four -- never for the bank statement, and never for a fifth item invented to fill the unclassified document's gap.

What you get

Four things, in plain language

Written to be read by whoever signs off on the EOFY chase, not only by whoever built the pipeline.

Chase letter

Built only from what is genuinely missing. Refused outright rather than sent if it would name something already on file or state a figure.

Answers: what does this client still owe?

CRM record

Written from the letter that actually exists, never before it. A refusal leaves the account reading "not chased" -- true, not softened.

Answers: did this client actually get chased?

Classification summary

How many documents rules handled for free, how many needed the model, and how many stayed unclassified -- a measured split, not a claim.

Answers: how much of this cost anything?

A clean "I don't know"

Every document a filename could not settle and a model could not either is counted, not silently dropped or forced into a category.

Answers: what does nobody actually know yet?

Docket is built and tested. It has never met a real client.

Every result above ran against a synthetic corpus and a Salesforce sandbox. Wiring it to a real firm's inbox and CRM is the next step, and it hasn't happened yet -- this page says so on purpose.