jaz-clio 5.74.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +8 -8
  2. package/assets/skills/api/SKILL.md +3 -36
  3. package/assets/skills/cli/SKILL.md +18 -28
  4. package/assets/skills/cli/references/agent-gotchas.md +2 -2
  5. package/assets/skills/cli/references/command-catalog.md +15 -31
  6. package/assets/skills/cli/references/common-workflows.md +19 -28
  7. package/assets/skills/conversion/SKILL.md +1 -1
  8. package/assets/skills/jaz-kit/SKILL.md +1 -1
  9. package/assets/skills/jaz-kit/references/flows.md +2 -2
  10. package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
  11. package/assets/skills/jobs/SKILL.md +42 -42
  12. package/assets/skills/jobs/references/audit-prep.md +8 -8
  13. package/assets/skills/jobs/references/bank-match.md +1 -1
  14. package/assets/skills/jobs/references/bank-recon.md +6 -6
  15. package/assets/skills/jobs/references/building-blocks.md +49 -30
  16. package/assets/skills/jobs/references/credit-control.md +13 -12
  17. package/assets/skills/jobs/references/document-collection.md +6 -6
  18. package/assets/skills/jobs/references/fa-review.md +28 -29
  19. package/assets/skills/jobs/references/gst-vat-filing.md +3 -3
  20. package/assets/skills/jobs/references/month-end-close.md +37 -33
  21. package/assets/skills/jobs/references/payment-run.md +3 -4
  22. package/assets/skills/jobs/references/quarter-end-close.md +20 -18
  23. package/assets/skills/jobs/references/supplier-recon.md +5 -5
  24. package/assets/skills/jobs/references/year-end-close.md +31 -21
  25. package/assets/skills/transaction-recipes/SKILL.md +54 -117
  26. package/assets/skills/transaction-recipes/references/accrued-expenses.md +86 -61
  27. package/assets/skills/transaction-recipes/references/asset-disposal.md +135 -93
  28. package/assets/skills/transaction-recipes/references/bad-debt-provision.md +87 -65
  29. package/assets/skills/transaction-recipes/references/bank-loan.md +104 -70
  30. package/assets/skills/transaction-recipes/references/building-blocks.md +168 -72
  31. package/assets/skills/transaction-recipes/references/capital-wip.md +9 -8
  32. package/assets/skills/transaction-recipes/references/declining-balance.md +91 -64
  33. package/assets/skills/transaction-recipes/references/deferred-revenue.md +105 -68
  34. package/assets/skills/transaction-recipes/references/dividend.md +100 -64
  35. package/assets/skills/transaction-recipes/references/employee-accruals.md +111 -73
  36. package/assets/skills/transaction-recipes/references/fixed-deposit.md +116 -63
  37. package/assets/skills/transaction-recipes/references/fx-revaluation.md +28 -19
  38. package/assets/skills/transaction-recipes/references/hire-purchase.md +45 -44
  39. package/assets/skills/transaction-recipes/references/ifrs16-lease.md +108 -73
  40. package/assets/skills/transaction-recipes/references/intercompany.md +8 -6
  41. package/assets/skills/transaction-recipes/references/prepaid-amortization.md +104 -65
  42. package/assets/skills/transaction-recipes/references/provisions.md +116 -64
  43. package/assets/templates/platform-rules/jaz-agent-rules.md +10 -9
  44. package/cli.mjs +529 -607
  45. package/package.json +1 -1
@@ -1,21 +1,23 @@
1
- # Recipe: Dividend (engine name: `dividend`)
1
+ # Recipe: Dividend (calculator type: `dividend`)
2
2
 
3
- > Two-step (or three-step with withholding) recipe for board-declared dividends. Engine emits 1 journal (declaration) + 1 cash-out (payment) + optional 1 cash-out (withholding tax remit). One-shot recipe: no schedule. Used annually (final dividend) or interim (mid-year).
3
+ > Two-step (or three-step with withholding) recipe for board-declared dividends. One journal (declaration), one cash-out (payment) and, with withholding tax, the withholding entries. One-shot recipe: no schedule. Used annually (final dividend) or interim (mid-year). You calculate, create the capsule and post each entry yourself (see `building-blocks.md` § The three-step flow).
4
4
 
5
- ## Tools, recipes, calculators this recipe uses
5
+ ## Tools and calculator this recipe uses
6
6
 
7
- ### Recipe engine entry point
8
- - **`plan_recipe(recipe: 'dividend', ...)`** (used in step 2): returns RecipePlan with declaration journal + payment cash-out + optional withholding cash-out.
9
- - **`execute_recipe(recipe: 'dividend', ...)`** (used in step 4): posts 2-3 entries (no future-dated DRAFTs: dividend is point-in-time).
7
+ ### Calculator (offline, posts nothing)
8
+ - **MCP: `calculate(type: 'dividend', amount, declarationDate, paymentDate, withholdingRate, currency)`** (step 1).
9
+ - **CLI: `clio calc dividend --amount <gross> --declaration-date <YYYY-MM-DD> --payment-date <YYYY-MM-DD> --withholding-rate <%> --currency <code> --json`** (step 1): the same result. Both dates are required.
10
10
 
