jaz-clio 5.55.1 → 5.55.3

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 (34) hide show
  1. package/assets/skills/api/SKILL.md +1 -1
  2. package/assets/skills/cli/SKILL.md +1 -1
  3. package/assets/skills/conversion/SKILL.md +1 -1
  4. package/assets/skills/jaz-kit/SKILL.md +1 -1
  5. package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
  6. package/assets/skills/jobs/SKILL.md +1 -1
  7. package/assets/skills/jobs/references/audit-prep.md +1 -1
  8. package/assets/skills/jobs/references/bank-recon.md +5 -4
  9. package/assets/skills/jobs/references/building-blocks.md +31 -3
  10. package/assets/skills/jobs/references/fa-review.md +3 -3
  11. package/assets/skills/jobs/references/gst-vat-filing.md +4 -4
  12. package/assets/skills/jobs/references/month-end-close.md +7 -7
  13. package/assets/skills/jobs/references/payment-run.md +6 -4
  14. package/assets/skills/jobs/references/quarter-end-close.md +13 -9
  15. package/assets/skills/jobs/references/supplier-recon.md +20 -7
  16. package/assets/skills/jobs/references/year-end-close.md +8 -8
  17. package/assets/skills/transaction-recipes/SKILL.md +1 -1
  18. package/assets/skills/transaction-recipes/references/accrued-expenses.md +6 -6
  19. package/assets/skills/transaction-recipes/references/asset-disposal.md +5 -5
  20. package/assets/skills/transaction-recipes/references/bad-debt-provision.md +2 -2
  21. package/assets/skills/transaction-recipes/references/bank-loan.md +4 -4
  22. package/assets/skills/transaction-recipes/references/building-blocks.md +3 -3
  23. package/assets/skills/transaction-recipes/references/capital-wip.md +4 -4
  24. package/assets/skills/transaction-recipes/references/declining-balance.md +4 -4
  25. package/assets/skills/transaction-recipes/references/deferred-revenue.md +3 -3
  26. package/assets/skills/transaction-recipes/references/dividend.md +2 -2
  27. package/assets/skills/transaction-recipes/references/employee-accruals.md +7 -7
  28. package/assets/skills/transaction-recipes/references/fixed-deposit.md +5 -5
  29. package/assets/skills/transaction-recipes/references/ifrs16-lease.md +4 -4
  30. package/assets/skills/transaction-recipes/references/intercompany.md +2 -2
  31. package/assets/skills/transaction-recipes/references/prepaid-amortization.md +2 -2
  32. package/assets/skills/transaction-recipes/references/provisions.md +4 -4
  33. package/cli.mjs +356 -356
  34. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill whenever you call, debug, or review code that touches the Jaz
6
6
  REST API. Covers field names, response shapes, 159 production gotchas, error
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill when running Clio CLI commands, building shell scripts with
6
6
  Clio, debugging auth issues, understanding --json output, paginating results,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill when migrating accounting data into Jaz — importing from Xero,
6
6
  QuickBooks, Sage, MYOB, or Excel exports. Covers the full conversion pipeline:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-kit
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill when an accountant, bookkeeper, or owner is running real books
6
6
  in Jaz across one or more organizations from the terminal — setting up a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-pseudo-sql
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill when answering ad-hoc data questions that aren't covered by
6
6
  download_export (canonical reports — anomaly, audit, aging, P&L, BS, GL,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill for recurring accounting workflows — month/quarter/year-end
6
6
  close, bank reconciliation, GST/VAT filing, payment runs, credit control,
@@ -138,7 +138,7 @@ Assert: `fa_recon.openingNbv + additions - disposals - depreciation == fa_recon.
138
138
 
139
139
  For non-FA-register schedules (loan, lease, ECL, fixed-deposit, prepaid, intercompany), pull the underlying capsules:
140
140
  ```
141
- search_capsules(filter: {capsuleType: {in: ['Loan Repayment', 'Lease', 'Fixed Deposit', 'Prepaid Expenses', 'Provision']}})
141
+ search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `building-blocks.md` § Filter limits)
142
142
  ```
143
143
  For each capsule, run the matching `clio calc <type>` to produce the independent schedule. Keep one schedule per capsule — the auditor uses these to test the IFRS 9 / IFRS 16 / IAS 37 measurements.
144
144
 
@@ -7,7 +7,7 @@
7
7
  ### Platform tools — discovery + auto-match
8
8
  - **`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).
9
9
  - **`search_accounts(filter: {accountType: {eq: 'Bank Accounts'}})`** — step 1 alternative: same data via standard CoA-search envelope if downstream wants pagination.
10
- - **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', valueDateRange: {from, to}, limit: 200, sort: 'valueDate:asc')`** — step 2: per-account work queue.
10
+ - **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', startDate: <from>, endDate: <to>, limit: 200, sort: 'valueDate:asc')`** — step 2: per-account work queue.
11
11
  - **`search_bank_records(accountResourceId: <id>, status: 'POSSIBLE_DUPLICATE')`** — step 3: handle dups FIRST or you'll double-create reconciling them.
12
12
  - **`view_auto_reconciliation(bankStatementEntryResourceIds: [<id>, ...], recommendationType: 'MAGIC_MATCH' | 'RECOMMENDATIONS' | 'MAGIC_RECONCILE_WITH_CASH_TRANSFER' | 'MAGIC_RECONCILE_WITH_BANK_RULE' | 'MAGIC_QUICK_RECONCILE' | 'MAGIC_RECONCILE_WITH_CASH_IN_OUT', bankAccountResourceId?: <id>, autoCommitMaxAmount?: <number>)`** — step 4: READ-ONLY auto-match suggestions. **Pick the group, not the whole world:** `RECOMMENDATIONS` returns every type except `MAGIC_MATCH` in one ranked call and is the cheaper request; `MAGIC_MATCH` scans open transactions across the account and is asked for on its own. The four specific values narrow to one type. There is no value that returns everything at once, so a two-sided sweep is two calls. `recommendationType` is a REQUEST selector only: `RECOMMENDATIONS` never comes back as a suggestion's own `recommendationType`, which is always a concrete type. **`bankStatementEntryResourceIds` is REQUIRED — this endpoint is per-entry and there is no account-wide mode.** Source the ids from `search_bank_records` with status `UNRECONCILED`. Pass `bankAccountResourceId` too: it is merged into each suggestion's `execute` args for `reconcile_magic_match`. Returns **execution-ready `suggestions[]`** — each carries `recommendedTool`, `execute` (ready-to-pass args), `confidenceTier`, and `autoCommitEligible`. This is the entry point for the auto-match decision gate (step 4a). `MAGIC_RECONCILE_WITH_CASH_IN_OUT` returns Learned-Predictions. Does NOT write. NOTE: cost tracks the entries you pass — batch large backlogs. On a 500 it degrades to `{degraded:true}`; fall back to the cascade matcher (see error table).
