Adds unit tests for the community submission flow: payload schema
(assemble_payload), the 200 success path, and the 401 token-refresh path,
plus an opt-in live end-to-end test that self-skips without credentials.
Corrects two assertions to match the current handler: sync_progress returns
a SyncResult (check .ok, not identity against True), and the success message
is "Sync successful!" (lowercase). The three unit tests pass locally.
From #1886, test files only; the bundled guard.js/auth.js auth change is left
for a separate, reviewable PR.
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.
Remove the doctor/health alias duplication in favor of a single
'tito system health' command for environment validation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)