11
- ### Calculator (cross-check, no API key needed)
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 }`.
11
+ ### Posting tools
12
+ - **`list_capsule_types` / `create_capsule_type(displayName: 'Dividends')` / `create_capsule(...)`** (step 3).
13
+ - **`create_journal(...)`** (step 4): the declaration, and the withholding transfer when tax is withheld.
14
+ - **`create_cash_out(...)`** (step 4): the payment to shareholders, and later the remittance of the withheld tax.
13
15
 
14
- ### Tools (jaz-api / direct)
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
- - **`search_accounts(filter: {name: {in: ['Retained Earnings', 'Dividends Payable', 'Withholding Tax Payable']}})`**: step 3.
17
- - **`search_contacts(filter: {name: {eq: <shareholder>}})`**: step 3 (the payee, typically a shareholder or a holding entity).
18
- - **`generate_balance_sheet(snapshotDate: <date>)`** (step 5 verification): Retained Earnings reduced; Dividends Payable nil after payment.
16
+ ### Lookup and verification tools
17
+ - **`search_capsules(filter: {title: {eq: <capsule title>}})`**: step 0 idempotency check. Each declared dividend gets its own capsule; duplicate setup means double-declaration.
18
+ - **`search_accounts(filter: {name: {in: ['Retained Earnings', 'Dividends Payable', 'Withholding Tax Payable']}})`**: step 2.
19
+ - **`search_contacts(filter: {name: {eq: <shareholder>}})`**: step 2 (the payee, typically a shareholder or a holding entity).
20
+ - **`generate_balance_sheet(snapshotDate: <date>)`** (step 2 pre-check and step 5 verification): Retained Earnings available before declaring; reduced after; Dividends Payable nil after payment.
19
21
  - **`generate_equity_movement(primarySnapshotStartDate, primarySnapshotEndDate)`** (step 5): dividends appear as a distinct line item in equity movement, separate from net profit.
20
22
 
21
23
  ### Cross-references
@@ -33,65 +35,101 @@
33
35
  search_capsules(filter: {title: {eq: 'FY2025 Final Dividend'}})
34
36
  ```
35
37
 
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`)."
38
+ If a result returns: halt and surface "Dividend capsule `<name>` already exists. Re-posting would create a duplicate declaration. Confirm: if posting an interim dividend, use a different capsule title (e.g., `Q3 2025 Interim Dividend`)."
37
39
 
38
- ### Step 1: Independent cross-check (calculator)
40
+ ### Step 1: Calculate
39
41
 
40
42
  ```
41
- clio calc dividend --amount 200000 --withholding-rate 0 --currency SGD --json
43
+ calculate(
44
+ type: 'dividend',
45
+ amount: 200000,
46
+ withholdingRate: 0,
47
+ declarationDate: '2025-12-31',
48
+ paymentDate: '2026-03-15',
49
+ currency: 'SGD'
50
+ )
42
51
  ```
43
52
 
44
- Returns: `{ grossAmount: 200000, withholdingTax: 0, netToShareholder: 200000 }` for SG (no withholding on dividends from SG-resident companies: SG operates a one-tier corporate tax system, dividends are tax-exempt at the shareholder level under ITA s13(1)(z)).
45
-
46
- For PH or jurisdictions with withholding (e.g., 10% PH dividend WHT to non-resident foreign corporations under NIRC §28(B)(5)(b)):
47
-
48
53
  ```
49
- clio calc dividend --amount 200000 --withholding-rate 10 --currency PHP --json
50
- # → { grossAmount: 200000, withholdingTax: 20000, netToShareholder: 180000 }
54
+ clio calc dividend --amount 200000 --declaration-date 2025-12-31 --payment-date 2026-03-15 --withholding-rate 0 --currency SGD --json
51
55
  ```
52
56
 
53
- ### Step 2: Plan the recipe
57
+ Returns `{ grossAmount: 200000, netToShareholders: 200000, withholdingTax: 0, declarationJournal, paymentJournal, withholdingJournal: null, blueprint }` for SG (no withholding on dividends from SG-resident companies: SG operates a one-tier corporate tax system, dividends are tax-exempt at the shareholder level under ITA s13(1)(z)).
58
+
59
+ For PH or jurisdictions with withholding (e.g., 10% PH dividend WHT to non-resident foreign corporations under NIRC §28(B)(5)(b)):
54
60
 
55
61
  ```
