jaz-clio 5.55.2 → 5.55.4

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 +7 -6
  9. package/assets/skills/jobs/references/building-blocks.md +31 -3
  10. package/assets/skills/jobs/references/credit-control.md +2 -2
  11. package/assets/skills/jobs/references/fa-review.md +4 -4
  12. package/assets/skills/jobs/references/gst-vat-filing.md +4 -4
  13. package/assets/skills/jobs/references/month-end-close.md +10 -10
  14. package/assets/skills/jobs/references/payment-run.md +8 -6
  15. package/assets/skills/jobs/references/quarter-end-close.md +13 -9
  16. package/assets/skills/jobs/references/supplier-recon.md +21 -8
  17. package/assets/skills/jobs/references/year-end-close.md +8 -8
  18. package/assets/skills/transaction-recipes/SKILL.md +1 -1
  19. package/assets/skills/transaction-recipes/references/accrued-expenses.md +6 -6
  20. package/assets/skills/transaction-recipes/references/asset-disposal.md +5 -5
  21. package/assets/skills/transaction-recipes/references/bad-debt-provision.md +2 -2
  22. package/assets/skills/transaction-recipes/references/bank-loan.md +4 -4
  23. package/assets/skills/transaction-recipes/references/building-blocks.md +3 -3
  24. package/assets/skills/transaction-recipes/references/capital-wip.md +4 -4
  25. package/assets/skills/transaction-recipes/references/declining-balance.md +4 -4
  26. package/assets/skills/transaction-recipes/references/deferred-revenue.md +3 -3
  27. package/assets/skills/transaction-recipes/references/dividend.md +2 -2
  28. package/assets/skills/transaction-recipes/references/employee-accruals.md +7 -7
  29. package/assets/skills/transaction-recipes/references/fixed-deposit.md +5 -5
  30. package/assets/skills/transaction-recipes/references/ifrs16-lease.md +4 -4
  31. package/assets/skills/transaction-recipes/references/intercompany.md +2 -2
  32. package/assets/skills/transaction-recipes/references/prepaid-amortization.md +2 -2
  33. package/assets/skills/transaction-recipes/references/provisions.md +4 -4
  34. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 5.55.2
3
+ version: 5.55.4
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.2
3
+ version: 5.55.4
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.2
3
+ version: 5.55.4
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.2
3
+ version: 5.55.4
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.2
3
+ version: 5.55.4
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.2
3
+ version: 5.55.4
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, sortBy: 'valueDate', sortOrder: '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
- sort: 'valueDate:asc'
72
+ sortBy: 'valueDate', sortOrder: '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
 
@@ -142,7 +143,7 @@ search_cashflow_transactions(
142
143
  totalAmount: { eq: 2500.00 },
143
144
  valueDate: { between: ['2025-01-08', '2025-01-22'] }
144
145
  },
145
- sort: 'valueDate:desc',
146
+ sortBy: 'valueDate', sortOrder: 'DESC',
146
147
  limit: 20
147
148
  )
148
149
  ```
@@ -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.
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### Platform tools
8
8
  - **`generate_aged_ar(period_end: <date>)`** — step 1: AR aging report with bucket breakdown.
9
- - **`search_invoices(filter: {status: {eq: 'UNPAID'}, dueDate: {lt: <date>}, contactResourceId: <customer>}, sort: 'dueDate:asc', limit: 200)`** — step 2: per-customer overdue detail. Paginate.
9
+ - **`search_invoices(filter: {status: {eq: 'UNPAID'}, dueDate: {lt: <date>}, contactResourceId: <customer>}, sortBy: 'dueDate', sortOrder: 'ASC', limit: 200)`** — step 2: per-customer overdue detail. Paginate.
10
10
  - **`get_contact(resourceId: <customer id>)`** — step 2: pull contact info (email, phone, primary contact).
11
11
  - **`get_contact_signals(resourceId: <id>, btType: 'SALE')`** — step 3: pull cadence + outlier signals + outstanding balance for the customer. Mid-7 endpoint.
12
12
  - **`apply_credit_to_invoice(...)`** / **`create_customer_credit_note(...)`** — step 6: write-off path A for stage-3 specific impairment.
@@ -44,7 +44,7 @@ search_invoices(
44
44
  contactResourceId: <customer id>,
45
45
  dueDate: {lt: '2025-01-31'}
46
46
  },
47
- sort: 'dueDate:asc',
47
+ sortBy: 'dueDate', sortOrder: 'ASC',
48
48
  limit: 200
49
49
  )
50
50
  ```
@@ -33,7 +33,7 @@ Walk steps 1-8 below. (Local CLI: `clio jobs fa-review` prints the same phased c
33
33
  ## Step 1 — Enumerate FAs
34
34
 
35
35
  ```
36
- search_fixed_assets(filter: {status: {in: ['ACTIVE', 'DISPOSED', 'WRITTEN_OFF']}}, limit: 200, sort: 'acquisitionDate:asc')
36
+ search_fixed_assets(filter: {status: {in: ['ACTIVE', 'DISPOSED', 'WRITTEN_OFF']}}, limit: 200, sortBy: 'purchaseDate', sortOrder: 'ASC')
37
37
  ```
38
38
 
39
39
  Paginate via offset. For year-end review: include DISPOSED and WRITTEN_OFF (disposed during the year are part of the recon).
@@ -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, sortBy: 'valueDate', sortOrder: '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). |
@@ -5,9 +5,9 @@
5
5
  ## Tools, recipes, calculators this job uses
6
6
 
7
7
  ### Platform tools — pre-close gates
8
- - **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, sort: 'valueDate:asc', limit: 200)`** — step 1: confirm sales invoices entered. Paginate via `offset`.
8
+ - **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, sortBy: 'valueDate', sortOrder: '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
 
@@ -56,7 +56,7 @@ This playbook runs 5 phases for the period: pre-close gates → accruals & adjus
56
56
  ### Step 1 — Verify sales invoices entered
57
57
 
58
58
  ```
