jaz-clio 5.55.1 → 5.55.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +5 -4
- package/assets/skills/jobs/references/building-blocks.md +31 -3
- package/assets/skills/jobs/references/fa-review.md +3 -3
- package/assets/skills/jobs/references/gst-vat-filing.md +4 -4
- package/assets/skills/jobs/references/month-end-close.md +7 -7
- package/assets/skills/jobs/references/payment-run.md +6 -4
- package/assets/skills/jobs/references/quarter-end-close.md +13 -9
- package/assets/skills/jobs/references/supplier-recon.md +20 -7
- 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/cli.mjs +356 -356
- 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, sort: 'valueDate:asc')`** — step 2: per-account work queue.
|
|
11
11
|
- **`search_bank_records(accountResourceId: <id>, status: 'POSSIBLE_DUPLICATE')`** — step 3: handle dups FIRST or you'll double-create reconciling them.
|
|
12
12
|
- **`view_auto_reconciliation(bankStatementEntryResourceIds: [<id>, ...], recommendationType: 'MAGIC_MATCH' | 'RECOMMENDATIONS' | 'MAGIC_RECONCILE_WITH_CASH_TRANSFER' | 'MAGIC_RECONCILE_WITH_BANK_RULE' | 'MAGIC_QUICK_RECONCILE' | 'MAGIC_RECONCILE_WITH_CASH_IN_OUT', bankAccountResourceId?: <id>, autoCommitMaxAmount?: <number>)`** — step 4: READ-ONLY auto-match suggestions. **Pick the group, not the whole world:** `RECOMMENDATIONS` returns every type except `MAGIC_MATCH` in one ranked call and is the cheaper request; `MAGIC_MATCH` scans open transactions across the account and is asked for on its own. The four specific values narrow to one type. There is no value that returns everything at once, so a two-sided sweep is two calls. `recommendationType` is a REQUEST selector only: `RECOMMENDATIONS` never comes back as a suggestion's own `recommendationType`, which is always a concrete type. **`bankStatementEntryResourceIds` is REQUIRED — this endpoint is per-entry and there is no account-wide mode.** Source the ids from `search_bank_records` with status `UNRECONCILED`. Pass `bankAccountResourceId` too: it is merged into each suggestion's `execute` args for `reconcile_magic_match`. Returns **execution-ready `suggestions[]`** — each carries `recommendedTool`, `execute` (ready-to-pass args), `confidenceTier`, and `autoCommitEligible`. This is the entry point for the auto-match decision gate (step 4a). `MAGIC_RECONCILE_WITH_CASH_IN_OUT` returns Learned-Predictions. Does NOT write. NOTE: cost tracks the entries you pass — batch large backlogs. On a 500 it degrades to `{degraded:true}`; fall back to the cascade matcher (see error table).
|
|
13
13
|
- **`search_cashflow_transactions(filter: {organizationAccountResourceId: <bank-id>, totalAmount: {eq: <amt>}, valueDate: {between: [<-3d>, <+3d>]}})`** — step 5 manual match: search book-side transactions for the same amount within ±3 day window.
|
|
@@ -66,13 +66,14 @@ For each bank account `B`:
|
|
|
66
66
|
search_bank_records(
|
|
67
67
|
accountResourceId: B.resourceId,
|
|
68
68
|
status: 'UNRECONCILED',
|
|
69
|
-
|
|
69
|
+
startDate: '2025-01-01',
|
|
70
|
+
endDate: '2025-01-31',
|
|
70
71
|
limit: 200,
|
|
71
72
|
sort: 'valueDate:asc'
|
|
72
73
|
)
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
Omit `
|
|
76
|
+
Omit `startDate`/`endDate` for full catch-up across all open periods. Paginate via `offset` if `totalElements > 200`. Each row: `{resourceId, valueDate, netAmount, extContactName, description, balance}`. `netAmount > 0` = cash-in; `< 0` = cash-out. `extContactName + description` are the highest-signal match clues.
|
|
76
77
|
|
|
77
78
|
Flag any item older than 60 days as red — surface to practitioner.
|
|
78
79
|
|
|
@@ -229,7 +230,7 @@ Per account: `bookBalance == bankStatementBalance ± documentedTimingDifference`
|
|
|
229
230
|
|
|
230
231
|
| Source | Error | Recovery |
|
|
231
232
|
|--------|-------|----------|
|
|
232
|
-
| `view_auto_reconciliation` | 500 on high-volume account → returns `{degraded:true}` | Documented OOM quirk on accounts with thousands of unreconciled rows. The tool degrades (doesn't throw): scope per-period (`
|
|
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.
|
|
@@ -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, sort: 'valueDate:asc')
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
Paginate via offset if `totalElements > 200`. For each invoice:
|
|
@@ -82,7 +82,7 @@ Flag invoices where:
|
|
|
82
82
|
## Step 4 — Input-tax detail review
|
|
83
83
|
|
|
84
84
|
```
|
|
85
|
-
search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {
|
|
85
|
+
search_bills(filter: {valueDate: {between: ['2025-01-01', '2025-03-31']}, status: {neq: 'DRAFT'}}, limit: 200)
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
For each bill:
|
|
@@ -172,7 +172,7 @@ Save the filing summary for the quarter. The user files via the appropriate port
|
|
|
172
172
|
|
|
173
173
|
| Source | Error | Recovery |
|
|
174
174
|
|--------|-------|----------|
|
|
175
|
-
| Step 1 | `generate_vat_ledger` returns 0 for input tax despite bills exist | Likely all bills are DRAFT. `search_bills(filter: {status: 'DRAFT', valueDate: {between: [<Q-start>, <Q-end>]}})`; finalize via `bulk_finalize_drafts` (or `finalize_bill` per ID). |
|
|
175
|
+
| Step 1 | `generate_vat_ledger` returns 0 for input tax despite bills exist | Likely all bills are DRAFT. `search_bills(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<Q-start>, <Q-end>]}})`; finalize via `bulk_finalize_drafts` (or `finalize_bill` per ID). |
|
|
176
176
|
| Step 2 | Tax profile missing for jurisdiction | `create_tax_profile(...)` per IRAS / BIR spec. Halt and surface to practitioner — practitioner judgment on rate. |
|
|
177
177
|
| Step 3 | Per-invoice GST ≠ tax-ledger output total | Investigate per-invoice tax-profile assignment. Quick Fix typically resolves. |
|
|
178
178
|
| Step 4 | BL bills coded as TX | Quick Fix re-assigns to BL. Practitioner approval required (changes input tax claim). |
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
### Platform tools — pre-close gates
|
|
8
8
|
- **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, sort: 'valueDate:asc', limit: 200)`** — step 1: confirm sales invoices entered. Paginate via `offset`.
|
|
9
9
|
- **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}}, ...)`** — step 2: confirm purchase bills entered.
|
|
10
|
-
- **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED',
|
|
10
|
+
- **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', startDate: <from>, endDate: <to>)`** — step 3: pull unreconciled bank statement entries per account.
|
|
11
11
|
- **`generate_aged_ar(period_end: <date>)` / `generate_aged_ap(period_end: <date>)`** — steps 4-5: aging reports tied to TB AR / AP balances.
|
|
12
12
|
|
|
13
13
|
### Platform tools — accruals + valuations
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- **`generate_trial_balance(period_end: <date>)`** — step 14: master reconciliation.
|
|
29
29
|
- **`generate_profit_and_loss(period_start, period_end)`** — step 15.
|
|
30
30
|
- **`generate_balance_sheet(period_end)`** — step 16.
|
|
31
|
-
- **`search_journals(filter: {status: 'DRAFT', valueDate: {between: [<period-start>, <period-end>]}})`** — step 17: gate on zero drafts.
|
|
31
|
+
- **`search_journals(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<period-start>, <period-end>]}})`** — step 17: gate on zero drafts.
|
|
32
32
|
- **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 17: clear residual drafts before lock.
|
|
33
33
|
- **`update_account(resourceId: <CoA root>, lockDate: <period-end>)`** — step 18: lock the period.
|
|
34
34
|
|
|
@@ -74,7 +74,7 @@ Cross-reference against email + supplier portals + physical mail. Late bills = m
|
|
|
74
74
|
For each bank account:
|
|
75
75
|
|
|
76
76
|
1. If you don't already have the account's resourceId: `list_bank_accounts()`, match by `name + currency`, confirm with the user.
|
|
77
|
-
2. `search_bank_records(accountResourceId: <bank account resourceId>, status: 'UNRECONCILED',
|
|
77
|
+
2. `search_bank_records(accountResourceId: <bank account resourceId>, status: 'UNRECONCILED', startDate: '2025-01-01', endDate: '2025-01-31', limit: 200, sort: 'valueDate:asc')`.
|
|
78
78
|
3. If results: drive the 5-phase cascade matcher (Step 4 in `bank-recon.md`; local CLI: `clio jobs bank-recon match --input <records> --tolerance 0.01 --date-window 14 --json`). For each match, invoke the matching `reconcile_*` tool.
|
|
79
79
|
4. `view_auto_reconciliation(bankStatementEntryResourceIds: [<id>, ...], recommendationType: 'MAGIC_MATCH')` — READ-ONLY suggestions for residuals (per-entry; get ids from `search_bank_records`, status `UNRECONCILED`); commit via `quick_reconcile` / `apply_bank_rule` / per-entry `reconcile_*`.
|
|
80
80
|
5. `generate_bank_recon_summary(period_end: '2025-01-31', accountResourceId: <id>)`. Confirm `unreconciledCount == 0` OR document the residuals for the period and surface to the user.
|
|
@@ -108,9 +108,9 @@ Cross-check: `generate_trial_balance(period_end: '2025-01-31')`. Sum credit move
|
|
|
108
108
|
|
|
109
109
|
### Step 7 — Prepaid expense recognition (finalize this period's pre-emitted journal)
|
|
110
110
|
|
|
111
|
-
For each existing `Prepaid Expenses` capsule (via `search_capsules(filter: {
|
|
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>}}, sort: 'dueDate:asc', limit: 200)`** — used in step 2: pull due bills (paginate via `offset` if `>200`).
|
|
8
|
+
- **`search_bills(filter: {status: {eq: 'UNPAID'}, balanceAmount: {gt: 0}, dueDate: {lte: <cutoff>}}, sort: 'dueDate:asc', limit: 200)`** — used in step 2: pull due bills (paginate via `offset` if `>200`).
|
|
9
9
|
- **`generate_aged_ap(period_end: <cutoff>)`** — used in step 3: total-AP cross-check; flag bills in 60d+ aging buckets.
|
|
10
10
|
- **`generate_bank_balance_summary(period_end: <cutoff>)`** — used in step 5: confirm cash availability before approving the batch.
|
|
11
11
|
- **`get_contact(resourceId: <contactResourceId>)`** — used in step 4 (per supplier): pull payment terms / preferred payment method / bank details (especially `taxId`, `bankAccountNumber`, `bicSwift` for GIRO file generation).
|
|
12
12
|
- **`create_bill_payment(billResourceId: <id>, payments: [{...}])`** — used in step 6: post the payment per bill. NO BATCH PAYMENT ENDPOINT yet — one POST per bill.
|
|
13
|
-
- **`search_payments(filter: {
|
|
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.
|
|
@@ -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:
|
|
@@ -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,7 +54,7 @@ Pull `paymentTerms`, `bankAccountNumber`, `taxId`, `paymentMethod` for narrative
|
|
|
41
54
|
|
|
42
55
|
```
|
|
43
56
|
search_bills(
|
|
44
|
-
filter: {
|
|
57
|
+
filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}},
|
|
45
58
|
sort: 'valueDate:asc',
|
|
46
59
|
limit: 200
|
|
47
60
|
)
|
|
@@ -54,7 +67,7 @@ For an opening-balance recon: also pull the supplier's pre-period balance via `g
|
|
|
54
67
|
## Step 3 — Pull payments
|
|
55
68
|
|
|
56
69
|
```
|
|
57
|
-
search_payments(filter: {
|
|
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
|
|