Tab switching: _buildTabs was recreating TabController on every build
because `_tabs == tabs` compares List by reference identity, not content.
programmerTasksTabsFor() always returns a new list, so the guard was
always false, resetting the controller to initialIndex 0 on every tap.
Fixed by using listEquals from flutter/foundation.
Help given: computeProgrammerStats accumulated helpGivenThisMonth only
from approvedSnapshot rows, which only exist after admin approval.
Programmers who helped others but had pending sheets saw 0m indefinitely.
Fixed by adding helpGivenThisMonthProvider (FutureProvider.family) that
queries programmer_task_work_logs directly for the current Manila month,
and passing it as liveHelpThisMonthSec to computeProgrammerStats.
Co-Authored-By: claude-flow <ruv@ruv.net>
Add ProgrammerDaySheet model with DaySheetStatus/DaySheetSnapshot,
computeProgrammerStats with streak, first-pass rate, approved totals,
hasCleanWeek, and tiered badge progress via computeBadges. 10 tests pass.
Co-Authored-By: claude-flow <ruv@ruv.net>
- Add Delta JSON happy-path test case to deltaJsonToPlainText tests
- Fix double-row bug: notes-only assignee rows only when userId == assigneeId
- Remove dead code: tautological taskMap.containsKey check in loop
Co-Authored-By: claude-flow <ruv@ruv.net>
- Add workDate field to ProgrammerTaskWorkLog (defaults to Manila day of createdAt)
- Add deltaJsonToPlainText function to quill_field.dart for Delta/plain text conversion
- Implement buildDayRows function to generate day sheet rows with proper sorting
- Implement DaySheetRow serialization and deserialization
- Add comprehensive tests for day rows builder and workDate field
- Verify backward compatibility via existing programmer_task_ledger_test
Co-Authored-By: claude-flow <ruv@ruv.net>
Capture whether segment was running before reassignment, and only reopen
for new assignee if it was. A paused task that gets reassigned should not
start accruing time for the new assignee until explicitly resumed.
Also add test: reassignment while paused does not open segment.
Co-Authored-By: claude-flow <ruv@ruv.net>
Implement daily time tracking and splitting for programmer tasks across
Manila midnights with proper assignee attribution, including support for
pauses, reassignments, and adjustments.
Co-Authored-By: claude-flow <ruv@ruv.net>
Separate feature for the `programmer` role to record dev work by category,
distinct from the IT help-desk `tasks` feature. Modeled on the IT Service
Requests pattern (Brick offline-first model -> Riverpod stream/controller ->
list/detail screens); seed of a future Project Management workflow.
- programmer_tasks + programmer_task_activity_logs (category enum, RLS,
realtime) via supabase migration
- single assignee, self-logged or lead-assigned; assign/reassign logged
- pause-on-switch: starting a task while another runs prompts to pause the
running one, keeping one active task per user for accurate time attribution
- worked-duration math shared with help-desk tasks via a generic core in
task_duration.dart (existing callers unchanged)
- list distinguishes running vs paused with a per-task Resume shortcut
- accessible dialog labels; route /programmer-tasks + nav gated to admin/programmer
- unit/widget tests: controller lifecycle, duration math, pause-switch dialog
Co-Authored-By: claude-flow <ruv@ruv.net>