59
- search_invoices(filter: {valueDate: {between: ['2025-01-01', '2025-01-31']}}, sort: 'valueDate:asc', limit: 200)
59
+ search_invoices(filter: {valueDate: {between: ['2025-01-01', '2025-01-31']}}, sortBy: 'valueDate', sortOrder: 'ASC', limit: 200)
60
60
  ```
61
61
 
62
62
  Compare count + sum against POS / sales register. Missing invoices = understated revenue. Per `jaz-api/SKILL.md` rule 38, paginate via `offset` if `totalElements > 200`.
@@ -64,7 +64,7 @@ Compare count + sum against POS / sales register. Missing invoices = understated
64
64
  ### Step 2 — Verify bills entered (most common SMB gap)
65
65
 
66
66
  ```
67
- search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-01-31']}}, sort: 'valueDate:asc', limit: 200)
67
+ search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-01-31']}}, sortBy: 'valueDate', sortOrder: 'ASC', limit: 200)
68
68
  ```
69
69
 
70
70
  Cross-reference against email + supplier portals + physical mail. Late bills = missed expenses = overstated profit. For PDFs in hand: invoke `mcp magic create --file <pdf>` (Jaz Magic OCR + autofill) to generate the bill draft.
@@ -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, sortBy: 'valueDate', sortOrder: '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>}}, sortBy: 'dueDate', sortOrder: '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.
@@ -47,7 +49,7 @@ search_bills(
47
49
  balanceAmount: {gt: 0},
48
50
  dueDate: {lte: '2025-02-28'}
49
51
  },
50
- sort: 'dueDate:asc',
52
+ sortBy: 'dueDate', sortOrder: 'ASC',
51
53
  limit: 200
52
54
  )
53
55
  ```
@@ -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:
@@ -149,7 +151,7 @@ Assert: per-account balance reduced by `sum(paymentAmount per accountResourceId)
149
151
 
150
152
  ## Variations
151
153
 
152
- - **Priority-based payment ordering:** `sort: 'dueDate:asc'` covers chronological. For overdue-first, sort by `daysOverdue:desc`. For supplier-strategic, ask the user which suppliers are priority and process those first.
154
+ - **Priority-based payment ordering:** `sortBy: 'dueDate', sortOrder: 'ASC'` covers chronological. For overdue-first there is no sort field — `daysOverdue` is not sortable and the API answers `422 sort.sortBy[0] must be one of [...]`, naming the set (measured 2026-09-07). Sort by `dueDate` ASC, which puts the most overdue first, or compute the age per row after fetching. For supplier-strategic, ask the user which suppliers are priority and process those first.
153
155
  - **Multi-currency runs:** Split the run by currency. SGD bills → SGD bank; USD bills → USD bank or SWIFT-routed. The actual bank disbursement is handled outside Jaz (via the bank's portal); Jaz records the payment after it clears.
154
156
  - **Approval workflow (multi-signatory SMBs):** Build the batch in step 5, get out-of-band approval, then execute step 6 only after sign-off. Do NOT post payments before the actual bank transfer is initiated — Jaz payments are not "payment instructions", they record completed payments.
155
157
  - **Early-payment discounts:** If supplier offers `2% 10 Net 30`, computing the equivalent annualized return is `(2% / 98%) × (365 / 20) ≈ 37.2%`. Take it when cash allows. Apply the discount as: pay `transactionAmount = (derived outstanding) × 0.98`, then post a separate journal Dr Bank Charges/Discount Income for the 2% saved (cleaner than partial payment of the original bill).
@@ -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,8 +54,8 @@ 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']}},
45
- sort: 'valueDate:asc',
57
+ filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}},
58
+ sortBy: 'valueDate', sortOrder: 'ASC',
46
59
  limit: 200
47
60
  )
48
61
  ```
@@ -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.2
3
+ version: 5.55.4
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
 
@@ -14,7 +14,7 @@
14
14
  ### Tools (jaz-api / direct)
15
15
  - **`get_fixed_asset(resourceId: <id>)`** — step 1: pull the asset's actual `cost`, `acquisitionDate`, `usefulLifeMonths`, `depreciationMethod`, `salvageValue` to feed the calculator (use the live FA-register values — auditor wants those, not a cached estimate).
16
16
  - **`generate_fa_summary(period_end: <disposalDate>)`** — step 1 alt: pull NBV directly from Jaz's running FA register. If this matches your independent calc, use it as the authoritative NBV. If they diverge: investigate (likely a missing depreciation journal).
17
- - **`search_capsules(filter: {capsuleType: {eq: 'Asset Disposal'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check. Each disposal is unique; duplicate disposal journals would corrupt the FA register reconciliation.
17
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check. Each disposal is unique; duplicate disposal journals would corrupt the FA register reconciliation.
18
18
  - **`search_accounts(filter: {name: {in: ['Vehicles', 'Accumulated Depreciation — Vehicles', 'Gain on Disposal', 'Loss on Disposal']}})`** — step 3.
19
19
  - **`update_fixed_asset(resourceId: <id>, status: 'DISPOSED' | 'WRITTEN_OFF')`** OR **`POST /api/v1/mark-as-sold/fixed-assets`** OR **`POST /api/v1/discard-fixed-assets/{id}`** — step 5 manual FA-register update (the engine-skipped note step).
20
20
  - **`generate_trial_balance(period_end: <disposalDate>)`** — step 6: verify cost + accumulated depreciation cleared; gain/loss in P&L.
@@ -31,7 +31,7 @@
31
31
  ### Step 0 — Idempotency check
32
32
 
33
33
  ```
34
- search_capsules(filter: {capsuleType: {eq: 'Asset Disposal'}, name: {eq: 'Disposal — Delivery Vehicle (Truck-001) — 2026-03-15'}})
34
+ search_capsules(filter: {title: {eq: 'Disposal — Delivery Vehicle (Truck-001) — 2026-03-15'}})
35
35
  ```
36
36
 
37
37
  If a result returns: halt. Disposal capsules are unique per asset+date — duplicates would double-book the disposal.
@@ -54,7 +54,7 @@ Cross-check with Jaz FA register:
54
54
  ```
55
55
  generate_fa_summary(period_end: '2026-03-15', fixedAssetResourceId: <FA UUID>)
