jaz-clio 5.4.4 → 5.4.6

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 (43) hide show
  1. package/README.md +4 -4
  2. package/assets/skills/api/SKILL.md +1 -1
  3. package/assets/skills/cli/SKILL.md +5 -4
  4. package/assets/skills/cli/references/command-catalog.md +1 -2
  5. package/assets/skills/conversion/SKILL.md +4 -2
  6. package/assets/skills/jobs/SKILL.md +4 -2
  7. package/assets/skills/jobs/references/audit-prep.md +153 -221
  8. package/assets/skills/jobs/references/bank-recon.md +165 -166
  9. package/assets/skills/jobs/references/building-blocks.md +112 -96
  10. package/assets/skills/jobs/references/credit-control.md +126 -203
  11. package/assets/skills/jobs/references/document-collection.md +142 -180
  12. package/assets/skills/jobs/references/fa-review.md +98 -215
  13. package/assets/skills/jobs/references/gst-vat-filing.md +137 -183
  14. package/assets/skills/jobs/references/month-end-close.md +165 -213
  15. package/assets/skills/jobs/references/payment-run.md +99 -179
  16. package/assets/skills/jobs/references/quarter-end-close.md +106 -202
  17. package/assets/skills/jobs/references/supplier-recon.md +79 -267
  18. package/assets/skills/jobs/references/year-end-close.md +161 -261
  19. package/assets/skills/practice/SKILL.md +1 -1
  20. package/assets/skills/practice/references/annual-statutory.md +17 -8
  21. package/assets/skills/practice/references/client-md-schema.md +2 -2
  22. package/assets/skills/practice/references/monthly-close.md +16 -12
  23. package/assets/skills/practice/references/troubleshooting.md +1 -1
  24. package/assets/skills/transaction-recipes/SKILL.md +5 -3
  25. package/assets/skills/transaction-recipes/references/accrued-expenses.md +97 -112
  26. package/assets/skills/transaction-recipes/references/asset-disposal.md +144 -117
  27. package/assets/skills/transaction-recipes/references/bad-debt-provision.md +146 -93
  28. package/assets/skills/transaction-recipes/references/bank-loan.md +111 -103
  29. package/assets/skills/transaction-recipes/references/building-blocks.md +128 -7
  30. package/assets/skills/transaction-recipes/references/capital-wip.md +183 -125
  31. package/assets/skills/transaction-recipes/references/declining-balance.md +96 -143
  32. package/assets/skills/transaction-recipes/references/deferred-revenue.md +102 -82
  33. package/assets/skills/transaction-recipes/references/dividend.md +113 -72
  34. package/assets/skills/transaction-recipes/references/employee-accruals.md +126 -102
  35. package/assets/skills/transaction-recipes/references/fixed-deposit.md +102 -117
  36. package/assets/skills/transaction-recipes/references/fx-revaluation.md +96 -86
  37. package/assets/skills/transaction-recipes/references/hire-purchase.md +76 -151
  38. package/assets/skills/transaction-recipes/references/ifrs16-lease.md +127 -139
  39. package/assets/skills/transaction-recipes/references/intercompany.md +178 -127
  40. package/assets/skills/transaction-recipes/references/prepaid-amortization.md +93 -81
  41. package/assets/skills/transaction-recipes/references/provisions.md +109 -92
  42. package/cli.mjs +424 -469
  43. package/package.json +1 -1
