Money format per budget (currency-based) and one shared amount input #1180

Open
opened 2026-10-06 05:04:31 +00:00 by kayg · 10 comments
Owner

Owner decisions (grill, 2026-10-06): Money format per budget + one amount input

Money format belongs to the budget

  • Each budget stores a money format: decimal separator, grouping separator and grouping style (3-digit, Indian lakh 2-digit after the first 3, Swiss apostrophe), symbol and its position/spacing, and minor-unit digits (ISO 4217: JPY 0, BHD/KWD 3, most 2).
  • Default from the currency's home convention (CLDR locale for the currency's primary region): INR → ₹12,34,567.89; JPY → ¥1,234,567; CHF → CHF 1'234.56; GBP → £1,234.56; USD → $1,234.56. Currencies used in many regions (EUR and others): use the User's region style when the User's region uses that currency, else a sensible default (EUR → 1.234,56 €).
  • One-tap override in the import wizard / Create budget step and Budget settings, with a live sample amount in each style (choose by sight).
  • Applies to every Money amount (display and input, exports, Analytics money values for that budget). Dates and other numbers elsewhere keep the device locale.
  • Stored in the budget's existing metadata (money/1 frontmatter) with an upgrade test; existing budgets get the default for their currency.

Typing amounts

  • One shared amount input for every Money amount field (assign, transactions, balances, targets): use the Numora core library (framework-agnostic package, not the React integration) configured from the budget format.
  • Parse in the budget's format with one forgiving rule: a single separator followed by exactly the currency's minor digits is the decimal point ("12.50" in a comma-decimal budget = 12,50), shown as a preview before commit; genuinely ambiguous input follows the budget format.
  • Live counters (Ready to assign, Available) animate value changes with Torph (already a dependency, 0.1.3); reduced motion respected.

Evidence

Property tests: format → parse round-trips for every supported style and minor-unit count; no float arithmetic (integer minor units end to end). Money numbers review before merge. Screenshots of the format picker and amounts in INR, EUR, CHF, JPY, BHD at 390/1440, light + dark.

## Owner decisions (grill, 2026-10-06): Money format per budget + one amount input ### Money format belongs to the budget - Each budget stores a money format: decimal separator, grouping separator and grouping style (3-digit, Indian lakh 2-digit after the first 3, Swiss apostrophe), symbol and its position/spacing, and minor-unit digits (ISO 4217: JPY 0, BHD/KWD 3, most 2). - Default from the currency's home convention (CLDR locale for the currency's primary region): INR → ₹12,34,567.89; JPY → ¥1,234,567; CHF → CHF 1'234.56; GBP → £1,234.56; USD → $1,234.56. Currencies used in many regions (EUR and others): use the User's region style when the User's region uses that currency, else a sensible default (EUR → 1.234,56 €). - One-tap override in the import wizard / Create budget step and Budget settings, with a live sample amount in each style (choose by sight). - Applies to every Money amount (display and input, exports, Analytics money values for that budget). Dates and other numbers elsewhere keep the device locale. - Stored in the budget's existing metadata (money/1 frontmatter) with an upgrade test; existing budgets get the default for their currency. ### Typing amounts - One shared amount input for every Money amount field (assign, transactions, balances, targets): use the Numora core library (framework-agnostic package, not the React integration) configured from the budget format. - Parse in the budget's format with one forgiving rule: a single separator followed by exactly the currency's minor digits is the decimal point ("12.50" in a comma-decimal budget = 12,50), shown as a preview before commit; genuinely ambiguous input follows the budget format. - Live counters (Ready to assign, Available) animate value changes with Torph (already a dependency, 0.1.3); reduced motion respected. ### Evidence Property tests: format → parse round-trips for every supported style and minor-unit count; no float arithmetic (integer minor units end to end). Money numbers review before merge. Screenshots of the format picker and amounts in INR, EUR, CHF, JPY, BHD at 390/1440, light + dark.
Author
Owner

Starting job/moneyfmt-1180 from d0061ec3d (origin/dev at worktree start). The resumed worktree is clean; I am tracing the existing money display/input paths before implementing the issue's shared format model and amount entry.

Starting `job/moneyfmt-1180` from `d0061ec3d` (origin/dev at worktree start). The resumed worktree is clean; I am tracing the existing money display/input paths before implementing the issue's shared format model and amount entry.
Author
Owner

Finished work — job/moneyfmt-1180

Head: 7cdc7ad034f4ae00e453e77dcf01f0bc0620c7a5

Built

  • Added six stable Budget money conventions and currency-based defaults for INR, JPY, CHF, GBP, EUR and other currencies.
  • Added Budget-style format and parse helpers. Amounts remain integer minor units; the existing parser remains the exact conversion path.
  • Added round-trip coverage for every convention against supported currency scales, plus explicit INR, EUR, CHF and JPY examples.

Files: apps/web/src/lib/money/amount.ts, apps/web/src/lib/money/amount.test.ts.

Gate output

Focused test:

 Test Files  1 passed (1)
      Tests  10 passed (10)

bun run check:

perf-lint: PASS; 0 violations; 22104 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
svelte-check found 0 errors and 4 warnings in 3 files

bun run test:

 Test Files  266 passed (266)
      Tests  1832 passed (1832)
   Duration  279.55s (environment 28%, transform 28%, import 22%, tests 16%, setup 6%)

No Rust files changed, so Rust crate gates were not applicable. Cleanup: Removed 1 file, 356B total.

Gaps left

This commit is a formatter/parser foundation and does not finish the full issue. Budget style is not yet persisted in Budget.md or returned by the Money API; existing budgets are not upgraded; there is no style picker or settings editor; existing amount fields and displays do not consume the new helpers; no common amount input or animated counters were added; no screenshots or hot-path benchmark were captured. Numora 4.0.0 is MIT and framework-agnostic, but its API exposes numeric values; I did not add it because the issue also requires exact integer minor units end to end. Torph remains an existing dependency but was not wired to Money counters.

