Before code

This commit is contained in:
vjrj 2026-07-07 13:20:00 +02:00
parent 23c12ac60c
commit 57c0eeadaf
3 changed files with 45 additions and 1 deletions

View file

@ -14,6 +14,7 @@ Context for AI agents (Claude Code) working in this repo. Read this first, then
- **Local-first**: everything works offline, no account, no central server. Online only enriches (degrades gracefully).
- **Progressive disclosure**: only `Variety.label` is mandatory; every other field optional. Audience is everyone 1080; simple by default, depth on demand. Never build "two modes".
- **License: AGPL-3.0.** Keep new deps compatible.
- **Tests, near-TDD.** Every behavior is covered by automated tests (unit / widget / integration); **do NOT rely on manual testing.** Write tests first for domain logic (`commons_core` is pure Dart — ideal for TDD). Nothing merges without tests covering the new behavior; CI gates it. See [`docs/design/testing.md`](docs/design/testing.md).
- Discussion/design docs may be in Spanish; code and specs in English.
## Stack & structure

View file

@ -6,6 +6,8 @@
Una persona puede: abrir la app, **añadir una semilla en 20 s** (etiqueta + foto + cantidad), verla en una lista por categorías, abrir su ficha, editarla con campos avanzados plegados, y que **todo persista cifrado** entre reinicios. Multilingüe (al menos ES/EN). Corre en un dispositivo/emulador real.
**Cada historia se entrega con sus tests** (unit/widget/integration) — casi-TDD, sin pruebas manuales como red de seguridad. Ver [`testing.md`](testing.md). Sin tests, la historia no está hecha.
## Pasos
0. **Prerequisitos (máquina):** Flutter SDK actualizado, un emulador o dispositivo. Quitar los locks del bare si hiciera falta (`rm -f ~/repos/tane.git/*.lock`).
@ -37,7 +39,8 @@ Una persona puede: abrir la app, **añadir una semilla en 20 s** (etiqueta + fot
6. **Catálogo de especies (semilla del bundle):** empezar con un CSV/JSON pequeño curado (unas pocas hortícolas ibéricas) con `scientific_name` + `wikidata_qid` + `gbif_key` + nombres comunes ES/EN, para probar el autocompletado. La "varilla" y Kew SID vienen después.
7. **Verificación:** `flutter analyze` limpio, `flutter test` (incl. test de migración), y arrancar en dispositivo. Añadir el texto canónico de la licencia: `curl -o LICENSE https://www.gnu.org/licenses/agpl-3.0.txt`.
7. **Tests y CI (transversal, no al final):** ver [`testing.md`](testing.md). Como mínimo en este sprint: unit de `commons_core` (Quantity, columnas comunes, UUIDv7/HLC), **test de migración** Drift, **test de "no hay texto en claro"** en el fichero de BD, widget tests de la lista y del alta rápida, y **un integration test** del flujo "alta → persiste cifrada → reabrir → sigue ahí". Montar CI (analyze + test + cobertura) desde el primer commit de código.
8. **Verificación final:** `flutter analyze` limpio, toda la suite en verde en emulador, cobertura publicada. Añadir el texto canónico de la licencia: `curl -o LICENSE https://www.gnu.org/licenses/agpl-3.0.txt`.
## Fuera de alcance de este sprint (no hacer)

40
docs/design/testing.md Normal file
View file

@ -0,0 +1,40 @@
# Tanemaki — Estrategia de pruebas (casi-TDD, sin depender de pruebas manuales)
*Convención del proyecto. Objetivo: **cada comportamiento cubierto por una prueba automática**; las pruebas manuales son la excepción, no la red de seguridad.*
## Principio
**Casi-TDD.** Para lógica nueva: test primero (red → green → refactor). Como mínimo innegociable: **ninguna rama se mergea sin tests que cubran lo nuevo.** La "definición de hecho" de cada historia **incluye sus tests**; sin tests, no está hecha. CI en cada push bloquea si algo falla o baja la cobertura.
`commons_core` es **Dart puro (sin Flutter)** → la lógica difícil (CRDT, identidad/derivación, cifrado, backup, pledge/WoT) se hace con TDD cómodo y rápido.
## La pirámide (Flutter/Dart)
- **Unit** (`dart test` / `flutter test`): lógica pura — CRDT, `Quantity`, derivación de claves, serialización, repositorios. Rápidos; el grueso vive en `commons_core`.
- **Widget** (`flutter_test`, `pumpWidget`): pantallas y componentes — interacción, *progressive disclosure*, i18n, accesibilidad (targets grandes).
- **Integration** (`integration_test` + `flutter test`): app entera en emulador/dispositivo, con **BD real cifrada (SQLCipher)**. Flujos e2e — **esto es lo que sustituye a las pruebas manuales.**
- **Golden** (regresión visual): pantallas clave; vigila que la accesibilidad no se rompa.
- **Migration** (Drift): `drift_dev schema generate` + `validateDatabaseSchema` por cada `schemaVersion`.
## Tests que este proyecto necesita sí o sí
- **Cifrado en reposo:** abrir el fichero de BD **en crudo** y afirmar que **NO hay texto en claro** (buscar una etiqueta conocida en los bytes y exigir ausencia). Regresión de seguridad clave para el "peor caso legal".
- **CRDT — convergencia:** *property-based* — fusionar operaciones en **cualquier orden** converge al mismo estado (LWW, OR-Set, log append-only, tombstones).
- **Migraciones:** cada versión migra desde la anterior y valida contra el esquema fresco.
- **Backup round-trip:** exportar → borrar → importar → **estado idéntico** (y cifrado).
- **Identidad:** derivación secp256k1 **determinista** desde la semilla (mismo input → misma clave) y unidireccional.
- **i18n:** ninguna cadena hardcodeada (lint), y todas las locales con las mismas claves.
## Lo difícil de automatizar (y cómo)
Cámara, keystore/biométrico, relays reales: **abstraer tras interfaces** y probar con *fakes/mocks*; dejar una capa fina de adaptadores de plataforma con un *smoke test* mínimo. Los *integration tests* en dispositivo cubren la integración real de la BD cifrada. Objetivo: **manual ≈ 0**.
## CI y cobertura
- CI en cada push/PR (Forgejo/Codeberg Actions o GitHub Actions): `flutter analyze` + unit + widget + **integration en emulador** + cobertura (lcov). **Merge bloqueado** si falla o baja la cobertura.
- Objetivo de cobertura **alto en `commons_core`** (p.ej. ≥ 85%); la UI, con widget + golden.
- Tests deterministas y rápidos: sin red real, reloj/UUID/HLC inyectables (para reproducibilidad).
## Flujo de trabajo
Dominio (`commons_core`): test primero. UI: al menos un widget test por pantalla/flujo antes de darla por terminada, y un *integration test* por flujo crítico (alta de semilla → persiste cifrada → reabrir → sigue ahí). Regla dura repetida: **sin tests, no se mergea.**