56
56
  ```
57
- Should report `accumulatedDepreciation: 28500, netBookValue: 21500` matching the independent calc within 1 cent. Variance investigation: missing monthly depreciation journals (search via `search_journals(filter: {capsuleResourceId: {eq: <dep capsule>}, status: 'DRAFT'})`); finalize them BEFORE disposal recipe.
57
+ Should report `accumulatedDepreciation: 28500, netBookValue: 21500` matching the independent calc within 1 cent. Variance investigation: missing monthly depreciation journals (search via **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.); finalize them BEFORE disposal recipe.
58
58
 
59
59
  ### Step 2 — Plan the recipe
60
60
 
@@ -174,7 +174,7 @@ Should reflect the disposal in the year's movement: `openingNbv − depreciation
174
174
  | `plan_recipe` | 422 `acquisition_after_disposal` | Inputs swapped. Verify and re-run. |
175
175
  | `execute_recipe` | 422 `account_not_found` for `Gain on Disposal` / `Loss on Disposal` | Step 3 incomplete. Create via `create_account(accountType: 'Other Revenue' / 'Other Expense', ...)`. |
176
176
  | Step 5 manual update missed | (process error — Jaz FA continues auto-depreciating) | Surface to practitioner: "Asset `<name>` (resourceId `<id>`) is still ACTIVE in FA register but disposal journal posted. Auto-depreciation will continue. Run `update_fixed_asset(status: 'DISPOSED')` immediately." |
177
- | `update_fixed_asset` to DISPOSED | 422 `pending_depreciation_journals` | DRAFT depreciation journals exist for periods after disposal date. Delete them: `search_journals(filter: {fixedAssetResourceId: <id>, valueDate: {gt: '<disposal>'}, status: 'DRAFT'})` then `delete_journal` per result. |
177
+ | `update_fixed_asset` to DISPOSED | 422 `pending_depreciation_journals` | DRAFT depreciation journals exist for periods after disposal date. Delete them: **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. then `delete_journal` per result. |
178
178
  | Cross-check | Calculator NBV ≠ FA register NBV | Investigate missing depreciation journals (recipe pre-emitted DRAFTs that weren't finalized monthly). Finalize all up to disposal date BEFORE running this recipe. |
179
179
  | Recipe NBV ≠ TB Vehicles − TB Accum Dep | (audit failure) | Likely a manual journal touched Vehicles or Accum Dep without going through the recipe. Audit `generate_general_ledger(accountResourceId: <Vehicles>, period_end: <today>)`. |
180
180
 
@@ -196,6 +196,6 @@ Should reflect the disposal in the year's movement: `openingNbv − depreciation
196
196
 
197
197
  - Year-end close — FA disposals discovered during the year-end review trigger this recipe per asset.
198
198
  - Month-end close — ad-hoc invocation when a disposal happens mid-period.
199
- - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {capsuleType: {eq: 'Asset Disposal'}, valueDate: {between: [<FY-start>, <FY-end>]}})` plus per-capsule recompute via `clio calc asset-disposal`. Auditor tests proceeds against bank statements, NBV against FA register.
199
+ - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {status: {eq: 'ACTIVE'}})` then narrow by date on the rows — **do not filter capsules by date**: `startDate`/`endDate` are declared on `CapsuleFilter` and pass validation, but every form of them answers `500 Internal Server Error` (measured 2026-09-07: `{gte}`, `{between}`, and `{gte}`+`{lte}` all 500) plus per-capsule recompute via `clio calc asset-disposal`. Auditor tests proceeds against bank statements, NBV against FA register.
200
200
  - `fa-review.md` job — annual FA register review identifies candidates for disposal (assets fully depreciated, assets no longer in use, assets damaged) → invoke this recipe per identified disposal.
201
201
  - Sibling recipe `declining-balance.md` — depreciation up to the disposal date; complete all DRAFT depreciation finalizations BEFORE running this recipe to ensure NBV is correct.
@@ -15,7 +15,7 @@
15
15
  - **`generate_aged_ar(period_end: <date>)`** — step 1 input: pull AR aged into the same 5 buckets the calculator expects (current, 30d, 60d, 90d, 120d+).
16
16
  - **`search_accounts(filter: {name: {in: ['Allowance for Doubtful Debts', 'Bad Debt Expense']}})`** — step 3.
17
17
  - **`generate_trial_balance(period_end: <date>)`** — step 1 input: pull `existingProvision` from current `Allowance for Doubtful Debts` balance; step 5 verify post-journal balance matches calculated ECL.
18
- - **`search_capsules(filter: {capsuleType: {eq: 'ECL Provision'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check (one ECL capsule per period; quarterly = 4 per FY).
18
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check (one ECL capsule per period; quarterly = 4 per FY).
19
19
  - **`apply_credit_to_invoice(...)` / `create_customer_credit_note(...)`** — step 6 specific write-off pattern: when individual invoices are deemed unrecoverable, write them off via credit note OR direct payment with `paymentMethod: 'DEBT_WRITE_OFF'` (per memory rule).
20
20
 
21
21
  ### Cross-references
@@ -30,7 +30,7 @@
30
30
  ### Step 0 — Idempotency check
31
31
 
32
32
  ```
33
- search_capsules(filter: {capsuleType: {eq: 'ECL Provision'}, name: {eq: 'FY2025 Year-End ECL True-Up'}})
33
+ search_capsules(filter: {title: {eq: 'FY2025 Year-End ECL True-Up'}})
34
34
  ```
35
35
 
36
36
  If a result returns: halt. ECL is one-shot per period; duplicate would double-recognize.
@@ -14,7 +14,7 @@
14
14
  ### Tools (jaz-api / direct)
15
15
  - **`list_bank_accounts()`** — used in step 3: resolve the disbursement target bank account by `name + currency` if the bank account resourceId isn't already known.
16
16
  - **`search_accounts(filter: {name: {in: ['Loan Payable', 'Interest Expense']}})`** — used in step 3: confirm liability + expense GL accounts exist.
17
- - **`search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}, name: {eq: <capsuleName>}})`** — used in step 0: detect duplicate setup before re-running. Loan capsules are unique per facility — duplicate creation is almost always an agent error.
17
+ - **`search_capsules(filter: {title: {eq: <capsuleName>}})`** — used in step 0: detect duplicate setup before re-running. Loan capsules are unique per facility — duplicate creation is almost always an agent error.
18
18
  - **`generate_trial_balance(period_end: <date>)`** — used in step 5: verify the loan liability balance matches the schedule's `closingBalance` column.
19
19
  - **`update_journal(resourceId: <id>, saveAsDraft: false)`** — used in step 4 verification: lift draft journals to ACTIVE once practitioner confirms.
20
20
 
@@ -30,7 +30,7 @@
30
30
  ### Step 0 — Idempotency check
31
31
 
32
32
  ```