@@ -1,236 +1,235 @@
1
- # Bank Reconciliation Catch-Up
2
-
3
- Clear unreconciled bank statement entries by matching them to existing transactions, creating missing ones, and flagging duplicates. This is the single most impactful thing you can do for book accuracy a clean bank recon means cash is right, and cash being right means everything else has a fighting chance.
4
-
5
- **CLI:** `clio jobs bank-recon [--account "DBS Current"] [--period 2025-01] [--json]`
1
+ # Bank Reconciliation
2
+
3
+ > Clear unreconciled bank statement entries by matching, creating, or flagging. Highest-leverage book-accuracy job in Jaz — clean cash means everything else has a fighting chance. Driver tool: `generate_bank_recon_blueprint`.
4
+
5
+ ## Tools, recipes, calculators this job uses
6
+
7
+ ### MCP tools — discovery + auto-match
8
+ - **`generate_bank_recon_blueprint(period: <YYYY-MM>, currency: <base>)`** — step 0: emit phased recon checklist.
9
+ - **`list_bank_accounts()`** — step 1: pull all bank-type CoA accounts (per `jaz-api/SKILL.md` rule 18: GET `/bank-accounts` returns flat array `[{...}]`, NOT the standard paginated `{ data, totalElements, totalPages }` shape — normalize before consuming).
10
+ - **`search_accounts(filter: {accountType: {eq: 'Bank Accounts'}})`** — step 1 alternative: same data via standard CoA-search envelope if downstream wants pagination.
11
+ - **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', valueDateRange: {from, to}, limit: 200, sort: 'valueDate:asc')`** — step 2: per-account work queue.
12
+ - **`search_bank_records(accountResourceId: <id>, status: 'POSSIBLE_DUPLICATE')`** — step 3: handle dups FIRST or you'll double-create reconciling them.
13
+ - **`view_auto_reconciliation(bankAccountResourceId: <id>, recommendationType: 'MAGIC_MATCH' | 'MAGIC_RECONCILE_WITH_CASH_TRANSFER' | 'MAGIC_RECONCILE_WITH_BANK_RULE' | 'MAGIC_QUICK_RECONCILE')`** — step 4: READ-ONLY auto-match suggestions. Does NOT write. NOTE: documented 500 quirk on high-volume accounts — see error table.
14
+ - **`search_cashflow_transactions(filter: {organizationAccountResourceId: <bank-id>, totalAmount: {eq: <amt>}, valueDate: {between: [<-3d>, <+3d>]}})`** — step 5 manual match: search book-side transactions for the same amount within ±3 day window.
15
+
16
+ ### MCP tools — execute reconciliation (NOT idempotent — see error table)
17
+ - **`apply_bank_rule(actionShortcutResourceId: <rule-id>, businessTransactionResourceIds: [<bank-entry-ids>])`** — step 4: rule-driven recon (async; returns jobId).
18
+ - **`quick_reconcile(bankAccountResourceId, journalsForReconciliation: [...])`** — step 4: bulk async (max 500 per call); returns jobId.
19
+ - **`reconcile_invoice_receipt(...)`** — step 4: 1:1 match of bank entry to AR invoice.
20
+ - **`reconcile_bill_receipt(...)`** — step 4: 1:1 match to AP bill.
21
+ - **`reconcile_direct_cash_entry(...)`** — step 4: bank entry to a single cash-in / cash-out line.
22
+ - **`reconcile_cash_journal(...)`** — step 4: bank entry to a multi-line cash journal.
23
+ - **`reconcile_manual_journal(...)`** — step 4: bank entry to a manual journal.
24
+ - **`reconcile_cash_transfer(...)`** — step 4: inter-account transfer.
25
+
26
+ ### MCP tools — create missing transactions
27
+ - **`mcp magic create --file <pdf>` / `create_business_transaction_from_attachment(...)`** — step 6 path B: OCR + autofill bill or invoice from receipt PDF/JPG.
28
+ - **`create_cash_in_entry(...)` / `create_cash_out_entry(...)`** — step 6 path C: bank fees, interest, FX charges that have no source document.
29
+ - **`create_bank_rule(...)`** — preventive: build a rule for any recurring pattern you handled this run (subscription, rent, utility) so it auto-applies next time.
30
+
31
+ ### MCP tools — verification
32
+ - **`generate_bank_recon_summary(period_end, accountResourceId)`** — step 7: per-account formal recon statement.
33
+ - **`generate_bank_recon_details(period_end, accountResourceId)`** — step 7: line-level recon detail for audit pack.
34
+ - **`generate_bank_balance_summary(period_end)`** — step 8: book balance vs bank statement balance per account.
35
+
36
+ ### CLI tools — bulk auto-match cascade (offline)
37
+ - **`clio jobs bank-recon match --input <records.json> --tolerance 0.01 --date-window 14 --max-group 5 --json`** — the 5-phase cascade matcher (Phase 1 exact 1:1 hash join, Phase 2 fuzzy 1:1 greedy with weighted scoring, Phase 3 N:1, Phase 4 1:N, Phase 5 N:M). Returns matches sorted by confidence — feed each into the appropriate `reconcile_*` tool. See `bank-match.md` for the full algorithm.
38
+
39
+ ### Cross-references
40
+ - Within an engagement: invoked from `practice/references/monthly-close.md` step 3 (mandatory pre-close gate). Practice playbook reads `CLIENT.bank_accounts[]` for the per-account loop.
41
+ - Sibling job: `bank-match.md` (the cascade matcher algorithm + scoring weights). Practitioner-facing recon step always invokes `bank-match` for any account with > ~10 unreconciled items.
42
+ - API rules: `jaz-api/SKILL.md` rules 18 (bank-accounts envelope), 26 (cash entries `accountResourceId` shape), 50a (search query DSL), 124 (recon NOT idempotent).
6
43
 
