The statement is ready. Goal: close the remaining remarks. The site gets an icon and the requests answered with 404 disappear, make check and CI start to check formatting, the checks run on a pull request into main, and the expenses section file and the money file are brought to the project rules. The behavior of the app does not change.
A plan of five commits, after each make check is green.
First: the constant of kopecks in a ruble is no longer exported, it is needed only inside the function that shows rubles, nobody uses it outside.
Second: the expenses section is split into functions of one action each without changing the markup, texts, attributes and behavior. Building the form is moved into a separate function with a description of the form fields, reading and checking the form return either an expense or an error, and the branching by the result is exhaustive. Submitting the form only names the steps: read the form, add the expense, check the sum limit, reset the form, change the bill. Filling the payer list and the recipient checkboxes is split into two actions. The description of the recipients is moved into a separate function: this way the chain of map and join inside the ternary operator and the template string disappears. The redraw only names the steps. Nesting no deeper than two levels, no new files.
Third: the site icon as an SVG file in the public directory, a coin split in half, in the colors from the styles, without external links and fonts; in index.html a link to it before the heading. Checked in a copy of the project: with a relative base path Vite rewrites the link and copies the file into the build, from the deployment subdirectory the file answers 200 with the type image/svg+xml.
Fourth: a formatting check script, a Makefile target that stands first in make check as the cheapest, and a line in the README. The Prettier ignore file does not change: the generated files and the journal are already in it, the current tree passes the check.
Fifth: the workflow "Checks" on pull request into main with read-only permissions, cancelling the previous run of the same branch, installing Node 22 with the npm cache, installing dependencies and make check; the action versions are the same as in the deployment. The README is extended with lines about the checks on PRs.
Accepted decisions. The icon lies as a file in the public directory, not as a data URI: this is simpler to read and edit, and Vite itself makes the link relative. We do not introduce a reusable workflow: only the installation of three steps is shared, and the checks themselves are already described in one place, in make check; extracting the installation would require passing the deployment artifact through a called workflow, and there would be more complexity than duplication. The Makefile target is called format-check, the script is format:check. The cancellation group is taken by the branch of the pull request. The ignore file does not need to be changed, the stop hook will not fail on the files that it writes itself.
Done criteria: make check is green and checks formatting as the first step, with a broken indent it fails; the formatting check passes; the constant export is removed; all tests pass without changing the expectations; in the expenses section there is no map and join inside a template or a ternary operator, nesting is no deeper than two, the redraw only calls named steps; the build has a link to the icon and the icon file, from a subdirectory it is served with 200; the workflow triggers on pull request into main with the needed permissions and cancellation; the README reflects everything said.
New tests are not needed: the refactoring is fixed by the existing DOM tests.
Out of scope: refactoring of other interface sections, the sections "Code and tests" and "Tasks" in AGENTS.md, merging the workflows, favicon.ico, the icon for Apple devices and the manifest. About AGENTS.md I will note to the human: it says that the domain logic lies in two directories, while ESLint and the README also attribute the sharing directory to it, so the file lags a little behind the code; the section "Tasks" is empty.