Decisions

  • Mapped EUR to de-DE and unknown currencies to en-US as the sensible fallback conventions.
  • Used the existing exact integer parser instead of Numora's numeric-value API to preserve the no-float invariant.
  • Merged origin/dev before verification; it was already up to date. No push, deploy or merge was done.
## Finished work — `job/moneyfmt-1180` Head: `7cdc7ad034f4ae00e453e77dcf01f0bc0620c7a5` ### Built - Added six stable Budget money conventions and currency-based defaults for INR, JPY, CHF, GBP, EUR and other currencies. - Added Budget-style format and parse helpers. Amounts remain integer minor units; the existing parser remains the exact conversion path. - Added round-trip coverage for every convention against supported currency scales, plus explicit INR, EUR, CHF and JPY examples. Files: `apps/web/src/lib/money/amount.ts`, `apps/web/src/lib/money/amount.test.ts`. ### Gate output Focused test: ``` Test Files 1 passed (1) Tests 10 passed (10) ``` `bun run check`: ``` perf-lint: PASS; 0 violations; 22104 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. svelte-check found 0 errors and 4 warnings in 3 files ``` `bun run test`: ``` Test Files 266 passed (266) Tests 1832 passed (1832) Duration 279.55s (environment 28%, transform 28%, import 22%, tests 16%, setup 6%) ``` No Rust files changed, so Rust crate gates were not applicable. Cleanup: `Removed 1 file, 356B total`. ### Gaps left This commit is a formatter/parser foundation and does not finish the full issue. Budget style is not yet persisted in `Budget.md` or returned by the Money API; existing budgets are not upgraded; there is no style picker or settings editor; existing amount fields and displays do not consume the new helpers; no common amount input or animated counters were added; no screenshots or hot-path benchmark were captured. Numora 4.0.0 is MIT and framework-agnostic, but its API exposes numeric values; I did not add it because the issue also requires exact integer minor units end to end. Torph remains an existing dependency but was not wired to Money counters. ### Decisions - Mapped EUR to `de-DE` and unknown currencies to `en-US` as the sensible fallback conventions. - Used the existing exact integer parser instead of Numora's numeric-value API to preserve the no-float invariant. - Merged `origin/dev` before verification; it was already up to date. No push, deploy or merge was done.
Author
Owner

Owner correction (2026-10-06, supersedes the Numora paragraph above)

Do NOT use Numora at all. The owner only wanted the visual effect from that page: Torph numeric morph transitions for changing amounts (Torph is already a dependency). Build the amount input with our own exact integer parser and the budget format; animate value changes (Ready to assign, Available, totals) with Torph. Remove any Numora dependency you added.

## Owner correction (2026-10-06, supersedes the Numora paragraph above) Do NOT use Numora at all. The owner only wanted the visual effect from that page: Torph numeric morph transitions for changing amounts (Torph is already a dependency). Build the amount input with our own exact integer parser and the budget format; animate value changes (Ready to assign, Available, totals) with Torph. Remove any Numora dependency you added.
Author
Owner

Continuing #1180 on job/moneyfmt-1180, base 7cdc7ad03. Read CLAUDE.md, CONTEXT.md and DESIGN §48. The foundation has six exact format/parser styles; metadata, API and screen adoption remain. Owner correction applies: no Numora; Torph for changing totals. Decision: persist money-format as a validated style key in money/1 Budget.md; ISO currency scale remains authoritative. File amounts stay plain decimals.

Continuing #1180 on `job/moneyfmt-1180`, base `7cdc7ad03`. Read CLAUDE.md, CONTEXT.md and DESIGN §48. The foundation has six exact format/parser styles; metadata, API and screen adoption remain. Owner correction applies: no Numora; Torph for changing totals. Decision: persist `money-format` as a validated style key in money/1 Budget.md; ISO currency scale remains authoritative. File amounts stay plain decimals.
Author
Owner

Core metadata committed as 89cef8c6b. Legacy INR/EUR/CHF/JPY/BHD budget projections receive their currency default without changing source bytes; explicit format edits preserve unknown frontmatter, BOM, CRLF and body bytes. Duplicate, empty and unknown format entries are rejected. cargo clippy -p calternal-money --all-targets -- -D warnings passed; cargo test -p calternal-money passed (full logs retained for the final report).

One existing Money route assertion requires the new money-format: european frontmatter line. #1180 explicitly requires this file-format addition; no amount, status code or unrelated assertion is changed. The first plugin run passed 92 tests and failed only that old file-prefix assertion; it has been updated for the required metadata.

Core metadata committed as `89cef8c6b`. Legacy INR/EUR/CHF/JPY/BHD budget projections receive their currency default without changing source bytes; explicit format edits preserve unknown frontmatter, BOM, CRLF and body bytes. Duplicate, empty and unknown format entries are rejected. `cargo clippy -p calternal-money --all-targets -- -D warnings` passed; `cargo test -p calternal-money` passed (full logs retained for the final report). One existing Money route assertion requires the new `money-format: european` frontmatter line. #1180 explicitly requires this file-format addition; no amount, status code or unrelated assertion is changed. The first plugin run passed 92 tests and failed only that old file-prefix assertion; it has been updated for the required metadata.
Author
Owner

API slice committed at 51ba5ae3c. Budget formats now persist through creation, import confirmation and the conditional format update endpoint. Month, account and transaction responses carry the convention. The generated client exposes the typed update.

Money gates passed:

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 93 filtered out; finished in 218.51s
test result: ok. 93 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 218.76s
test result: ok. 27 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 55.28s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The browser shares one exact integer AmountInput, keeps native caret/IME behavior, previews the parsed amount and groups valid text on blur. No Numora dependency was added. Production screenshot evidence and final web gates are in progress.

API slice committed at 51ba5ae3c. Budget formats now persist through creation, import confirmation and the conditional format update endpoint. Month, account and transaction responses carry the convention. The generated client exposes the typed update. Money gates passed: ``` test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 93 filtered out; finished in 218.51s test result: ok. 93 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 218.76s test result: ok. 27 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 55.28s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` The browser shares one exact integer AmountInput, keeps native caret/IME behavior, previews the parsed amount and groups valid text on blur. No Numora dependency was added. Production screenshot evidence and final web gates are in progress.
Author
Owner