7
44
  ---
8
45
 
9
- ## Phase 1: Identify Bank Accounts
10
-
11
- List all bank accounts in the org. If `--account` is specified, filter to that one. Otherwise, reconcile all of them.
12
-
13
- ### Step 1: List bank accounts
46
+ ## Step 0 Emit blueprint
14
47
 
15
48
  ```
16
- GET /api/v1/bank-accounts?limit=100&offset=0
49
+ generate_bank_recon_blueprint(period: '2025-01', currency: <CLIENT.base_currency>)
17
50
  ```
18
51
 
19
- Or via CoA search (more reliable gives you the resourceId directly):
52
+ ## Step 1Discover bank accounts
20
53
 
21
- ```
22
- POST /api/v1/chart-of-accounts/search
23
- {
24
- "filter": { "accountType": { "eq": "Bank Accounts" } },
25
- "sort": { "sortBy": ["name"], "order": "ASC" }
26
- }
27
- ```
28
-
29
- **What you get:** A list of bank-type CoA accounts with `resourceId`, `name`, `currencyCode`. You need the `resourceId` for every subsequent step.
30
-
31
- ---
54
+ For multi-org agents: invoke `list_bank_accounts()`. For each account: `{resourceId, name, currencyCode, openingBalance, currentBalance}`. Per rule 18, normalize the flat-array response. Use `search_accounts(filter: {accountType: {eq: 'Bank Accounts'}})` if you also need full CoA metadata (parent group, etc.).
32
55
 
33
- ## Phase 2: Pull Unreconciled Items
56
+ If `--account "DBS Current"` flag was passed: filter by `name == 'DBS Current'` first, then run the rest of the playbook on that account only.
34
57
 
35
- For each bank account, pull all unreconciled bank records. This is your working list.
58
+ ## Step 2 — Per-account work queue
36
59
 
37
- ### Step 2: Search unreconciled bank records
60
+ For each bank account `B`:
38
61
 
39
62
  ```
40
- POST /api/v1/bank-records/{accountResourceId}/search
41
- {
42
- "filter": {
43
- "status": { "eq": "UNRECONCILED" },
44
- "valueDate": { "between": ["2025-01-01", "2025-01-31"] }
45
- },
46
- "sort": { "sortBy": ["valueDate"], "order": "ASC" },
47
- "limit": 1000
48
- }
63
+ search_bank_records(
64
+ accountResourceId: B.resourceId,
65
+ status: 'UNRECONCILED',
66
+ valueDateRange: { from: '2025-01-01', to: '2025-01-31' },
67
+ limit: 200,
68
+ sort: 'valueDate:asc'
69
+ )
49
70
  ```
