RESEARCH: Money plugin — YNAB + Actual Budget deep study, envelope maths, import formats, polish gaps (NO implementation) #316

Closed
opened 2026-09-28 08:12:00 +00:00 by kayg · 8 comments
Owner

Owner (2026-09-28): 'we also need to add an actualbudget/ynab like "Money" plugin which lets users manage their own money via a zero-budget / envelope approach… it should have the versatility of Actual Budget, ease of use of YNAB and our own aesthetics / polish / finesse… since numbers can get really nasty if miscalculated, i want you to run more reviews than usual for this module.' The owner used YNAB 2022–2026 ('it changed my financial life'), then switched to Actual Budget ('a great product but lacks finesse'). No bank sync (manual entry and file import only; iOS Shortcuts later). The orchestrator is grilling the owner in parallel; this research supplies the facts.

Research (primary sources: YNAB help docs and API docs, Actual Budget docs and its open-source code at github.com/actualbudget/actual, community forums, reviews):

  1. The envelope maths, exactly. YNAB: Ready to Assign, assigned/activity/available, month rollover, overspending (cash vs credit: cash overspending reduces next month's Ready to Assign; credit overspending becomes debt), credit card payment categories and how card spending moves money, returns and refunds, split transactions, transfers (budget vs tracking accounts), tracking accounts and net worth, income for next month, 'age of money', targets/goals (all types and how 'underfunded' is computed), the 'move money' and 'cover overspending' flows, reconciliation, starting balances, and what happens when a past month is edited. Actual: envelope budgeting vs 'tracking budget' (report budget) modes, 'to budget', carryover and rollover overspending flags, hold for next month, templates (goal templates syntax), schedules, rules (conditions and actions), payee management, transfers, off-budget accounts, reconciliation, split transactions, reports and custom reports, multi-currency status, the CRDT sync model. Write each rule as an invariant (for example 'the sum of Available across categories + Ready to Assign = the sum of on-budget account balances − credit card debt not covered'), with worked examples and the known edge cases and bugs from forums and the issue tracker. These invariants become the Money plugin's property tests.
  2. Money correctness engineering. Integer minor units vs decimal types; rounding (splits, currency conversion, percentage targets); currency minor-unit exponents (JPY 0, INR/USD/EUR 2, KWD 3); how Actual stores amounts (integer cents) and dates; timezone and date-only rules; idempotent imports; the audit trail. Rust crates for decimals and money with AGPL-compatible permissive licences. Property-based and differential testing approaches (proptest; differential testing against Actual's own budget engine if its licence allows running it in tests: check Actual's licence, MIT).
  3. Import formats: YNAB (the API export JSON, the CSV register and budget exports, the YNAB 4 legacy format), Actual (export zip / SQLite schema), bank formats (CSV with column mapping, OFX/QFX, QIF, CAMT.053, MT940), and dedup on re-import (Actual's imported_id and fuzzy matching). Indian banks' common CSV/XLS statements are a bonus.
  4. Polish gaps: what users praise in YNAB's UX (the assign flow, keyboard entry, mobile quick entry, the reflect reports, the calm tone) and what they complain about in Actual (search Reddit r/ynab, r/actualbudget, GitHub issues, blog reviews). List concrete finesse opportunities for calternal (DESIGN §34 chrome rules, deep links §33, the composer, Calendar integration, Search).
  5. calternal fit: the 'file over app' principle (the filesystem is the source of truth, databases are only indexes): evaluate plain-text ledger formats (hledger/ledger/beancount journals) as the canonical storage vs a database, and how envelope budgets map onto them (hledger/beancount budgeting and envelope practices, e.g. virtual postings). Performance at 100k transactions. Concurrency with a shared household budget (Groups/Shares).
    Output: docs/research/money-plugin.md (ASD-STE100) with sources, the invariant list, a comparison table, and suggested grill questions (the orchestrator merges them into the live grill). Do NOT implement anything. Commit on the branch, push, and post a summary on this issue.
Owner (2026-09-28): 'we also need to add an actualbudget/ynab like "Money" plugin which lets users manage their own money via a zero-budget / envelope approach… it should have the versatility of Actual Budget, ease of use of YNAB and our own aesthetics / polish / finesse… since numbers can get really nasty if miscalculated, i want you to run more reviews than usual for this module.' The owner used YNAB 2022–2026 ('it changed my financial life'), then switched to Actual Budget ('a great product but lacks finesse'). **No bank sync** (manual entry and file import only; iOS Shortcuts later). The orchestrator is grilling the owner in parallel; this research supplies the facts. Research (primary sources: YNAB help docs and API docs, Actual Budget docs and its open-source code at github.com/actualbudget/actual, community forums, reviews): 1. **The envelope maths, exactly.** YNAB: Ready to Assign, assigned/activity/available, month rollover, overspending (cash vs credit: cash overspending reduces next month's Ready to Assign; credit overspending becomes debt), credit card payment categories and how card spending moves money, returns and refunds, split transactions, transfers (budget vs tracking accounts), tracking accounts and net worth, income for next month, 'age of money', targets/goals (all types and how 'underfunded' is computed), the 'move money' and 'cover overspending' flows, reconciliation, starting balances, and what happens when a past month is edited. Actual: envelope budgeting vs 'tracking budget' (report budget) modes, 'to budget', carryover and rollover overspending flags, hold for next month, templates (goal templates syntax), schedules, rules (conditions and actions), payee management, transfers, off-budget accounts, reconciliation, split transactions, reports and custom reports, multi-currency status, the CRDT sync model. **Write each rule as an invariant** (for example 'the sum of Available across categories + Ready to Assign = the sum of on-budget account balances − credit card debt not covered'), with worked examples and the known edge cases and bugs from forums and the issue tracker. These invariants become the Money plugin's property tests. 2. **Money correctness engineering.** Integer minor units vs decimal types; rounding (splits, currency conversion, percentage targets); currency minor-unit exponents (JPY 0, INR/USD/EUR 2, KWD 3); how Actual stores amounts (integer cents) and dates; timezone and date-only rules; idempotent imports; the audit trail. Rust crates for decimals and money with AGPL-compatible permissive licences. Property-based and differential testing approaches (proptest; differential testing against Actual's own budget engine if its licence allows running it in tests: check Actual's licence, MIT). 3. **Import formats**: YNAB (the API export JSON, the CSV register and budget exports, the YNAB 4 legacy format), Actual (export zip / SQLite schema), bank formats (CSV with column mapping, OFX/QFX, QIF, CAMT.053, MT940), and dedup on re-import (Actual's imported_id and fuzzy matching). Indian banks' common CSV/XLS statements are a bonus. 4. **Polish gaps**: what users praise in YNAB's UX (the assign flow, keyboard entry, mobile quick entry, the reflect reports, the calm tone) and what they complain about in Actual (search Reddit r/ynab, r/actualbudget, GitHub issues, blog reviews). List concrete finesse opportunities for calternal (DESIGN §34 chrome rules, deep links §33, the composer, Calendar integration, Search). 5. **calternal fit**: the 'file over app' principle (the filesystem is the source of truth, databases are only indexes): evaluate plain-text ledger formats (hledger/ledger/beancount journals) as the canonical storage vs a database, and how envelope budgets map onto them (hledger/beancount budgeting and envelope practices, e.g. virtual postings). Performance at 100k transactions. Concurrency with a shared household budget (Groups/Shares). Output: docs/research/money-plugin.md (ASD-STE100) with sources, the invariant list, a comparison table, and suggested grill questions (the orchestrator merges them into the live grill). Do NOT implement anything. Commit on the branch, push, and post a summary on this issue.
Author
Owner

Starting research on branch job/money-research, based on dev at c99fc31dd9. I have read CLAUDE.md, docs/DESIGN.md and CONTEXT.md. Scope: research only; no implementation or builds.

Starting research on branch job/money-research, based on dev at c99fc31dd9e0f542a02956a787010bbf1250384c. I have read CLAUDE.md, docs/DESIGN.md and CONTEXT.md. Scope: research only; no implementation or builds.
Author
Owner

Owner grill round 1 (2026-09-28), verbatim where it matters:

  • What YNAB got right: ease of use. 'There's a very easy and clear way to assign to categories. Categories are relaxed enough that they are easily readable. I can easily see how much assignment there is per month by navigating to that month. I could easily see where my money was being assigned, spent and saved.' Also credit card categories: 'credit cards auto created categories and money moved there automatically. actualbudget really fumbles in both those places.'
  • What YNAB lacks: versatility. 'the views are static… no AI in the product, there are no smart views. i cannot dynamically have "overfunded" categories in a view or a view that is completely arbitrary like overspent thrice in a row.' Actual 'lets me do basically anything! including graphs / analytics where I can even use complex formulas… While we don't need that level of complexity yet, a middle ground would be best.'
  • Automation: Actual has a Node API but no HTTP API. calternal's HTTP API + app passwords lets Windmill, Zapier etc. auto-log transactions or read data. (The owner already runs ~/Developer/money/ynab-auto-log, a Windmill-based auto-logger for YNAB/Actual.)
  • Summary: 'Actualbudget gets versatility right, ynab gets ease of use right.'
  • Q2 model: envelope mode only (no tracking/report budget).
  • Q3 storage: the owner wants plain text; asked to see the ledger format (shown in chat; research must confirm the dialect and the envelope mapping).
  • Q4 currency: B: one budget currency, accounts may hold other currencies, with a per-transaction rate. 'we need to refine this further as visa exchange rate might not be the bank exchange rate. If it ends up too complex, we can go with A.'
  • Q5: C: several budgets per user, then shared budgets with other calternal users (sharing as a later slice).
  • Q6: importers for both YNAB and Actual ('everything is in actualbudget', but both importers are wanted).
  • Q7: B: composer quick entry, Calendar (bills, paydays, day spending), Search, deep links. 'this would be fucking awesome. again, we need more reviews here to not fuck up numbers.'
Owner grill round 1 (2026-09-28), verbatim where it matters: - **What YNAB got right: ease of use.** 'There's a very easy and clear way to assign to categories. Categories are relaxed enough that they are easily readable. I can easily see how much assignment there is per month by navigating to that month. I could easily see where my money was being assigned, spent and saved.' Also **credit card categories**: 'credit cards auto created categories and money moved there automatically. actualbudget really fumbles in both those places.' - **What YNAB lacks: versatility.** 'the views are static… no AI in the product, there are no smart views. i cannot dynamically have "overfunded" categories in a view or a view that is completely arbitrary like overspent thrice in a row.' Actual 'lets me do basically anything! including graphs / analytics where I can even use complex formulas… While we don't need that level of complexity yet, a middle ground would be best.' - **Automation:** Actual has a Node API but no HTTP API. calternal's HTTP API + **app passwords** lets Windmill, Zapier etc. auto-log transactions or read data. (The owner already runs ~/Developer/money/ynab-auto-log, a Windmill-based auto-logger for YNAB/Actual.) - Summary: 'Actualbudget gets versatility right, ynab gets ease of use right.' - Q2 model: **envelope mode only** (no tracking/report budget). - Q3 storage: the owner **wants plain text**; asked to see the ledger format (shown in chat; research must confirm the dialect and the envelope mapping). - Q4 currency: **B**: one budget currency, accounts may hold other currencies, with a per-transaction rate. 'we need to refine this further as visa exchange rate might not be the bank exchange rate. If it ends up too complex, we can go with A.' - Q5: **C**: several budgets per user, then shared budgets with other calternal users (sharing as a later slice). - Q6: **importers for both YNAB and Actual** ('everything is in actualbudget', but both importers are wanted). - Q7: **B**: composer quick entry, Calendar (bills, paydays, day spending), Search, deep links. 'this would be fucking awesome. again, we need more reviews here to not fuck up numbers.'
Author
Owner

Research finding: Actual's engine has two distinct month-boundary policies. Its normal envelope formula carries positive category balances forward, but clears negative balances and subtracts them from the next month's To Budget. A per-category rollover flag carries a negative balance instead. The same source has a separate tracking-budget formula. YNAB's current help documents the same cash-versus-credit overspending split, while its exact target funding calculation is not fully specified in public docs; the note will state that gap and use fixtures/differential properties rather than invent a formula. I am pinning Actual code links to the reviewed source commit 24deae74e653fca34e0057a30427cfe9939332ab.

Research finding: Actual's engine has two distinct month-boundary policies. Its normal envelope formula carries positive category balances forward, but clears negative balances and subtracts them from the next month's To Budget. A per-category rollover flag carries a negative balance instead. The same source has a separate tracking-budget formula. YNAB's current help documents the same cash-versus-credit overspending split, while its exact target funding calculation is not fully specified in public docs; the note will state that gap and use fixtures/differential properties rather than invent a formula. I am pinning Actual code links to the reviewed source commit 24deae74e653fca34e0057a30427cfe9939332ab.
Author
Owner

Owner grill round 2 (2026-09-28):

  • Q3b: hledger-compatible plain text (accounts.journal, per-month transaction journals, budget.journal with virtual [Budget:…] assignment postings, @@ total price for foreign-currency charges, a stable id: per transaction, exact decimals parsed into integer minor units).
  • Q8: B. Smart views = saved searches/smart folders over categories and transactions. 'make the syntax extremely simple and stupid.' Pre-made views + user views, deep-linkable. Formulas later only if missed.
  • Q9: A (auto-categorise from own history, local) + C (nudges) first; Ask later; receipts later. Plus: 'i should be able to attach anything to a transaction' (see below).
  • Q10: B. YNAB credit card payment categories + a visible 'debt not covered: ₹X' + one-tap cover. 'we need to make it easier whenever we find UX holes.'
  • Q11: A, simplified; no user-written target syntax ('manually writing syntax here buys nothing'). The orchestrator proposes a simpler target model in the next round.
  • Q12: HTTP API with Money-scoped app passwords, in the first release. The owner asks about the state of the existing API/MCP/WebMCP and CalDAV (answered in chat).
    Attachments (Q9 follow-up): transactions may carry any attachments (receipts, invoices, PDFs, photos). Proposal: the files live in Home (normal Files items, deduplicated), and the journal references them by stable calternal ID, not by path, via an hledger tag: ; attach:cid-01J… (several allowed). Renames and moves never break the link; hledger ignores the tag, and calternal resolves it.
Owner grill round 2 (2026-09-28): - Q3b: **hledger-compatible plain text** (accounts.journal, per-month transaction journals, budget.journal with virtual [Budget:…] assignment postings, `@@` total price for foreign-currency charges, a stable `id:` per transaction, exact decimals parsed into integer minor units). - Q8: **B**. Smart views = saved searches/smart folders over categories and transactions. **'make the syntax extremely simple and stupid.'** Pre-made views + user views, deep-linkable. Formulas later only if missed. - Q9: **A (auto-categorise from own history, local) + C (nudges) first**; Ask later; receipts later. Plus: **'i should be able to attach anything to a transaction'** (see below). - Q10: **B**. YNAB credit card payment categories + a visible 'debt not covered: ₹X' + one-tap cover. 'we need to make it easier whenever we find UX holes.' - Q11: **A, simplified; no user-written target syntax** ('manually writing syntax here buys nothing'). The orchestrator proposes a simpler target model in the next round. - Q12: **HTTP API with Money-scoped app passwords, in the first release.** The owner asks about the state of the existing API/MCP/WebMCP and CalDAV (answered in chat). Attachments (Q9 follow-up): transactions may carry **any attachments** (receipts, invoices, PDFs, photos). Proposal: the files live in Home (normal Files items, deduplicated), and the journal references them by **stable calternal ID**, not by path, via an hledger tag: `; attach:cid-01J…` (several allowed). Renames and moves never break the link; hledger ignores the tag, and calternal resolves it.
Author
Owner

Additional finding: Actual's official credit-card docs distinguish it from YNAB. A normally paid-in-full card is an on-budget account with a negative balance; Actual does not create YNAB-style automatic payment categories for that path. Its separate carried-debt workflow uses a “Card Debt” category with rollover overspending because the card liability is already reflected in on-budget funds. I added this distinction and a no-double-counting property. YNAB's current Underfunded help also publishes an explicit priority order; the note records that order and marks overlap/tie details as requiring frozen differential fixtures.

Additional finding: Actual's official credit-card docs distinguish it from YNAB. A normally paid-in-full card is an on-budget account with a negative balance; Actual does not create YNAB-style automatic payment categories for that path. Its separate carried-debt workflow uses a “Card Debt” category with rollover overspending because the card liability is already reflected in on-budget funds. I added this distinction and a no-double-counting property. YNAB's current Underfunded help also publishes an explicit priority order; the note records that order and marks overlap/tie details as requiring frozen differential fixtures.
Author
Owner

Finished research-only work on job/money-research.

  • Head: 0ca22426ea0ac4186819d582d70128d95169674e (pushed to origin).
  • Built: docs/research/money-plugin.md with YNAB and Actual rules, 34 property-test invariants and examples, import-format findings, Rust money crate versions/licenses, UX evidence, calternal fit, and owner questions.
  • No implementation, tests, or builds were added or run.

Key findings:

  • YNAB and Actual differ in cash and credit overspending, month rollover, and card-payment modeling. YNAB uses a special payment category; Actual's normal paid-in-full card is a negative on-budget account. Its carried-debt guide uses a separate rollover category to prevent double-counting.
  • The note records Actual's pinned envelope and tracking formulas, import/dedup behavior, transfer pairing, and cell-level last-write-wins sync.
  • YNAB's published Underfunded priority order and current target behaviors are recorded. Public docs leave overlap and tie details open; the report calls for frozen differential fixtures.

Decisions to confirm because DESIGN does not settle them: one currency per ledger; the canonical envelope and card-debt rules; the exact target set and compatibility goal; a versioned User-owned JSON ledger with hledger as an import/export adapter; and whether household editing uses a Share on one User's Home item. These are recommendations in the note, not approved product decisions.

Gate output: cargo fmt, clippy, Rust tests, and web checks were NOT RUN because this issue is research-only and forbids builds. git diff --cached --check produced no output and exited 0 before commit. cargo clean output: Removed 0 files.

Finished research-only work on `job/money-research`. - Head: `0ca22426ea0ac4186819d582d70128d95169674e` (pushed to origin). - Built: `docs/research/money-plugin.md` with YNAB and Actual rules, 34 property-test invariants and examples, import-format findings, Rust money crate versions/licenses, UX evidence, calternal fit, and owner questions. - No implementation, tests, or builds were added or run. Key findings: - YNAB and Actual differ in cash and credit overspending, month rollover, and card-payment modeling. YNAB uses a special payment category; Actual's normal paid-in-full card is a negative on-budget account. Its carried-debt guide uses a separate rollover category to prevent double-counting. - The note records Actual's pinned envelope and tracking formulas, import/dedup behavior, transfer pairing, and cell-level last-write-wins sync. - YNAB's published Underfunded priority order and current target behaviors are recorded. Public docs leave overlap and tie details open; the report calls for frozen differential fixtures. Decisions to confirm because DESIGN does not settle them: one currency per ledger; the canonical envelope and card-debt rules; the exact target set and compatibility goal; a versioned User-owned JSON ledger with hledger as an import/export adapter; and whether household editing uses a Share on one User's Home item. These are recommendations in the note, not approved product decisions. Gate output: cargo fmt, clippy, Rust tests, and web checks were NOT RUN because this issue is research-only and forbids builds. `git diff --cached --check` produced no output and exited 0 before commit. `cargo clean` output: `Removed 0 files`.
Author
Owner

Owner grill rounds 3 and 3b (2026-09-28):

  • R1: the owner asks: 'can't we invent our own plaintext format? and don't you mean hledger superset if it does not support certain features we want?' Yes, superset is the right word. Orchestrator proposal (to confirm): a calternal ledger dialect that is a strict superset of hledger journal syntax. Every calternal file stays a valid hledger file; the extra meaning (targets, assignment metadata, card payment links, ids, attachments) rides on hledger-tolerated syntax (comment tags, virtual postings, directives hledger ignores). hledger reads the ledger, calternal reads everything, and a round-trip test proves it is lossless. The alternative is a fully custom format.
  • Q11b targets: agreed (three kinds, sentence input, suggestions, 'Assign underfunded', snooze, refill vs set-aside).
  • R2: A: manual-balance off-budget accounts + net worth; holdings/prices later.
  • R3: delayed. The owner will provide bank statement PDFs later; CSV/OFX/QIF mapping waits for them.
  • R4: A: exact duplicates auto-link with an undo badge; fuzzy = suggestion; reconciled rows are never changed by an import.
  • R5: agreed: YNAB reconciliation flow (adjustment to Ready to Assign, lock through the date, one-line explanation).
  • R6: agreed: calternal 'days of buffer' + YNAB Age of Money in reports.
  • R7: agreed: payee memory in Money; real rules via Automations (#296).
  • R8: agreed: YNAB layout + sidebar accounts and smart views + ⌘I category inspector + number-key assignment + Copy link everywhere.
  • R9: the phone is a full-fledged client, with a phone-specific UX (not a reduced one): Spend-first home, category cards, full budgeting also possible on the phone.
  • R10: A: scheduled transactions wait for one-tap Approve (Money + Calendar day view); per-schedule auto-enter opt-in.
  • R11: agreed: YNAB split/transfer rules exactly, each with its own break-the-numbers test.
  • R12: owner: 'Don't we have version control already? Would it be that hard to maintain history and version control for money too?' Answer: no. Money files get calternal's existing file versions (.calternal/versions) for free, and every mutation also writes a structured change-log entry (who/what/when, the ids touched), so the History panel can revert any single past step (only that step's changes, with a conflict check) across sessions.
  • R13: both: sidebar switcher + each budget is a folder in Files (Money//) with Copy link/Share/backups.
  • R14: A: composer auto-detects money intent as a rejectable chip. Owner: 'our NLP needs to be god-tier at recognizing intent'. The Money NLP gets its own intent test corpus (amounts in ₹/k/L/lakh/crore, currencies, payees, accounts, categories, ambiguity like '450 steps') with precision/recall targets.
Owner grill rounds 3 and 3b (2026-09-28): - R1: the owner asks: 'can't we invent our own plaintext format? and don't you mean hledger **superset** if it does not support certain features we want?' Yes, superset is the right word. Orchestrator proposal (to confirm): a **calternal ledger dialect that is a strict superset of hledger journal syntax**. Every calternal file stays a valid hledger file; the extra meaning (targets, assignment metadata, card payment links, ids, attachments) rides on hledger-tolerated syntax (comment tags, virtual postings, directives hledger ignores). hledger reads the ledger, calternal reads everything, and a round-trip test proves it is lossless. The alternative is a fully custom format. - Q11b targets: **agreed** (three kinds, sentence input, suggestions, 'Assign underfunded', snooze, refill vs set-aside). - R2: **A**: manual-balance off-budget accounts + net worth; holdings/prices later. - R3: **delayed**. The owner will provide bank statement PDFs later; CSV/OFX/QIF mapping waits for them. - R4: **A**: exact duplicates auto-link with an undo badge; fuzzy = suggestion; reconciled rows are never changed by an import. - R5: **agreed**: YNAB reconciliation flow (adjustment to Ready to Assign, lock through the date, one-line explanation). - R6: **agreed**: calternal 'days of buffer' + YNAB Age of Money in reports. - R7: **agreed**: payee memory in Money; real rules via Automations (#296). - R8: **agreed**: YNAB layout + sidebar accounts and smart views + ⌘I category inspector + number-key assignment + Copy link everywhere. - R9: **the phone is a full-fledged client, with a phone-specific UX** (not a reduced one): Spend-first home, category cards, full budgeting also possible on the phone. - R10: **A**: scheduled transactions wait for one-tap Approve (Money + Calendar day view); per-schedule auto-enter opt-in. - R11: **agreed**: YNAB split/transfer rules exactly, each with its own break-the-numbers test. - R12: owner: 'Don't we have version control already? Would it be that hard to maintain history and version control for money too?' Answer: no. Money files get calternal's existing file versions (.calternal/versions) for free, and every mutation also writes a structured change-log entry (who/what/when, the ids touched), so the History panel can revert any single past step (only that step's changes, with a conflict check) across sessions. - R13: **both**: sidebar switcher + each budget is a folder in Files (Money/<Budget>/) with Copy link/Share/backups. - R14: **A**: composer auto-detects money intent as a rejectable chip. Owner: 'our NLP needs to be god-tier at recognizing intent'. The Money NLP gets its own intent test corpus (amounts in ₹/k/L/lakh/crore, currencies, payees, accounts, categories, ambiguity like '450 steps') with precision/recall targets.
Author
Owner

Research complete in ebc5d5f10 (origin/dev); the requested Money study and findings are recorded in the merged report.

Research complete in `ebc5d5f10` (origin/dev); the requested Money study and findings are recorded in the merged report.
kayg closed this issue 2026-10-03 11:55:40 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#316
No description provided.