33
- search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}, name: {eq: 'Bank Loan — ABC Bank — 2025'}})
33
+ search_capsules(filter: {title: {eq: 'Bank Loan — ABC Bank — 2025'}})
34
34
  ```
35
35
 
36
36
  If a result returns: halt and surface "Loan capsule `<name>` already exists (resourceId `<id>`). Re-running the recipe would create a duplicate disbursement. Confirm the practitioner intent — if extending an existing loan, use `update_capsule` not `execute_recipe`."
@@ -95,7 +95,7 @@ Note: This is NOT the Jaz scheduler primitive. The recipe pre-emits all 60 journ
95
95
  After the actual bank payment posts each month, the corresponding repayment journal already exists in the capsule as DRAFT. Monthly close action:
96
96
 
97
97
  ```
98
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
98
+ **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.
99
99
  ```
100
100
 
101
101
  Returns the one DRAFT for that period (the engine pre-emitted it). Finalize:
@@ -131,7 +131,7 @@ After the FINAL period (60th repayment) is finalized:
131
131
  | `execute_recipe` | 422 `currency_mismatch_bank_account` | Loan currency ≠ bank account currency. Either pass a `currencyAccount` for FX-on-disbursement, or pick a bank account in the loan's source currency (per `jaz-api/SKILL.md` rule 24). |
132
132
  | `execute_recipe` | 409 `capsule_already_exists` | Duplicate setup. Step 0 idempotency check should have caught this — go back to step 0. |
133
133
  | Scheduler | Repayment journal posts but interest amount is off by cents | Engine uses effective interest method per period; if the entity's materiality threshold is below 1 cent, narrow the assertion. Otherwise expected behavior. |
134
- | Scheduler | Repayment journal does NOT post on expected date | `update_scheduler` may have paused it. `search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {eq: <expected>}})` — if empty, check scheduler status. Resume or document the pause in your working notes. |
134
+ | Scheduler | Repayment journal does NOT post on expected date | `update_scheduler` may have paused it. **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 empty, check scheduler status. Resume or document the pause in your working notes. |
135
135
  | `update_capsule` | 422 `capsule_locked` | The capsule is in a closed period (lock date passed). Lift the lock first via `update_account` lock_date OR add the new entry in the next open period. |
136
136
 
137
137
  ---
@@ -61,7 +61,7 @@ The recipe engine uses capsules automatically. But capsules also enable advanced
61
61
 
62
62
  1. **One capsule per LIFECYCLE, not per period.** A 5-year loan = ONE capsule (not 12 per year). A construction project = ONE capsule (not one per contractor bill). The capsule's job is to span the full lifecycle.
63
63
 
64
- 2. **Use Capsule Types as the search axis, not Capsule Name.** Capsule names are unique per instance ("FY2025 Office Insurance"); types are reusable ("Prepaid Expenses"). `search_capsules(filter: {capsuleType: {eq: 'Prepaid Expenses'}})` returns ALL prepaid capsules across history.
64
+ 2. **Use Capsule Types as the search axis, not Capsule Name.** Capsule names are unique per instance ("FY2025 Office Insurance"); types are reusable ("Prepaid Expenses"). `search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)` returns ALL prepaid capsules across history.
65
65
 
66
66
  3. **Tie capsule entries back for the auditor.** `generate_general_ledger` does NOT group by capsule -- `groupBy` is ACCOUNT, CONTACT, TRANSACTION or RELATIONSHIP, and `CAPSULE` returns 422 (verified live 2026-09-01). Auditor sample-test: pick 3 capsules per type, read each with `get_capsule` to get its transaction resource ids, then pull those documents (bills, invoices, journals) directly. Same evidence, one more hop.
67
67
 
@@ -87,9 +87,9 @@ create_cash_out_entry(..., capsuleResourceId: <capsule id>)
87
87
  **Search and audit patterns:**
88
88
 
89
89
  ```
90
- search_capsules(filter: {capsuleType: {eq: 'Loan Repayment'}}, status: {eq: 'ACTIVE'}})
90
+ search_capsules(filter: {status: {eq: 'ACTIVE'}}) # capsule type is not filterable — narrow on the row's `type` / `capsuleType.name`
91
91
  # All open loan capsules — feed into year-end-close.md Y6 reclassification
92
- search_journals(filter: {capsuleResourceId: {eq: <id>}}, sort: 'valueDate:asc')
92
+ **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.
93
93
  # Full GL for one capsule — the auditor's view
94
94
  get_capsule(resourceId) # returns the capsule's transactions; GL cannot group by capsule
95
95
  # Period activity grouped by capsule — the practitioner's view
@@ -15,10 +15,10 @@ CWIP costs accumulate as construction progresses — multiple bills from contrac
15
15
  - **`create_fixed_asset(...)`** — step 4: register the completed asset in Jaz native FA register; from this point forward, Jaz auto-posts SL depreciation.
16
16
 
17
17
  ### Tools (jaz-api / direct)
18
- - **`search_capsules(filter: {capsuleType: {eq: 'Capital Projects'}, name: {eq: <project>}})`** — step 1 idempotency check.
18
+ - **`search_capsules(filter: {title: {eq: <project>}})`** — step 1 idempotency check.
19
19
  - **`search_accounts(filter: {name: {in: ['Capital Work-in-Progress', '<target FA category>', '<target Accumulated Depreciation>']}})`** — step 0 + step 4.
20
20
  - **`generate_general_ledger(accountResourceId: <CWIP id>, period_start: <project start>, period_end: <today>)`** — step 3: pull all CWIP entries to confirm the accumulated cost.
21
- - **`search_bills(filter: {capsuleResourceId: {eq: <CWIP capsule id>}})`** — step 3 alt: pull all bills attached to the project capsule.
21
+ - ****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 3 alt: pull all bills attached to the project capsule.
22
22
  - **`generate_trial_balance(period_end: <date>)`** — step 5 verify CWIP balance is zero post-transfer; FA balance reflects new asset.
23
23
 
24
24
  ### Cross-references
@@ -50,7 +50,7 @@ create_capsule(
50
50
  )
