docs(adr-022): taxonomie des catégories + catégorisation assistée 100 % locale#269
Merged
Conversation
Fourteen agents read the actual code and studied the market, a synthesis agent turned it into a roadmap, and three adversarial critics were told to destroy that roadmap rather than approve it. This is the revision that survived them. Three premises of the original request turned out to be false, and each changes what needs building. Editing an expense already works. ExpenseEditDrawer.tsx is 217 lines, mounted at ExpensesClient.tsx:337, calls updateExpenseAction and has four test blocks. Its trigger is a muted pencil sitting next to a red bin that takes the eye. An affordance defect, not missing code — repaired in step 1 for almost nothing. Real categories already exist too. The table has shipped since the initial schema, eight are seeded at every signup with colour tokens, expenses.category_id exists, the Zod schema carries it and createExpenseAction writes it. Two lines of UI unplug the whole thing: categoryId: null hardcoded, and an RSC mapping that drops the field before it reaches the component. Not a model to redesign, a wire to reconnect. And the menus are not the problem. The navigation exposes six table names as seven equal-rank destinations, three of which describe the same mental act — money going out. No visual redesign fixes that, which is why polish is deliberately last rather than first. The market study reframes the product itself: Belgian banks already ship free automatic categorisation, so manual entry loses that fight outright. What none of them knows is what is already committed — and that figure cannot be derived from a transaction history, it has to be declared. It is the one thing PSD2 will never supply, which turns the missing aggregation from a handicap into the position. Seventeen steps, one branch each, ordered so no step depends on a later one. Step 1 is deliberately small and independently shippable, per the rule that nothing starts until it is finished. The critics earned their place. They killed an ON DELETE SET NULL that would have made deleting a category impossible on three tables at once, forced a rollback gate on every migration (one Supabase project, Free tier, no PITR, a real user), and pushed the only remaining migration off the critical path entirely.
… at entry @Thierry asked for sub-categories so charts could break spending down. The goal is right; the mechanism would have cost more than it returns, so this ADR takes a different route to the same result and says why. A two-level pick doubles the cost of every expense recorded. The market study is unambiguous about what kills manually-entered budget apps — Goodbudget, the closest comparable to Ankora: "if you go three days without opening the app, you have a backlog of transactions to remember and enter". Entry friction ends the product before any chart gets used. So: a flat list at entry, a group column on the category for aggregation. One gesture for the user, two levels in the charts — "Vie courante 640 €" unfolds into Courses, Restaurant, Carburant. Eighteen categories across five groups. The eight already seeded are kept verbatim, because production rows reference them and renaming would break the history. Ten are added, all for day-to-day spending, which is what the original eight were missing — they are a fixed-charges taxonomy, and without the addition most manual entries would land in "Autres". Assisted categorisation turns out to be an advantage rather than catching up. Belgian banks categorise because they see your transactions; KBC files the feature under Privacy, framed as a convenience you grant. Ankora reads the label you type and nothing leaves the server. Rules are learned from your own corrections — Actual's mechanism — over a seed dictionary of Belgian merchants so the first month is not an empty screen. The correction offers "this once" or "always for this label" inside the flow, per Revolut, rather than in a separate rules screen. The free colour picker stays banned: an arbitrary hex breaks WCAG AA contrast and the visual contract. That is a design decision, not a limitation. NORTH_STAR's "8 mandatory dashboard sections" from April collide with July's "the users are lost". A list of mandatory sections constrains content where the problem is hierarchy, so "no important question left unanswered" replaces it. One invariant to test rather than assume: the category enters no calculation. Changing an expense's category must move no aggregate. That is what keeps a wrong taxonomy cheap to correct.
Contributor
There was a problem hiding this comment.
Sorry @thierryvm, your pull request is larger than the review limit of 150000 diff characters
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tranche les deux arbitrages que tu m'as délégués. Décision uniquement, zéro code.
Je ne fais pas exactement ce que tu as demandé — voici pourquoi
Tu voulais des sous-catégories pour générer des graphiques. L'objectif est juste, le moyen coûterait cher : un choix à deux niveaux double le coût de chaque saisie.
L'étude de marché est sans appel sur ce qui tue les apps à saisie manuelle. Goodbudget, le comparable le plus direct d'Ankora : « si vous passez trois jours sans ouvrir l'app, vous avez un arriéré de transactions à retrouver et à saisir ». La friction de saisie tue le produit avant que le graphique n'ait servi.
Ma décision : liste plate à la saisie, colonne
groupsur la catégorie pour l'agrégation. Un seul geste pour toi, deux niveaux dans les graphiques — « Vie courante 640 € » se déplie en Courses, Restaurant, Carburant.Tu obtiens le résultat visé sans en payer le prix.
La taxonomie — 18 catégories, 5 groupes
ᴱ = existante, conservée telle quelle (des lignes en prod la référencent, la renommer casserait l'historique).
18 et pas 60 : Monarch en livre ~60, mais sa propre recommandation de praticien est 3-6 groupes × 3-12 catégories. Au-delà, on ne choisit plus — on prend la première qui ressemble, ou « Autres ».
Oui, l'automatisation est faisable — et c'est un avantage
Les banques belges catégorisent parce qu'elles voient tes transactions. KBC range d'ailleurs la fonction sous « Privacy », présentée comme un confort que tu accordes.
Ankora lit le libellé que tu tapes. Rien ne quitte le serveur.
Désactivable, avec la liste des règles apprises supprimables une par une.
NORTH_STAR
« Aucune question importante sans réponse » remplace « 8 sections obligatoires ». Une liste de sections contraint le contenu là où ton problème est la hiérarchie.
L'invariant à tester, pas à supposer
La catégorie n'entre dans aucun calcul. Changer la catégorie d'une dépense ne doit déplacer aucun montant agrégé. C'est ce qui rend une taxonomie ratée bon marché à corriger.
Fichier :
docs/adr/ADR-022-taxonomie-categories-et-categorisation-assistee.md