Feature slices committed through 8e4b703ae4.

Create budget and import review have the live sample picker. Budget settings use the stable Budget link with ?settings=1, support persistence and Undo, and stay usable while background refresh is blocked. All existing Money displays and amount inputs use the saved convention; Ready to Assign, Available, month totals and Account balances use Torph. French and Dutch EUR choices also cover the User-region default at creation. No Numora dependency was added. Shared visible controls: Select/Menu, TextInput amount/assigned variants, Pill, SettingsCard, RequestState, SidebarLinks and the shared Undo toast.

Focused browser gates:

Test Files  5 passed (5)
     Tests  23 passed (23)
Test Files  1 passed (1)
     Tests  3 passed (3)
perf-lint: PASS; 0 violations; 22355 scoped exceptions

Both Money crate gates passed after the last Rust changes. The first full web run had only six 5-second timeouts outside Money (1910 passed); the rerun changes only the command-line time allowance to 30 seconds. The production web build passed. The local server binary build and the screenshot matrix are still in progress.

Feature slices committed through 8e4b703ae472d2fa8f5eebca8a29244f31d95da2. Create budget and import review have the live sample picker. Budget settings use the stable Budget link with `?settings=1`, support persistence and Undo, and stay usable while background refresh is blocked. All existing Money displays and amount inputs use the saved convention; Ready to Assign, Available, month totals and Account balances use Torph. French and Dutch EUR choices also cover the User-region default at creation. No Numora dependency was added. Shared visible controls: Select/Menu, TextInput amount/assigned variants, Pill, SettingsCard, RequestState, SidebarLinks and the shared Undo toast. Focused browser gates: ``` Test Files 5 passed (5) Tests 23 passed (23) Test Files 1 passed (1) Tests 3 passed (3) perf-lint: PASS; 0 violations; 22355 scoped exceptions ``` Both Money crate gates passed after the last Rust changes. The first full web run had only six 5-second timeouts outside Money (1910 passed); the rerun changes only the command-line time allowance to 30 seconds. The production web build passed. The local server binary build and the screenshot matrix are still in progress.
Author
Owner

Production contract generation rejected money_set_format because its explicit action policy was missing. Added the existing Money write policy (authority write, scope data, no automatic replay) in contracts/action-policy.json. This is the required public declaration for the new endpoint; no existing route policy changes. Extended the existing server authority regression to include this operation. Server gates and canonical contract generation now run before the browser evidence.

Production contract generation rejected `money_set_format` because its explicit action policy was missing. Added the existing Money write policy (authority write, scope data, no automatic replay) in `contracts/action-policy.json`. This is the required public declaration for the new endpoint; no existing route policy changes. Extended the existing server authority regression to include this operation. Server gates and canonical contract generation now run before the browser evidence.
Author
Owner

Head b1a507e78. Both Money crate clippy/test gates pass. Web check has 0 errors and 2 existing CSS warnings; full web tests now pass: Test Files 277 passed | 1 skipped (278) and Tests 1920 passed | 1 skipped (1921). The skipped test is the explicit opt-in performance profile. Server clippy passes. Extra server tests fail only in the existing separate-process upgrade-startup timing test: first HTTP startup exceeds 10 seconds, then a focused retry times out waiting for background backfills. No test timeout or assertion was changed. I will include those failures verbatim in the final report. The production capture found a phone BHD Assigned field inset issue; fixed in the shared TextInput assigned variant, with 9 focused Money component tests passing. Final screenshot/cache-return verification is running. No Numora dependency exists.

Head b1a507e78. Both Money crate clippy/test gates pass. Web check has 0 errors and 2 existing CSS warnings; full web tests now pass: `Test Files 277 passed | 1 skipped (278)` and `Tests 1920 passed | 1 skipped (1921)`. The skipped test is the explicit opt-in performance profile. Server clippy passes. Extra server tests fail only in the existing separate-process upgrade-startup timing test: first HTTP startup exceeds 10 seconds, then a focused retry times out waiting for background backfills. No test timeout or assertion was changed. I will include those failures verbatim in the final report. The production capture found a phone BHD Assigned field inset issue; fixed in the shared TextInput assigned variant, with 9 focused Money component tests passing. Final screenshot/cache-return verification is running. No Numora dependency exists.
Author
Owner

Implemented #1180 on job/moneyfmt-1180. Head: 2f005fc5168d767d050dd8a0cecd033b9c9e72a7. Merged fetched origin/dev once (6724654d5). No push, deployment or additional branch merge.

Built:

  • Budget money/1 metadata stores money-format. Legacy Budgets receive their currency default without a write on read. Tests check upgrades and preservation of unknown metadata, BOM, CRLF and Markdown.
  • Money API exposes the format on Budget, month, Account and Transaction responses. Create/import accept it. The format mutation uses the existing User scope, write lock and conditional single-file writer. Canonical OpenAPI, action declarations and client are generated from the server. The only shared server addition is the required authority declaration and its test; generation refuses an undeclared operation.
  • Create budget, import confirmation and Budget settings use one picker with eight live samples. All existing Money displays use the Budget convention, including assignments, targets, account balances, register amounts, import review and month totals. All existing editable amount fields use one exact integer AmountInput.
  • Torph morphs Ready to Assign, Available and totals with shared motion tokens and reduced-motion support. No Numora dependency was added.

Shared controls: TextInput (amount/assigned variants), Select/Menu, Pill, SettingsCard/LinkedHeading/Copy link, RequestState, SidebarLinks and the existing Undo toast. Feature controls do not replace the shared styling.