50
71
 
51
- **Omit the `valueDate` filter** if you want to see ALL unreconciled items regardless of date. For a catch-up, you usually want everything.
72
+ Omit `valueDateRange` for full catch-up across all open periods. Paginate via `offset` if `totalElements > 200`. Each row: `{resourceId, valueDate, netAmount, extContactName, description, balance}`. `netAmount > 0` = cash-in; `< 0` = cash-out. `extContactName + description` are the highest-signal match clues.
52
73
 
53
- **What to check:**
54
- - Count of unreconciled items — this is your work queue
55
- - Any items older than 60 days are red flags (investigate immediately)
56
- - `netAmount` positive = cash-in, negative = cash-out
57
- - `extContactName` and `description` are your best clues for matching
74
+ Flag any item older than 60 days as red — surface to practitioner.
58
75
 
59
- ### Step 3: Check for possible duplicates
76
+ ## Step 3 Handle duplicates FIRST
60
77
 
61
78
  ```
62
- POST /api/v1/bank-records/{accountResourceId}/search
63
- {
64
- "filter": { "status": { "eq": "POSSIBLE_DUPLICATE" } },
65
- "sort": { "sortBy": ["valueDate"], "order": "ASC" },
66
- "limit": 1000
67
- }
79
+ search_bank_records(accountResourceId: B.resourceId, status: 'POSSIBLE_DUPLICATE', limit: 200)
68
80
  ```
69
81
 
70
- **Handle duplicates first.** If two bank feed entries have the same date, amount, and description, the system flags them as `POSSIBLE_DUPLICATE`. Review and archive the genuine duplicates before proceeding otherwise you'll create double entries trying to reconcile them.
71
-
72
- ---
73
-
74
- ## Phase 3: Categorize and Resolve
82
+ Two bank-feed entries with same `valueDate + netAmount + description` = system-flagged duplicate. Review each pair: archive the duplicate via `archive_bank_record(resourceId: <id>)` BEFORE running step 4. If you reconcile a duplicated row, you'll create double cashflow entries.
75
83
 
76
- Work through each unreconciled item. There are four resolution paths.
84
+ ## Step 4 Auto-match cascade
77
85
 
78
- ### Path A: Match to existing transaction
79
-
80
- The bank record matches an invoice payment, bill payment, or journal already in the books. This is the ideal case — the transaction exists, it just hasn't been linked to the bank record.
81
-
82
- **For large volumes:** Use `clio jobs bank-recon match --input data.json --json` to auto-match bank records to transactions before manual review. The calculator finds 1:1, N:1, 1:N, and N:M matches with confidence scores. See the [bank-match reference](./bank-match.md) for input format and algorithm details.
83
-
84
- **How to find the match manually:** Search cashflow transactions for the same amount and approximate date:
86
+ For accounts with > ~10 unreconciled rows, use the cascade matcher first:
85
87
 
86
88
  ```
87
- POST /api/v1/cashflow-transactions/search
88
- {
89
- "filter": {
90
- "organizationAccountResourceId": { "eq": "<bank-account-uuid>" },
91
- "totalAmount": { "eq": 2500.00 },
92
- "valueDate": { "between": ["2025-01-10", "2025-01-20"] }
93
- },
94
- "sort": { "sortBy": ["valueDate"], "order": "DESC" },
95
- "limit": 20
96
- }
89
+ clio jobs bank-recon match \
90
+ --input recurring/monthly/<period>/bank-records-<account-name>.json \
91
+ --tolerance 0.01 \
92
+ --date-window 14 \
93
+ --max-group 5 \
94
+ --json
97
95
  ```
98
96
 