56
- plan_recipe(
57
- // Accounts, capsule and counterparty are not plan_recipe params: execute_recipe resolves accounts from the CoA and takes bankAccountName / contactName.
58
- recipe: 'dividend',
59
- amount: 200000,
60
- withholdingRate: 0,
61
- declarationDate: '2025-12-31',
62
- paymentDate: '2026-03-15',
63
- currency: 'SGD'
64
- )
62
+ clio calc dividend --amount 200000 --declaration-date 2025-12-31 --payment-date 2026-03-15 --withholding-rate 10 --currency PHP --json
63
+ # → { grossAmount: 200000, netToShareholders: 180000, withholdingTax: 20000, ... }
65
64
  ```
66
65
 
67
- Returns `RecipePlan` with `requiredAccounts: ['Retained Earnings', 'Dividends Payable', 'Cash / Bank Account']` (+ `Withholding Tax Payable` if `withholdingRate > 0`), `needsContact: false` (shareholder is metadata only), `needsBankAccount: true`, `steps`:
68
- - Step 1: declaration journal dated `declarationDate`, Dr Retained Earnings 200,000 / Cr Dividends Payable 200,000
69
- - Step 2: payment cash-out dated `paymentDate`, Dr Dividends Payable 200,000 / Cr Cash 200,000 (or net amount if withholding)
70
- - Step 3 (if withholdingRate > 0): withholding cash-out dated `paymentDate`, Dr Dividends Payable (withholding portion) / Cr Withholding Tax Payable
66
+ `blueprint.steps`:
67
+ - Step 1, `journal`, dated `declarationDate`: Dr Retained Earnings 200,000 / Cr Dividends Payable 200,000.
68
+ - Step 2, `cash-out`, dated `paymentDate`: Dr Dividends Payable 200,000 / Cr Cash / Bank Account 200,000. With withholding: Dr Dividends Payable 200,000 / Cr Cash / Bank Account 180,000 / Cr Withholding Tax Payable 20,000.
69
+ - Step 3 (only if `withholdingRate > 0`), `cash-out`, dated `paymentDate`: the remittance to the tax authority, Dr Withholding Tax Payable 20,000 / Cr Cash / Bank Account 20,000.
71
70
 
72
- ### Step 3: Resolve dependencies
71
+ ### Step 2: Resolve accounts, bank account and distributable profits
73
72
 
74
- For each account in `requiredAccounts`:
75
- - `search_accounts(filter: {name: {eq: <accountName>}})`. Suggested classifications: `Retained Earnings` → `Shareholders Equity`; `Dividends Payable` → `Current Liability`; `Withholding Tax Payable` → `Current Liability`.
73
+ The blueprint's account names are labels. Map each to the real account:
74
+ - `search_accounts(filter: {name: {in: ['Retained Earnings', 'Dividends Payable', 'Withholding Tax Payable']}})`. Suggested classifications: `Retained Earnings` → `Shareholders Equity`; `Dividends Payable` → `Current Liability`; `Withholding Tax Payable` → `Current Liability`.
76
75
 
77
76
  If `Dividends Payable` doesn't exist: `create_account(name: 'Dividends Payable', code: <unused account code>, accountType: 'Current Liability', currencyCode: <base currency>)` first. This is a common gap in CoAs that haven't paid dividends before.
78
77
 
79
- Bank account: resolve `bankAccountResourceId` via `list_bank_accounts()` if the bank account resourceId isn't already known.
78
+ Bank account: `list_bank_accounts()` if the bank account resourceId isn't already known.
80
79
 
81
80
  Shareholder contact: optional but recommended for narrative tagging. `search_contacts(filter: {name: {eq: <shareholder>}})`. If empty: `create_contact(name: <shareholder>, customer: false, supplier: false)`; mark as "other" / shareholder type if your CoA has a custom field for that.
82
81
 
83
- ### Step 4: Execute
82
+ **Distributable profits check.** Nothing blocks a declaration that exceeds retained earnings, so check it yourself: `generate_balance_sheet(snapshotDate: <declarationDate>)`. If the dividend would push Retained Earnings negative, halt and surface: "Declaration would result in a dividend out of capital. Verify available retained earnings." In Singapore a dividend is payable only out of profits (Companies Act s403).
83
+
84
+ ### Step 3: Create the capsule
85
+
86
+ ```
87
+ list_capsule_types()
88
+ create_capsule(
89
+ capsuleTypeResourceId: <id of 'Dividends'>,
90
+ title: 'FY2025 Final Dividend',
91
+ description: <blueprint.capsuleDescription>
92
+ )
93
+ ```
94
+
95
+ If `Dividends` is not in the list: `create_capsule_type(displayName: 'Dividends')` first.
96
+
97
+ ### Step 4: Post the entries
98
+
99
+ **4a. Declaration** (blueprint step 1), dated the board resolution date:
100
+
101
+ ```
102
+ create_journal(
103
+ valueDate: '2025-12-31',
104
+ reference: 'DIV-FY2025-DECL',
105
+ journalEntries: [
106
+ { accountResourceId: <Retained Earnings>, type: 'DEBIT', amount: 200000, description: 'Dividend declaration, FY2025 final' },
107
+ { accountResourceId: <Dividends Payable>, type: 'CREDIT', amount: 200000, description: 'Dividend declaration, FY2025 final' }
108
+ ],
109
+ saveAsDraft: false,
110
+ capsuleResourceId: <capsule id>
111
+ )
112
+ ```
113
+
114
+ **4b. Payment** (blueprint step 2). Post it on the actual payment date, once the money has left the bank account: a cash entry posts ACTIVE immediately and has no draft state, so a payment recorded ahead of time is a live bank payment that has not happened, which the bank reconciliation will not match until the real payment arrives.
84
115
 
85
116
  ```
86
- execute_recipe(recipe: 'dividend', ...same args...) // accounts auto-resolved from CoA; pass `bankAccountName` / `contactName` for fuzzy resolve
117
+ create_cash_out(
118
+ valueDate: '2026-03-15',
119
+ accountResourceId: <bank account>,
120
+ reference: 'DIV-FY2025-PAY',
121
+ lines: [{ accountResourceId: <Dividends Payable>, amount: 200000, description: 'Dividend payment to shareholders' }],
122
+ capsuleResourceId: <capsule id>
123
+ )
87
124
  ```
88
125
 
89
- Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...], summary: {total: 2 or 3, created: 2 or 3} }`. The recipe creates 2 entries (or 3 with withholding), all attached to the same capsule:
90
- - Declaration journal (DRAFT or ACTIVE per `finalize` flag)
91
- - Payment cash-out: posted ACTIVE immediately, dated `paymentDate`. Cash entries have no draft state, so `finalize` does not apply and there is nothing to finalize later.
92
- - Withholding cash-out: same, posted ACTIVE immediately, dated `paymentDate`.
126
+ **With withholding tax** the payment step has a credit to Withholding Tax Payable beside the bank line, and a cash-out can only debit its lines. Split it in two, both dated `paymentDate`:
127
+ - `create_cash_out` for the NET amount (180,000) against Dividends Payable.
128
+ - `create_journal`: Dr Dividends Payable 20,000 / Cr Withholding Tax Payable 20,000.
129
+
130
+ Together they clear Dividends Payable (200,000) and leave the withheld tax owing to the authority.
93
131
 
94
- **Run the recipe on the actual payment date**, once the money has left the bank account. The declaration journal still carries `declarationDate`, so booking it late puts it in the right period. Running at declaration time instead posts a live bank payment that has not happened yet, which the bank reconciliation will not match until the real payment arrives. If the declaration must be booked before the payment (for example at FY-end), post the declaration alone with `create_journal` (Dr Retained Earnings / Cr Dividends Payable) and record the payment with `create_cash_out` when the money leaves the account.
132
+ **4c. Withholding remittance** (blueprint step 3). When the tax is actually remitted: `create_cash_out` for 20,000 against Withholding Tax Payable, with `capsuleResourceId`.
95
133
 
