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.
- package/assets/skills/api/SKILL.md +1 -1
- package/assets/skills/cli/SKILL.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jaz-kit/SKILL.md +1 -1
- package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/jobs/references/audit-prep.md +1 -1
- package/assets/skills/jobs/references/bank-recon.md +7 -6
- package/assets/skills/jobs/references/building-blocks.md +31 -3
- package/assets/skills/jobs/references/credit-control.md +2 -2
- package/assets/skills/jobs/references/fa-review.md +4 -4
- package/assets/skills/jobs/references/gst-vat-filing.md +4 -4
- package/assets/skills/jobs/references/month-end-close.md +10 -10
- package/assets/skills/jobs/references/payment-run.md +8 -6
- package/assets/skills/jobs/references/quarter-end-close.md +13 -9
- package/assets/skills/jobs/references/supplier-recon.md +21 -8
- package/assets/skills/jobs/references/year-end-close.md +8 -8
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/references/accrued-expenses.md +6 -6
- package/assets/skills/transaction-recipes/references/asset-disposal.md +5 -5
- package/assets/skills/transaction-recipes/references/bad-debt-provision.md +2 -2
- package/assets/skills/transaction-recipes/references/bank-loan.md +4 -4
- package/assets/skills/transaction-recipes/references/building-blocks.md +3 -3
- package/assets/skills/transaction-recipes/references/capital-wip.md +4 -4
- package/assets/skills/transaction-recipes/references/declining-balance.md +4 -4
- package/assets/skills/transaction-recipes/references/deferred-revenue.md +3 -3
- package/assets/skills/transaction-recipes/references/dividend.md +2 -2
- package/assets/skills/transaction-recipes/references/employee-accruals.md +7 -7
- package/assets/skills/transaction-recipes/references/fixed-deposit.md +5 -5
- package/assets/skills/transaction-recipes/references/ifrs16-lease.md +4 -4
- package/assets/skills/transaction-recipes/references/intercompany.md +2 -2
- package/assets/skills/transaction-recipes/references/prepaid-amortization.md +2 -2
- package/assets/skills/transaction-recipes/references/provisions.md +4 -4
- package/package.json +1 -1
|
@@ -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: {
|
|
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',
|
|
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
|
-
|
|
69
|
+
startDate: '2025-01-01',
|
|
70
|
+
endDate: '2025-01-31',
|
|
70
71
|
limit: 200,
|
|
71
|
-
|
|
72
|
+
sortBy: 'valueDate', sortOrder: 'ASC'
|
|
72
73
|
)
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
Omit `
|
|
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
|
-
|
|
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 (`
|
|
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: {
|
|
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: {
|
|
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
|
|
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>},
|
|
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
|
-
|
|
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,
|
|
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:
|
|
72
|
-
- If
|
|
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.
|
|
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: {
|
|
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: ['
|
|
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: {
|
|
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>]}},
|
|
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',
|
|
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']}},
|
|
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']}},
|
|
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',
|
|
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: {
|
|
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.
|
|
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: {
|
|
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.
|
|
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>}},
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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:** `
|
|
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: {
|
|
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: {
|
|
17
|
-
- **`search_capsules(filter: {
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
119
|
-
|
|
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: {
|
|
11
|
-
- **`search_payments(filter: {
|
|
12
|
-
- **`search_supplier_credit_notes(filter: {
|
|
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: {
|
|
45
|
-
|
|
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: {
|
|
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: {
|
|
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>},
|
|
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: {
|
|
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: {
|
|
23
|
-
- **`search_capsules(filter: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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. |
|
|
@@ -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: {
|
|
16
|
-
- **`search_journals(filter: {
|
|
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
|
-
-
|
|
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: {
|
|
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
|
-
|
|
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.
|
|
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: {
|
|
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: {
|
|
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
|
|
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:
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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.
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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
|
-
-
|
|
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
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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.
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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
|
-
-
|
|
20
|
-
-
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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.
|