UX gaps closed:

  • Exact decimal preview before commit; native caret, selection and IME remain intact while typing. Valid completed edits group on blur. Malformed or over-precision input stays editable and is not posted.
  • Settings is a Budget-ID sub-view (?settings=1). Header and menu Copy link retain that view. Open budget returns to the same month.
  • A confirmed convention refresh reaches the mounted month without navigation or reload and without waiting for a background refresh to enable the picker. User/session and revision fences remain in force. Undo saves the prior convention.
  • The shared Assigned inset was too wide for three-decimal BHD at phone width. It is now compact enough for the reviewed value.
  • Existing pointer, touch, keyboard, focus and loading/error/offline controls are retained. Input targets are at least 44 px.

Decisions:

  • Persist a named CLDR preset rather than duplicate separators and symbol layout. Currency still determines the ISO minor-unit count. Eight presets: US, European, Indian, Swiss, Japanese, British, French and Dutch. EUR uses the User region at creation where supported; the selected key then stays independent of the device.
  • Keep canonical Money Markdown amounts unchanged. The metadata travels with the Budget; a display preference must not change stored amounts or source import grammar.
  • Use native text editing and our exact integer parser. A single alternate separator followed by the exact minor-digit count is decimal when unambiguous; genuine grouping ambiguity follows the saved convention.
  • Deliver the confirmed month refresh to its mounted owner. The existing local cache retains a revision before storage publication, so a settings callback must not rely on a storage event to repaint its parent.

Cost and performance:

  • Each displayed or parsed amount costs O(digits); locale templates are cached with a 32-entry bound. Picker work is eight samples. A format write replaces one Budget.md through the existing bounded Budget lookup; it does not rewrite Transactions.
  • Added bench/money-format-1180.mjs and an opt-in profile for 5, 10,000 and 100,000 format/parse pairs. It reports p50/p95, CPU and RSS and checks exact round trips. No corresponding baseline exists in docs/perf/baseline.json. No performance measurement is claimed: the current verification policy restricts measurements to performance issues on the locked perf VM.
  • Exact live performance pins were refreshed; no rule or limit was weakened. Exception count decreased by four to 22,355.

Known gaps / UX gaps left:

  • The five requested currency families plus GBP and EUR regional overrides have native defaults. Other currencies still use the US preset fallback; the full ISO currency-home and multi-region default mapping is not complete.
  • This branch has no dedicated Money Analytics screen, formatted export route or target amount editor. All existing Money consumers were changed; those future consumers must use the saved convention and shared field. Portable Money files carry the metadata.
  • Visual approval and the independent Money numbers review remain with the orchestrator. Captures are evidence, not my approval of their visual quality.
  • Extra server-suite startup/backfill deadlines failed on this shared host, including one focused retry. The failures are reported below; they were not hidden by changing tests.

Files:

apps/web/e2e/money-format-1180.mjs
apps/web/src/lib/components/money/AddAccountForm.svelte
apps/web/src/lib/components/money/AmountInput.svelte
apps/web/src/lib/components/money/AmountInput.svelte.test.ts
apps/web/src/lib/components/money/AssignedCell.svelte
apps/web/src/lib/components/money/AvailablePill.svelte
apps/web/src/lib/components/money/BudgetSettings.svelte
apps/web/src/lib/components/money/BudgetSettings.svelte.test.ts
apps/web/src/lib/components/money/CreateBudgetForm.svelte
apps/web/src/lib/components/money/FormatPicker.svelte
apps/web/src/lib/components/money/MoneyImport.svelte
apps/web/src/lib/components/money/MoneySidebar.svelte
apps/web/src/lib/components/money/TransactionForm.svelte
apps/web/src/lib/money/amount.profile.test.ts
apps/web/src/lib/money/amount.test.ts
apps/web/src/lib/money/amount.ts
apps/web/src/lib/money/api.test.ts
apps/web/src/lib/money/api.ts
apps/web/src/lib/money/currencies.ts
apps/web/src/routes/money/[budget]/[month]/+page.svelte
apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte
bench/money-format-1180.mjs
contracts/action-policy.json
contracts/actions.json
contracts/openapi.json
contracts/perf/adoption-1058.json
contracts/perf/exceptions.json
contracts/perf/ratchet.json
contracts/perf/registry.json
crates/calternal-money/src/codec.rs
crates/calternal-money/src/edit.rs
crates/calternal-money/src/ledger.rs
crates/calternal-money/tests/money_format.rs
crates/calternal-server/src/action_contract.rs
crates/plugins/money/examples/openapi.rs
crates/plugins/money/src/routes.rs
crates/plugins/money/src/tests.rs
crates/plugins/money/src/views.rs
docs/DESIGN.md
packages/api-client/src/generated.ts
packages/ui/src/components/TextInput.svelte
tests/adversarial/money_api.mjs

Gate output (verbatim summary lines; full logs are attached):

cargo fmt --check: exit 0, no output.

cargo clippy -p calternal-money --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 02s

cargo test -p calternal-money -- --test-threads=4

    Finished `test` profile [unoptimized + debuginfo] target(s) in 27.24s
test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.20s
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 22.47s
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.73s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 3.22s
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.96s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo clippy -p calternal-plugin-money --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 21.62s

cargo test -p calternal-plugin-money -- --test-threads=4

    Finished `test` profile [unoptimized + debuginfo] target(s) in 8.72s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 94 filtered out; finished in 100.25s
test result: ok. 94 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 100.34s
test result: ok. 27 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 17.52s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo clippy -p calternal-server --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 21m 03s

bun run test --maxWorkers=2 --testTimeout=30000:

 Test Files  277 passed | 1 skipped (278)
      Tests  1920 passed | 1 skipped (1921)

The opt-in performance profile is the one skipped test. After the last mounted-view fix, the focused settings regression file passes:

 Test Files  1 passed (1)
      Tests  4 passed (4)

Nine focused amount/input/settings tests passed before that last callback fix. No existing status or amount assertion was weakened. The existing file-prefix assertion now includes the new required metadata line, as #1180 changes that file layout.

Extra server test failure:

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 272 filtered out; finished in 25.50s
test result: FAILED. 262 passed; 1 failed; 10 ignored; 0 measured; 0 filtered out; finished in 155.47s