96
134
  ### Step 5: Verify (after the declaration is finalized and the payment is posted)
97
135
 
@@ -110,22 +148,21 @@ After payment posted (Mar 15, 2026):
110
148
 
111
149
  After payment AND WHT remittance:
112
150
  - `balance['Withholding Tax Payable']` back to 0.
113
- - Capsule lifecycle complete; close via a manual `update_capsule(title: '<original> [CLOSED]')` (the API has no `status` field for capsules; closure is informational only).
151
+ - Capsule lifecycle complete; close via a manual `update_capsule(resourceId: <id>, title: '<original> [CLOSED]')` (the API has no `status` field for capsules; closure is informational only).
114
152
 
115
153
  ---
116
154
 
117
- ## Common error classes and recovery
155
+ ## Common problems and recovery
118
156
 
119
- | Source | Error | Recovery |
157
+ | Where | Problem | Recovery |
120
158
  |--------|-------|----------|
121
- | `plan_recipe` | 422 `unsupported_recipe` | Use canonical engine name `dividend` (already canonical). |
122
- | `plan_recipe` | 422 `withholding_rate_invalid` | Rate must be 0-100. Verify jurisdiction; SG = 0; PH non-resident foreign = 10% (NIRC §28(B)(5)(b)); others vary by treaty. |
123
- | `execute_recipe` | 422 `account_not_found` | Step 3 incomplete. `Dividends Payable` is the most-commonly-missing account. Create via `create_account`. |
124
- | `execute_recipe` | 422 `negative_retained_earnings` | The dividend would push Retained Earnings negative. SG ITA s403(2): companies cannot declare dividends out of capital (must be from accumulated profits). Halt and surface to practitioner: "Declaration would result in dividend out of capital. Verify available retained earnings via `generate_balance_sheet`." |
125
- | `execute_recipe` | 422 `currency_mismatch_bank_account` | Dividend currency ≠ bank account currency. Pass `currency` matching the disbursement bank, or model as FX cash-out (different `paymentAmount` and `transactionAmount`). |
126
- | Step 5 verification | Net Profit affected by dividend | Should NEVER happen via recipe (engine debits Retained Earnings, not P&L). If TB shows P&L impact: practitioner posted a manual journal mis-mapping. Reverse and re-run via recipe. |
127
- | Withholding tax remitted but `Withholding Tax Payable` still nonzero | (process gap) | Practitioner forgot to post the WHT remittance to authority. Post `create_cash_out` with line: Dr Withholding Tax Payable / Cr Cash for the WHT amount. |
128
- | Interim dividend declared after final dividend already in capsule | (process) | Use a NEW capsule name (e.g., `Q1 2026 Interim Dividend` if it's the next FY's interim). Idempotency check protects against duplicate same-name. |
159
+ | Calculator | Withholding rate questioned | The rate is a percentage (10 = 10%). Verify jurisdiction; SG = 0; PH non-resident foreign = 10% (NIRC §28(B)(5)(b)); others vary by treaty. |
160
+ | Step 2 | `Dividends Payable` is missing | The most-commonly-missing account. Create via `create_account`. |
161
+ | Step 2 | Dividend exceeds retained earnings | Halt (see the distributable profits check). Do not post the declaration. |
162
+ | `create_cash_out` | Dividend currency ≠ bank account currency | Pay from a bank account in the dividend's currency, or record the FX on the cash-out. |
163
+ | Step 5 verification | Net Profit affected by dividend | Should NEVER happen: the declaration debits Retained Earnings, not P&L. If the TB shows P&L impact, a journal was mis-mapped to an expense account. Reverse it and re-post against Retained Earnings. |
164
+ | Withholding tax remitted but `Withholding Tax Payable` still nonzero | (process gap) | The WHT remittance to the authority was not posted. Post `create_cash_out` with a line against Withholding Tax Payable for the WHT amount. |
165
+ | Interim dividend declared after final dividend already in capsule | (process) | Use a NEW capsule title (e.g., `Q1 2026 Interim Dividend` if it's the next FY's interim). The idempotency check protects against a duplicate same-title capsule. |
129
166
 
130
167
  ---
131
168
 
@@ -133,16 +170,15 @@ After payment AND WHT remittance:
133
170
 
134
171
  - **Interim dividend** (mid-year, ad-hoc): same recipe, different `declarationDate` and capsule name. Sometimes paid same day as declaration → `paymentDate == declarationDate`.
135
172
  - **Stock dividend** (bonus shares, no cash): NOT supported by this recipe. Manual journal pattern: Dr Retained Earnings / Cr Share Capital (or Bonus Issue Reserve) for the par value of new shares issued.
136
- - **Multiple shareholders with different proportions**: For each shareholder, run `plan_recipe + execute_recipe` separately with their portion of the dividend. Each gets its own capsule for traceability. Or run one combined recipe with the total amount and use journal narratives + tags to split.
137
- - **Cross-border dividend with treaty rate**: pass the treaty `withholdingRate` (e.g., SG-MY DTA dividend WHT is 0%-10% depending on shareholding). Practitioner confirms treaty applicability before invoking.
173
+ - **Multiple shareholders with different proportions**: Either calculate and post each shareholder's portion separately (each with its own capsule for traceability), or post one combined dividend for the total and use journal narratives + tags to split.
174
+ - **Cross-border dividend with treaty rate**: pass the treaty `withholdingRate` (e.g., SG-MY DTA dividend WHT is 0%-10% depending on shareholding). Practitioner confirms treaty applicability before posting.
138
175
  - **Dividend in foreign currency**: pass `currency: 'USD'` (e.g., dividend to USD-denominated holding company). Per `jaz-api/SKILL.md` rule 25, payment cash-out uses `currency: { sourceCurrency: 'USD' }`. Jaz auto-handles FX revaluation of any USD-denominated `Dividends Payable` outstanding at period-end.