99
- **Tip:** Widen the date range by a few days bank processing delays mean the book date and bank date often differ by 1-3 business days.
97
+ Returns matches with confidence scores: `exact` (Phase 1 hash), `fuzzy-high` (Phase 2 weighted 0.85), `fuzzy-medium` (0.70-0.85), `nm-confident` (Phase 5). For each match returned:
100
98
 
101
- ### Path B: Create missing transaction from attachment
99
+ | Match type | Tool to invoke |
100
+ |------------|----------------|
101
+ | AR invoice ↔ bank cash-in | `reconcile_invoice_receipt(bankRecordResourceId, invoiceResourceId, paymentMethod, ...)` |
102
+ | AP bill ↔ bank cash-out | `reconcile_bill_receipt(bankRecordResourceId, billResourceId, paymentMethod, ...)` |
103
+ | Cash entry (single line) ↔ bank | `reconcile_direct_cash_entry(...)` |
104
+ | Cash journal (multi-line) ↔ bank | `reconcile_cash_journal(...)` |
105
+ | Manual journal ↔ bank | `reconcile_manual_journal(...)` |
106
+ | Inter-account transfer | `reconcile_cash_transfer(...)` |
107
+ | Bulk same-shape (>5 items) | `quick_reconcile(bankAccountResourceId, journalsForReconciliation: [...])` (async, returns jobId) |
108
+ | Bank rule applies | `apply_bank_rule(actionShortcutResourceId, businessTransactionResourceIds: [...])` (async) |
102
109
 
103
- The bank record represents a real transaction, but nothing has been entered in the books yet. If you have the receipt, invoice, or bill document, use Jaz Magic to create the transaction automatically.
110
+ For `view_auto_reconciliation` suggestions outside the cascade: invoke once per account, walk the suggestions, commit via the matching `reconcile_*`. Pure read no execution side effect.
104
111
 
105
- ```
106
- POST /api/v1/magic/createBusinessTransactionFromAttachment
107
- Content-Type: multipart/form-data
112
+ ## Step 5 — Manual match (residuals)
108
113
 
109
- Fields:
110
- - sourceFile: <PDF or JPG of the invoice/receipt>
111
- - businessTransactionType: "BILL" (for expenses) or "INVOICE" (for income)
112
- - sourceType: "FILE"
113
- ```
114
+ For unreconciled rows the cascade missed:
114
115
 
115
- Jaz Magic handles OCR, line item extraction, contact matching, and CoA mapping. It creates a draft transaction that you review and post.
116
+ ```
117
+ search_cashflow_transactions(
118
+ filter: {
119
+ organizationAccountResourceId: { eq: B.resourceId },
120
+ totalAmount: { eq: 2500.00 },
121
+ valueDate: { between: ['2025-01-08', '2025-01-22'] }
122
+ },
123
+ sort: 'valueDate:desc',
124
+ limit: 20
125
+ )
126
+ ```
116
127
 
117
- **When you don't have a document:** Create the transaction manually using the appropriate endpoint (invoice, bill, cash-in, cash-out).
128
+ Widen `valueDate` ±7 days for bank processing delays. Match candidate found invoke matching `reconcile_*` tool.
118
129
 
119
- ### Path C: Create cash journal for bank fees/charges
130
+ ## Step 6 Create missing transactions
120
131
 
121
- Bank fees, interest charges, service charges, and similar items don't have a corresponding invoice or bill. Record them as cash-out journals.
132
+ For unreconciled rows that have no book-side counterpart yet:
122
133
 
