feat(app): ask 'how did it do?' when a harvest is noted (schema v13)

The note growers most wish they had two seasons later — did it do well,
was it worth keeping — never had a home. New append-only GardenOutcomes
table (lotId, season year, three-face rating, free note); the question
appears ONCE, inline, right after recording a harvest in the batch story,
and is skippable without a trace. The answer shows as one more story
line. Rides backups/sync like every mutable table (JSON codec, LWW
import, HLC clock absorb). Migration v12→v13 guarded + verified from
every historical version.
This commit is contained in:
vjrj 2026-07-18 12:18:25 +02:00
parent 92fd84590b
commit bb5b3d4a43
20 changed files with 6030 additions and 15 deletions

View file

@ -717,7 +717,18 @@
"created": "Added to your collection",
"from": "From {origin}",
"germinationResult": "Germination test — {percent}%",
"linkedEarlier": "Comes from an earlier batch"
"linkedEarlier": "Comes from an earlier batch",
"outcomeQuestion": "How did it do?",
"outcomeGood": "Well",
"outcomeMixed": "So-so",
"outcomePoor": "Poorly",
"outcomeNoteHint": "A note for your future self (optional)",
"outcomeSaved": "Noted",
"ratedGood": "It did well",
"ratedMixed": "It did so-so",
"ratedPoor": "It did poorly",
"outcomeTitle": "Season note",
"outcomeYear": "Season {year}"
},
"sale": {
"title": "Sales",

View file

@ -716,7 +716,18 @@
"created": "Entró en tu colección",
"from": "De {origin}",
"germinationResult": "Prueba de germinación — {percent}%",
"linkedEarlier": "Viene de un lote anterior"
"linkedEarlier": "Viene de un lote anterior",
"outcomeQuestion": "¿Qué tal se dio?",
"outcomeGood": "Bien",
"outcomeMixed": "Regular",
"outcomePoor": "Mal",
"outcomeNoteHint": "Una nota para tu yo del futuro (opcional)",
"outcomeSaved": "Anotado",
"ratedGood": "Se dio bien",
"ratedMixed": "Se dio regular",
"ratedPoor": "Se dio mal",
"outcomeTitle": "Nota de temporada",
"outcomeYear": "Temporada {year}"
},
"sale": {
"title": "Ventas",

View file

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 7
/// Strings: 3528 (504 per locale)
/// Strings: 3550 (507 per locale)
///
/// Built on 2026-07-18 at 04:22 UTC
/// Built on 2026-07-18 at 10:13 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View file

@ -2039,6 +2039,39 @@ class Translations$history$en {
/// en: 'Comes from an earlier batch'
String get linkedEarlier => 'Comes from an earlier batch';
/// en: 'How did it do?'
String get outcomeQuestion => 'How did it do?';
/// en: 'Well'
String get outcomeGood => 'Well';
/// en: 'So-so'
String get outcomeMixed => 'So-so';
/// en: 'Poorly'
String get outcomePoor => 'Poorly';
/// en: 'A note for your future self (optional)'
String get outcomeNoteHint => 'A note for your future self (optional)';
/// en: 'Noted'
String get outcomeSaved => 'Noted';
/// en: 'It did well'
String get ratedGood => 'It did well';
/// en: 'It did so-so'
String get ratedMixed => 'It did so-so';
/// en: 'It did poorly'
String get ratedPoor => 'It did poorly';
/// en: 'Season note'
String get outcomeTitle => 'Season note';
/// en: 'Season {year}'
String outcomeYear({required Object year}) => 'Season ${year}';
}
// Path: sale
@ -3277,6 +3310,17 @@ extension on Translations {
'history.from' => ({required Object origin}) => 'From ${origin}',
'history.germinationResult' => ({required Object percent}) => 'Germination test — ${percent}%',
'history.linkedEarlier' => 'Comes from an earlier batch',
'history.outcomeQuestion' => 'How did it do?',
'history.outcomeGood' => 'Well',
'history.outcomeMixed' => 'So-so',
'history.outcomePoor' => 'Poorly',
'history.outcomeNoteHint' => 'A note for your future self (optional)',
'history.outcomeSaved' => 'Noted',
'history.ratedGood' => 'It did well',
'history.ratedMixed' => 'It did so-so',
'history.ratedPoor' => 'It did poorly',
'history.outcomeTitle' => 'Season note',
'history.outcomeYear' => ({required Object year}) => 'Season ${year}',
'sale.title' => 'Sales',
'sale.help' => 'Record seed you sold or bought — money, Ğ1, or any currency. A separate model from a gift or a Plantare. No commission is ever taken on seeds.',
'sale.add' => 'Record a sale',

View file

@ -1046,6 +1046,17 @@ class _Translations$history$es extends Translations$history$en {
@override String from({required Object origin}) => 'De ${origin}';
@override String germinationResult({required Object percent}) => 'Prueba de germinación — ${percent}%';
@override String get linkedEarlier => 'Viene de un lote anterior';
@override String get outcomeQuestion => '¿Qué tal se dio?';
@override String get outcomeGood => 'Bien';
@override String get outcomeMixed => 'Regular';
@override String get outcomePoor => 'Mal';
@override String get outcomeNoteHint => 'Una nota para tu yo del futuro (opcional)';
@override String get outcomeSaved => 'Anotado';
@override String get ratedGood => 'Se dio bien';
@override String get ratedMixed => 'Se dio regular';
@override String get ratedPoor => 'Se dio mal';
@override String get outcomeTitle => 'Nota de temporada';
@override String outcomeYear({required Object year}) => 'Temporada ${year}';
}
// Path: sale
@ -2055,6 +2066,17 @@ extension on TranslationsEs {
'history.from' => ({required Object origin}) => 'De ${origin}',
'history.germinationResult' => ({required Object percent}) => 'Prueba de germinación — ${percent}%',
'history.linkedEarlier' => 'Viene de un lote anterior',
'history.outcomeQuestion' => '¿Qué tal se dio?',
'history.outcomeGood' => 'Bien',
'history.outcomeMixed' => 'Regular',
'history.outcomePoor' => 'Mal',
'history.outcomeNoteHint' => 'Una nota para tu yo del futuro (opcional)',
'history.outcomeSaved' => 'Anotado',
'history.ratedGood' => 'Se dio bien',
'history.ratedMixed' => 'Se dio regular',
'history.ratedPoor' => 'Se dio mal',
'history.outcomeTitle' => 'Nota de temporada',
'history.outcomeYear' => ({required Object year}) => 'Temporada ${year}',
'sale.title' => 'Ventas',
'sale.help' => 'Registra semilla vendida o comprada — dinero, Ğ1 o cualquier moneda. Un modelo aparte del regalo y del Plantare. Nunca se cobra comisión por las semillas.',
'sale.add' => 'Registrar venta',