51
51
  ```
52
52
 
53
- Each construction project gets its own capsule. The capsule is the audit trail — every bill paid for this project, plus the eventual transfer journal, attaches to it. Auditor can pull `search_bills(filter: {capsuleResourceId: {eq: <id>}})` and see the full cost build.
53
+ Each construction project gets its own capsule. The capsule is the audit trail — every bill paid for this project, plus the eventual transfer journal, attaches to it. Auditor can pull **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. and see the full cost build.
54
54
 
55
55
  ### Step 2 — Accumulate construction costs (multiple bills over months)
56
56
 
@@ -98,7 +98,7 @@ generate_general_ledger(accountResourceId: <CWIP GL>, period_start: <project sta
98
98
  Confirm the accumulated CWIP balance matches expectations vs the project's estimated cost. Variance > 10% → flag for budget review.
99
99
 
100
100
  ```
101
- search_bills(filter: {capsuleResourceId: {eq: <project capsule id>}, status: {ne: 'PAID'}})
101
+ **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.
102
102
  ```
103
103
 
104
104
  Identify unpaid bills attached to the project — payment timing matters for cash-flow planning.
@@ -12,7 +12,7 @@
12
12
  - **`clio calc depreciation --cost <c> --salvage <s> --life <years> --method <ddb|150db|sl> --frequency <annual|monthly> --json`** — used in step 1: full depreciation schedule. Returns `{ totalDepreciation, schedule[n] }` where each row carries `period`, `openingBookValue`, `depreciationAmount`, `accumulatedDepreciation`, `closingBookValue`. Final period absorbs rounding to land at salvage value exactly.
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_capsules(filter: {capsuleType: {eq: 'Depreciation'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check. One depreciation capsule per asset; duplicate setup is almost always an error.
15
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check. One depreciation capsule per asset; duplicate setup is almost always an error.
16
16
  - **`search_accounts(filter: {name: {in: ['Vehicles', 'Accumulated Depreciation — Vehicles', 'Depreciation Expense']}})`** — step 3: confirm the asset, contra-asset, and expense GL accounts exist.
17
17
  - **`generate_trial_balance(period_end: <date>)`** — step 5: verify NBV matches schedule.
18
18
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 5 monthly: finalize this period's pre-emitted DRAFT depreciation journal.
@@ -29,7 +29,7 @@
29
29
  ### Step 0 — Idempotency check
30
30
 
31
31
  ```
32
- search_capsules(filter: {capsuleType: {eq: 'Depreciation'}, name: {eq: 'DDB Depreciation — 5 years (Delivery Vehicle FY2025)'}})
32
+ search_capsules(filter: {title: {eq: 'DDB Depreciation — 5 years (Delivery Vehicle FY2025)'}})
33
33
  ```
34
34
 
35
35
  If a result returns: halt and surface "Depreciation capsule for asset `<name>` already exists. Re-running would create duplicate depreciation journals. Confirm — if revising the depreciation schedule (changed useful life or salvage), close the existing capsule, reverse remaining DRAFT journals via `delete_journal`, then re-execute."
@@ -93,7 +93,7 @@ If the asset MUST be in the FA register for reporting reasons (e.g. fixed-assets
93
93
  For each month after recipe execution, this period's DRAFT depreciation journal already exists. Monthly close action:
94
94
 
95
95
  ```
96
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
96
+ **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.
97
97
  update_journal(resourceId: <journal id>, saveAsDraft: false)
