Remove manual tagging

A tag could come from two places: rules.toml, or the TUI's t key, which wrote
manual_tag with COALESCE(manual_tag, rule_tag) deciding the winner. That split
paid for itself in the first invariant of the codebase, in ClearOverrides and
the c key, in the * marker on the tag column, and in the one exception to a
disposable index -- a tag set by hand was the only thing in index.db that the
statements could not reproduce.

Now rules.toml decides every tag. The index is derived entirely from the
statements plus that file, so deleting it and re-importing gets back exactly
what was there, and retag has nothing to be careful of. Tagging a one-off means
writing a narrow rule on screen 4, which previews what the glob catches before
it is saved.

A manual tag in an existing index is dropped along with the column the first
time this build opens it, and those rows read as whatever the rules say, or as
untagged. TestManualTagSurvivesRetag guarded the invariant that has just been
removed; TestRetagRewritesEveryTag replaces it with the one that took its
place, and keeps Retag itself covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 23:19:24 +02:00
co-authored by Claude Opus 5
parent 5ca6cff87b
commit 02814d09e5
10 changed files with 85 additions and 247 deletions
+8 -7
View File
@@ -21,8 +21,8 @@ tagged by glob rules you write.
2026-01.csv
```
\* Deleting the index loses the tags you set by hand, which live only there.
Everything else is re-derived from the statements.
\* Nothing lives only in the index: it is derived entirely from the statements
plus rules.toml, so deleting it and re-importing gets you exactly what you had.
## Where the data root lives
@@ -80,8 +80,7 @@ imported — creating an `account.toml` is not enough on its own. Run
| --- | --- |
| `1` `2` `3` `4` `5` / `tab` | accounts · transactions · report · rule builder · rules |
| `enter` | open the selected account (accounts view) |
| `t` | set the tag on the selected transaction |
| `c` | clear a tag set by hand, falling back to the rules |
| `4` | write a rule for what you are looking at — the only way to tag |
| `/` | filter by description |
| `u` | show only untagged transactions |
| `a` | clear the account filter |
@@ -222,9 +221,11 @@ match = "*LIDL*"
tag = "groceries"
```
Editing rules never touches tags you set by hand: rule verdicts and manual
overrides are stored separately, and the manual one always wins. `money retag`
is therefore safe to run whenever you change the file.
Every tag comes from this file, so a tag is never something you have to keep
safe: `money retag` recomputes all of them from the current rules and is safe
to run whenever you change it. A transaction no rule matches simply stays
untagged, and shows up under `money ls --untagged`, the `u` view, and
`(untagged)` in the report.
## account.toml