139
- - **Scrip dividend** (option to receive cash or shares): NOT supported. Two recipe invocations OR manual pattern depending on take-up.
176
+ - **Scrip dividend** (option to receive cash or shares): NOT supported. Cash portion via this recipe, share portion via the stock-dividend manual pattern, depending on take-up.
140
177
 
141
178
  ---
142
179
 
143
180
  ## Cross-references
144
181
 
145
- - Year-end close (Y3 in year-end-close): final FY dividend declaration AFTER the FY's audited net profit is determined. The declared amount and withholding rate drive the recipe inputs.
146
- - Month-end close: interim dividends declared mid-year are posted in the month they were declared. The payment cash-outs post ACTIVE the moment the recipe runs, so run it once the bank disbursement has happened (typically next month), or book the declaration alone with `create_journal` in the declaration month and record the payment with `create_cash_out` when it is made.
182
+ - Year-end close (Y3 in year-end-close): final FY dividend declaration AFTER the FY's audited net profit is determined. The declared amount and withholding rate are the calculator inputs.
183
+ - Month-end close: interim dividends declared mid-year are posted in the month they were declared. Book the declaration with `create_journal` in the declaration month; record the payment with `create_cash_out` only when the bank disbursement has happened (typically next month), because a cash entry posts ACTIVE immediately.
147
184
  - `audit-prep.md` step 8: auditor reviews `generate_equity_movement` to verify dividends are correctly classified as equity reduction (not P&L expense).
148
- - `statutory-filing.md`: SG Form C-S Box 12 (dividends paid during YA) reads from this capsule's payment cash-out entries.
@@ -1,138 +1,176 @@
1
- # Recipe: Employee Benefit Accruals (engine names: `leave-accrual` + `accrued-expense`)
1
+ # Recipe: Employee Benefit Accruals (calculator types: `leave-accrual` + `accrued-expense`)
2
2
 
3
- > Two distinct patterns in one reference: monthly leave accrual (engine `leave-accrual`, no reversal) + quarterly/annual bonus accrual (engine `accrued-expense`, reversal pattern). IAS 19 employee benefits.
3
+ > Two distinct patterns in one reference: monthly leave accrual (calculator `leave-accrual`, no reversal) + quarterly/annual bonus accrual (calculator `accrued-expense`, reversal pattern). IAS 19 employee benefits. You calculate, create the capsule and post each entry yourself (see `building-blocks.md` § The three-step flow).
4
4
 
5
- ## Why two engines
5
+ ## Why two calculators
6
6
 