134
+ **Path B — has document (PDF/JPG):**
123
135
  ```
124
- POST /api/v1/cash-out-entries
125
- {
126
- "saveAsDraft": false,
127
- "reference": "BANK-FEE-JAN25-001",
128
- "valueDate": "2025-01-15",
129
- "accountResourceId": "<bank-account-uuid>",
130
- "lines": [
131
- { "accountResourceId": "<bank-fees-expense-uuid>", "amount": 25.00, "type": "DEBIT", "name": "Monthly service charge — Jan 2025" }
132
- ]
133
- }
136
+ mcp magic create --file <invoice-or-receipt-path>
137
+ # OR equivalent MCP call:
138
+ create_business_transaction_from_attachment(
139
+ sourceFile: <base64 or upload>,
140
+ businessTransactionType: 'BILL' | 'INVOICE',
141
+ sourceType: 'FILE'
142
+ )
134
143
  ```
144
+ Magic does OCR + line item extraction + contact matching + CoA suggestion. Returns draft. Review, finalize via `finalize_bill` / `finalize_invoice`, then loop back to step 4 to reconcile.
135
145
 
136
- For bank interest earned (cash-in):
137
-
146
+ **Path C — bank fees / interest / FX charges (no document):**
138
147
  ```
139
- POST /api/v1/cash-in-entries
140
- {
141
- "saveAsDraft": false,
142
- "reference": "BANK-INT-JAN25-001",
143
- "valueDate": "2025-01-31",
144
- "accountResourceId": "<bank-account-uuid>",
145
- "lines": [
146
- { "accountResourceId": "<interest-income-uuid>", "amount": 12.50, "type": "CREDIT", "name": "Interest earned — Jan 2025" }
147
- ]
148
- }
148
+ create_cash_out_entry(
149
+ reference: 'BANK-FEE-2025-01-15-001',
150
+ valueDate: '2025-01-15',
151
+ accountResourceId: <bank-account-id>,
152
+ lines: [{
153
+ accountResourceId: <Bank Charges expense GL>,
154
+ amount: 25.00,
155
+ type: 'DEBIT',
156
+ name: 'Monthly service charge — Jan 2025'
157
+ }],
158
+ saveAsDraft: false
159
+ )
149
160
  ```
150
161
 
151
- ### Path D: Flag for investigation
162
+ Per rule 26: `accountResourceId` at top level is the BANK account; `lines[]` carries the offset (expense / income).
152
163
 
153
- Some items don't have an obvious match or explanation. Flag these for the business owner or finance manager to investigate. Common causes:
154
- - Personal transactions through the business account
155
- - Refunds or chargebacks
156
- - Intercompany transfers not yet recorded
157
- - Errors in the bank feed (rare but happens)
164
+ For interest income: `create_cash_in_entry(...)` with `type: 'CREDIT'` line against `Interest Income`.
158
165
 
159
- ---
166
+ After creating, loop back to step 4 to reconcile.
160
167
 
161
- ## Phase 4: Verification
168
+ **Preventive build a bank rule:**
169
+ ```
170
+ create_bank_rule(
171
+ name: 'Monthly DBS Service Charge',
172
+ matchCriteria: {description: {contains: 'service charge'}, amount: {between: [20, 30]}},
173
+ action: 'RECONCILE_WITH_DIRECT_CASH_ENTRY',
174
+ cashEntryTemplate: {accountResourceId: <Bank Charges>, ...}
175
+ )
176
+ ```
177
+ Next month's same charge auto-reconciles via `apply_bank_rule`.
162
178
 
163
- After resolving all items, verify the reconciliation is clean.
179
+ **Path D flag for investigation:** if no match and no source document, surface to practitioner with the `extContactName + description` and the `netAmount`. Common: personal transactions, refunds, intercompany unrecorded, bank-feed errors. Document in `ENGAGEMENT.risk_areas`.
164
180
 
165
- ### Step 4: Re-check unreconciled count
181
+ ## Step 7 Verify per account
166
182
 
167
183
  ```
168
- POST /api/v1/bank-records/{accountResourceId}/search
169
- {
170
- "filter": { "status": { "eq": "UNRECONCILED" } },
171
- "sort": { "sortBy": ["valueDate"], "order": "ASC" },
172
- "limit": 1
173
- }
184
+ search_bank_records(accountResourceId: B.resourceId, status: 'UNRECONCILED', limit: 1)
174
185
  ```