The separate-process startup test exceeded its HTTP startup deadline. One focused retry reached HTTP startup but exceeded the background-backfill deadline:

background backfills did not finish: Elapsed(())
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 272 filtered out; finished in 97.06s

No further retry loop. Server clippy and all Money tests pass.

For the merge round:

  • cargo test -p calternal-server -- --test-threads=4: check the server startup/backfill test on the combined branch.
  • bun tests/adversarial/money_api.mjs with the merge round's server environment: run the full Money matrix, including the new invalid-format cases. This job ran focused hostile format probes in the production capture script.
  • Run the normal full e2e/adversarial matrices and the independent Money numbers review once on the combined branch.
  • If a performance measurement is scheduled: flock /root/perf.lock bash -c 'cat /proc/loadavg; /usr/bin/time -v bun bench/money-format-1180.mjs' on the perf VM; record numbers beside a new baseline. No compile on the VM.

bun run check (final source and exact pins, exit 0):

perf-lint: PASS; 0 violations; 22355 scoped exceptions
svelte-check found 0 errors and 2 warnings in 2 files

The warnings are existing empty CSS rules in shared AttachmentDeck and AgendaList. Production build exits 0:

Compressed 912 static variants; saved 21143184 bytes.

Production evidence:

  • 150 captures: INR, EUR, CHF, JPY and BHD; 390, 820 and 1440 px; light and dark; macOS platform emulation. Create picker, settings picker, month amounts, transaction input and import picker. Representative captures inspected at original size, including the corrected BHD Assigned field. Claude must review visual quality.
  • The final combined capture run completed INR, EUR and CHF, including settings clipboard links and the EUR return-without-reload regression. Chromium closed during JPY. Separate final-source JPY and BHD runs completed successfully; there is no missing device/theme combination. Earlier full matrix also passed before the final UX fixes.
  • Focused real-server hostile format probes reject empty, uppercase, traversal, zero-width, NUL, oversized and unknown-field payloads with 4xx; format and recorded values remain unchanged.
PASS #1180 production picker, persistence, exact assignment and amount input; Mac 390/820/1440 light/dark.

The line above is from both final-source focused JPY and BHD runs. Full logs record the interrupted combined run as well as the successful runs.

Cleanup: cargo clean run for this job's preset target; web build/output removed. Screenshots, logs and review packs remain in ignored artifacts. No screenshot or review artifact is committed. No credential was printed.

Attached review evidence:

Currency / width Picker light Picker dark Amounts light Amounts dark
INR / 390 settings-picker-INR-390-light.png settings-picker-INR-390-dark.png amounts-INR-390-light.png amounts-INR-390-dark.png
INR / 1440 settings-picker-INR-1440-light.png settings-picker-INR-1440-dark.png amounts-INR-1440-light.png amounts-INR-1440-dark.png
EUR / 390 settings-picker-EUR-390-light.png settings-picker-EUR-390-dark.png amounts-EUR-390-light.png amounts-EUR-390-dark.png
EUR / 1440 settings-picker-EUR-1440-light.png settings-picker-EUR-1440-dark.png amounts-EUR-1440-light.png amounts-EUR-1440-dark.png
CHF / 390 settings-picker-CHF-390-light.png settings-picker-CHF-390-dark.png amounts-CHF-390-light.png amounts-CHF-390-dark.png
CHF / 1440 settings-picker-CHF-1440-light.png settings-picker-CHF-1440-dark.png amounts-CHF-1440-light.png amounts-CHF-1440-dark.png
JPY / 390 settings-picker-JPY-390-light.png settings-picker-JPY-390-dark.png amounts-JPY-390-light.png amounts-JPY-390-dark.png
JPY / 1440 settings-picker-JPY-1440-light.png settings-picker-JPY-1440-dark.png amounts-JPY-1440-light.png amounts-JPY-1440-dark.png
BHD / 390 settings-picker-BHD-390-light.png settings-picker-BHD-390-dark.png amounts-BHD-390-light.png amounts-BHD-390-dark.png
BHD / 1440 settings-picker-BHD-1440-light.png settings-picker-BHD-1440-dark.png amounts-BHD-1440-light.png amounts-BHD-1440-dark.png

Complete 150-screen matrix (also includes tablet, Create/import and amount-input captures):

Full gate and capture logs.