98
98
  ```
99
99
 
@@ -140,4 +140,4 @@ After the FINAL period (month 60):
140
140
  - Year-end close — full FY-end depreciation reconciliation: sum 12 monthly journals against `clio calc depreciation --frequency annual` cross-check; auditor will sample-test.
141
141
  - Data migration — opening accumulated depreciation loaded via conversion (Conversion Clearing > Accumulated Depreciation account); recipe runs forward from the migration date with `cost: <NBV at migration>` instead of original cost. Useful-life-years should be `remaining life`, not original.
142
142
  - Sibling recipe `asset-disposal.md` — end-of-life de-recognition.
143
- - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {capsuleType: {eq: 'Depreciation'}})` + per-capsule `clio calc depreciation` recompute.
143
+ - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)` + per-capsule `clio calc depreciation` recompute.
@@ -16,7 +16,7 @@
16
16
  - **`create_contact(...)` with `customer: true`** — step 3 fallback: create the customer if `search_contacts` returns empty.
17
17
  - **`search_accounts(filter: {name: {in: ['<deferred liability GL>', '<revenue GL>']}})`** — step 3: confirm both GL accounts exist.
18
18
  - **`generate_trial_balance(period_end: <date>)`** — step 5: verify Deferred Revenue balance unwinds correctly.
19
- - **`search_capsules(filter: {capsuleType: {eq: 'Deferred Revenue'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check.
19
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check.
20
20
  - **`finalize_invoice(resourceId: <id>)`** — step 4 fallback: lift the upfront invoice from DRAFT to ACTIVE once practitioner confirms the engagement is genuinely starting.
21
21
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 5 monthly: finalize this period's pre-emitted DRAFT recognition journal.
22
22
 
@@ -32,7 +32,7 @@
32
32
  ### Step 0 — Idempotency check
33
33
 
34
34
  ```
35
- search_capsules(filter: {capsuleType: {eq: 'Deferred Revenue'}, name: {eq: 'FY2025 Acme Annual License'}})
35
+ search_capsules(filter: {title: {eq: 'FY2025 Acme Annual License'}})
36
36
  ```
37
37
 
38
38
  If a result returns: halt and surface "Deferred revenue capsule `<name>` already exists. Re-running would create a duplicate upfront invoice. Confirm intent — if extending an existing arrangement, use `update_capsule` not `execute_recipe`."
@@ -94,7 +94,7 @@ All N journals attach to the same capsule. Customer payment: handled separately
94
94
  For each month after recipe execution, the corresponding DRAFT recognition journal already exists in the capsule. Monthly close action:
95
95
 
96
96
  ```
97
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
97
+ **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.
98
98
  update_journal(resourceId: <journal id>, saveAsDraft: false)
99
99
  ```
100
100
 
@@ -12,7 +12,7 @@
12
12
  - **`clio calc dividend --amount <gross> --withholding-rate <%> --currency <code> --json`** — used in step 1: computes net dividend payable to shareholder + withholding tax to remit. Returns `{ grossAmount, withholdingTax, netToShareholder }`.
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_capsules(filter: {capsuleType: {eq: 'Dividends'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check. Each declared dividend gets its own capsule; duplicate setup means double-declaration.
15
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check. Each declared dividend gets its own capsule; duplicate setup means double-declaration.
16
16
  - **`search_accounts(filter: {name: {in: ['Retained Earnings', 'Dividends Payable', 'Withholding Tax Payable']}})`** — step 3.
17
17
  - **`search_contacts(filter: {name: {eq: <shareholder>}})`** — step 3 (the payee — typically a shareholder or a holding entity).
18
18
  - **`generate_balance_sheet(period_end: <date>)`** — step 5 verification: Retained Earnings reduced; Dividends Payable nil after payment.
@@ -30,7 +30,7 @@
30
30
  ### Step 0 — Idempotency check
31
31
 
32
32
  ```
33
- search_capsules(filter: {capsuleType: {eq: 'Dividends'}, name: {eq: 'FY2025 Final Dividend'}})
33
+ search_capsules(filter: {title: {eq: 'FY2025 Final Dividend'}})
34
34
  ```
35
35
 
36
36
  If a result returns: halt and surface "Dividend capsule `<name>` already exists. Re-running would create a duplicate declaration. Confirm — if posting an interim dividend, use a different capsule name (e.g., `Q3 2025 Interim Dividend`)."
@@ -25,9 +25,9 @@ The two patterns share the same `Employee Benefits` capsule type but use differe
25
25
  - **`clio calc accrued-expense --amount <quarterly bonus> --periods 1 --json`** — bonus cross-check.
26
26
 
27
27
  ### Tools (jaz-api / direct)
28
- - **`search_capsules(filter: {capsuleType: {eq: 'Employee Benefits'}})`** — step 0: discover existing leave + bonus capsules.
28
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)`** — step 0: discover existing leave + bonus capsules.
29
29
  - **`search_accounts(filter: {name: {in: ['Leave Expense', 'Leave Liability', 'Bonus Expense', 'Bonus Payable']}})`** — step 3.
30
- - **`search_journals(filter: {tag: 'leave-accrual', valueDate: {between: [<period-start>, <period-end>]}, status: 'DRAFT'})`** — step 5 monthly: pull this period's pre-emitted leave DRAFT.
30
+ - **`search_journals(filter: {tags: {eq: 'leave-accrual'}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})`** — step 5 monthly: pull this period's pre-emitted leave DRAFT.
31
31
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — monthly finalize.
32
32
  - **`generate_trial_balance(period_end: <date>)`** — verification.
33
33
  - For year-end true-up: see `year-end-close.md` Y2 — manual journal pattern with HR-supplied actuals.
@@ -44,7 +44,7 @@ The two patterns share the same `Employee Benefits` capsule type but use differe
44
44
  ### Step 0A — Idempotency check
45
45
 
46
46
  ```
47
- search_capsules(filter: {capsuleType: {eq: 'Employee Benefits'}, name: {eq: 'Annual Leave Accrual — FY2025'}})
47
+ search_capsules(filter: {title: {eq: 'Annual Leave Accrual — FY2025'}})
48
48
  ```
49
49
 
50
50
  If returns: halt. One leave capsule per FY.
@@ -82,7 +82,7 @@ Engine emits **12 future-dated DRAFT journals** (one per month, fixed $7,000 eac
82
82
  ### Step 5A — Monthly action
83
83
 
84
84
  ```
85
- search_journals(filter: {capsuleResourceId: {eq: <leave capsule id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
85
+ **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.
86
86
  update_journal(resourceId: <journal id>, saveAsDraft: false)
87
87
  ```
88
88
 
@@ -99,7 +99,7 @@ Year-end true-up: see `year-end-close.md` Y2a. Compare actual unused-leave-balan
99
99
  ### Step 0B — Idempotency check
100
100
 
101
101
  ```
102
- search_capsules(filter: {capsuleType: {eq: 'Employee Benefits'}, name: {startsWith: 'Bonus Accrual — Q'}})
102
+ search_capsules(filter: {title: {startWith: 'Bonus Accrual — Q'}})
103
103
  ```
104
104
 
105
105
  If a current-quarter result returns: halt. One bonus capsule per quarter.
@@ -108,7 +108,7 @@ If a current-quarter result returns: halt. One bonus capsule per quarter.
108
108
 
109
109
  Estimate quarterly bonus per the entity's bonus policy estimation method:
110
110
  - `revenue_pct` (e.g., 5% of quarterly revenue): pull `generate_profit_and_loss(period_start: <quarter-start>, period_end: <quarter-end>)`, multiply Operating Revenue by the percentage.
111
- - `prior_quarter`: pull last quarter's posted bonus journal via `search_journals(filter: {tag: 'bonus-accrual', valueDate: <prior-quarter>-end})`.
111
+ - `prior_quarter`: pull last quarter's posted bonus journal via `search_journals(filter: {tags: {eq: 'bonus-accrual'}, valueDate: <prior-quarter>-end})`.
112
112
  - `fixed_amount`: use the bonus policy's fixed amount per quarter.
113
113
 
114
114
  ```
@@ -157,7 +157,7 @@ Per quarter-end-close (`quarter-end-close.md`):
157
157
  | `plan_recipe` (bonus) | 422 `unsupported_recipe` | Use `accrued-expense` for bonus — leave is `leave-accrual`. |
158
158
  | `execute_recipe` | 422 `account_not_found` | Step 3 incomplete. Common gap: `Bonus Payable` (most CoAs lack); create via `create_account(accountType: 'Current Liability')`. |
159
159
  | Verification | Leave Liability balance > expected | Practitioner posted manual leave-utilization journals against the wrong account, OR the original recipe estimate was high. Year-end Y2a true-up will catch this. |
160
- | Verification | Bonus accrual nonzero after quarterly reversal posts | Reversal didn't finalize. `search_journals(filter: {capsuleResourceId: {eq: <bonus capsule>}, valueDate: <reversal date>, status: 'DRAFT'})` then `bulk_finalize_drafts`. |
160
+ | Verification | Bonus accrual nonzero after quarterly reversal posts | Reversal didn't finalize. **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. then `bulk_finalize_drafts`. |
161
161
  | 13th-month bonus (PH-specific) | (process — separate from Q4 bonus) | Use `accrued-expense` recipe with `amount: <annual base / 12>`, `periods: 12`, accruing throughout FY. Settle in December via Dr Bonus Payable / Cr Cash. |
162
162
 
163
163
  ---
@@ -12,7 +12,7 @@
12
12
  - **`clio calc fixed-deposit --principal <p> --rate <annual %> --term <months> --start-date <YYYY-MM-DD> --currency <code> [--compound monthly|annually] --json`** — used in step 1: compute monthly accrual amounts. Default simple interest; `--compound` for compound interest. Returns `{ totalInterest, schedule[n] }` where each row carries `period`, `accrualDate`, `accrualAmount`, `accruedToDate`, `journal`.
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_capsules(filter: {capsuleType: {eq: 'Fixed Deposit'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check.
15
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check.
16
16
  - **`search_accounts(filter: {name: {in: ['Fixed Deposit Receivable', 'Accrued Interest Receivable', 'Interest Income']}})`** — step 3.
17
17
  - **`search_contacts(filter: {supplier: true, name: {eq: <bank>}})`** — step 3 optional: bank contact for narrative.
18
18
  - **`generate_trial_balance(period_end: <date>)`** — step 5 verify accrued interest unwinds; FD principal stays at carrying amount until maturity.
@@ -30,7 +30,7 @@
30
30
  ### Step 0 — Idempotency check
31
31
 
32
32
  ```
33
- search_capsules(filter: {capsuleType: {eq: 'Fixed Deposit'}, name: {eq: 'DBS FD — SGD 100,000 — 12 months — 3.5% (FY2025)'}})
33
+ search_capsules(filter: {title: {eq: 'DBS FD — SGD 100,000 — 12 months — 3.5% (FY2025)'}})
34
34
  ```
35
35
 
36
36
  If a result returns: halt. Each FD placement is unique; duplicate setup means double-counted financial asset.
@@ -90,7 +90,7 @@ Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, r
90
90
  For each month after recipe execution, this period's DRAFT accrual journal already exists. Monthly close action:
91
91
 
92
92
  ```
93
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
93
+ **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.
94
94
  update_journal(resourceId: <journal id>, saveAsDraft: false)
95
95
  ```
96
96
 
@@ -102,7 +102,7 @@ Verify after finalize:
102
102
 
103
103
  At maturity (month 12), finalize the maturity cash-in:
104
104
  ```
105
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {eq: <maturityDate>}, status: {eq: 'DRAFT'}})
105
+ **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.
106
106
  update_cash_in(resourceId: <cash-in id>, saveAsDraft: false)
107
107
  ```
108
108
 
@@ -145,5 +145,5 @@ If the bank auto-rolls the FD at maturity: do NOT close the capsule. Instead, po
145
145
 
146
146
  - Month-end close — invoked monthly to finalize this period's pre-emitted accrual DRAFT for each existing FD capsule. New FD placements during the period: invoke recipe; this period's accrual auto-included in the bulk_finalize queue.
147
147
  - Year-end close — final FY accrual cross-check + classification (current vs non-current depending on remaining term at FY-end).
148
- - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {capsuleType: {eq: 'Fixed Deposit'}})` + per-capsule recompute via `clio calc fixed-deposit`. Auditor reconciles to bank confirmation letters.
148
+ - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)` + per-capsule recompute via `clio calc fixed-deposit`. Auditor reconciles to bank confirmation letters.
149
149
  - `bank-loan.md` — mirror pattern (money out instead of in, expense vs income).
@@ -12,7 +12,7 @@
12
12
  - **`clio calc lease --payment <monthly> --term <months> --rate <annual %> --start-date <YYYY-MM-DD> --currency <code> --json`** — used in step 1: independently produce `{ presentValue, totalInterest, schedule[n] }` (monthly payment splits into interest + principal portions, principal reducing the liability).
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_capsules(filter: {capsuleType: {eq: 'Lease'}, name: {eq: <capsuleName>}})`** — step 0 idempotency check.
15
+ - **`search_capsules(filter: {title: {eq: <capsuleName>}})`** — step 0 idempotency check.
16
16
  - **`search_accounts(filter: {name: {in: ['Right-of-Use Asset', 'Lease Liability', 'Interest Expense — Leases']}})`** — step 3.
17
17
  - **`search_contacts(filter: {supplier: true, name: {eq: <lessor>}})`** — step 3 (lease counterparty).
18
18
  - **`create_fixed_asset(...)`** — step 4 manual: register the ROU asset in Jaz native FA. `cost` = PV from calculator, `usefulLifeMonths` = lease term, `depreciationMethod` = 'sl' (straight-line). Jaz auto-posts monthly depreciation thereafter.
@@ -32,7 +32,7 @@
32
32
  ### Step 0 — Idempotency check
33
33
 
34
34
  ```
35
- search_capsules(filter: {capsuleType: {eq: 'Lease'}, name: {eq: 'Office Lease — Marina One — 36 months'}})
35
+ search_capsules(filter: {title: {eq: 'Office Lease — Marina One — 36 months'}})
36
36
  ```
37
37
 
38
38
  If a result returns: halt and surface "Lease capsule `<name>` already exists. Re-running would create a duplicate ROU + Lease Liability. Confirm intent — if modifying lease terms (rent revision, term extension), use the IFRS 16 lease re-measurement pattern (manual journal); do NOT re-execute the recipe."
@@ -116,7 +116,7 @@ For each month after recipe execution:
116
116
  **5a — Finalize this period's unwinding journal (3-line, lease payment):**
117
117
 
118
118
  ```
119
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
119
+ **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.
120
120
  update_journal(resourceId: <journal id>, saveAsDraft: false)
121
121
  ```
122
122
 
@@ -173,5 +173,5 @@ After the FINAL period (month 36):
173
173
  - Month-end close — invoked monthly to finalize this period's pre-emitted unwinding DRAFT (5a) + verify Jaz auto-posted ROU depreciation (5b).
174
174
  - `jobs/references/year-end-close.md` Y6 — current/non-current reclassification (manual annual journal) + auditor sample-test of the lease schedule via `clio calc lease`.
175
175
  - Data migration — opening lease balances loaded via conversion (`jaz-conversion/SKILL.md § Option 2` with the Conversion Clearing > Lease account); recipe runs forward only from migration date.
176
- - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {capsuleType: {eq: 'Lease'}})` + per-capsule `clio calc lease` recompute. Auditor reconciles to TB Lease Liability + ROU Asset NBV.
176
+ - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)` + per-capsule `clio calc lease` recompute. Auditor reconciles to TB Lease Liability + ROU Asset NBV.
177
177
  - Sibling recipe `hire-purchase.md` — same engine, different useful-life parameter.
@@ -16,8 +16,8 @@ Intercompany requires posting MIRRORED entries in TWO different Jaz orgs (Entity
16
16
  - **`apply_credit_to_invoice(...)` / `apply_credit_to_bill(...)`** — netting if both entities owe each other (one entity's invoice clears against the other's bill via credit note).
17
17
 
18
18
  ### Search tools for reconciliation
19
- - **`search_invoices(filter: {capsuleResourceId: {eq: <Entity A IC capsule>}})`** — pull all Entity A intercompany invoices.
20
- - **`search_bills(filter: {capsuleResourceId: {eq: <Entity B IC capsule>}})`** — pull all Entity B intercompany bills.
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.** — pull all Entity A intercompany invoices.
20
+ - ****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.** — pull all Entity B intercompany bills.
21
21
  - **`generate_general_ledger(accountResourceId: <Intercompany Receivable>, period_end: <date>)` / same for Intercompany Payable** — eliminate at consolidation.
22
22
 
23
23
  ### Multi-org targeting (CRITICAL)
@@ -16,7 +16,7 @@
16
16
  - **`create_contact(...)`** — used in step 3 fallback: create the supplier if `search_contacts` returns empty.
17
17
  - **`search_accounts(filter: {name: {in: ['<asset GL>', '<expense GL>']}})`** — used in step 3: confirm the prepaid asset and expense GL accounts exist; if missing, surface to practitioner before retry.
18
18
  - **`generate_trial_balance(period_end: <date>)`** — used in step 5: verify the recognition has unwound the prepaid balance correctly.
19
- - **`search_capsules(filter: {capsuleType: {eq: 'Prepaid Expenses'}, name: {eq: <capsule.name>}})`** — used to detect duplicate setup in re-runs.
19
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — used to detect duplicate setup in re-runs.
20
20
 
21
21
  ### Cross-references
22
22
  - Operational context: invoked during month-end close (initial setup of new prepaids; ongoing recognition runs from the scheduler created here).
@@ -86,7 +86,7 @@ Note: This is NOT the Jaz scheduler primitive (`create_scheduled_journal`). The
86
86
  For each month after recipe execution, the corresponding DRAFT journal already exists in the capsule. Monthly close action:
87
87
 
88
88
  ```
89
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
89
+ **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.
90
90
  ```
91
91
 
92
92
  Returns the one DRAFT for that period. Finalize:
@@ -12,7 +12,7 @@
12
12
  - **`clio calc provision --amount <undiscounted total> --rate <annual %> --term <months> --start-date <YYYY-MM-DD> --currency <code> --json`** — used in step 1: compute PV at recognition + per-period unwinding charge. Returns `{ presentValue, totalUnwindingCharge, schedule[n] }` where each row has `period`, `openingProvision`, `unwindingCharge`, `closingProvision`.
13
13
 
14
14
  ### Tools (jaz-api / direct)
15
- - **`search_capsules(filter: {capsuleType: {eq: 'Provisions'}, name: {eq: <capsule.name>}})`** — step 0 idempotency check.
15
+ - **`search_capsules(filter: {title: {eq: <capsule.name>}})`** — step 0 idempotency check.
16
16
  - **`search_accounts(filter: {name: {in: ['Provision for Warranties', 'Finance Cost', 'Warranty Expense']}})`** — step 3.
17
17
  - **`generate_trial_balance(period_end: <date>)`** — step 5 verify provision balance matches schedule's `closingProvision`.
18
18
  - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 5 monthly finalize.
@@ -29,7 +29,7 @@
29
29
  ### Step 0 — Idempotency check
30
30
 
31
31
  ```
32
- search_capsules(filter: {capsuleType: {eq: 'Provisions'}, name: {eq: 'Warranty Provision — FY2025-FY2029'}})
32
+ search_capsules(filter: {title: {eq: 'Warranty Provision — FY2025-FY2029'}})
33
33
  ```
34
34
 
35
35
  If a result returns: halt. Provision capsules are unique per obligation; duplicate setup means double-recognition.
@@ -90,7 +90,7 @@ Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, r
90
90
  For each month after recipe execution:
91
91
 
92
92
  ```
93
- search_journals(filter: {capsuleResourceId: {eq: <id>}, valueDate: {between: [<period-start>, <period-end>]}, status: {eq: 'DRAFT'}})
93
+ **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.
94
94
  update_journal(resourceId: <journal id>, saveAsDraft: false)
95
95
  ```
96
96
 
@@ -156,5 +156,5 @@ If actual settlement amount differs from estimated $500,000 (highly likely for w
156
156
 
157
157
  - Year-end close (Y5) — year-end provision remeasurement per IAS 37.59. Review each `Provisions` capsule's underlying assumptions vs current data; trigger manual remeasurement if needed.
158
158
  - Month-end close — finalize this period's pre-emitted unwinding DRAFT for each existing provision capsule.
159
- - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {capsuleType: {eq: 'Provisions'}})` + per-capsule recompute via `clio calc provision`. Auditor tests assumptions (cash flow estimate, discount rate, term).
159
+ - `audit-prep.md` step 8 — supporting schedule via `search_capsules(filter: {status: {eq: 'ACTIVE'}}) (capsule type is not filterable — see `jobs/references/building-blocks.md` § Filter limits)` + per-capsule recompute via `clio calc provision`. Auditor tests assumptions (cash flow estimate, discount rate, term).
160
160
  - Sibling `bad-debt-provision.md` (engine name `ecl`) — much simpler IFRS 9 ECL pattern, no PV unwinding.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaz-clio",
3
- "version": "5.55.2",
3
+ "version": "5.55.4",
4
4
  "description": "Clio: Command Line Interface Operator for Jaz AI.",
5
5
  "type": "module",
6
6
  "bin": {