175
186
 
176
- **Target:** Zero unreconciled items for the period, or only genuine timing differences (outstanding cheques, deposits in transit that will clear next period).
177
-
178
- ### Step 5: Bank balance summary
187
+ Target: zero rows OR all remaining are documented timing differences (outstanding cheques, deposits in transit clearing next period practitioner annotates).
179
188
 
180
189
  ```
181
- POST /api/v1/generate-reports/bank-balance-summary
182
- { "primarySnapshotDate": "2025-01-31" }
190
+ generate_bank_recon_summary(period_end: '2025-01-31', accountResourceId: B.resourceId)
191
+ generate_bank_recon_details(period_end: '2025-01-31', accountResourceId: B.resourceId)
183
192
  ```
184
193
 
185
- **What to check:**
186
- - Book balance per Jaz should match the bank statement closing balance
187
- - Any difference should equal the sum of known timing items
188
- - Zero unreconciled difference = clean recon
194
+ Save both to `recurring/monthly/<period>/bank-recon-<account-name>.{json,details.json}`. Audit-prep step 7 will require these files.
189
195
 
190
- ### Step 6: Bank reconciliation summary report
196
+ ## Step 8 Cross-account verify
191
197
 
192
198
  ```
193
- POST /api/v1/generate-reports/bank-reconciliation-summary
194
- { "primarySnapshotDate": "2025-01-31" }
199
+ generate_bank_balance_summary(period_end: '2025-01-31')
195
200
  ```
196
201
 
197
- This gives you the formal reconciliation statement showing: opening balance + cash in - cash out = closing balance, with the reconciling items listed.
202
+ Per account: `bookBalance == bankStatementBalance ± documentedTimingDifference`. Discrepancy = unreconciled item missed loop back to step 2 for that account.
198
203
 
199
204
  ---
200
205
 
201
- ## Bank Recon Checklist (Quick Reference)
202
-
203
- | # | Step | Phase | What |
204
- |---|------|-------|------|
205
- | 1 | List bank accounts | Identify | Get all bank-type CoA accounts |
206
- | 2 | Pull unreconciled items | Pull | Search by status = UNRECONCILED |
207
- | 3 | Check duplicates | Pull | Review POSSIBLE_DUPLICATE items |
208
- | A | Match to existing | Resolve | Link to existing invoice/bill/journal |
209
- | B | Create from attachment | Resolve | Use Jaz Magic for documents |
210
- | C | Create cash journal | Resolve | Bank fees, interest, charges |
211
- | D | Flag for investigation | Resolve | Unexplained items |
212
- | 4 | Re-check count | Verify | Should be zero (or timing items only) |
213
- | 5 | Bank balance summary | Verify | Book balance = bank statement |
214
- | 6 | Reconciliation report | Verify | Formal reconciliation statement |
215
-
216
- ---
206
+ ## Common error classes and recovery
217
207
 
