docs(balance): ADR 0015 + guide + architecture + CHANGELOG (#218) #227

Merged
maximus merged 1 commit from issue-218-docs into main 2026-06-10 01:09:07 +00:00
Owner

Resolves #218

Final docs link of the Étape 2 (per-security detail) stack. Stacked on #226 (issue-217-tests).

What changed (docs-only — no production TS/Rust logic touched)

  • ADR 0015 (docs/adr/0015-balance-detail-par-titre.md, Accepted): holdings-per-snapshot model; the aggregated-line-is-source-of-truth invariant (value = SUM(holdings.value), why Étape 2 is non-breaking — every aggregator + Modified Dietz per account reads only this value, cites ADR 0008); transaction-based alternative rejected (cites PP PR #779); latent gain (value − book_cost) vs per-security Modified Dietz (out of scope, needs dated per-lot flows); detailed_since authoritative pivot; security-immortal-once-referenced (ON DELETE RESTRICT, mirror of balance_account_transfers). Mirrors ADR 0014 structure.
  • Guide: new "Détail par titre" section in docs/guide-utilisateur.md (per-security entry, detail-account wizard, latent gain) and matching docs.balance.* i18n keys (FR + EN) — the in-app guide renders from those keys, so both surfaces were updated. FR/EN array parity verified.
  • architecture.md + CLAUDE.md: reconciled the stale DB counters to the real source-of-truth values — 20 tables / 24 indexes / 16 migrations (CLAUDE.md was "13/15/7", architecture.md "18/16" and migrations stopped at v9; both predate the whole Bilan feature). Étape 2 delta: +2 tables (balance_securities, balance_snapshot_holdings) + 2 indexes + migrations v14/v15/v16. Backfilled v10-v16 in the migrations table, fixed the ADR table (0012 Proposed→Rejected, added 0013/0014/0015), documented the new service surface (securities CRUD, transactional detailed save, latent gain).
  • CHANGELOG.md + CHANGELOG.fr.md [Unreleased]: extended (did not duplicate #214) with #215 (detail-account wizard, frozen history), #216 (drill-down + latent gain), #211 (existing priced accounts auto-converted to detailed 1-position). Bilingual parity.

Quality gate

  • npm run build (tsc + vite): PASS
  • npm test (vitest): PASS — 627/627 across 36 files
  • JSON locales valid, docs.balance.* FR/EN parity verified

Generated autonomously by /autopilot run of 2026-06-06

Resolves #218 Final docs link of the Étape 2 (per-security detail) stack. Stacked on #226 (issue-217-tests). ## What changed (docs-only — no production TS/Rust logic touched) - **ADR 0015** (`docs/adr/0015-balance-detail-par-titre.md`, Accepted): holdings-per-snapshot model; the **aggregated-line-is-source-of-truth** invariant (`value = SUM(holdings.value)`, why Étape 2 is non-breaking — every aggregator + Modified Dietz per account reads only this `value`, cites **ADR 0008**); transaction-based alternative **rejected** (cites **PP PR #779**); latent gain (`value − book_cost`) vs per-security Modified Dietz (out of scope, needs dated per-lot flows); `detailed_since` authoritative pivot; security-immortal-once-referenced (`ON DELETE RESTRICT`, mirror of `balance_account_transfers`). Mirrors ADR 0014 structure. - **Guide**: new "Détail par titre" section in `docs/guide-utilisateur.md` (per-security entry, detail-account wizard, latent gain) **and** matching `docs.balance.*` i18n keys (FR + EN) — the in-app guide renders from those keys, so both surfaces were updated. FR/EN array parity verified. - **architecture.md + CLAUDE.md**: reconciled the **stale** DB counters to the real source-of-truth values — **20 tables / 24 indexes / 16 migrations** (CLAUDE.md was "13/15/7", architecture.md "18/16" and migrations stopped at v9; both predate the whole Bilan feature). Étape 2 delta: +2 tables (`balance_securities`, `balance_snapshot_holdings`) + 2 indexes + migrations **v14/v15/v16**. Backfilled v10-v16 in the migrations table, fixed the ADR table (0012 Proposed→Rejected, added 0013/0014/0015), documented the new service surface (securities CRUD, transactional detailed save, latent gain). - **CHANGELOG.md + CHANGELOG.fr.md** `[Unreleased]`: **extended** (did not duplicate #214) with #215 (detail-account wizard, frozen history), #216 (drill-down + latent gain), #211 (existing priced accounts auto-converted to detailed 1-position). Bilingual parity. ## Quality gate - `npm run build` (tsc + vite): PASS - `npm test` (vitest): PASS — 627/627 across 36 files - JSON locales valid, `docs.balance.*` FR/EN parity verified Generated autonomously by /autopilot run of 2026-06-06
maximus added the
status:review
autopilot:pending-human
labels 2026-06-06 18:17:35 +00:00
maximus added 1 commit 2026-06-06 18:17:36 +00:00
Final docs link of the Étape 2 stack (#210-#217).

- ADR 0015 (Accepted): holdings-per-snapshot model; aggregated-line-is-source-of-truth invariant (why non-breaking, cites ADR 0008 Modified Dietz per account); transaction-based alternative rejected (PP PR #779); latent gain vs per-security Modified Dietz (out of scope); detailed_since authoritative pivot; security-immortal-once-referenced (ON DELETE RESTRICT). Mirrors ADR 0014 structure.
- Guide: new 'Détail par titre' section in docs/guide-utilisateur.md (per-security entry, detail-account wizard, latent gain) + matching docs.balance.* i18n keys (FR + EN, in-app guide surface).
- architecture.md + CLAUDE.md: reconciled stale DB counters to real values — 20 tables / 24 indexes / 16 migrations (were 13/15/7 and 18/16/v9). Étape 2 delta: +2 tables (balance_securities, balance_snapshot_holdings) + 2 indexes + migrations v14/v15/v16. Backfilled v10-v16 in the migrations table, ADR table (0012 Rejected, +0013/0014/0015), new securities/detailed-save/latent-gain service surface.
- CHANGELOG.md + CHANGELOG.fr.md [Unreleased]: extended with #215 (wizard), #216 (drill-down + latent gain), #211 (auto-conversion note); did not duplicate #214's per-security entry. Bilingual parity.

Docs-only: no production TS/Rust logic touched. Gate green: build (tsc+vite) + 627 tests pass.

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

Adversarial review — PR #227 (issue #218) · docs(balance): ADR 0015 + guide + architecture + CHANGELOG

Verdict : APPROVE — Link 9/9 (docs-only). Toutes les réconciliations de compteurs et les affirmations factuelles de l'ADR 0015 sont vérifiées exactes contre le code. Aucun blocant. Un seul should-fix (liens spec morts) sans impact sur l'exactitude technique.

Vérifié contre la réalité (head issue-218-docs)

Compteurs BDD — tous corrects :

Claim Vérification OK
20 tables grep -c CREATE TABLE consolidated_schema.sql = 20
24 index grep -c CREATE INDEX = 24 (15 existants + 7 v9 + 2 v14)
16 migrations lib.rs : 16 déclarations version: distinctes (v1→v16)
CLAUDE.md « module Bilan = 7 tables / 9 index » 7 balance_ tables, 9 idx_balance index
architecture.md tables (20), backfill v10–v16, table ADR (0012 Rejected, 0013/0014/0015 ajoutés) conformes

La correction des compteurs périmés (CLAUDE.md « 13/15/7 », architecture.md « 18/16 ») est exacte.

ADR 0015 — exactitude confirmée :

  • Status Accepted · cite ADR 0008 pour l'invariant source-de-vérité + Modified Dietz par compte (compute_account_return présent dans balance_commands.rs, enregistré dans lib.rs)
  • Rejette l'alternative transaction-based en citant PP PR #779
  • Gain latent vs Dietz par titre hors scope · detailed_since pivot faisant autorité · titre immortel ON DELETE RESTRICT
  • Schéma vérifié 1:1 dans consolidated_schema.sql : security_id … ON DELETE RESTRICT, snapshot_line_id … ON DELETE CASCADE, symbol TEXT NOT NULL COLLATE NOCASE UNIQUE, currency DEFAULT 'CAD', asset_type CHECK IN ('stock','crypto'), UNIQUE(snapshot_line_id, security_id)
  • v15 backfill (category.kind='priced'account.kind='detailed') et v16 (conversion 1-position, garde anti-perte) conformes à lib.rs
  • 11 fonctions service citées (validateDetailedSnapshot, computeUnrealizedGain, findOrCreateSecurity, getHoldingsForLatestSnapshot, etc.) toutes présentes dans balance.service.ts

CHANGELOG :

  • Étend le [Unreleased] existant, ne duplique pas #214 (#214 = saisie par titre ; #216 = drill-down + agrégation gain latent → surfaces distinctes)
  • Chaque ref nouvelle (#211/#214/#215/#216) apparaît exactement une fois
  • Parité FR/EN parfaite : distribution des refs identique entre CHANGELOG.md et CHANGELOG.fr.md ; en-tête FR [Non publié] correct

i18n docs.balance.* :

  • fr.json et en.json valides (JSON parse OK)
  • Parité de longueur des tableaux : features 17/17, steps 10/10, tips 8/8 ; overview + title présents des deux côtés

Should-fix (non-blocant)

  • docs/adr/0015-balance-detail-par-titre.md (ligne Spec: + section « Liens ») — référence deux fichiers spec inexistants : spec-decisions-bilan-detail-titres.md et spec-plan-bilan-detail-titres.md. Vérifié absents à head, sur main, et sur les 9 branches du stack (issue-210→218). Liens morts. L'ADR 0014 (le miroir structurel) ne cite aucun fichier spec — donc ce n'est pas imposé par le précédent ; le stack Étape 2 n'est apparemment pas passé par /spec. Impact nul sur l'exactitude technique (la vraie source de design, docs/audit-bilan-2026-05.md, existe et est correctement liée). Correctif : soit supprimer ces deux références, soit committer les specs si elles existent ailleurs. Reportable à une PR de suivi — ne bloque pas ce merge.

Note d'observation (hors PR)

  • docs/adr/0012-balance-two-level-model.md porte désormais Status: **Rejected** en tête (cohérent avec architecture.md), mais conserve plus bas une ligne historique **Status: Proposed.**. Incohérence interne dans l'ADR 0012, pas dans cette PR — à nettoyer un jour, hors scope ici.

Bilan : docs/i18n uniquement, zéro logique TS/Rust de production touchée. Documentation rigoureuse, fidèle à l'implémentation. Merge OK.

Review adversariale automatisée.

## Adversarial review — PR #227 (issue #218) · docs(balance): ADR 0015 + guide + architecture + CHANGELOG **Verdict : APPROVE** ✅ — Link 9/9 (docs-only). Toutes les réconciliations de compteurs et les affirmations factuelles de l'ADR 0015 sont vérifiées exactes contre le code. Aucun blocant. Un seul *should-fix* (liens spec morts) sans impact sur l'exactitude technique. ### Vérifié contre la réalité (head `issue-218-docs`) **Compteurs BDD — tous corrects :** | Claim | Vérification | OK | |---|---|---| | **20 tables** | `grep -c CREATE TABLE consolidated_schema.sql` = **20** | ✅ | | **24 index** | `grep -c CREATE INDEX` = **24** (15 existants + 7 v9 + 2 v14) | ✅ | | **16 migrations** | `lib.rs` : 16 déclarations `version:` distinctes (v1→v16) | ✅ | | CLAUDE.md « module Bilan = 7 tables / 9 index » | 7 `balance_` tables, 9 `idx_balance` index | ✅ | | architecture.md tables (20), backfill v10–v16, table ADR (0012 Rejected, 0013/0014/0015 ajoutés) | conformes | ✅ | La correction des compteurs périmés (CLAUDE.md « 13/15/7 », architecture.md « 18/16 ») est **exacte**. **ADR 0015 — exactitude confirmée :** - Status **Accepted** ✅ · cite **ADR 0008** pour l'invariant source-de-vérité + Modified Dietz **par compte** (`compute_account_return` présent dans `balance_commands.rs`, enregistré dans `lib.rs`) ✅ - Rejette l'alternative transaction-based en citant **PP PR #779** ✅ - Gain latent vs Dietz par titre **hors scope** ✅ · `detailed_since` pivot **faisant autorité** ✅ · titre immortel **ON DELETE RESTRICT** ✅ - Schéma vérifié 1:1 dans `consolidated_schema.sql` : `security_id … ON DELETE RESTRICT`, `snapshot_line_id … ON DELETE CASCADE`, `symbol TEXT NOT NULL COLLATE NOCASE UNIQUE`, `currency DEFAULT 'CAD'`, `asset_type CHECK IN ('stock','crypto')`, `UNIQUE(snapshot_line_id, security_id)` ✅ - v15 backfill (`category.kind='priced'` → `account.kind='detailed'`) et v16 (conversion 1-position, garde anti-perte) conformes à `lib.rs` ✅ - 11 fonctions service citées (`validateDetailedSnapshot`, `computeUnrealizedGain`, `findOrCreateSecurity`, `getHoldingsForLatestSnapshot`, etc.) **toutes présentes** dans `balance.service.ts` ✅ **CHANGELOG :** - Étend le `[Unreleased]` existant, **ne duplique pas #214** (#214 = saisie par titre ; #216 = drill-down + agrégation gain latent → surfaces distinctes) ✅ - Chaque ref nouvelle (#211/#214/#215/#216) apparaît **exactement une fois** ✅ - Parité FR/EN parfaite : distribution des refs identique entre `CHANGELOG.md` et `CHANGELOG.fr.md` ; en-tête FR `[Non publié]` correct ✅ **i18n `docs.balance.*` :** - `fr.json` **et** `en.json` valides (JSON parse OK) ✅ - Parité de longueur des tableaux : **features 17/17, steps 10/10, tips 8/8** ; `overview` + `title` présents des deux côtés ✅ ### Should-fix (non-blocant) - **`docs/adr/0015-balance-detail-par-titre.md` (ligne `Spec:` + section « Liens »)** — référence deux fichiers spec **inexistants** : `spec-decisions-bilan-detail-titres.md` et `spec-plan-bilan-detail-titres.md`. Vérifié absents à `head`, sur `main`, et sur **les 9 branches du stack** (issue-210→218). Liens morts. L'ADR 0014 (le miroir structurel) ne cite **aucun** fichier spec — donc ce n'est pas imposé par le précédent ; le stack Étape 2 n'est apparemment pas passé par `/spec`. **Impact nul sur l'exactitude technique** (la vraie source de design, `docs/audit-bilan-2026-05.md`, existe et est correctement liée). Correctif : soit supprimer ces deux références, soit committer les specs si elles existent ailleurs. Reportable à une PR de suivi — ne bloque pas ce merge. ### Note d'observation (hors PR) - `docs/adr/0012-balance-two-level-model.md` porte désormais `Status: **Rejected**` en tête (cohérent avec architecture.md), mais conserve plus bas une ligne historique `**Status: Proposed.**`. Incohérence interne **dans l'ADR 0012**, pas dans cette PR — à nettoyer un jour, hors scope ici. **Bilan :** docs/i18n uniquement, zéro logique TS/Rust de production touchée. Documentation rigoureuse, fidèle à l'implémentation. Merge OK. *Review adversariale automatisée.*
maximus changed target branch from issue-217-tests to main 2026-06-10 01:08:03 +00:00
maximus merged commit ae0f8150ff into main 2026-06-10 01:09:07 +00:00
Sign in to join this conversation.
No reviewers
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: maximus/Simpl-Resultat#227
No description provided.