Skip to content

[2G-Bug-02]: Credit habit_completions rows toward evaluate_graduation "Already done" rate on expired nudges - #196

Merged
WilliM233 merged 1 commit into
developfrom
feature/2G-Bug-02-evaluate-graduation-hybrid-credit
Apr 19, 2026
Merged

WilliM233 merged 1 commit into
developfrom
feature/2G-Bug-02-evaluate-graduation-hybrid-credit

Conversation

@WilliM233

Copy link
Copy Markdown
Owner

Verification

  • ruff check . — ✅ Pass (All checks passed!)
  • pytest -v — ✅ Pass (1292 passed, 4 skipped)
  • Migration applied locally on brain3-dev: N/A (no schema change)
  • Postgres-backed test confirmed: N/A (pure ORM logic; no Postgres-specific behavior)

Ran locally against develop HEAD at 90d6989 immediately before opening this PR.

Summary

evaluate_graduation now credits a same-date habit_completions row when an expired nudge has no response. The result: a user who completes a habit through any path (direct complete, routine cascade, reconciliation) gets credit toward graduation — not only when they explicitly tap "Already done" on a nudge. This is the ADHD quality lens in action: multiple low-friction completion paths work better than a single path, and all of them feel like "I did it" to the user.

Explicit responses still win. An explicit "Already done" counts on its own (back-compat preserved). An explicit non-"Already done" response (e.g., "Skip today") is never overridden by a completion row — a user saying "no" to a nudge means no, even if reconciliation later recorded a completion.

Changes

  • app/services/graduation.py — evaluate_graduation now queries habit_completions over the evaluation window and builds a set of completion dates. The already_done_count derivation iterates notifications: "Already done" responses count as before; expired notifications with response IS NULL count if a same-date completion exists; all other explicit responses are untouched. GraduationResult shape unchanged.
  • tests/test_graduation.py — new TestEvaluateGraduationHybridCredit class covers the five acceptance tests from the issue (routine-cascade credit, individual credit, no-credit-without-row, no-credit-on-date-mismatch, explicit-"Already done" back-compat) plus an explicit-negative-override guard.

How to Verify

  1. git checkout feature/2G-Bug-02-evaluate-graduation-hybrid-credit
  2. ruff check . — passes clean
  3. pytest -v tests/test_graduation.py — all 160 graduation tests pass, including the 6 new hybrid-credit tests
  4. pytest -v — full suite: 1292 passed, 4 skipped

Deviations

None. Implementation matches the GitHub issue acceptance criteria and [2G-01] v2 Amendment 12.

Per Wave 2 brief guidance (D7, Wave 3 #186): the hybrid-credit logic here is deliberately inline. Duplication with the companion step-down fix (#185) is expected and retained — the shared read_completion_history helper refactor lands in Wave 3 as #186.

Test Results

```
$ ruff check .
All checks passed!

$ pytest -v
====================== 1292 passed, 4 skipped in 21.73s =======================
```

New tests in TestEvaluateGraduationHybridCredit:

  • test_routine_cascade_completion_credited_toward_graduation
  • test_individual_completion_credited_toward_graduation
  • test_no_credit_when_no_completion_row
  • test_no_credit_when_date_mismatch
  • test_response_already_done_still_counts_without_completion_row
  • test_explicit_negative_response_not_overridden_by_completion

All existing graduation tests continue to pass (AC #6).

Acceptance Checklist

  • evaluate_graduation reads both notification_queue.response='Already done' and habit_completions rows dated to expired-nudge dates
  • Expired notification with response IS NULL + matching same-date HabitCompletion → counted toward already_done_count
  • Explicit "Already done" continues to count regardless of completion-row presence (back-compat)
  • Non-"Already done" responses (e.g., "Skip today") are NOT overridden by a completion row
  • GraduationResult response shape unchanged; only already_done_count / derived current_rate differ
  • All existing graduation tests continue to pass
  • New integration tests added (see above)

Closes #184

…ation (#184)

Expired nudges with no response are now credited when a HabitCompletion
row exists for the same date. Preserves back-compat: explicit 'Already
done' responses still count, and explicit non-'Already done' responses
(e.g., 'Skip today') are never overridden.

Implements D5 hybrid credit per [2G-01] Amendment 12 — reflects the
ADHD quality lens that multiple low-friction completion paths (direct
complete, routine cascade, reconciliation) all represent 'I did it'
from the user's perspective.

Duplication with evaluate_frequency_step_down (#185) is expected and
retained; the shared read_completion_history helper refactor lives in
Wave 3 (#186).
@WilliM233
WilliM233 merged commit 2d0a13a into develop Apr 19, 2026
2 checks passed
@WilliM233
WilliM233 deleted the feature/2G-Bug-02-evaluate-graduation-hybrid-credit branch April 19, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2G-Bug-02]: Credit habit_completions rows toward evaluate_graduation "Already done" rate on expired nudges

1 participant