13
13
  - **`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.
@@ -66,13 +66,14 @@ For each bank account `B`:
66
66
  search_bank_records(
67
67
  accountResourceId: B.resourceId,
68
68
  status: 'UNRECONCILED',
69
- valueDateRange: { from: '2025-01-01', to: '2025-01-31' },
69
+ startDate: '2025-01-01',
70
+ endDate: '2025-01-31',
70
71
  limit: 200,
71
72
  sort: 'valueDate:asc'
72
73
  )
73
74
  ```
74
75
 
75
- 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.
76
+ Omit `startDate`/`endDate` 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.
76
77
 
77
78
  Flag any item older than 60 days as red — surface to practitioner.
78
79
 
@@ -229,7 +230,7 @@ Per account: `bookBalance == bankStatementBalance ± documentedTimingDifference`
229
230
 
230
231
  | Source | Error | Recovery |
231
232
  |--------|-------|----------|
232
- | `view_auto_reconciliation` | 500 on high-volume account → returns `{degraded:true}` | Documented OOM quirk on accounts with thousands of unreconciled rows. The tool degrades (doesn't throw): scope per-period (`valueDateRange`) OR fall back to `clio jobs bank-recon match` cascade. |
233
+ | `view_auto_reconciliation` | 500 on high-volume account → returns `{degraded:true}` | Documented OOM quirk on accounts with thousands of unreconciled rows. The tool degrades (doesn't throw): scope per-period (`startDate`/`endDate`) OR fall back to `clio jobs bank-recon match` cascade. |
233
234
  | `view_auto_reconciliation` | 404 → returns `{notSupported:true}` | Endpoint not enabled for the org's plan tier. Use cascade matcher only. |
234
235
  | `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. |
235
236
  | `quick_reconcile` / `reconcile_*` | (any) — NOT idempotent (rule 125) | On 500 / network error, do NOT retry. Confirm reconciled state via `view_auto_reconciliation` OR `search_bank_records(status: 'RECONCILED')` first. |
@@ -54,7 +54,7 @@ Recipe engine creates ALL future-dated journals upfront as DRAFT (loan: 60 month
54
54
 
55
55
  Monthly action per recipe-managed capsule:
56
56
  ```
57
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
57
+ search_journals(filter: {valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
58
58
  update_journal(resourceId: <this period's pre-emitted journal>, saveAsDraft: false)
59
59
  ```
60
60
 
@@ -65,7 +65,7 @@ For Jaz-scheduler-driven recurrences (`create_scheduled_journal`, `create_schedu
65
65
  Every recipe-engine call attaches its outputs to a capsule. Search across all capsules of a type for cross-cutting reporting:
66
66
 
67
67
  ```
68
- search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}, status: {eq: 'ACTIVE'}})
68
+ search_capsules(filter: {status: {eq: 'ACTIVE'}})
69
69
  ```
70
70
 
71
71
  Capsule types used by jobs:
@@ -87,7 +87,7 @@ Capsule types used by jobs:
87
87
 
88
88
  Group GL by capsule for the auditor:
89
89
  ```
90
- get_capsule(resourceId) # returns the capsule's transactions; GL cannot group by capsule
90
+ get_capsule(resourceId) # returns totalTransactions (a COUNT), not the transactions; GL cannot group by capsule
91
91
  ```
92
92
 
93
93
  ## Platform tools every job uses
@@ -148,3 +148,31 @@ Every leg carries its own explicit `org_id` — a wrong "active" org silently po
148
148
 
149
149
  - `transaction-recipes/references/building-blocks.md` — recipe-side primitives (capsules, schedulers, the engine itself, recipe-name aliases). Pair with this file for full context.
150
150
  - `jaz-api/SKILL.md` — endpoint-by-endpoint API rules. Cited per-job for specific gotchas.
151
+
152
+ ### Filter limits on capsules and journals (measured 2026-09-07)
153
+
154
+ Two things these playbooks used to instruct are **not supported by the search filters**, and an
155
+ undeclared filter field is REJECTED, not ignored — the call returns a 400 rather than a wider result.
156
+
157
+ **Capsules cannot be filtered by type.** `CapsuleFilter` declares only `and`, `description`,
158
+ `endDate`, `or`, `resourceId`, `startDate`, `status`, `title`. Fetch with the filters that exist and
159
+ narrow client-side on the row: `type` is the flat string, `capsuleType` is an OBJECT
160
+ (`{name, displayName, resourceId, status, ...}`). Match on `type` or `capsuleType.name`, and expect
161
+ BOTH casings — the same field carries `Prepaid Expenses` on one row and `TAX_PAYMENT` on another, so
162
+ compare case-insensitively with separators normalized rather than testing equality against a label.
163
+
164
+ **Journals cannot be filtered by capsule or by fixed asset.** `JournalFilter` declares `and`,
165
+ `andGroup`, `contact`, `createdAt`, `creator`, `internalNotes`, `or`, `orGroup`, `reference`,
166
+ `resourceId`, `status`, `tags`, `templateType`, `type`, `updatedAt`, `valueDate` — no
167
+ `capsuleResourceId`, no `fixedAssetResourceId`. There is no reverse route either: a capsule exposes
168
+ only `totalTransactions` (a count), and no `/capsules/{id}/journals` endpoint exists. Narrow with
169
+ the declared fields — `valueDate`, `status`, `type`, `templateType`, `tags`, `reference` — and report the capsule
170
+ and its `totalTransactions` count and let the practitioner identify the journals. Do NOT assume the
171
+ recipe left a link to match on: `referencePrefix` is optional with no default (`core/recipe/types.ts`),
172
+ is caller-chosen text unrelated to the capsule id, and the engine sets no tags on anything it creates
173
+ (`core/recipe/engine.ts`). Note `tags` is PLURAL; `tag` is rejected.
174
+
175
+ **Capsules cannot be filtered by date either.** `startDate` and `endDate` are declared on
176
+ `CapsuleFilter` and pass validation, but every form measured on 2026-09-07 — `{gte}`, `{between}`,
177
+ and `{gte}` paired with `{lte}` — answers `500 Internal Server Error`. Filter on `status`/`title`
178
+ and narrow dates on the rows.
@@ -68,8 +68,8 @@ For each ACTIVE SL asset (Jaz auto-depreciates):
68
68
  - Should match within rounding ($0.12 tolerance for full-year SL).
69
69
 
70
70
  For each ACTIVE DDB / 150DB asset (recipe-managed, see the `depreciation` recipe):
71
- - Per capsule: `search_journals(filter: {capsuleResourceId: {eq: <dep capsule>}, valueDate: {between: [<year-start>, <year-end>]}, status: 'DRAFT'})`. Should be zero — all 12 months' DRAFT depreciation journals should already be FINALIZED via the monthly close.
72
- - If non-zero: `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])` for each remaining DRAFT.
71
+ - Per capsule: the 12 monthly DRAFT depreciation journals should already be FINALIZED via the monthly close. This cannot be verified with a filter — journals carry no capsule or fixed-asset link in either direction (measured 2026-09-07) — so report the capsule and its `totalTransactions` count for the practitioner to check, rather than searching by date.
72
+ - If the practitioner identifies remaining DRAFTs, finalize those specific resourceIds with `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])` — never a set collected by an unscoped search.
73
73
 
74
74
  Cross-check via `clio calc depreciation --frequency annual --json` per asset; auditor will sample-test.
75
75
 
@@ -134,7 +134,7 @@ These feed `audit-prep.md` step 8 supporting schedules.
134
134
  | Step 3 | Recon doesn't tie | Disposed asset still ACTIVE in register (the `asset-disposal` recipe leaves the FA-register status update to you). Audit each disposal's status. |
135
135
  | Step 4 | DDB / 150DB DRAFTs unfinalized | Likely a missed monthly close. Finalize the current ones and surface to the user — the auditor will otherwise see 12 months' depreciation in one period. |
136
136
  | Step 4 | SL depreciation off by > $0.12 | A monthly depreciation period was skipped (asset created mid-month with mis-aligned `acquisitionDate`). Reconcile per asset. |
137
- | Step 5 | `update_fixed_asset` to DISPOSED | 422 `pending_depreciation_journals` | DRAFT depreciation journals exist for periods after disposal date. `search_journals(filter: {fixedAssetResourceId: <id>, valueDate: {gt: <disposal>}, status: 'DRAFT'})` → `delete_journal` per result. Then retry. |
137
+ | Step 5 | `update_fixed_asset` to DISPOSED | 422 `pending_depreciation_journals` | DRAFT depreciation journals exist for periods after disposal date. **Do not select these with a filter** — journals cannot be narrowed to one fixed asset (`JournalFilter` has no `fixedAssetResourceId`, and a journal row carries no asset link), so a date+status search returns every DRAFT in the org and `delete_journal` over it would destroy unrelated work. Surface the asset and the blocking periods to the practitioner and let them identify the journals, then retry. |
138
138
  | Step 6 | Trying to dispose an FA at NBV = 0 with no proceeds | Recipe still works but creates a no-effect journal. May be skippable; surface to practitioner. |
139
139
 
140
140
  ---
@@ -8,7 +8,7 @@
8
8
  - **`generate_vat_ledger(period_start: <period-start>, period_end: <period-end>)`** — step 1: the canonical tax ledger. Returns input + output tax totals + per-tax-profile breakdown.
9
9
  - **`search_tax_profiles(filter: {})`** — step 2 setup verification: confirm all expected tax profiles exist (`SR`, `ZR`, `ES`, `IES`, `OS`, `TX`, `BL`, `OP`, `EP`, `RC` for SG; `VAT-RC`, `VAT-EXP`, `VAT-ZR`, `VAT-EXM`, `VAT-EXC` for PH).
10
10
  - **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** — step 3 output-tax detail: per-invoice GST cross-check against tax ledger.
11
- - **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}, status: {ne: 'DRAFT'}}, limit: 200)`** — step 4 input-tax detail: per-bill GST cross-check, with blocked-input filter.
11
+ - **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}, status: {neq: 'DRAFT'}}, limit: 200)`** — step 4 input-tax detail: per-bill GST cross-check, with blocked-input filter.
12
12
  - **`quick_fix_invoices(...)` / `quick_fix_bills(...)`** — step 5 corrections: bulk-update tax-profile / tax-vat-applicable across multiple transactions if errors found.
13
13
  - **`download_export(exportType: 'analysis-exchange-rate-audit', startDate, endDate)`** — step 6 pre-filing check: FX rates outside expected band can shift GST on FX invoices.
14
14
  - **`generate_trial_balance(period_end: <period-end>)`** — step 7 GST account reconciliation: `GST Control` / `Input Tax Recoverable` / `Output Tax Payable` accounts.
@@ -66,7 +66,7 @@ Halt if any expected profile is missing — surface to practitioner with create
66
66
  ## Step 3 — Output-tax detail review
67
67
 
68
68
  ```
69
- search_invoices(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {in: ['ACTIVE', 'PAID', 'PARTIALLY_PAID']}}, limit: 200, sort: 'valueDate:asc')
69
+ search_invoices(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {in: ['UNPAID', 'PARTIALLY_PAID', 'PAID']}}, limit: 200, sort: 'valueDate:asc')
70
70
  ```
71
71
 
72
72
  Paginate via offset if `totalElements > 200`. For each invoice:
@@ -82,7 +82,7 @@ Flag invoices where:
82
82
  ## Step 4 — Input-tax detail review
83
83
 
84
84
  ```
85
- search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {ne: 'DRAFT'}}, limit: 200)
85
+ search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {neq: 'DRAFT'}}, limit: 200)
86
86
  ```
87
87
 
88
88
  For each bill:
@@ -172,7 +172,7 @@ Save the filing summary for the quarter. The user files via the appropriate port
172
172
 
173
173
  | Source | Error | Recovery |
174
174
  |--------|-------|----------|
175
- | Step 1 | `generate_vat_ledger` returns 0 for input tax despite bills exist | Likely all bills are DRAFT. `search_bills(filter: {status: 'DRAFT', valueDate: {between: [<Q-start>, <Q-end>]}})`; finalize via `bulk_finalize_drafts` (or `finalize_bill` per ID). |
175
+ | Step 1 | `generate_vat_ledger` returns 0 for input tax despite bills exist | Likely all bills are DRAFT. `search_bills(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<Q-start>, <Q-end>]}})`; finalize via `bulk_finalize_drafts` (or `finalize_bill` per ID). |
176
176
  | Step 2 | Tax profile missing for jurisdiction | `create_tax_profile(...)` per IRAS / BIR spec. Halt and surface to practitioner — practitioner judgment on rate. |
177
177
  | Step 3 | Per-invoice GST ≠ tax-ledger output total | Investigate per-invoice tax-profile assignment. Quick Fix typically resolves. |
178
178
  | Step 4 | BL bills coded as TX | Quick Fix re-assigns to BL. Practitioner approval required (changes input tax claim). |
@@ -7,7 +7,7 @@
7
7
  ### Platform tools — pre-close gates
8
8
  - **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, sort: 'valueDate:asc', limit: 200)`** — step 1: confirm sales invoices entered. Paginate via `offset`.
9
9
  - **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}}, ...)`** — step 2: confirm purchase bills entered.
10
- - **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', valueDateRange: {from, to})`** — step 3: pull unreconciled bank statement entries per account.
10
+ - **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', startDate: <from>, endDate: <to>)`** — step 3: pull unreconciled bank statement entries per account.
11
11
  - **`generate_aged_ar(period_end: <date>)` / `generate_aged_ap(period_end: <date>)`** — steps 4-5: aging reports tied to TB AR / AP balances.
12
12
 
13
13
  ### Platform tools — accruals + valuations
@@ -28,7 +28,7 @@
28
28
  - **`generate_trial_balance(period_end: <date>)`** — step 14: master reconciliation.
29
29
  - **`generate_profit_and_loss(period_start, period_end)`** — step 15.
30
30
  - **`generate_balance_sheet(period_end)`** — step 16.
31
- - **`search_journals(filter: {status: 'DRAFT', valueDate: {between: [<period-start>, <period-end>]}})`** — step 17: gate on zero drafts.
31
+ - **`search_journals(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<period-start>, <period-end>]}})`** — step 17: gate on zero drafts.
32
32
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 17: clear residual drafts before lock.
33
33
  - **`update_account(resourceId: <CoA root>, lockDate: <period-end>)`** — step 18: lock the period.
34
34
 
@@ -74,7 +74,7 @@ Cross-reference against email + supplier portals + physical mail. Late bills = m
74
74
  For each bank account:
75
75
 
76
76
  1. If you don't already have the account's resourceId: `list_bank_accounts()`, match by `name + currency`, confirm with the user.
77
- 2. `search_bank_records(accountResourceId: <bank account resourceId>, status: 'UNRECONCILED', valueDateRange: {from: '2025-01-01', to: '2025-01-31'}, limit: 200, sort: 'valueDate:asc')`.
77
+ 2. `search_bank_records(accountResourceId: <bank account resourceId>, status: 'UNRECONCILED', startDate: '2025-01-01', endDate: '2025-01-31', limit: 200, sort: 'valueDate:asc')`.
78
78
  3. If results: drive the 5-phase cascade matcher (Step 4 in `bank-recon.md`; local CLI: `clio jobs bank-recon match --input <records> --tolerance 0.01 --date-window 14 --json`). For each match, invoke the matching `reconcile_*` tool.
79
79
  4. `view_auto_reconciliation(bankStatementEntryResourceIds: [<id>, ...], recommendationType: 'MAGIC_MATCH')` — READ-ONLY suggestions for residuals (per-entry; get ids from `search_bank_records`, status `UNRECONCILED`); commit via `quick_reconcile` / `apply_bank_rule` / per-entry `reconcile_*`.
80
80
  5. `generate_bank_recon_summary(period_end: '2025-01-31', accountResourceId: <id>)`. Confirm `unreconciledCount == 0` OR document the residuals for the period and surface to the user.
@@ -108,9 +108,9 @@ Cross-check: `generate_trial_balance(period_end: '2025-01-31')`. Sum credit move
108
108
 
109
109
  ### Step 7 — Prepaid expense recognition (finalize this period's pre-emitted journal)
110
110
 
111
- For each existing `Prepaid Expenses` capsule (via `search_capsules(filter: {capsuleType: {eq: 'Prepaid Expenses'}})`):
111
+ For each existing `Prepaid Expenses` capsule (via `search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)):
112
112
 
113
- 1. `search_journals(filter: {capsuleResourceId: {eq: <capsule.id>}, valueDate: {between: ['2025-01-01', '2025-01-31']}, status: {eq: 'DRAFT'}})`. The recipe pre-emitted this period's recognition journal as DRAFT at recipe-execution time.
113
+ 1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule: `JournalFilter` declares no `capsuleResourceId`, a journal row carries no capsule link even at `view: 'full'` or on `GET /journals/{id}`, and `GET /capsules/{id}` returns only `totalTransactions` — a count (all measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(saveAsDraft: false)` finalizes unrelated work. Surface the capsule and its expected journal count and let the practitioner identify the journals to finalize.
114
114
  2. If empty: either the recipe was set up wrong (no journal for this period — investigate via `search_journals` without status filter to see if it's already ACTIVE, then skip), OR the practitioner went off-recipe. Surface to practitioner.
115
115
  3. If found: collect resourceIds, then `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`.
116
116
  4. New prepaid setups during this period (a new prepaid started this month): invoke `plan_recipe(recipe: 'prepaid-expense', ...)` (see the `prepaid-expense` recipe in the transaction-recipes skill) — this creates the bill + N future-dated DRAFT journals; the current period's journal is then in the bulk_finalize_drafts queue above.
@@ -139,9 +139,9 @@ On first month of FY only — engine creates the scheduler and posts the first a
139
139
 
140
140
  ### Step 11 — Loan interest (finalize this period's pre-emitted journal)
141
141
 
142
- For each active loan capsule (via `search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}})`):
142
+ For each active loan capsule (via `search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)):
143
143
 
144
- 1. `search_journals(filter: {capsuleResourceId: {eq: <loan-capsule-id>}, valueDate: {between: ['2025-01-01', '2025-01-31']}, status: {eq: 'DRAFT'}})`. The `loan` recipe pre-emitted all `termMonths` future-dated DRAFT journals at execution time — this period's repayment is one of them.
144
+ 1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule: `JournalFilter` declares no `capsuleResourceId`, a journal row carries no capsule link even at `view: 'full'` or on `GET /journals/{id}`, and `GET /capsules/{id}` returns only `totalTransactions` — a count (all measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(saveAsDraft: false)` finalizes unrelated work. Surface the capsule and its expected journal count and let the practitioner identify the journals to finalize.
145
145
  2. Should return exactly one DRAFT journal per active loan. Each is a 3-line entry (debit Loan Payable, debit Interest Expense, credit Cash) with the correct amortization split for the period.
146
146
  3. Collect resourceIds, then `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`.
147
147
  4. Do NOT post manual loan-interest accruals — the recipe already emitted the journal with the correct split per `clio calc loan` schedule.
@@ -5,12 +5,14 @@
5
5
  ## Tools, recipes, calculators this job uses
6
6
 
7
7
  ### Platform tools (jaz-api)
8
- - **`search_bills(filter: {status: 'UNPAID', balanceAmount: {gt: 0}, dueDate: {lte: <cutoff>}}, sort: 'dueDate:asc', limit: 200)`** — used in step 2: pull due bills (paginate via `offset` if `>200`).
8
+ - **`search_bills(filter: {status: {eq: 'UNPAID'}, balanceAmount: {gt: 0}, dueDate: {lte: <cutoff>}}, sort: 'dueDate:asc', limit: 200)`** — used in step 2: pull due bills (paginate via `offset` if `>200`).
9
9
  - **`generate_aged_ap(period_end: <cutoff>)`** — used in step 3: total-AP cross-check; flag bills in 60d+ aging buckets.
10
10
  - **`generate_bank_balance_summary(period_end: <cutoff>)`** — used in step 5: confirm cash availability before approving the batch.
11
11
  - **`get_contact(resourceId: <contactResourceId>)`** — used in step 4 (per supplier): pull payment terms / preferred payment method / bank details (especially `taxId`, `bankAccountNumber`, `bicSwift` for GIRO file generation).
12
12
  - **`create_bill_payment(billResourceId: <id>, payments: [{...}])`** — used in step 6: post the payment per bill. NO BATCH PAYMENT ENDPOINT yet — one POST per bill.
13
- - **`search_payments(filter: {reference: {startsWith: <run-prefix>}, valueDate: {eq: <run-date>}})`** — used in step 8: idempotency / verification check (re-running the run won't duplicate-pay if all references match).
13
+ - **`search_payments(filter: {businessTransactionReference: {startWith: <run-prefix>}, valueDate: {eq: <run-date>}})`** — used in step 8: idempotency / verification check (re-running the run won't duplicate-pay if all references match).
14
+
15
+ > **The field and the operator are both exact.** `search_payments` hits `POST /cashflow-transactions/search` → `TransactionsFilter`, which declares no `additionalProperties`, so an undeclared field is rejected outright rather than ignored. It has **no `reference`** (that is `businessTransactionReference`) and `StringExpression` has **no `startsWith`** — the prefix operator is spelled **`startWith`**, no "s". Until 5.55.3 this line asked for both wrong names, so the idempotency check — the step standing between a re-run and paying every supplier twice — could not return anything. Use `startWith`, not `contains`: measured on the sandbox 2026-09-07, `contains: 'PR-'` matched 3 rows that do **not** start with that prefix, and a looser match here silently widens what the run treats as already-paid.
14
16
  - **`finalize_bill(resourceId: <id>)`** — used in step 0 fallback: bills must be `status: APPROVED` (not `DRAFT`) before they accept payments.
15
17
 
16
18
  ### CLI tools (jaz-cli)
@@ -29,7 +31,7 @@
29
31
  Generate a run prefix: `PAYRUN-<YYYY-MM-DD>-<seq>`. Before proceeding:
30
32
 
31
33
  ```
32
- search_payments(filter: {reference: {startsWith: 'PAYRUN-2025-02-28-'}})
34
+ search_payments(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}})
33
35
  ```
34
36
 
35
37
  If results: surface "A payment run with prefix `PAYRUN-2025-02-28-*` already executed on this date (`<n>` payments totalling `<amt>`). Confirm intent — re-run will create duplicate payments." Halt unless practitioner confirms.
@@ -118,7 +120,7 @@ After all `create_bill_payment` calls succeed:
118
120
 
119
121
  ```
120
122
  generate_aged_ap(period_end: '2025-02-28')
121
- search_payments(filter: {reference: {startsWith: 'PAYRUN-2025-02-28-'}, valueDate: {eq: '2025-02-28'}})
123
+ search_payments(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}, valueDate: {eq: '2025-02-28'}})
122
124
  ```
123
125
 
124
126
  Assert:
@@ -11,10 +11,10 @@
11
11
  - **`generate_vat_ledger(period_start: <Q-start>, period_end: <Q-end>)`** — Q1 GST/VAT filing prep: full quarterly tax ledger.
12
12
  - **`generate_aged_ar(period_end: <Q-end>)`** — Q2 ECL formal review input.
13
13
  - **`plan_recipe(recipe: 'ecl', ...)` + `execute_recipe(...)`** — Q2 ECL top-up if material.
14
- - **`search_journals(filter: {tag: 'bonus-accrual', valueDate: {between: [<Q-start>, <Q-end>]}})`** — Q3 bonus YTD pull.
14
+ - **`search_journals(filter: {tags: {eq: 'bonus-accrual'}, valueDate: {between: [<Q-start>, <Q-end>]}})`** — Q3 bonus YTD pull.
15
15
  - **`create_journal(...)`** — Q3 bonus true-up adjustment (manual one-off).
16
- - **`search_capsules(filter: {capsuleType: {eq: 'Intercompany'}})`** — Q4 IC reconciliation per pair of entities (multi-org coordination — see the `intercompany` recipe).
17
- - **`search_capsules(filter: {capsuleType: {eq: 'Provisions'}})` + `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — Q5 finalize each provision capsule's quarter-end DRAFT unwinding journals.
16
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)** — Q4 IC reconciliation per pair of entities (multi-org coordination — see the `intercompany` recipe).
17
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits) + `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — Q5 finalize each provision capsule's quarter-end DRAFT unwinding journals.
18
18
  - **`generate_trial_balance(period_end: <Q-end>)`** — verification.
19
19
  - **`update_account(resourceId: <CoA root>, lockDate: <Q-end>)`** — final lock.
20
20
 
@@ -87,7 +87,7 @@ Save the ECL analysis for the quarter — the auditor will request it each quart
87
87
  If the org has a bonus policy with an estimation method:
88
88
 
89
89
  ```
90
- search_journals(filter: {tag: 'bonus-accrual', valueDate: {between: ['2025-01-01', '2025-03-31']}})
90
+ search_journals(filter: {tags: {eq: 'bonus-accrual'}, valueDate: {between: ['2025-01-01', '2025-03-31']}})
91
91
  ```
92
92
 
93
93
  Sum YTD accruals. Re-estimate full-year bonus per current performance data. If revised quarterly estimate ≠ already-accrued amount: post manual `create_journal` true-up against `Bonus Expense` / `Bonus Payable` for the delta.
@@ -109,15 +109,19 @@ Full pattern in the `intercompany` recipe.
109
109
  For each active IAS 37 provision capsule:
110
110
 
111
111
  ```
112
- search_capsules(filter: {capsuleType: {eq: 'Provisions'}, status: {eq: 'ACTIVE'}})
112
+ search_capsules(filter: {status: {eq: 'ACTIVE'}})
113
113
  ```
114
114
 
115
115
  Per capsule: this period's quarter-end unwinding DRAFT journals (3 monthly DRAFTs from `provision` recipe execution) should already be in the capsule. Verify and finalize:
116
116
 
117
- ```
118
- search_journals(filter: {capsuleResourceId: {eq: <provision capsule id>}, valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {eq: 'DRAFT'}})
119
- bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])
120
- ```
117
+ > **STOP — this step cannot be scoped, and must not be automated.** Narrowing journals to one
118
+ > capsule is not possible: `JournalFilter` declares no `capsuleResourceId`, a journal row carries no
119
+ > capsule link even at `view: 'full'` or on `GET /journals/{id}`, and `GET /capsules/{id}` returns
120
+ > only `totalTransactions` — a count (all measured 2026-09-07). A search by date and status alone
121
+ > returns **every** matching DRAFT in the org, including drafts a practitioner deliberately parked,
122
+ > so feeding it to `bulk_update_journals(saveAsDraft: false)` or `delete_journal` would finalize or
123
+ > destroy unrelated work. Surface the capsule and its expected journal count to the practitioner and
124
+ > let them identify the journals; do not select them with a filter.
121
125
 
122
126
  If the user determines remeasurement is needed (cash-flow estimate changed, discount rate moved): recompute, post the adjustment, reverse the remaining DRAFT unwinding journals, and re-execute the `provision` recipe with the new inputs.
123
127
 
@@ -7,9 +7,22 @@
7
7
  ### Platform tools
8
8
  - **`search_contacts(filter: {supplier: true, name: {eq: <supplier>}})`** — step 1: resolve the supplier resourceId. Use fuzzy match if exact fails.
9
9
  - **`get_contact(resourceId: <supplier id>)`** — step 1 detail: pull the supplier's payment terms, contact info.
10
- - **`search_bills(filter: {contactResourceId: <supplier id>, valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** — step 2: pull all bills from this supplier in the period. Paginate.
11
- - **`search_payments(filter: {contactResourceId: <supplier id>, valueDate: {between: [<period-start>, <period-end>]}, type: 'PAYOUT'})`** — step 3: pull all payments to this supplier.
12
- - **`search_supplier_credit_notes(filter: {contactResourceId: <supplier id>, valueDate: {between: [<period-start>, <period-end>]}})`** — step 4: pull credit notes that may have been applied.
10
+ - **`search_bills(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** — step 2: pull all bills from this supplier in the period. Paginate.
11
+ - **`search_payments(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}, direction: {eq: 'PAYOUT'}})`** — step 3: pull all payments to this supplier.
12
+ - **`search_supplier_credit_notes(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}})`** — step 4: pull credit notes that may have been applied.
13
+
14
+ > **A filter value must be an OBJECT, not a bare scalar.** This is the trap these lines fell into:
15
+ > `filter: {contactResourceId: <supplier id>}` was rejected with a bare `Invalid request body` that
16
+ > named nothing, and the obvious reading — "the field does not exist" — is wrong. `contactResourceId`
17
+ > **is** declared on bills, supplier credit notes and invoices; it is typed `StringExpression`, so it
18
+ > needs an operator: `{eq: <id>}`. Measured 2026-09-07: the bare form 400s on both, `{eq: …}` returns
19
+ > 200 on both. The nested `contact: {resourceId: {eq: <id>}}` form used above also works and is what
20
+ > `search_payments` requires, because `TransactionsFilter` is the one of the four that genuinely does
21
+ > **not** declare `contactResourceId` — there, and only there, the field really is absent.
22
+ >
23
+ > The amount filter differs by endpoint: `totalAmount` is accepted on bills and on
24
+ > cashflow-transactions but **rejected on supplier credit notes**, and no `paymentAmount` filter
25
+ > exists anywhere — it is a response field on a payment, not a filter key.
13
26
  - **`generate_aged_ap(period_end: <date>)`** — step 5: per-supplier outstanding balance.
14
27
  - **`create_bill(...)`** / **`apply_credit_to_bill(...)`** / **`create_supplier_credit_note(...)`** — step 6: post any missing items identified during recon.
15
28
 
@@ -41,7 +54,7 @@ Pull `paymentTerms`, `bankAccountNumber`, `taxId`, `paymentMethod` for narrative
41
54
 
42
55
  ```
43
56
  search_bills(
44
- filter: {contactResourceId: <supplier id>, valueDate: {between: ['2025-01-01', '2025-01-31']}},
57
+ filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}},
45
58
  sort: 'valueDate:asc',
46
59
  limit: 200
47
60
  )
@@ -54,7 +67,7 @@ For an opening-balance recon: also pull the supplier's pre-period balance via `g
54
67
  ## Step 3 — Pull payments
55
68
 
56
69
  ```
57
- search_payments(filter: {contactResourceId: <supplier id>, valueDate: {between: ['2025-01-01', '2025-01-31']}, type: {eq: 'PAYOUT'}})
70
+ search_payments(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}, direction: {eq: 'PAYOUT'}})
58
71
  ```
59
72
 
60
73
  Per payment: `{resourceId, reference, valueDate, paymentAmount, transactionAmount, paymentMethod, billResourceId}`. Save.
@@ -62,7 +75,7 @@ Per payment: `{resourceId, reference, valueDate, paymentAmount, transactionAmoun
62
75
  ## Step 4 — Pull credit notes
63
76
 
64
77
  ```
65
- search_supplier_credit_notes(filter: {contactResourceId: <supplier id>, valueDate: {between: [<period-start>, <period-end>]}})
78
+ search_supplier_credit_notes(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}})
66
79
  ```
67
80
 
68
81
  Save. Each credit note may have been applied to one or more bills; the application reduces the bill balance.
@@ -85,7 +98,7 @@ Practitioner provides the supplier's statement (PDF, email, paper). Per-line-ite
85
98
  | Bill in Jaz, not on supplier statement | Supplier hasn't issued / lost the invoice | Verify with supplier; if confirmed bogus, `delete_bill` (DRAFT) OR `create_supplier_credit_note` (if ACTIVE). |
86
99
  | Different amounts on same reference | Pricing dispute | Practitioner contacts supplier for clarification. Possible adjustment journal post-resolution. |
87
100
  | Bill paid per Jaz, supplier says unpaid | Bank reconciliation gap | Pull bank statement for the payment date; verify the wire/cheque cleared. If cleared, send remittance proof to supplier. |
88
- | Bill unpaid per Jaz, supplier says paid | Payment recorded against wrong supplier OR bill | Audit `search_payments(filter: {valueDate: {eq: <date>}, paymentAmount: {eq: <amount>}})`; identify mis-routing; post correcting journal OR re-issue payment. |
101
+ | Bill unpaid per Jaz, supplier says paid | Payment recorded against wrong supplier OR bill | Audit `search_payments(filter: {valueDate: {eq: <date>}, totalAmount: {eq: <amount>}})`; identify mis-routing; post correcting journal OR re-issue payment. |
89
102
  | Supplier credit note not in Jaz | Missed credit | `create_supplier_credit_note(...)` per supplier statement. Then `apply_credit_to_bill(...)` to the offsetting bill. |
90
103
  | Currency mismatch | FX bills with different rates | Confirm Jaz used the right rate per `jaz-api/SKILL.md` rule 25; the supplier statement may use spot rate, Jaz uses recorded rate. Document the FX gap. |
91
104
 
@@ -12,15 +12,15 @@
12
12
  - **`generate_fa_recon_summary(period_start: <FY-start>, period_end: <FY-end>)`** — Y1 verification: opening NBV + additions − disposals − depreciation = closing NBV.
13
13
  - **`search_fixed_assets(filter: {status: {in: ['ACTIVE', 'DISPOSED']}})`** — Y1 enumeration of FAs.
14
14
  - **`update_fixed_asset(resourceId: <id>, status: 'ACTIVE'|'DISPOSED'|'WRITTEN_OFF')`** — Y1 fallback if any FA has incorrect status at FY-end.
15
- - **`search_journals(filter: {tag: 'leave-accrual', valueDate: {between: [<FY-start>, <FY-end>]}})` / `search_journals(filter: {tag: 'bonus-accrual', ...})`** — Y2 true-up: pull all FY accrual journals to compare against actuals.
15
+ - **`search_journals(filter: {tags: {eq: 'leave-accrual'}, valueDate: {between: [<FY-start>, <FY-end>]}})` / `search_journals(filter: {tags: {eq: 'bonus-accrual'}, ...})`** — Y2 true-up: pull all FY accrual journals to compare against actuals.
16
16
  - **`create_journal(...)`** — Y2 true-up adjustment journals (manual one-off, not recipe-driven).
17
17
  - **`plan_recipe(recipe: 'dividend', ...)` + `execute_recipe(...)`** — Y3 dividend declaration + payment (engine emits the 2-step pattern: declaration journal + payment cash-out).
18
18
  - **`plan_recipe(recipe: 'ecl', ...)` + `execute_recipe(...)`** — Y4 IFRS 9 ECL year-end true-up against `generate_aged_ar`.
19
19
  - **`update_account(resourceId: <CoA root>, lockDate: <FY-end>)`** — Y8 final lock.
20
20
 
21
21
  ### Platform tools — current/non-current reclassification (manual annual journals)
22
- - **`search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}})`** + per-capsule `clio calc loan` to compute next-12-months principal portion.
23
- - **`search_capsules(filter: {capsuleType: {eq: 'Lease'}})`** + per-capsule `clio calc lease` for IFRS 16 reclassification.
22
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)** + per-capsule `clio calc loan` to compute next-12-months principal portion.
23
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)** + per-capsule `clio calc lease` for IFRS 16 reclassification.
24
24
  - **`create_journal(...)`** for the reclassification entries (Dr Loan Payable Non-current / Cr Loan Payable Current; Dr Lease Liability Non-current / Cr Lease Liability Current).
25
25
 
26
26
  ### Handoff to audit-prep
@@ -66,16 +66,16 @@ generate_fa_recon_summary(period_start: '2025-01-01', period_end: '2025-12-31')
66
66
 
67
67
  For Jaz native straight-line depreciation: should be automatic and correct. Verify the 12-month aggregate against `generate_general_ledger(accountResourceId: <Depreciation Expense>, period_start, period_end)`.
68
68
 
69
- For non-SL assets (DDB, 150DB) where `plan_recipe(recipe: 'depreciation', method: 'ddb' | '150db')` was used: each capsule pre-emitted 12 future-dated DRAFT journals at recipe-execution time. Confirm all 12 are FINALIZED via `search_journals(filter: {capsuleResourceId: {eq: <dep capsule>}, status: {eq: 'DRAFT'}, valueDate: {between: [<FY-start>, <FY-end>]}})` — should be empty. If non-empty: route back to `month-end-close.md` step 9.
69
+ For non-SL assets (DDB, 150DB) where `plan_recipe(recipe: 'depreciation', method: 'ddb' | '150db')` was used: each capsule pre-emitted 12 future-dated DRAFT journals at recipe-execution time. Confirm all 12 are FINALIZED via `search_journals(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<FY-start>, <FY-end>]}})` — should be empty. If non-empty: route back to `month-end-close.md` step 9.
70
70
 
71
- Reconcile `generate_fa_recon_summary` formula: `openingNbv + additions − disposals − depreciation == closingNbv == TB[Fixed Assets].balance`. Mismatch beyond the materiality threshold → investigate via `search_fixed_assets(filter: {status: {eq: 'ACTIVE'}})` cross-referenced against the depreciation capsule's journals (`search_journals(filter: {capsuleResourceId: {eq: <dep capsule>}, startDate: <FY-start>, endDate: <FY-end>})`) — typical cause is a disposal posted without `update_fixed_asset(status: 'DISPOSED')`.
71
+ Reconcile `generate_fa_recon_summary` formula: `openingNbv + additions − disposals − depreciation == closingNbv == TB[Fixed Assets].balance`. Mismatch beyond the materiality threshold → investigate via `search_fixed_assets(filter: {status: {eq: 'ACTIVE'}})` cross-referenced against the depreciation capsule's journals (`search_journals(filter: {valueDate: {between: [<FY-start>, <FY-end>]}})`) — typical cause is a disposal posted without `update_fixed_asset(status: 'DISPOSED')`.
72
72
 
73
73
  ### Y2 — Annual true-ups (manual journals)
74
74
 
75
75
  **Leave balance true-up:**
76
76
 
77
77
  ```
