4915 Commits

Author SHA1 Message Date
Nikhil Verma
e3952d2a24 [AI] Add option to 'Copy [budget] to future months' (#7420)
* [AI] Add 'Copy to future months' budget option

Adds a new per-category budget menu option that copies the current
month's budgeted amount to all future months that already exist in
the budget. Works for both envelope and tracking budget types, and
on both desktop (inline popover) and mobile (modal) views.

* [AI] Rename release note to PR #7420

* [AI] Skip empty budget months in copyToFutureMonths

Only copy the budget value to future months that already have a
non-zero budget set for the category. Months with no budget (zero)
are left untouched.

* [AI] Rename to 'Copy until year end', limit to tracking budget, add year-end cap

* [AI] Address CodeRabbit feedback: i18n undo notification, clarify docs

* [AI] Fix typecheck: branch dispatch by budgetType for proper modal narrowing

* [AI] Fix lint: add t to useCallback deps
2026-05-06 18:19:40 +00:00
Michael Clark
fea36466d2 fix rss feed (#7732) 2026-05-06 18:18:30 +00:00
youngcw
1fadfa4e9b [AI] Fix #2155: duplicated transactions are marked as uncleared (#7723)
* init

* note
2026-05-06 17:43:30 +00:00
Aaron
6ead7ea42c docs: add Enable Actual to community repos (#7697)
Co-authored-by: Aaron <aaron@noreply.squaresine.com>
2026-05-06 00:31:41 +00:00
Matt Fiddaman
d6fc3212b9 re-sort preview transactions after rule application (#7691)
* resort schedules after rule application

* note
2026-05-05 23:48:26 +00:00
Alec Bakholdin
071611fcc5 Cannot read properties of null (reading 'toLowerCase') (#7704)
* added null safety in throwIfNot200

* release notes

* updated release notes

---------

Co-authored-by: Alec Bakholdin <alecbakholdin.com>
2026-05-05 23:03:02 +00:00
Matt Fiddaman
263358b5cf fix vrt update workflow (#7699)
* fix vrt update workflow

* note
2026-05-05 20:26:48 +00:00
Michael Clark
44fc959ed8 :electron: Fix electron dev mode not starting (#7712)
* fix electron dev mode

* release notes
2026-05-05 08:08:49 +00:00
Dan Hopkins
d787d0ce43 fix: only count failed attempts against auth rate limit (#7707)
* fix: only count failed attempts against auth rate limit

Add skipSuccessfulRequests: true to authRateLimiter so that successful
logins do not consume quota. This fixes breakage for API clients
(actual-cli, actual-mcp, custom scripts) that re-authenticate per
operation — they always provide the correct password, so they should
never be rate-limited.

Brute-force attackers generate repeated failures and still hit the wall.

Fixes #7706

* Update upcoming-release-notes/7706.md

Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>

* fix: rename release note to match PR number

---------

Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>
2026-05-04 22:27:18 +00:00
Aurora-Flipped
2c3e2a34fd Fix/spending report date range save (#7672)
* Fix saved spending report date range

* Add release note
2026-05-04 20:28:19 +00:00
lelemm
78d533c800 Bank sync page refactor (#7449)
* Bank sync refactor extracted from plugins

* code review

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7449

* [AI] Resolve bank sync PR conflicts

Co-authored-by: lelemm <lelemm@users.noreply.github.com>

* Change author name in 7449 release notes

Updated author name in release notes.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: lelemm <lelemm@users.noreply.github.com>
Co-authored-by: youngcw <calebyoung94@gmail.com>
2026-05-04 14:51:33 +00:00
Juulz
49f6b21f2c [Bugfix]🐛 Fix refresh icon (sync) centering in Titlebar (#7674)
* Fix svg rendering in Titlebar component

* Fix conditional rendering of syncState text

* Fix string interpolation in Titlebar component

* Add release notes for bugfix on refresh icon centering

* Clarify refresh icon centering fix in Titlebar
2026-05-04 14:49:33 +00:00
Emil Tveden Bjerglund
9f05207fe8 Fix Cover Overspending menu closing when view too narrow (#7687)
* Fix Cover Overspending menu closing when view too narrow

* Update upcoming-release-notes/7687.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Increase min width

* Set minWidth instead

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-04 14:48:30 +00:00
Matt Fiddaman
8366c442a2 automation UI: seperate percentage sources in error logic (#7694)
* seperate percentage sources in error logic

* note

* restructure and add test

* fix income category resolution and add regression test
2026-05-04 13:59:55 +00:00
Matt Fiddaman
4b73fd7e45 link budget automation UI experimental feature to a feedback issue (#7693)
* link to feedback issue

* note
2026-05-03 22:46:10 +00:00
Julian Dominguez-Schatz
c593bda145 Update release docs to reflect latest process (#7690)
* Update release docs to reflect latest process

* Add missed space

* GitHub doesn't like non-American spelling

* PR feedback
2026-05-03 22:02:08 +00:00
Andreas Offenhaeuser
1b86bba2cd [Bugfix] Disable 2-day lookback for automatic transactions (#7299)
* disable 2-day lookback for automatic transactions

* add PR release notes
2026-05-03 21:44:28 +00:00
Matiss Janis Aboltins
6c2c96e826 🔖 (26.5.0) (#7621)
* 🔖 (26.5.0)

* fix release note generation script (#7635)

* fix release note generation script

* note

* fix cherrypicked commits not being respected and lint race in release note generation workflow (#7640)

* fix cherrypicked commits not being respected and lint race

* note

* coderabbit suggestions

* fix lint

* make double restore possibility safe

* fix lint (#7643)

* Generate release notes for v26.5.0

* add release note highlights

* Fix Sankey income bug, when payee it not set (#7632)

* Ensure income categories are shown correct, even if payee is not set

* Add release note

* Generate release notes for v26.5.0

* increase test coverage for budget templates (#7620)

* [AI] cover existing template engine logic with regression tests

Adds tests for goal template behavior that predates this PR so the
suite can be cherry-picked onto master to confirm no regressions. No
production code changes.

Covers:
- init() validation: schedule names, by/schedule priority match, past
  by-target with and without annual/repeat, percentage source not
  found, special source aliases, duplicate limit/spend/goal
  directives, weekly limit missing start date, invalid limit period,
  unrecognized periodic period
- runRemainder cap clamping and hideDecimal fraction removal
- Income-category branch in runTemplatesForPriority
- getLimitExcess against an aggregate weekly cap
- Past by-target rolling forward via the annual period
- runSchedule full=true (no sinking accumulation), percent and fixed
  adjustments, completed-schedule filtering, past-date error for
  non-repeating schedules, monthly/weekly/daily sinking contribution
  branches when interval exceeds the pay-month-of cap, surplus
  absorption when last-month balance exceeds the target, and
  tracking-budget mode forcing all schedules pay-month-of
- applyMultipleCategoryTemplates orchestration: per-category writes,
  cross-category priority clamping when funds run out, error
  notification path
- applyTemplate force=false skipping already-budgeted categories

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* note

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix infinite loop when remainder is impossible to solve (#7623)

* fix infinite loop when remainder is impossible to solve

* note

* Generate release notes for v26.5.0

* Update author

Updated author information in the release notes.

* Fix shared worker resumption after tab suspend (#7656)

* [AI] Fix SharedWorker tab resume recovery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [AI] Fix SharedWorker reload readiness

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add release notes

* Update packages/desktop-client/src/shared-browser-server-core.ts

Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>

* Update docs release date

* Empty commit to bump CI

* Generate release notes for v26.5.0

* Revert "Generate release notes for v26.5.0"

This reverts commit b42c48bed5.

---------

Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Emil Tveden Bjerglund <emilbp@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-03 17:41:17 +00:00
Matt Fiddaman
6298f6a324 improve experimental budget automation UI (#7597)
* [AI] initial

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] review pass 1

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] review pass 2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] review pass 3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] review pass 4

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* remove dev localstorage gate

* [AI] block migration for #goal and #cleanup directives

Detect goal templates (`type: 'goal'`) and `#cleanup` lines in the
category notes before rendering the editor. When either is present,
show an unsupported-directive notice instead of the modal body so the
migration helper never runs and the Save flow can't silently overwrite
`template_settings.source` to `'ui'` (which would stop the engine from
reading the notes for those directives).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* note

* [autofix.ci] apply automated fixes

* [AI] don't synthesise refill for monthly+limit simple templates

A `#template 50 up to 200` line parses to a simple template with both
monthly and limit set. The migration helper previously expanded that
into limit + refill + periodic, but the engine's runSimple just budgets
the monthly amount and clamps to the cap — there is no implicit refill
to undo.

Only synthesise the refill for the limit-only form
(`#template up to 200`), where runSimple's fallback returns
limitAmount - fromLastMonth. Update the migration test to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] coderabbit fixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] coderabbit fixes v2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] attribute schedule batch contributions per template

Replace the equal-split fallback with each schedule's actual monthly
contribution (computed inside runSchedule) so the per-row UI projection
reflects real cost rather than total / count.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] coderabbit v3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] coderabbit v4

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] fix unclearable integer inputs in automation editors

GenericInput type=number fired onChange on every keystroke and the
dispatcher coerced empty/0 back to 1, so the field snapped back before
the user could retype. Switch to a local string state that commits and
clamps on blur, with min/step constraints on the native input.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] coderabbit v5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update packages/desktop-client/src/components/budget/goals/templateHelpers.tsx

Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>

* Update packages/desktop-client/src/components/budget/goals/templateHelpers.tsx

Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>

* [autofix.ci] apply automated fixes

* remove comment

* s/rule/automation

* update note wording

* tweak hold checkbox wording

* deduplicate translation strings

* rename buildPresetSeeds

* deduplicate example text

* update wording about how easy automations are

* s/P/Priority

* reuse week template

* replace week displayType with fixed

* lodash debounce

* [autofix.ci] apply automated fixes

* more graceful error handling

* change default priority to 1

* align ui and text language for available funds & all income

* fix tests

* coderabbit v{lost_count}

* more coderabbit

* extract isValidYearMonth

* extract automationExamples

* split out into multiple files

* split down templateHelpers

* [AI] cover PR additions to template engine

Tests targeting code introduced in this PR:
- per-template attribution map (perTemplateContribution) on
  CategoryTemplateContext for sibling periodic templates, batched `by`
  templates, limit-clamped totals, and remainder weights
- runBy now returns { toBudget, perTemplateNeed }
- runSchedule now returns perScheduleMonthly keyed by trimmed name,
  including a multi-schedule pay-month-of + sinking-fund mix
- dryRunCategoryTemplate end-to-end through computeTemplates, in both
  narrow-scope and wide-scope (remainder / available funds) branches
- checkPercentage now accepts category ids (UI form), not just names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix repeat every month error

* coderabbit again.

* Update packages/desktop-client/src/components/budget/goals/automationMessages.tsx

Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>

* Update packages/desktop-client/src/components/budget/goals/automationMessages.tsx

Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>

* [autofix.ci] apply automated fixes

* plural aware translation strings

* move + out of translation string

* fix types

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>
2026-05-01 10:33:02 +00:00
Matiss Janis Aboltins
1afe7c9a1e Enable auto enrichment in coderabbit configuration (#7664)
* Enable auto enrichment in coderabbit configuration

* Add release notes for PR #7664

* Change category to Maintenance and update description

Updated the category from 'Features' to 'Maintenance' and revised the description.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-30 17:02:52 +00:00
Julian Dominguez-Schatz
24279264da Fix shared worker resumption after tab suspend (#7656)
* [AI] Fix SharedWorker tab resume recovery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [AI] Fix SharedWorker reload readiness

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add release notes

* Update packages/desktop-client/src/shared-browser-server-core.ts

Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>
2026-04-30 07:37:02 +00:00
Matiss Janis Aboltins
4a5ee9c2dc [AI] Make TypeScript work in test files across packages (#7642)
* [AI] Make TypeScript work in test files across packages

Match the CRDT package's tsconfig pattern in loot-core, desktop-client,
api, and desktop-electron so test files participate in the project graph
(IDE intellisense, project-wide typecheck) while production builds still
emit clean declaration files.

- Remove test-file exclusions from each package's main tsconfig
- Add tsconfig.build.json for loot-core and api with test exclusions,
  used by the build scripts
- Add e2e/tsconfig.json for desktop-client and desktop-electron with
  Playwright types
- Fix latent type errors in test files now caught by typecheck
- Disable typescript/unbound-method for test files (mock matcher pattern)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Release notes

* [AI] Address review feedback on test type fixes

- goal-template.test.ts: extract amounts to typed locals so single-value
  assertions no longer compare against unknown
- category-template-context.test.ts: replace `as unknown as DbCategory`
  double-cast with a fully-typed object using `satisfies DbCategory`
  (the previous mock had `is_income: true` which doesn't match the
  `1 | 0` shape the cast was hiding)
- api/tsconfig.build.json: broaden test exclude pattern to `**/*.test.ts`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Widen toMatchThemeScreenshots matcher to accept Page

The matcher's runtime impl already handled both Page and Locator
(via `typeof locator.page === 'function'` branch), but the type only
declared Locator. Call sites pass a Page (`expect(page).toMatchThemeScreenshots()`),
which now compiles cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Type window.Actual in e2e fixtures and refactor matcher

- Pull loot-core/typings/window.ts into the e2e tsconfig include so
  the ambient `window.Actual` augmentation is visible.
- Refactor toMatchThemeScreenshots to derive a Page once via
  `'page' in target`, then call evaluate on the page consistently.
  The previous union-typed access (locator.evaluate, locator.page)
  didn't typecheck on Locator | Page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Drop tsconfig.build.json for loot-core and api

The build-config indirection was incomplete protection: typecheck
(`tsgo -b` against the main tsconfig, which now includes test files)
already emits `*.test.d.ts` into `@types/`, and the build step does
not clean before re-emitting. The same is observable in crdt's
`dist/`, which currently contains test declarations on disk.

What actually keeps test declarations out of the npm tarball is the
`files` field in package.json — and loot-core already uses that
mechanism for source files (`\!src/**/*.test.ts`). Extending the same
pattern to `@types/` is more direct than maintaining a duplicate
tsconfig that doesn't reliably do its job.

- Delete loot-core/tsconfig.build.json; revert build to `tsgo -b`;
  add `\!@types/**/*.test.d.ts*`, `\!@types/**/__tests__/**`,
  `\!@types/**/__mocks__/**` to `files`.
- Delete api/tsconfig.build.json; revert build to
  `vite build && tsgo --emitDeclarationOnly`; add
  `\!@types/**/*.test.d.ts*` to `files`.

Verified: `yarn pack --dry-run` excludes all test declarations from
both packages while production declarations still pack (428 .d.ts
files for loot-core, methods.d.ts for api).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Standardise crdt to drop tsconfig.build.json

Apply the same simplification as loot-core and api: a single tsconfig
per package, with `files`-field negations preventing test
declarations from being published.

Note: this also fixes a pre-existing issue where crdt was shipping
`crdt/timestamp.test.d.ts` and `crdt/merkle.test.d.ts` to npm. The
old `tsconfig.build.json` excluded test files from declaration emit,
but the `typecheck` script (`tsgo -b` via the main tsconfig) had
already emitted them into `dist/` and the build did not clean
first, so they were packed via `"files": ["dist"]`.

After this change, `yarn pack --dry-run` packs only production
declarations (10 .d.ts files) and excludes the test ones.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:06:58 +00:00
arjunrawal1
a8eb204ce7 Fix release notes link in PR template (#7655)
* Fix release notes link in PR template

* Add release note
2026-04-29 16:39:10 +00:00
rboadu
f68e4fbb2a Updated API Documentation for Splitting Transactions (#7593)
* Updated API Documentation for Splitting Transactions

* Update check-spelling metadata

* Updated category name in example

* Update packages/docs/docs/api/reference.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Fixed documentation to CodeRabbits feedback

* Update packages/docs/docs/api/reference.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Updated wording of reference document

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: youngcw <calebyoung94@gmail.com>
2026-04-29 16:28:14 +00:00
Matiss Janis Aboltins
dd3b1144d1 [AI] Mobile: iconography, placeholders, and dropdown chevrons for transaction form (#7639)
* [AI] Add iconography, placeholders, and dropdown chevrons to mobile transaction form

Brings the mobile new-transaction screen in line with the design mockup so
each field shows a leading icon, dropdown affordances surface on the right,
and empty pickers display a placeholder hint.

- Extend TapField with optional icon/placeholder props (placeholder uses
  formInputTextPlaceholder when value is empty).
- Extend InputField with an optional icon prop that wraps the input in a
  bordered row when present.
- Wire SvgUser/SvgTag/SvgWallet/SvgCalendar/SvgNotesPaper into Payee,
  Category, Account, Date, and Notes for both the main form and split
  child rows; add a SvgCheveronDown rightContent on Category and Account.

* Add release notes for PR #7639

* [AI] Forward consumer style to inner Input in icon path of InputField

CodeRabbit flagged that consumer-supplied `style` was being applied to the
wrapper View in the icon branch, so input-targeted properties like
`appearance: 'none'` and `minWidth: '150px'` on the Date field never reached
the underlying `<input type="date">`. Move the style spread onto the inner
Input so those styles take effect.

* [AI] Add dropdown chevron to mobile Payee field

Show the chevron on the Payee TapField in both the main form (as the
fallback when neither the Save-location nor Nearby-payee button applies)
and in split child rows, matching Category and Account.

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7639

* [AI] Hide native date picker icon on mobile transaction form

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7639

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-29 07:56:05 +00:00
Matiss Janis Aboltins
ff0f5bdb35 [AI] lage - move browser build to using lage (#7602)
* Simplify desktop client browser build

* [AI] Move browser build orchestration into vite config and lage

Moves loot-core worker build, public/ staging (migrations, default-db,
sql-wasm, data-file-index), and build-stats wiring from the deleted
packages/desktop-client/bin/build-browser shell script into a
lootCoreBackend vite plugin in packages/desktop-client/vite.config.mts.

Adds a build:browser target to lage.config.js so bin/package-browser
runs as a single `lage build:browser --to=@actual-app/web` call, with
crdt + loot-core built via lage's ^build dependency before the
desktop-client build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Refactor e2e-test workflow and update desktop-client configurations

* [AI] Move plugins-service staging into desktop-client vite config

Declares plugins-service as a workspace devDependency of @actual-app/web
so lage's ^build edge picks it up automatically in the build:browser
pipeline, and moves the cross-package file staging (production copy +
dev serving) into vite.config.mts, mirroring the lootCoreBackend
pattern. Drops the plugins-service shell wrapper script and simplifies
its package.json scripts to invoke vite build directly. Updates root
start:browser to run plugins-service watch in parallel with the dev
server instead of pre-building once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Sync tsconfig project references for plugins-service edge

Follow-up to the plugins-service workspace edge: adds the
../plugins-service project reference in packages/desktop-client/tsconfig.json
via yarn sync:tsconfig-references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Release notes

* [AI] Ignore .venv/ so lage's git hasher skips Electron CI's Python venv

Electron CI provisions a Python virtualenv at the repo root for
setuptools. With browser builds now routed through lage, lage's
git hash-object pass walks untracked-not-ignored files and fails on
the venv's broken lib64 symlink ("fatal: Unable to hash .../.venv/lib64").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Bake Weblate translations back into VRT/e2e bundle

build-web set download-translations: false and relied on bin/package-browser's
ad-hoc git clone + git pull. That path is fragile inside the playwright
container, so vite's import.meta.glob('/locale/*.json') frequently produced an
empty languages map and the bundle shipped with no en.json. VRTs then rendered
source-code English and diffed against snapshots authored from Weblate strings.

Route translation provisioning back through actions/checkout (download-translations: true)
in build-web and vrt-update-generate, and add --skip-translations to bin/package-browser
(mirroring bin/package-electron) so the in-script git pull is bypassed when CI
has already staged the locale dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Skip translation cloning in build-web bundle for VRT determinism

bin/package-browser used to unconditionally clone actualbudget/translations
before vite ran, baking Weblate en.json into the build artifact. With the
e2e-test pipeline now serving that artifact via serve-build.mjs, VRT
screenshots ended up rendering Weblate strings — drifting from the snapshots,
which were authored against source-code English (master VRTs ran on vite dev
without a locale dir).

Pass --skip-translations to bin/package-browser from build-web so the bundle
ships with no locale chunks. download-translations stays 'false' across the
e2e-test and vrt-update-generate workflows, matching the prior behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 20:20:13 +00:00
Rudra Sarker
11ce29e7fd fix: disable Inter font contextual alternates to prevent x→× substitution (#7375)
* fix: disable contextual alternates in Inter font to prevent unwanted character substitution

Fixes #6351

The Inter font calt feature replaces x between digits with a
multiplication sign. Disable it while preserving ss01 and ss04.

* [autofix.ci] apply automated fixes

* Add release notes for PR #7375

* [autofix.ci] apply automated fixes

* Fix release notes category casing

* Add authors field to release notes

* Update upcoming-release-notes/7375.md

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>
2026-04-28 10:56:20 +00:00
Trevin Chow
d58c9a9a07 fix(transactions): show 'Date is a required field' error when adding without date (#7511)
* fix: show consistent 'Date is a required field' error in add transaction

When adding a new transaction with a missing date, the UI surfaced the
generic 'Something internally went wrong' error instead of a specific
message, while missing account showed 'Account is a required field'.
Add an analogous date validation mirroring the existing account check,
so both required-field errors are consistent.

Fixes #7424

* fix: prevent empty date from reaching server when clearing date input

When adding a transaction, clearing the date field and clicking Add
caused DateSelect's blur handler to save an empty string as the date
via onSelect(''). The server rejected '' as an invalid date, emitting
a generic "Something internally went wrong" error.

The previous fix (adding a date check in the shouldAdd guard) didn't
work because the cell save fires on blur BEFORE shouldAdd runs — by
the time shouldAdd checks the date, it's either already sent to the
server or reverted by DateSelect's clearOnBlur logic.

Fix: change DateSelect's empty-input blur path to restore the previous
valid date instead of propagating ''. This prevents the invalid value
from ever reaching the cell save handler or the server.

Verified locally: clear date → click Add → date restores to previous
value and transaction saves normally. No generic error.

Fixes #7424
2026-04-28 10:50:54 +00:00
Matiss Janis Aboltins
598e3ec9d8 [AI] Keep mobile transaction amount field at a consistent height when empty (#7638)
* [AI] Keep mobile transaction amount field at a consistent height when empty

When the user backspaced every digit while editing the amount on the
mobile transaction form, the inner <Text> span had no content and
collapsed the pill to zero height. Fall back to a non-breaking space so
the line box keeps its natural font-driven height even when the input
is momentarily empty.

* Add release notes for PR #7638

* [AI] Use amountToCurrency(0) instead of nbsp when amount input is empty

Mirrors the unfocused-zero display rather than rendering a blank pill,
and respects the user's hideFraction pref and locale separators
through amountToCurrency.

* Simplify description of mobile transaction field height

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-28 07:31:57 +00:00
Matt Fiddaman
c2987af64f fix lint (#7643) 2026-04-27 21:24:16 +00:00
Matt Fiddaman
c7d39961cf fix cherrypicked commits not being respected and lint race in release note generation workflow (#7640)
* fix cherrypicked commits not being respected and lint race

* note

* coderabbit suggestions

* fix lint

* make double restore possibility safe
2026-04-27 20:52:07 +00:00
Matt Fiddaman
a42b7c5777 fix release note generation script (#7635)
* fix release note generation script

* note
2026-04-27 19:32:24 +00:00
Emil Tveden Bjerglund
33af9bf906 Fix Sankey income bug, when payee it not set (#7632)
* Ensure income categories are shown correct, even if payee is not set

* Add release note
2026-04-26 19:23:07 +00:00
Matt Fiddaman
46687da7a8 fix infinite loop when remainder is impossible to solve (#7623)
* fix infinite loop when remainder is impossible to solve

* note
2026-04-26 04:20:49 +00:00
Matt Fiddaman
3928d5b2a8 increase test coverage for budget templates (#7620)
* [AI] cover existing template engine logic with regression tests

Adds tests for goal template behavior that predates this PR so the
suite can be cherry-picked onto master to confirm no regressions. No
production code changes.

Covers:
- init() validation: schedule names, by/schedule priority match, past
  by-target with and without annual/repeat, percentage source not
  found, special source aliases, duplicate limit/spend/goal
  directives, weekly limit missing start date, invalid limit period,
  unrecognized periodic period
- runRemainder cap clamping and hideDecimal fraction removal
- Income-category branch in runTemplatesForPriority
- getLimitExcess against an aggregate weekly cap
- Past by-target rolling forward via the annual period
- runSchedule full=true (no sinking accumulation), percent and fixed
  adjustments, completed-schedule filtering, past-date error for
  non-repeating schedules, monthly/weekly/daily sinking contribution
  branches when interval exceeds the pay-month-of cap, surplus
  absorption when last-month balance exceeds the target, and
  tracking-budget mode forcing all schedules pay-month-of
- applyMultipleCategoryTemplates orchestration: per-category writes,
  cross-category priority clamping when funds run out, error
  notification path
- applyTemplate force=false skipping already-budgeted categories

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* note

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 23:35:32 +00:00
Matt Fiddaman
8b29ee40a7 show all blog posts on docs site (#7622) 2026-04-25 23:20:40 +00:00
Matiss Janis Aboltins
9acbd6388b [AI] Cache the CLI's local budget between invocations (#7539)
* [AI] Cache the CLI's local budget between invocations

Every `actual <cmd>` call currently delta-syncs the budget with the
sync server via `api.downloadBudget`, which hits the server's
500-req/min rate limit on scripted workflows. Actual is local-first:
once the budget is on disk, most read commands do not need fresh
server data.

Introduce a CLI-only cache layer inside `withConnection` that
decides per invocation whether to skip, sync, or re-download:

- Cache state lives at `{dataDir}/.actual-cli/{syncId}/state.json`,
  keyed by `syncId` to avoid the chicken-and-egg of not knowing the
  on-disk `budgetId` before the first download. The on-disk id is
  resolved via `api.getBudgets()` and persisted after first download.
- Read commands (list, balance, query run, …) skip the `/sync`
  call while `now - lastSyncedAt < cacheTtl`. Write commands
  (create, update, delete, set-*, etc.) sync before and after the
  operation to keep server state consistent.
- Encrypted budgets force a sync per call since `api/load-budget`
  does not re-verify the password.
- New `proper-lockfile`-backed shared/exclusive lock serializes
  writes while allowing parallel reads. Reader markers live in
  `{meta}/readers/`; writers sweep stale markers by PID.

New `actual sync` command with three modes: default (sync now),
`--status` (print cache age, TTL, stale flag), `--clear` (delete
cache, holding the exclusive lock to avoid racing writers).

New config surface, following the existing flag → env → config file
→ default precedence chain:

- `--cache-ttl <s>` / `ACTUAL_CACHE_TTL` / `cacheTtl` (default 60)
- `--refresh` / `--no-cache`
- `--lock-timeout <s>` / `ACTUAL_LOCK_TIMEOUT` / `lockTimeout` (10)
- `--no-lock` / `ACTUAL_NO_LOCK` / `noLock`

Every `withConnection` call site now passes an explicit
`{ mutates: boolean, skipBudget?: boolean }` so read/write intent is
visible at the edge.

The old `budgets sync` subcommand is removed — it silently diverged
from the new top-level `actual sync`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Simplify CLI cache/lock internals

Use a discriminated SyncDecision union so connection.ts no longer needs
non-null assertions on the cached state. Thread the resolved CliConfig
through withConnection's callback to drop duplicate resolveConfig calls
in the sync and budgets commands. Extract an errorCode helper and
replace the existsSync+readdirSync TOCTOU pattern in the reader-wait
polling loop with a single readdir that tolerates ENOENT.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Address PR #7539 review comments

- cache.ts: use a unique per-writer tmp filename so concurrent shared-
  lock writers (encrypted budgets, --refresh, stale TTL) don't clobber
  each other's publish and silently drop state updates.

- index.ts/config.ts: fix --no-cache and --no-lock flags. Commander
  stores --no-foo under the positive key (cache/lock) and an explicit
  false default makes the flag a no-op; the previous code also read
  the wrong keys (noCache/noLock) so the flags had no effect at all.
  Derive refresh/noLock from the correct keys.

- budgets.ts: invert encryption password precedence so the subcommand
  flag (--encryption-password) wins over env/config-file values.

- sync.ts: report stale=true in --status when lastSyncedAt is in the
  future, matching decideSyncAction's clock-skew handling.

- connection.ts: drop unnecessary `as` cast on api.getBudgets() now
  that the return type is Promise<APIFileEntity[]>.

- utils.ts: parseBoolEnv throws on unrecognized values instead of
  silently returning undefined so typos like ACTUAL_NO_LOCK=yes fail
  loudly.

- Shorten 7539 release note to a single user-facing sentence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:58:18 +00:00
Alec Bakholdin
77f0a3e58b Update documentation for transaction import behavior based (#7614)
* Update documentation for transaction import behavior

Updated docs per the change in #7610

* [autofix.ci] apply automated fixes

* release notes

* removed patch notes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-25 21:44:38 +00:00
Matt Fiddaman
eb922fd191 sankey card should follow report settings (#7619)
* sankey card should follow report rules

* note
2026-04-25 16:17:45 +00:00
Julian Dominguez-Schatz
2b584e1ad0 Make double ctrl-f trigger browser-native search (#7605)
* Make double Ctrl-f trigger browser find

* Add release notes

* Invert condition

* Rename release note
2026-04-25 00:53:25 +00:00
dependabot[bot]
4f1bc3fcdd Bump postcss from 8.5.8 to 8.5.10 (#7613)
* Bump postcss from 8.5.8 to 8.5.10

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.8 to 8.5.10.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.8...8.5.10)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Add release notes for postcss version bump

Updated postcss version for maintenance.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>
2026-04-25 00:23:54 +00:00
Julian Dominguez-Schatz
ea50db524b Enable stricter electron build options (#7609)
* Enable stricter electron build options

* Add release notes

* Fix build signatures when no signing credentials are provided

* Attempt fix again
2026-04-24 23:59:28 +00:00
Julian Dominguez-Schatz
da1d0a94b9 Migrate file service to TypeScript (#7606)
* Migrate file service to TypeScript

* Add release notes

* Rabbit

* Stricter types
2026-04-24 22:50:43 +00:00
Alec Bakholdin
daab7f737e Import Transactions - Persist and set reimport deleted transactions config to true (#7610)
* fix: restored default functionality from v26.3.0 for reimport deleted transactions. import-reimport-deleted is now a synced pref that persists between imports

* release notes

* release note update

---------

Co-authored-by: Alec Bakholdin <alecbakholdin.com>
2026-04-24 18:21:45 +00:00
Emil Tveden Bjerglund
686f10247d Enhance Sankey chart datamodel, show income and allow layer filtering (#7582)
* Refactor to use directed, weighted graph as datamodel

* Fix percentage labels

* Reimplement sorting and topN handling

* Fix typing. Show toBudget on graph.

* Implement better DAG model

* Fix Other-grouping with new datamodel

* Add global sorting

* Reorder spreadsheet code for clarity

* Add percentageLabels back

* Fix all sorting modes

* Better color handling

* Handle if overbudgeted

* Fix filtering issue related to hidden nodes for Spent report

* Implement enums for special names

* Linting and typechecking

* Add layer selectors

* Trim SankeyCard

* Fix issue with empty nodes making the graph unreadable

* Add release note

* Update release note

* Reorder code

* Address coderabbit comments

* Ensure that layer-from and layer-to cannot be equal

* Update layer selectors to match selected view mode

* Fix wrong graph object reference

* Cap regex length

* Fixed wrong layer assignment for budget income categories

* Make translation not optional in createSpreadsheet

* Use predefined suffix for 'Other'

* Avoid invalid layer selection for Budgeted

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7582

* Import translation in spreadsheet, instead of passing as argument

* Remove all non-null assertions and handle safely

* Fix most uses of 'as'

* Fix issues hiding Other categories and giving wrong toBudget value

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-24 18:20:15 +00:00
Julian Dominguez-Schatz
227c995155 Disallow reconfiguring OpenID after initialization (#7608)
* Disallow reconfiguring OpenID after initialization

* Add release notes
2026-04-24 15:12:01 +00:00
dependabot[bot]
c8224d24be Bump @xmldom/xmldom from 0.8.12 to 0.8.13 (#7596)
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.12 to 0.8.13.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.12...0.8.13)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-version: 0.8.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 20:06:30 +00:00
Dakyne
29a06b23ea Add Gruvbox Light and Dark themes to custom theme catalog (#7571)
* Add Gruvbox Light and Dark custom themes to catalog

* Add release note for PR #7571

* [autofix.ci] apply automated fixes

* Update packages/desktop-client/src/data/customThemeCatalog.json

Co-authored-by: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>

---------

Co-authored-by: Dakyne <fawn_salable_73@icloud.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>
2026-04-23 14:25:05 +00:00
Matiss Janis Aboltins
aeb28d3b87 Add Discord notification for nightly theme catalog scan failures (#7595)
* [AI] Notify Discord when nightly theme catalog scan fails

Adds an if: failure() step to the validate-theme-catalog job that posts a
minimal alert to the DISCORD_WEBHOOK_URL webhook with a link back to the
failing workflow run. Fires on both theme validation failures (script exits
1) and earlier step failures (checkout/setup), so infrastructure breakage
is also surfaced. nofail: true keeps a Discord outage from cascading into
a red job.

* [AI] Drop setup comment from Discord notify step

* [AI] Move Discord notify to its own job gated by an environment

Splits the notify step into a separate notify-failure job that depends on
validate-theme-catalog and runs only on failure. The new job binds to the
nightly-alerts GitHub Environment so the DISCORD_WEBHOOK_URL secret is
scoped to a dedicated environment rather than inherited at the repo level
(zizmor secrets-without-environment).

* [AI] Add release notes for 7595

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-23 06:58:21 +00:00
dependabot[bot]
bd1da27404 Bump dompurify from 3.3.2 to 3.4.1 (#7591)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.3.2 to 3.4.1.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.3.2...3.4.1)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>
2026-04-22 20:51:12 +00:00