Implemented #1180 on `job/moneyfmt-1180`. Head: `2f005fc5168d767d050dd8a0cecd033b9c9e72a7`. Merged fetched `origin/dev` once (`6724654d5`). No push, deployment or additional branch merge. Built: - Budget `money/1` metadata stores `money-format`. Legacy Budgets receive their currency default without a write on read. Tests check upgrades and preservation of unknown metadata, BOM, CRLF and Markdown. - Money API exposes the format on Budget, month, Account and Transaction responses. Create/import accept it. The format mutation uses the existing User scope, write lock and conditional single-file writer. Canonical OpenAPI, action declarations and client are generated from the server. The only shared server addition is the required authority declaration and its test; generation refuses an undeclared operation. - Create budget, import confirmation and Budget settings use one picker with eight live samples. All existing Money displays use the Budget convention, including assignments, targets, account balances, register amounts, import review and month totals. All existing editable amount fields use one exact integer AmountInput. - Torph morphs Ready to Assign, Available and totals with shared motion tokens and reduced-motion support. No Numora dependency was added. Shared controls: TextInput (amount/assigned variants), Select/Menu, Pill, SettingsCard/LinkedHeading/Copy link, RequestState, SidebarLinks and the existing Undo toast. Feature controls do not replace the shared styling. UX gaps closed: - Exact decimal preview before commit; native caret, selection and IME remain intact while typing. Valid completed edits group on blur. Malformed or over-precision input stays editable and is not posted. - Settings is a Budget-ID sub-view (`?settings=1`). Header and menu Copy link retain that view. Open budget returns to the same month. - A confirmed convention refresh reaches the mounted month without navigation or reload and without waiting for a background refresh to enable the picker. User/session and revision fences remain in force. Undo saves the prior convention. - The shared Assigned inset was too wide for three-decimal BHD at phone width. It is now compact enough for the reviewed value. - Existing pointer, touch, keyboard, focus and loading/error/offline controls are retained. Input targets are at least 44 px. Decisions: - Persist a named CLDR preset rather than duplicate separators and symbol layout. Currency still determines the ISO minor-unit count. Eight presets: US, European, Indian, Swiss, Japanese, British, French and Dutch. EUR uses the User region at creation where supported; the selected key then stays independent of the device. - Keep canonical Money Markdown amounts unchanged. The metadata travels with the Budget; a display preference must not change stored amounts or source import grammar. - Use native text editing and our exact integer parser. A single alternate separator followed by the exact minor-digit count is decimal when unambiguous; genuine grouping ambiguity follows the saved convention. - Deliver the confirmed month refresh to its mounted owner. The existing local cache retains a revision before storage publication, so a settings callback must not rely on a storage event to repaint its parent. Cost and performance: - Each displayed or parsed amount costs O(digits); locale templates are cached with a 32-entry bound. Picker work is eight samples. A format write replaces one Budget.md through the existing bounded Budget lookup; it does not rewrite Transactions. - Added `bench/money-format-1180.mjs` and an opt-in profile for 5, 10,000 and 100,000 format/parse pairs. It reports p50/p95, CPU and RSS and checks exact round trips. No corresponding baseline exists in `docs/perf/baseline.json`. No performance measurement is claimed: the current verification policy restricts measurements to performance issues on the locked perf VM. - Exact live performance pins were refreshed; no rule or limit was weakened. Exception count decreased by four to 22,355. Known gaps / UX gaps left: - The five requested currency families plus GBP and EUR regional overrides have native defaults. Other currencies still use the US preset fallback; the full ISO currency-home and multi-region default mapping is not complete. - This branch has no dedicated Money Analytics screen, formatted export route or target amount editor. All existing Money consumers were changed; those future consumers must use the saved convention and shared field. Portable Money files carry the metadata. - Visual approval and the independent Money numbers review remain with the orchestrator. Captures are evidence, not my approval of their visual quality. - Extra server-suite startup/backfill deadlines failed on this shared host, including one focused retry. The failures are reported below; they were not hidden by changing tests. Files: ```text apps/web/e2e/money-format-1180.mjs apps/web/src/lib/components/money/AddAccountForm.svelte apps/web/src/lib/components/money/AmountInput.svelte apps/web/src/lib/components/money/AmountInput.svelte.test.ts apps/web/src/lib/components/money/AssignedCell.svelte apps/web/src/lib/components/money/AvailablePill.svelte apps/web/src/lib/components/money/BudgetSettings.svelte apps/web/src/lib/components/money/BudgetSettings.svelte.test.ts apps/web/src/lib/components/money/CreateBudgetForm.svelte apps/web/src/lib/components/money/FormatPicker.svelte apps/web/src/lib/components/money/MoneyImport.svelte apps/web/src/lib/components/money/MoneySidebar.svelte apps/web/src/lib/components/money/TransactionForm.svelte apps/web/src/lib/money/amount.profile.test.ts apps/web/src/lib/money/amount.test.ts apps/web/src/lib/money/amount.ts apps/web/src/lib/money/api.test.ts apps/web/src/lib/money/api.ts apps/web/src/lib/money/currencies.ts apps/web/src/routes/money/[budget]/[month]/+page.svelte apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte bench/money-format-1180.mjs contracts/action-policy.json contracts/actions.json contracts/openapi.json contracts/perf/adoption-1058.json contracts/perf/exceptions.json contracts/perf/ratchet.json contracts/perf/registry.json crates/calternal-money/src/codec.rs crates/calternal-money/src/edit.rs crates/calternal-money/src/ledger.rs crates/calternal-money/tests/money_format.rs crates/calternal-server/src/action_contract.rs crates/plugins/money/examples/openapi.rs crates/plugins/money/src/routes.rs crates/plugins/money/src/tests.rs crates/plugins/money/src/views.rs docs/DESIGN.md packages/api-client/src/generated.ts packages/ui/src/components/TextInput.svelte tests/adversarial/money_api.mjs ``` Gate output (verbatim summary lines; full logs are attached): `cargo fmt --check`: exit 0, no output. `cargo clippy -p calternal-money --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 02s ``` `cargo test -p calternal-money -- --test-threads=4` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 27.24s test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.20s test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 22.47s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.73s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 3.22s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.96s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-plugin-money --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 21.62s ``` `cargo test -p calternal-plugin-money -- --test-threads=4` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 8.72s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 94 filtered out; finished in 100.25s test result: ok. 94 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 100.34s test result: ok. 27 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 17.52s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-server --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 21m 03s ``` `bun run test --maxWorkers=2 --testTimeout=30000`: ```text Test Files 277 passed | 1 skipped (278) Tests 1920 passed | 1 skipped (1921) ``` The opt-in performance profile is the one skipped test. After the last mounted-view fix, the focused settings regression file passes: ```text Test Files 1 passed (1) Tests 4 passed (4) ``` Nine focused amount/input/settings tests passed before that last callback fix. No existing status or amount assertion was weakened. The existing file-prefix assertion now includes the new required metadata line, as #1180 changes that file layout. Extra server test failure: ```text test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 272 filtered out; finished in 25.50s test result: FAILED. 262 passed; 1 failed; 10 ignored; 0 measured; 0 filtered out; finished in 155.47s ``` The separate-process startup test exceeded its HTTP startup deadline. One focused retry reached HTTP startup but exceeded the background-backfill deadline: ```text background backfills did not finish: Elapsed(()) test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 272 filtered out; finished in 97.06s ``` No further retry loop. Server clippy and all Money tests pass. For the merge round: - `cargo test -p calternal-server -- --test-threads=4`: check the server startup/backfill test on the combined branch. - `bun tests/adversarial/money_api.mjs` with the merge round's server environment: run the full Money matrix, including the new invalid-format cases. This job ran focused hostile format probes in the production capture script. - Run the normal full e2e/adversarial matrices and the independent Money numbers review once on the combined branch. - If a performance measurement is scheduled: `flock /root/perf.lock bash -c 'cat /proc/loadavg; /usr/bin/time -v bun bench/money-format-1180.mjs'` on the perf VM; record numbers beside a new baseline. No compile on the VM. `bun run check` (final source and exact pins, exit 0): ```text perf-lint: PASS; 0 violations; 22355 scoped exceptions svelte-check found 0 errors and 2 warnings in 2 files ``` The warnings are existing empty CSS rules in shared AttachmentDeck and AgendaList. Production build exits 0: ```text Compressed 912 static variants; saved 21143184 bytes. ``` Production evidence: - 150 captures: INR, EUR, CHF, JPY and BHD; 390, 820 and 1440 px; light and dark; macOS platform emulation. Create picker, settings picker, month amounts, transaction input and import picker. Representative captures inspected at original size, including the corrected BHD Assigned field. Claude must review visual quality. - The final combined capture run completed INR, EUR and CHF, including settings clipboard links and the EUR return-without-reload regression. Chromium closed during JPY. Separate final-source JPY and BHD runs completed successfully; there is no missing device/theme combination. Earlier full matrix also passed before the final UX fixes. - Focused real-server hostile format probes reject empty, uppercase, traversal, zero-width, NUL, oversized and unknown-field payloads with 4xx; format and recorded values remain unchanged. ```text PASS #1180 production picker, persistence, exact assignment and amount input; Mac 390/820/1440 light/dark. ``` The line above is from both final-source focused JPY and BHD runs. Full logs record the interrupted combined run as well as the successful runs. Cleanup: cargo clean run for this job's preset target; web build/output removed. Screenshots, logs and review packs remain in ignored artifacts. No screenshot or review artifact is committed. No credential was printed. Attached review evidence: | Currency / width | Picker light | Picker dark | Amounts light | Amounts dark | |---|---|---|---|---| | INR / 390 | [settings-picker-INR-390-light.png](https://git.kayg.org/attachments/d1da694c-a505-4340-a4fa-849c4a00273b) | [settings-picker-INR-390-dark.png](https://git.kayg.org/attachments/4b433569-eda6-405a-9e76-d270762e5bb6) | [amounts-INR-390-light.png](https://git.kayg.org/attachments/1a3e9d2b-0e53-4cce-be53-f67553b31e92) | [amounts-INR-390-dark.png](https://git.kayg.org/attachments/012d9215-eb37-4517-bf5c-95657bcde6b0) | | INR / 1440 | [settings-picker-INR-1440-light.png](https://git.kayg.org/attachments/a403c2c2-e0ce-4b3d-a7e6-7d42ff92a82e) | [settings-picker-INR-1440-dark.png](https://git.kayg.org/attachments/b4c6627d-f066-4b98-b785-aec25ccb1193) | [amounts-INR-1440-light.png](https://git.kayg.org/attachments/40028480-cb60-4803-961c-329dc3888699) | [amounts-INR-1440-dark.png](https://git.kayg.org/attachments/7c217cf0-0b3e-4d75-8821-1209a53863bd) | | EUR / 390 | [settings-picker-EUR-390-light.png](https://git.kayg.org/attachments/93e7ff60-adc0-496a-b967-692129044e2b) | [settings-picker-EUR-390-dark.png](https://git.kayg.org/attachments/30ada556-6d6a-48c5-b17d-d4f311f52667) | [amounts-EUR-390-light.png](https://git.kayg.org/attachments/a3dbcc57-a76f-412d-b09e-63b64be33df7) | [amounts-EUR-390-dark.png](https://git.kayg.org/attachments/f3680ed5-d1ec-4166-9f44-4f4e93bb1dc1) | | EUR / 1440 | [settings-picker-EUR-1440-light.png](https://git.kayg.org/attachments/c2fc8b7b-422d-4319-8fa4-06afe8b530fb) | [settings-picker-EUR-1440-dark.png](https://git.kayg.org/attachments/7456eee2-eccc-4cba-be28-c08390b06b6d) | [amounts-EUR-1440-light.png](https://git.kayg.org/attachments/dcd66afa-7b1a-411a-aae7-195450723958) | [amounts-EUR-1440-dark.png](https://git.kayg.org/attachments/e15c7917-1fcf-4e78-9266-395798383a6b) | | CHF / 390 | [settings-picker-CHF-390-light.png](https://git.kayg.org/attachments/340063f8-234d-42fe-a137-e99a249bec34) | [settings-picker-CHF-390-dark.png](https://git.kayg.org/attachments/5acdd6d0-598e-49d0-ba21-8e53fca56200) | [amounts-CHF-390-light.png](https://git.kayg.org/attachments/a11386c2-ef4a-4fe0-8a19-c52c5f7cd989) | [amounts-CHF-390-dark.png](https://git.kayg.org/attachments/b5c15a23-d9f9-4149-9cfd-4e5207d94ca2) | | CHF / 1440 | [settings-picker-CHF-1440-light.png](https://git.kayg.org/attachments/49cc17da-076e-430d-ab09-843fc14cb552) | [settings-picker-CHF-1440-dark.png](https://git.kayg.org/attachments/73c5c416-3ada-4b7f-948e-ff8ed6ac9bdb) | [amounts-CHF-1440-light.png](https://git.kayg.org/attachments/4fd658ad-1b99-4ef2-9fdd-9a721cbd217a) | [amounts-CHF-1440-dark.png](https://git.kayg.org/attachments/23a118c8-ab6e-4ce0-bfe6-e7380f53aa13) | | JPY / 390 | [settings-picker-JPY-390-light.png](https://git.kayg.org/attachments/c2583f50-94df-4c87-999a-c707b60de66c) | [settings-picker-JPY-390-dark.png](https://git.kayg.org/attachments/b057fff5-bfc6-446f-9391-9c22c670ba88) | [amounts-JPY-390-light.png](https://git.kayg.org/attachments/ab841657-2e09-47bf-8072-d59f9b6bb56a) | [amounts-JPY-390-dark.png](https://git.kayg.org/attachments/23295f35-e957-417a-bd53-7a4ad6260bbd) | | JPY / 1440 | [settings-picker-JPY-1440-light.png](https://git.kayg.org/attachments/b609943c-928b-4714-ae5b-e448e9858e46) | [settings-picker-JPY-1440-dark.png](https://git.kayg.org/attachments/39cdbca2-21ee-4d33-b526-d238c9f8b2b3) | [amounts-JPY-1440-light.png](https://git.kayg.org/attachments/29e854b3-06df-4a6f-9f4a-b7c56a8bd18e) | [amounts-JPY-1440-dark.png](https://git.kayg.org/attachments/52741c69-6c05-4e4f-a5de-aa3bbb30fdf9) | | BHD / 390 | [settings-picker-BHD-390-light.png](https://git.kayg.org/attachments/a1a8c438-6bd9-4b76-80db-19ec880ce50f) | [settings-picker-BHD-390-dark.png](https://git.kayg.org/attachments/6c1115e7-8821-4630-8b87-8de9d2aed6c0) | [amounts-BHD-390-light.png](https://git.kayg.org/attachments/34e3813c-4e5d-4c63-9615-0316f6668554) | [amounts-BHD-390-dark.png](https://git.kayg.org/attachments/20823d60-9c96-4b90-bad5-9e2308c90e11) | | BHD / 1440 | [settings-picker-BHD-1440-light.png](https://git.kayg.org/attachments/f4de2e31-5e78-460c-bc64-269e38f1961a) | [settings-picker-BHD-1440-dark.png](https://git.kayg.org/attachments/3491ff21-80a7-4132-aab9-c989e0fbd243) | [amounts-BHD-1440-light.png](https://git.kayg.org/attachments/7f63a12d-5a23-4954-a059-13e1e71af0d3) | [amounts-BHD-1440-dark.png](https://git.kayg.org/attachments/fac3c4d8-b4d5-4b19-a941-44c27c6749e2) | Complete 150-screen matrix (also includes tablet, Create/import and amount-input captures): - INR: [money-format-1180-INR-1.zip](https://git.kayg.org/attachments/c87fa670-436a-408c-9ae6-ff4760eefffc), [money-format-1180-INR-2.zip](https://git.kayg.org/attachments/0fb983c4-1b9e-4ba6-b53e-bcdb388eaf04), [money-format-1180-INR-3.zip](https://git.kayg.org/attachments/3e7385bd-919a-479f-b165-7cc4841ac85c), [money-format-1180-INR-4.zip](https://git.kayg.org/attachments/881527df-a527-4bf1-b1f4-022eed6df6f4), [money-format-1180-INR-5.zip](https://git.kayg.org/attachments/e2664b04-933c-4652-a368-17001e40edd0) - EUR: [money-format-1180-EUR-1.zip](https://git.kayg.org/attachments/cfde953e-7450-4bec-9d6d-5a03be389944), [money-format-1180-EUR-2.zip](https://git.kayg.org/attachments/41155b05-05ed-46fe-a5d4-87038ca220b1), [money-format-1180-EUR-3.zip](https://git.kayg.org/attachments/cbbe5eb1-8283-4638-8467-d05e6e153725), [money-format-1180-EUR-4.zip](https://git.kayg.org/attachments/2f3e2497-a276-4bba-a56f-81132dbc66d2), [money-format-1180-EUR-5.zip](https://git.kayg.org/attachments/b11e0c47-6527-4e1c-b3eb-6c96fb15cf40) - CHF: [money-format-1180-CHF-1.zip](https://git.kayg.org/attachments/d7ab7452-607d-428f-8f68-9a8d7445f0ad), [money-format-1180-CHF-2.zip](https://git.kayg.org/attachments/b813799a-4e75-4bc6-8ae8-1b55aa181de8), [money-format-1180-CHF-3.zip](https://git.kayg.org/attachments/9ca726a6-d196-4672-a2e5-ef14bca2879e), [money-format-1180-CHF-4.zip](https://git.kayg.org/attachments/5753f61b-4731-48db-8a9e-98f46f2890ef), [money-format-1180-CHF-5.zip](https://git.kayg.org/attachments/b2dc3522-516f-4c24-816c-4e26e8495424) - JPY: [money-format-1180-JPY-1.zip](https://git.kayg.org/attachments/71ceaea6-f75b-45ef-8189-2859874073bc), [money-format-1180-JPY-2.zip](https://git.kayg.org/attachments/593319f5-d1df-42a3-9c44-0b7603eaacc9), [money-format-1180-JPY-3.zip](https://git.kayg.org/attachments/a53e56db-592f-47e0-a64f-9a8ef8ef8255), [money-format-1180-JPY-4.zip](https://git.kayg.org/attachments/613b5661-bae7-48cd-b185-5c677775cb13) - BHD: [money-format-1180-BHD-1.zip](https://git.kayg.org/attachments/20eb7512-d407-4619-aa2a-7586f1b5404e), [money-format-1180-BHD-2.zip](https://git.kayg.org/attachments/29af8ddb-010d-431a-bd4e-efffb8c8f503), [money-format-1180-BHD-3.zip](https://git.kayg.org/attachments/0631d452-72e5-45f2-b96c-90ce098b4d76), [money-format-1180-BHD-4.zip](https://git.kayg.org/attachments/81817cc1-8a66-4352-a0de-c23082e01090), [money-format-1180-BHD-5.zip](https://git.kayg.org/attachments/69e5eedf-9e2a-42bf-8345-d866d734d291) [Full gate and capture logs](https://git.kayg.org/attachments/1441b9c2-ed31-4fad-8324-a80c806be972).
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#1180
No description provided.