You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Corrected 2 Sep 2026 against main: both inputs now exist, so this ticket is unblocked. #141 landed (closed) — the active-day set is stored and the streak derives from it. And the card model now does distinguish the five module collectibles: CollectibleUnlock carries exactly one of lessonId / moduleId, and the bank holds 32 lesson-unlocked and 5 module-unlocked cards — the Module Reward count is a pure derivation, with no content-model change owed. The screen still shows the substitutions ('Cards collected' / 'Day streak', course_completion_screen.dart), so the ask stands.
Parent
Follow-up owed by #120's build notes: the two completion-moment stats #128 shipped as substitutions, upgraded to what the spec asked for once their inputs exist.
What to build
The Foundations completion moment shows three stats. Two shipped as flagged substitutions (#120 build notes) because their spec form was not derivable at the time:
"Cards collected" → the Module Reward count. The spec names "every Field Guide" — the five module collectibles — but the card model does not distinguish them from lesson cards. Settle the distinction by derivation (e.g. the module-reward ids are already known content-side), not by a new stored marker; if it needs a content-model change, that goes back to the extractor's owner as a question first.
Both changes are label + derivation swaps on the existing screen; the moment's structure, firing rule and hand-off are untouched.
Acceptance criteria
The completion moment shows the longest streak, derived purely from the active-day set — verified against a day set holding a broken streak (e.g. 5 then gap then 3 shows 5)
The Module Reward stat counts exactly the module collectibles, derived, with the derivation's source named in the code
No new stored field anywhere; a reset leaves nothing behind
The screen's stat labels match what they actually show
Unit tests cover the longest-streak derivation (gap cases) and the Module Reward derivation; the existing widget tests are updated to the new labels
Vocabulary note (22 Aug 2026). This ticket was written when the five module collectibles were called Field Guides. CONTEXT.md now rules them Module Rewards and lists Field Guide under Avoid (#106, swept in #222). The title and criteria above are updated; the quoted phrase "every Field Guide" is left as-is, because it quotes the design spec as it was written. Nothing this ticket asks for changes — only the name of the thing being counted.
Built — PR #557. What verified each box: the longest-streak cases (5-gap-3 reads 5, three-then-five reads 5, an abandoned history keeps its best, a freeze-covered miss joins one run rather than two) are in streak_engine_test.dart, and the property test's day-by-day oracle now derives the longest run independently and agrees. The Module Reward count is checked against the real bank in collected_module_rewards_test.dart — 5 of 37, and 5 for a full collection. Nothing is stored: both come off the day set and the owned-collectible set a reset already clears. The screen was driven on a simulator with a nine-day run behind a gap and a live three-day one, and showed 9.
Parent
Follow-up owed by #120's build notes: the two completion-moment stats #128 shipped as substitutions, upgraded to what the spec asked for once their inputs exist.
What to build
The Foundations completion moment shows three stats. Two shipped as flagged substitutions (#120 build notes) because their spec form was not derivable at the time:
Both changes are label + derivation swaps on the existing screen; the moment's structure, firing rule and hand-off are untouched.
Acceptance criteria
Blocked by
Vocabulary note (22 Aug 2026). This ticket was written when the five module collectibles were called Field Guides.
CONTEXT.mdnow rules them Module Rewards and lists Field Guide under Avoid (#106, swept in #222). The title and criteria above are updated; the quoted phrase "every Field Guide" is left as-is, because it quotes the design spec as it was written. Nothing this ticket asks for changes — only the name of the thing being counted.Built — PR #557. What verified each box: the longest-streak cases (5-gap-3 reads 5, three-then-five reads 5, an abandoned history keeps its best, a freeze-covered miss joins one run rather than two) are in
streak_engine_test.dart, and the property test's day-by-day oracle now derives the longest run independently and agrees. The Module Reward count is checked against the real bank incollected_module_rewards_test.dart— 5 of 37, and 5 for a full collection. Nothing is stored: both come off the day set and the owned-collectible set a reset already clears. The screen was driven on a simulator with a nine-day run behind a gap and a live three-day one, and showed 9.