78
- search_journals(filter: {tag: 'leave-accrual', valueDate: {between: ['2025-01-01', '2025-12-31']}})
78
+ search_journals(filter: {tags: {eq: 'leave-accrual'}, valueDate: {between: ['2025-01-01', '2025-12-31']}})
79
79
  ```
80
80
 
81
81
  Sum FY accruals (the recipe-pre-emitted journals already finalized monthly). Compare against actual unused leave days × daily rate per employee at FY-end (HR data). Difference: post manual `create_journal`:
@@ -149,7 +149,7 @@ For specific large customers requiring stage-3 provision (specific impairment vs
149
149
  For each existing IAS 37 provision capsule (warranty, legal, decommissioning):
150
150
 
151
151
  ```
152
- search_capsules(filter: {capsuleType: {eq: 'Provision'}, status: 'ACTIVE'})
152
+ search_capsules(filter: {status: {eq: 'ACTIVE'}})
153
153
  ```
154
154
 
155
155
  Per capsule, recompute the present value at FY-end (`clio calc provision`). Top-up via additional `plan_recipe(recipe: 'provision', ...)` + `execute_recipe` if required, OR reverse via `create_journal` if the obligation reduced.
@@ -211,7 +211,7 @@ Invoke `audit-prep.md` job. Year-end-close output (TB final, all reports, all re
211
211
  | Source | Error | Recovery |
212
212
  |--------|-------|----------|
213
213
  | Phase 1-7 (standalone) | Quarters not all closed | One or more quarters incomplete. Route back to the missing `quarter-end-close.md`. Run annual extras only once all 4 quarters are locked. |
214
- | Y1 FA recon | NBV doesn't tie | Investigate disposed assets posted without status update. `search_fixed_assets(filter: {status: 'ACTIVE'})` then check each against current physical existence. |
214
+ | Y1 FA recon | NBV doesn't tie | Investigate disposed assets posted without status update. `search_fixed_assets(filter: {status: {eq: 'ACTIVE'}})` then check each against current physical existence. |
215
215
  | Y3 `execute_recipe` for dividend | 422 `dividends_payable_account_missing` | Create `Dividends Payable` account (`Current Liability`) via `create_account` first. |
216
216
  | Y4 ECL | top-up amount surprisingly large | Possibly the existing provision is stale (no monthly mental ECL check ran). Confirm `--existing-provision` matches `TB[Allowance for Doubtful Debts].balance`. If yes, real impairment event occurred — surface to practitioner. |
217
217
  | Y6 reclassification | Existing reclassification entry from prior year still present | Reverse the prior-year reclassification first (it sits in opening balances). The reclassification entry is per-FY; should be reset at the start of each FY. |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 5.55.1
3
+ version: 5.55.3
4
4
  description: >-
5
5
  Use this skill when modeling complex multi-step accounting transactions —
6
6
  anything that spans multiple periods, involves changing amounts, or requires
@@ -12,11 +12,11 @@
12
12
  - **`clio calc accrued-expense --amount <per-period> --periods <n> --start-date <YYYY-MM-DD> --currency <code> --json`** — used in step 1: independently produce the schedule. Returns `{ totalAccrued, schedule[n] }` where each row carries `accrualDate`, `reversalDate`, `accrualJournal`, `reversalJournal`.
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_journals(filter: {tag: <accrual.name>, valueDate: <prior-period>-end})`** — step 1 estimation: pull last period's posted accrual amount when `estimation_method: 'prior_month'`.
16
- - **`search_journals(filter: {tag: <accrual.name>, valueDate: {between: [<-3 months>, <today>]}})`** — step 1 alt: trailing 3-month average when `estimation_method: 'trailing_3m_avg'`.
15
+ - **`search_journals(filter: {tags: {eq: <accrual.name>}, valueDate: <prior-period>-end})`** — step 1 estimation: pull last period's posted accrual amount when `estimation_method: 'prior_month'`.
16
+ - **`search_journals(filter: {tags: {eq: <accrual.name>}, valueDate: {between: [<-3 months>, <today>]}})`** — step 1 alt: trailing 3-month average when `estimation_method: 'trailing_3m_avg'`.
17
17
  - **`search_contacts(filter: {name: {eq: <vendor>}})`** — step 3: resolve the accrual's vendor.