7
- - **Leave accrual**: accumulates monthly as employees earn leave entitlement. NO reversal pattern (employees don't unaccumulate leave). Released into actual leave taken / paid out via separate journals. Engine: `leave-accrual`.
8
- - **Bonus accrual**: accrues each quarter against an estimate, reversed at quarter-start, fresh accrual at quarter-end. Same pattern as utility/electricity accrual. Engine: `accrued-expense`.
7
+ - **Leave accrual**: accumulates monthly as employees earn leave entitlement. NO reversal pattern (employees don't unaccumulate leave). Released into actual leave taken / paid out via separate journals. Calculator: `leave-accrual`.
8
+ - **Bonus accrual**: accrues each quarter against an estimate, reversed at quarter-start, fresh accrual at quarter-end. Same pattern as utility/electricity accrual. Calculator: `accrued-expense`.
9
9
 
10
- The two patterns share the same `Employee Benefits` capsule type but use different engines. Each gets its own capsule invocation per FY.
10
+ The two patterns share the `Employee Benefits` capsule type but use different calculators. Each gets its own capsule per FY.
11
11
 
12
- ## Tools, recipes, calculators this recipe uses
12
+ ## Tools and calculators this recipe uses
13
13
 
14
- ### Recipe engine entry points
14
+ ### Calculators (offline, post nothing)
15
15
 
16
- **Leave (engine: `leave-accrual`):**
17
- - **`plan_recipe(recipe: 'leave-accrual', ...)`** (used in step 2A): returns RecipePlan with N future-dated DRAFT accrual journals (one per month, fixed amount). NO reversal.
18
- - **`execute_recipe(recipe: 'leave-accrual', ...)`** (used in step 4A): posts N future-dated DRAFT journals upfront.
16
+ **Leave:**
17
+ - **MCP: `calculate(type: 'leave-accrual', employees, daysPerYear, dailyRate, periods, startDate, currency)`** (step 1A).
18
+ - **CLI: `clio calc leave-accrual --employees <n> --days <days per employee per year> --daily-rate <amt> --periods <months> --start-date <YYYY-MM-DD> --currency <code> --json`**: the same result. Returns `{ totalAnnualCost, periodAccrual, schedule[periods], blueprint }`.
19
19
 
20
- **Bonus (engine: `accrued-expense`):**
21
- - **`plan_recipe(recipe: 'accrued-expense', amount: <quarterly bonus est>, periods: 1, ...)`** (used in step 2B): returns 2-journal pair (accrual at period-end + reversal at next-period-start). See `accrued-expenses.md` for the full pattern.
20
+ **Bonus:**
21
+ - **MCP: `calculate(type: 'accrued-expense', amount: <quarterly bonus est>, periods: 1, startDate, currency)`** (step 1B): returns the accrual + reversal pair. See `accrued-expenses.md` for the full pattern.
22
+ - **CLI: `clio calc accrued-expense --amount <quarterly bonus> --periods 1 --start-date <YYYY-MM-DD> --json`**.
22
23
 
23
- ### Calculators
24
- - **`clio calc leave-accrual --headcount <n> --days-per-employee <days> --daily-rate <amt> --periods <months> --start-date <YYYY-MM-DD> --currency <code> --json`**: leave cross-check. Returns `{ totalAnnualCost, perPeriodAmount, schedule[periods] }`.
25
- - **`clio calc accrued-expense --amount <quarterly bonus> --periods 1 --json`**: bonus cross-check.
24
+ ### Posting tools
25
+ - **`list_capsule_types` / `create_capsule_type(displayName: 'Employee Benefits')` / `create_capsule(...)`**.
26
+ - **`create_scheduled_journal(...)`** (leave: the same amount every month) or **`create_journal(...)`** per period.
27
+ - **`create_journal(...)`** (bonus: accrual and reversal).
26
28
 
27
- ### Tools (jaz-api / direct)
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
- - **`search_accounts(filter: {name: {in: ['Leave Expense', 'Leave Liability', 'Bonus Expense', 'Bonus Payable']}})`**: step 3.
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
- - **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`**: monthly finalize.
29
+ ### Lookup and verification tools
30
+ - **`search_capsules(filter: {status: {eq: 'ACTIVE'}})`** (step 0; capsule type is not filterable, see `jobs/references/building-blocks.md` § Filter limits): discover existing leave + bonus capsules.
31
+ - **`search_accounts(filter: {name: {in: ['Leave Expense', 'Leave Liability', 'Bonus Expense', 'Bonus Payable']}})`**: resolve accounts.
32
+ - **`search_journals(filter: {reference: {eq: <period reference>}})`** (monthly): find this period's journal.
33
+ - **`update_journal(resourceId: <id>, saveAsDraft: false)`**: monthly finalize of a draft.
32
34
  - **`generate_trial_balance(endDate: <date>)`**: verification.
33
35
  - For year-end true-up: see `year-end-close.md` Y2 (manual journal pattern with HR-supplied actuals).
34
36
 
35
37
  ### Cross-references
36
38
  - Operational context: invoked during month-end close (monthly leave) and during year-end close (Y2 in `year-end-close.md`, bonus accrual true-up).
37
- - Sibling: `accrued-expenses.md` (the engine that drives the bonus pattern); `dividend.md` (annual P&L distribution to shareholders, mirror to bonus).
39
+ - Sibling: `accrued-expenses.md` (the calculator that drives the bonus pattern); `dividend.md` (annual P&L distribution to shareholders, mirror to bonus).
38
40
  - IFRS / accounting context: IAS 19.11 (short-term employee benefits, recognized as expense in the period the service is rendered); IAS 19.13 (accrual of leave entitlement); IAS 19.19 (recognition criteria for bonuses: present obligation + reliable estimate).
39
41
 
40
42
  ---
41
43
 
42
- ## Pattern A: Monthly leave accrual (engine: `leave-accrual`)
44
+ ## Pattern A: Monthly leave accrual (calculator: `leave-accrual`)
43
45
 
44
46
  ### Step 0A: Idempotency check
45
47
 
46
48
  ```
47
- search_capsules(filter: {title: {eq: 'Annual Leave Accrual — FY2025'}})
49
+ search_capsules(filter: {title: {eq: 'Annual Leave Accrual, FY2025'}})
48
50
  ```
49
51
 
50
52
  If returns: halt. One leave capsule per FY.
51
53
 
52
- ### Step 1A: Cross-check (calculator)
54
+ ### Step 1A: Calculate
53
55
 
54
56
  ```
55
- clio calc leave-accrual --employees 20 --days 14 --daily-rate 300 --periods 12 --start-date 2025-01-01 --currency SGD --json
56
- ```
57
-
58
- Returns: `{ totalAnnualCost: 84000, perPeriodAmount: 7000, schedule: [{period: 1, accrualDate: '2025-01-31', accrualAmount: 7000, journal: {...}}, ...12] }`. `daily-rate` should be average daily compensation rate (annual salary / 260 working days).
59
-
60
- ### Step 2A: Plan + execute
61
-
62
- ```
63
- plan_recipe(
64
- // Accounts, capsule and counterparty are not plan_recipe params: execute_recipe resolves accounts from the CoA and takes bankAccountName / contactName.
65
- recipe: 'leave-accrual',
57
+ calculate(
58
+ type: 'leave-accrual',
66
59
  employees: 20,
67
60
  daysPerYear: 14,
68
61
  dailyRate: 300,
69
62
  periods: 12,
70
- startDate: '2025-01-01',
63
+ startDate: '2025-01-31',
71
64
  currency: 'SGD'
72
65
  )
73
- execute_recipe(recipe: 'leave-accrual', ...same args...) // accounts auto-resolved from CoA; pass `bankAccountName` / `contactName` for fuzzy resolve
74
66
  ```
75
67
 
76
- Engine emits **12 future-dated DRAFT journals** (one per month, fixed $7,000 each: Dr Leave Expense / Cr Leave Liability).
68
+ ```
69
+ clio calc leave-accrual --employees 20 --days 14 --daily-rate 300 --periods 12 --start-date 2025-01-31 --currency SGD --json
70
+ ```
71
+
72
+ Returns: `{ totalAnnualCost: 84000, periodAccrual: 7000, schedule: [{ period: 1, date: '2025-01-31', accrual: 7000, cumulativeBalance: 7000, journal }, ...12], blueprint }`. `dailyRate` should be the average daily compensation rate (annual salary / 260 working days). The first accrual is dated ON the start date, so pass the first month-end.
73
+
74
+ `blueprint.steps`: 12 `journal` steps, one per month: Dr Leave Expense 7,000 / Cr Accrued Leave Liability 7,000.
75
+
76
+ ### Step 2A: Resolve accounts and create the capsule
77
+
78
+ Map the labels `Leave Expense` and `Accrued Leave Liability` to real accounts with `search_accounts` (create with `create_account` if missing: expense → `Operating Expense`; liability → `Current Liability`). Then:
79
+
80
+ ```
81
+ list_capsule_types()
82
+ create_capsule(
83
+ capsuleTypeResourceId: <id of 'Employee Benefits'>,
84
+ title: 'Annual Leave Accrual, FY2025',
85
+ description: <blueprint.capsuleDescription>
86
+ )
87
+ ```
88
+
89
+ If `Employee Benefits` is not in the list: `create_capsule_type(displayName: 'Employee Benefits')` first.
90
+
91
+ ### Step 3A: Post the accruals
92
+
93
+ The amount is the same every month, so one schedule replaces the twelve journals:
94
+
95
+ ```
96
+ create_scheduled_journal(
97
+ startDate: '2025-01-31',
98
+ endDate: '2025-12-31',
99
+ repeat: 'MONTHLY',
100
+ valueDate: '2025-01-31',
101
+ reference: 'LEAVE-FY2025',
102
+ schedulerEntries: [
103
+ { accountResourceId: <Leave Expense>, type: 'DEBIT', amount: 7000, description: 'Leave accrual: {{MONTH_NAME}} {{YEAR}}' },
104
+ { accountResourceId: <Leave Liability>, type: 'CREDIT', amount: 7000, description: 'Leave accrual: {{MONTH_NAME}} {{YEAR}}' }
105
+ ],
106
+ capsuleResourceId: <capsule id>
107
+ )
108
+ ```
109
+
110
+ Read `building-blocks.md` § "Same amount every period" for the schedule's limits (fixed amount, so if the final period differs by a rounding cent end the schedule one period early and post the last journal by hand). With `capsuleResourceId` on the schedule, every journal it generates lands in the capsule. The alternative is one `create_journal` per blueprint step, each with `valueDate` = the step date, a findable `reference` (`LEAVE-FY2025-01` ...) and `capsuleResourceId`.
77
111
 
78
- ### Step 5A: Monthly action
112
+ ### Step 4A: Monthly action
113
+
114
+ With a schedule, confirm the month's journal posted. With dated draft journals, find this month's by its reference and finalize it:
79
115
 
80
116
  ```
81
- **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.
117
+ search_journals(filter: {reference: {eq: 'LEAVE-FY2025-03'}})
82
118
  update_journal(resourceId: <journal id>, saveAsDraft: false)
83
119
  ```
84
120
 
121
+ Journals cannot be filtered by capsule, and a date-plus-status search returns every matching DRAFT in the org: never feed one into `bulk_update_journals` or `delete_journal`.
122
+
85
123
  When an employee actually takes leave:
86
124
  - Manual journal: Dr Leave Liability / Cr Cash (or Salary Payable) for the days × daily-rate. This RELEASES the accrued obligation.
87
- - The leave-accrual recipe does NOT track per-employee balances; that's HR/payroll system territory. The recipe maintains the company-level liability.
125
+ - The leave-accrual calculator does NOT track per-employee balances; that's HR/payroll system territory. The recipe maintains the company-level liability.
88
126
 
89
127
  Year-end true-up: see `year-end-close.md` Y2a. Compare actual unused-leave-balance × daily-rate per employee at FY-end vs the cumulative accrued. Post adjustment journal for the delta.
90
128
 
91
129
  ---
92
130
 
93
- ## Pattern B: Quarterly/annual bonus accrual (engine: `accrued-expense`)
131
+ ## Pattern B: Quarterly/annual bonus accrual (calculator: `accrued-expense`)
94
132
 
95
133
  ### Step 0B: Idempotency check
96
134
 
97
135
  ```
98
- search_capsules(filter: {title: {startWith: 'Bonus Accrual — Q'}})
136
+ search_capsules(filter: {title: {startWith: 'Bonus Accrual, Q'}})
99
137
  ```
100
138
 
101
139
  If a current-quarter result returns: halt. One bonus capsule per quarter.
102
140
 
103
- ### Step 1B: Cross-check + estimate
141
+ ### Step 1B: Estimate + calculate
104
142
 
105
143
  Estimate quarterly bonus per the entity's bonus policy estimation method:
106
144
  - `revenue_pct` (e.g., 5% of quarterly revenue): pull `generate_profit_and_loss(startDate: <quarter-start>, endDate: <quarter-end>)`, multiply Operating Revenue by the percentage.
107
- - `prior_quarter`: pull last quarter's posted bonus journal via `search_journals(filter: {tags: {eq: 'bonus-accrual'}, valueDate: <prior-quarter>-end})`.
145
+ - `prior_quarter`: pull last quarter's posted bonus journal via `search_journals` on its reference.
108
146
  - `fixed_amount`: use the bonus policy's fixed amount per quarter.
109
147
 
110
148
  ```
111
- clio calc accrued-expense --amount <est> --periods 1 --start-date 2025-03-31 --json
112
- ```
113
-
114
- ### Step 2B: Plan + execute
115
-
116
- ```
117
- plan_recipe(
118
- // Accounts, capsule and counterparty are not plan_recipe params: execute_recipe resolves accounts from the CoA and takes bankAccountName / contactName.
119
- recipe: 'accrued-expense',
149
+ calculate(
150
+ type: 'accrued-expense',
120
151
  amount: <est>,
121
152
  periods: 1,
122
153
  startDate: '2025-03-31',
123
154
  currency: 'SGD'
124
155
  )
125
- execute_recipe(recipe: 'accrued-expense', ...)
126
156
  ```
127
157
 
128
- Engine emits 2 journals: accrual (Mar 31) + reversal (Apr 1). Mirror Q2 / Q3 / Q4.
158
+ ```
159
+ clio calc accrued-expense --amount <est> --periods 1 --start-date 2025-03-31 --json
160
+ ```
161
+
162
+ Returns the accrual (dated `2025-03-31`) and its reversal (the calculator dates it one month on; post it on the first day of the next quarter, `2025-04-01`).
163
+
164
+ ### Step 2B: Capsule + post
165
+
166
+ Create a `Bonus Accrual, Q1 2025` capsule under `Employee Benefits`, then post the pair with `create_journal`, exactly as in `accrued-expenses.md` step 4: the accrual (Dr Bonus Expense / Cr Bonus Payable) on Mar 31, the reversal as a DRAFT dated Apr 1. Mirror for Q2 / Q3 / Q4.
129
167
 
130
- ### Step 5B: Quarterly action
168
+ ### Step 3B: Quarterly action
131
169
 
132
170
  Per quarter-end-close (`quarter-end-close.md`):
133
- - Finalize this quarter's accrual DRAFT (in March).
171
+ - Post this quarter's accrual (in March).
134
172
  - April's monthly-close finalizes the reversal DRAFT.
135
- - Create the next quarter's accrual capsule + execute.
173
+ - Create the next quarter's accrual capsule and post its pair.
136
174
 
137
175
  ### Year-end true-up
138
176
 
@@ -140,26 +178,26 @@ Per quarter-end-close (`quarter-end-close.md`):
140
178
 
141
179
  ---
142
180
 
143
- ## Common error classes and recovery
181
+ ## Common problems and recovery
144
182
 
145
- | Source | Error | Recovery |
183
+ | Where | Problem | Recovery |
146
184
  |--------|-------|----------|
147
- | `plan_recipe` (leave) | 422 `unsupported_recipe` | Use canonical engine name `leave-accrual` (file alias `employee-accruals` covers BOTH leave and bonus). |
148
- | `plan_recipe` (bonus) | 422 `unsupported_recipe` | Use `accrued-expense` for bonus; leave is `leave-accrual`. |
149
- | `execute_recipe` | 422 `account_not_found` | Step 3 incomplete. Common gap: `Bonus Payable` (most CoAs lack); create via `create_account(name: 'Bonus Payable', code: <unused account code>, accountType: 'Current Liability')`. |
150
- | 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. |
151
- | Verification | Bonus accrual nonzero after quarterly reversal posts | Reversal didn't finalize. Identify the reversal journal (journals cannot be filtered by capsule: check each candidate with `get_journal` (its `capsule.resourceId`) and confirm the set with the practitioner), then finalize it with `update_journal(resourceId, saveAsDraft: false)`. |
152
- | 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. |
185
+ | Calculator (leave) | "Employees must be a positive number" / "Days per year must be a positive number" | Fix the input. The CLI flags are `--employees` and `--days`; the MCP params are `employees` and `daysPerYear`. |
186
+ | Calculator | Wrong calculator for the benefit | Leave is `leave-accrual` (no reversal); bonus is `accrued-expense` (accrual + reversal). |
187
+ | Account resolution | An account is missing | Common gap: `Bonus Payable` (most CoAs lack); create via `create_account(name: 'Bonus Payable', code: <unused account code>, accountType: 'Current Liability')`. |
188
+ | Verification | Leave Liability balance > expected | Practitioner posted manual leave-utilization journals against the wrong account, OR the original estimate was high. Year-end Y2a true-up will catch this. |
189
+ | Verification | Bonus accrual nonzero after quarterly reversal posts | Reversal didn't finalize. Find the reversal journal by its reference (journals cannot be filtered by capsule), then finalize it with `update_journal(resourceId, saveAsDraft: false)`. |
190
+ | 13th-month bonus (PH-specific) | (process, separate from Q4 bonus) | Accrue `<annual base / 12>` each month throughout the FY (Dr 13th Month Expense / Cr Bonus Payable) with NO reversal, since the obligation accumulates: a monthly `create_scheduled_journal` fits. Settle in December via Dr Bonus Payable / Cr Cash. |
153
191
 
154
192
  ---
155
193
 
156
194
  ## Variations
157
195
 
158
- - **Profit-share bonus** (% of net profit, declared post-audit): NOT this recipe. Mirror `dividend` recipe pattern: declaration journal + payment cash-out at year-end after audit closes.
159
- - **PH 13th-month pay**: monthly accrual via `accrued-expense` recipe (`amount: <annual base / 12>`, `periods: 12`). Mandatory by Philippine law (PD 851). Settle in December.
160
- - **Long-term employee benefits** (gratuity, severance, post-employment benefits): NOT supported by these engines. Per IAS 19.55-58, requires actuarial valuation. Manual journals only; consider hiring an actuary.
196
+ - **Profit-share bonus** (% of net profit, declared post-audit): NOT this recipe. Mirror the `dividend.md` pattern: declaration journal + payment cash-out at year-end after audit closes.
197
+ - **PH 13th-month pay**: monthly accrual of `<annual base / 12>` with no reversal (see the problems table). Mandatory by Philippine law (PD 851). Settle in December.
198
+ - **Long-term employee benefits** (gratuity, severance, post-employment benefits): NOT supported by these calculators. Per IAS 19.55-58, requires actuarial valuation. Manual journals only; consider hiring an actuary.
161
199
  - **Stock-based compensation**: NOT supported. IFRS 2 (separate accounting model). Manual journals only.
162
- - **Multi-currency leave** (employees paid in different currencies): one leave capsule per currency. Each gets its own recipe invocation.
200
+ - **Multi-currency leave** (employees paid in different currencies): one leave capsule per currency. Each gets its own calculation.
163
201
 
164
202
  ---
165
203
 
@@ -167,4 +205,4 @@ Per quarter-end-close (`quarter-end-close.md`):
167
205
 
168
206
  - Month-end close: monthly leave-accrual finalize per existing leave capsule.
169
207
  - Year-end close (Y2 in `year-end-close.md`): both leave and bonus true-ups against actuals; transition from accrual to actual cash payment in early Q1 next FY. (No quarterly bonus-accrual step; true-up runs annually only.)
170
- - Sibling `accrued-expenses.md`: the engine that drives the bonus pattern; full error table + variations there.
208
+ - Sibling `accrued-expenses.md`: the calculator that drives the bonus pattern; full problems table + variations there.