5.1 KiB
5.1 KiB
Tasks: enterprise-money
Change ID: enterprise-money
Package: @suaveplan/money
Target path: finance/currency/money
Prerequisites on Verdaccio: @suaveplan/error, zod
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create full directory tree per
proposal.md. package.jsonat0.1.0,"sideEffects": false, exports"."+core/money+core/currency-registry+core/currencies+core/money-range+formatting+allocation+schemas+serialization.- Deps:
@suaveplan/error workspace:^,zod catalog:forms,tslib catalog:build. - DevDeps:
vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,fast-check catalog:testing,@suaveplan/testing workspace:^. tsconfig.jsonextendinglibrary.json;vitest.config.tswithcreateTestConfig().- Scripts:
lint,typecheck,test,test:coverage,build,docs:check.
2. Error hierarchy
src/error-codes.ts: defineMoneyErrorCodeunion; implementMoneyError,CurrencyMismatchError,UnknownCurrencyError,AllocationError,ParseErrorextendingSuaveplanError;registerMoneyErrorCodes(); eager call.
3. Currency registry + ISO data
- Implement
CurrencyRegistryinsrc/core/currency-registry/currency-registry.ts: internalMap<string, CurrencyInfo>; all methods per API surface. src/core/currencies/currencies.ts: ISO 4217 data (≥50 common currencies minimum, full list preferred); seed the globalCurrencyRegistry.global()on module load.- Write tests: register/get/virtual/multiplier;
getCurrencyOrThrowthrowsUnknownCurrencyError; virtual vs ISO separation.
4. Money class
- Implement
Moneyinsrc/core/money/money.ts:fromMajor(value, currency, registry?): useBigInt(Math.round(Number(value) * Number(multiplier)))for number; use exact decimal-string parse for string inputs (no float intermediate).- All arithmetic: BigInt operations; throw
CurrencyMismatchErroron mismatched currencies. toDecimalString(): format as exact decimal (e.g."12.34"for USD with 2 minor units).toJSON()/Money.withRegistry(registry).- Negative-zero guard: ensure
0nnever becomes-0n.
- Write
money.test.ts(≤500 lines): all operators, edge cases, currency mismatch, negative-zero, decimal-string round-trip.
5. Formatting + parse
- Implement
formatMoney,formatMoneyCompact,parseMoneyinsrc/formatting/formatter/formatter.ts. parseMoney: handle comma decimals, grouped separators, currency symbol removal viaIntl.NumberFormat.- Write
formatter.test.ts: multiple locales, compact, parseMoney round-trip.
6. Allocation
- Implement all five allocators +
sumMoney+minMoney+maxMoney+applyRoundinginsrc/allocation/allocator/allocator.ts. - Remainder redistribution: no minor unit lost or invented.
- Write
allocator.test.ts: even/ratio/percentage edge cases, remainder, sum invariant.
7. MoneyRange
- Implement
MoneyRangeinsrc/core/money-range/money-range.ts: constructor validatesmin <= max; all methods per API surface. - Write
money-range.test.ts: contains, intersect (null on no overlap), union, toArray.
8. Zod schemas + serialization
- Implement
MoneyLikeSchema,CurrencyCodeSchema,FormatOptionsSchemainsrc/schemas/money-schemas/money-schemas.ts. - Implement
moneyToJSON/moneyFromJSONinsrc/serialization/json/json.ts. - Write tests for each.
9. Property-based tests
tests/property.test.ts(fast-check,{ timeout: 30000 }):a + b - b = afor arbitrary same-currencyMoneypairs.allocateEvenly(m, n)sums tom.allocateByRatios(m, rs)sums tom.toDecimalStringround-trip identity.parseMoney(formatMoney(m, locale), m.currency, locale)equalsmfor common locales.MoneyRangeintersectis commutative and associative on overlapping ranges.
10. Docs + verify + publish
- All
.mdfiles per layout; rootREADME.mdwith arithmetic quick-start, allocation example, MoneyRange, API table. bunx turbo lint --filter=@suaveplan/money— zero errors.bunx turbo typecheck --filter=@suaveplan/money— zero errors.bunx turbo test --filter=@suaveplan/money— all pass.bunx turbo test:coverage --filter=@suaveplan/money— 100%.bun scripts/publish.ts --package @suaveplan/money.- Update
CLAUDE.md; archive toopenspec/archive/2026-04-24-enterprise-money/.