18
18
  - **`search_accounts(filter: {name: {in: ['<expense GL>', '<accrued liability GL>']}})`** — step 3: confirm both sides of the journal exist in CoA.
19
- - **`search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: 'DRAFT'})`** — step 5 monthly: find this period's pre-emitted DRAFT for finalization.
19
+ - ****STOP — not selectable by filter.** Journals carry no capsule or fixed-asset link in either direction (`JournalFilter` declares neither; a journal row has no such field even at `view: 'full'`; `GET /capsules/{id}` returns only a `totalTransactions` count — measured 2026-09-07). A date+status search returns every matching DRAFT in the org, so it must never feed `bulk_update_journals` or `delete_journal`. Surface the capsule and its expected count to the practitioner and let them identify the journals.** — step 5 monthly: find this period's pre-emitted DRAFT for finalization.
20
20
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 5: finalize this period's accrual + reversal pair.
21
21
  - **`generate_trial_balance(period_end: <date>)`** — step 5 verification: confirm Accrued Expenses balance and net P&L impact.
22
22
 
@@ -33,7 +33,7 @@
33
33
 
34
34
  Per the accrual's estimation method:
35
35
 
36
- - **`prior_month`**: pull last period's posted amount via `search_journals(filter: {tag: <accrual.name>, valueDate: <prior-period>-end})`. Use that amount.
36
+ - **`prior_month`**: pull last period's posted amount via `search_journals(filter: {tags: {eq: <accrual.name>}, valueDate: <prior-period>-end})`. Use that amount.
37
37
  - **`trailing_3m_avg`**: pull last 3 months' posted amounts and average.
