The dashboard did not reflect CLI progress for users across Windows and
Ubuntu. Three independent client defects, now fixed:
1. Automatic sync was silently skipped on any non-TTY shell. _trigger_submission
gated on `not sys.stdin.isatty()`, which is False on Windows Git Bash/MinTTY
and many IDE terminals even when interactive, so `tito module complete`
updated local progress.json but never uploaded, with no message. Decouple
"should we sync" (logged-in and not CI) from "should we prompt" (needs a
TTY): non-interactive real users now sync without a prompt instead of being
skipped.
2. A 2xx response with synced_modules null/0 was reported as success using the
local count, hiding backend failures. sync_progress now returns a SyncResult
and reports an honest accepted-but-unconfirmed warning when the server does
not confirm persistence.
3. No standalone resync path and login did not sync, so modules completed before
logging in never reached the dashboard. Add `tito community sync` and an
offer to sync existing progress after login.
The sync trigger decision now lives in one shared helper
(auto_sync_after_completion) used by the module, milestone, and login paths,
plus a small core/runtime.py that owns is_ci()/is_interactive(). Adds
tests/cli/test_progress_sync.py (15 tests) covering the non-TTY regression, the
CI/not-logged-in branches, honest 2xx interpretation, and the new command.