218
- ## Tips for SMBs
208
+ | Source | Error | Recovery |
209
+ |--------|-------|----------|
210
+ | `view_auto_reconciliation` | 500 on high-volume account | Documented quirk — service can OOM on accounts with thousands of unreconciled rows. Workaround: invoke per-period (`valueDateRange: {from, to}`) instead of all-time, OR fall back to `clio jobs bank-recon match` cascade which doesn't hit this endpoint. |
211
+ | `view_auto_reconciliation` | 404 | Endpoint not enabled for the org's plan tier. Use cascade matcher only. |
212
+ | `quick_reconcile` | PARTIAL_SUCCESS jobId | Async result. Poll `search_background_jobs(filter: {resourceId: {eq: <jobId>}})` until terminal. Read `data[0].errorDetails[]` for per-row failures; loop back to step 4 for the failed rows. |
213
+ | `quick_reconcile` / `reconcile_*` | (any) — NOT idempotent (rule 124) | On 500 / network error, do NOT retry. Confirm reconciled state via `view_auto_reconciliation` OR `search_bank_records(status: 'RECONCILED')` first. |
214
+ | `reconcile_invoice_receipt` | 422 `invoice_status_invalid` | Matched invoice still DRAFT. `finalize_invoice(resourceId: <id>)` first. |
215
+ | `reconcile_invoice_receipt` | 422 `amount_mismatch` | Bank amount ≠ invoice balance. Either partial payment (post via `create_invoice_payment` with partial amount, then reconcile), or wrong match (revisit step 4/5). |
216
+ | `apply_bank_rule` | 422 `rule_action_unsupported` | Rule's configured action doesn't match the bank entry shape (e.g., rule expects positive amount, entry is negative). Edit the rule via `update_bank_rule`. |
217
+ | `create_cash_out_entry` | 422 `lock_date_violated` | `valueDate` in locked period. Lift lock via `update_account` lockDate, post, re-lock. |
218
+ | Step 7 `unreconciledCount > 0` after step 6 | (residual misses) | Surface to practitioner with categorized residual ("3 bank charges to expense via path C, 1 unidentified deposit pending client query"). Document in `ENGAGEMENT.risk_areas`. Do NOT progress to monthly-close step 4 with open items. |
219
219
 
220
- **Do this weekly, not monthly.** A weekly 15-minute recon is far easier than a monthly 3-hour catch-up. Monday morning is ideal — reconcile the prior week's bank activity before the new week starts.
220
+ ---
221
221
 
222
- **Set up bank rules for recurring items.** If you pay the same rent, subscription, or utility every month, create a bank rule to auto-categorize it. This eliminates the most repetitive part of recon.
222
+ ## Tips
223
223
 
224
- ```
225
- POST /api/v1/bank-rules
226
- ```
224
+ - **Weekly cadence beats monthly catch-up.** Monday-morning 15-min recon vs end-of-month 3-hour scramble. Recipe + cascade matcher amortize across short queues much faster.
225
+ - **Bank rules are the highest-ROI investment.** Every recurring transaction (rent, subscription, utility) handled this run = a one-line `create_bank_rule` away from never seeing it again.
226
+ - **Aspire + Airwallex direct feeds eliminate CSV imports.** No file step before step 2.
227
+ - **Common bank-fee account suggestions:** `Bank Charges` / `Bank Fees` (Operating Expense), `Interest Expense` (for overdraft / loan interest paid to bank), `Interest Income` (savings / deposits), `Foreign Exchange Gain/Loss` (for FX conversion spreads).
227
228
 
228
- **Use bank feeds if available.** Aspire and Airwallex direct feeds auto-import bank records daily. This eliminates the CSV import step entirely.
229
+ ---
229
230
 
230
- **Don't let it pile up.** The longer a bank record sits unreconciled, the harder it is to figure out what it was. After 90 days, you're essentially doing forensic accounting. Stay current.
231
+ ## Cross-references back to engagements
231
232
 
232
- **Common SMB bank fee accounts:**
233
- - Bank Charges / Bank Fees (operating expense)
234
- - Interest Expense (for overdraft/loan interest)
235
- - Interest Income (for savings/deposit interest)
236
- - Foreign Exchange Gain/Loss (for FX conversion fees)
233
+ - `practice/references/monthly-close.md` step 3 — invoked for every bank account in `CLIENT.bank_accounts[]`. Practice playbook owns the per-account orchestration.
234
+ - `practice/references/quarterly-gst.md` step 3 same recon job, scoped to the quarter; F5 Box-1 cash receipts must reconcile against bank cash-in totals.
235
+ - `practice/references/annual-statutory.md` step 3 — final pre-FYE recon. Output feeds into `audit-prep.md` step 7 (NON-NEGOTIABLE deliverable: `unreconciledCount == 0` per account).