38
38
  - **`budget`**: use the accrual's budget amount.
39
39
  - **`fixed_amount`**: use the accrual's fixed amount directly.
@@ -92,7 +92,7 @@ Engine output journals:
92
92
  For the current period (Jan 2025), the accrual journal exists in DRAFT in the capsule. Monthly close action:
93
93
 
94
94
  ```
95
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: ['2025-01-01', '2025-01-31']}, status: {eq: 'DRAFT'}})
95
+ **STOP — not selectable by filter.** Journals carry no capsule or fixed-asset link in either direction (`JournalFilter` declares neither; a journal row has no such field even at `view: 'full'`; `GET /capsules/{id}` returns only a `totalTransactions` count — measured 2026-09-07). A date+status search returns every matching DRAFT in the org, so it must never feed `bulk_update_journals` or `delete_journal`. Surface the capsule and its expected count to the practitioner and let them identify the journals.
96
96
  update_journal(resourceId: <accrual journal id>, saveAsDraft: false)
97
97
  ```
98
98
 
@@ -119,7 +119,7 @@ When the actual quarterly bill arrives (typically Mar 31, $9,000 total): post a
119
119
  | `plan_recipe` | 422 `invalid_amount` | Amount is non-positive. Computed amount may have been a credit (e.g. `prior_month` returned a credit balance). Switch `estimation_method` to `fixed_amount` for this row this period, OR investigate the credit. |
120
120
  | `execute_recipe` | 422 `account_not_found` | Step 3 resolution incomplete. `search_accounts`; create via `create_account` if the practitioner confirms classification. |
121
121
  | `bulk_finalize_drafts` | 422 `journal_unbalanced` | Engine-emitted journals are always balanced. If you see this, the source schema changed — escalate (do not retry). |
122
- | Verification | Net P&L impact stuck after reversal posts | Likely the reversal hasn't been finalized yet. `search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: <reversal-date>, status: 'DRAFT'})` — if non-empty, finalize. |
122
+ | Verification | Net P&L impact stuck after reversal posts | Likely the reversal hasn't been finalized yet. **STOP — not selectable by filter.** Journals carry no capsule or fixed-asset link in either direction (`JournalFilter` declares neither; a journal row has no such field even at `view: 'full'`; `GET /capsules/{id}` returns only a `totalTransactions` count — measured 2026-09-07). A date+status search returns every matching DRAFT in the org, so it must never feed `bulk_update_journals` or `delete_journal`. Surface the capsule and its expected count to the practitioner and let them identify the journals. — if non-empty, finalize. |
123
123
  | Verification | Accrued Expenses balance nonzero after the actual bill posts AND all reversals run | Either the bill amount diverged from the accrual estimate (post a true-up journal: Dr/Cr `<expense GL>` for the difference) OR a reversal was missed. Audit via `generate_general_ledger(accountResourceId: 'Accrued Expenses', period_end: <today>)`. |
124
124
  | Actual bill posted against `Accrued Expenses` instead of `<expense GL>` | (process error) | The reversal AND the bill both touch `Accrued Expenses` — net to zero on liability, but expense gets double-recognized. Reverse the bill, re-post against `<expense GL>`. Note the risk in your working notes. |
125
125