Study Focus (Desktop Pomodoro + Incentive System)
D:\daima\cursor\合作项目
2026-03-07
Record completed backend, frontend, and desktop-guard milestones, plus debugging actions and verification outcomes.
- Implemented auth APIs (
register,login) with JWT. - Implemented dictionary APIs (
regions,schools,colleges). - Implemented user profile APIs (
get me,update me).
- Implemented focus session APIs:
- start
- complete
- interrupt
- abandon
- list
- Implemented point APIs:
- balance
- ledger list
- Implemented leaderboard API:
- period: day/month/year
- scope: school/college
- Implemented daily question API.
- Implemented AI chat API.
- Added provider adapter support:
- openai-compatible
- anthropic-compatible
- Implemented redeem order APIs:
- create order (deduct points)
- list my orders
- get order detail
- verify by coupon token
- cancel order (refund points)
- Added anti-repeat verification checks and status transitions.
- Created standalone frontend workspace in
frontend/. - Implemented dashboard-style single-page UI with:
- login
- register
- profile summary
- focus controls
- active countdown timer
- session history
- point balance and ledger
- leaderboard
- daily question
- AI chat
- redeem order create/verify/list
- Added exact local startup instructions in
frontend/README.md.
- Created standalone desktop workspace in
desktop/. - Added Electron shell entry files:
main.jspreload.js
- Added medium-strength local guard service:
- blocked app process watch on Windows
- always-on-top / maximize focus window policy
- optional blocked-site control through a managed hosts-file section
- Wired frontend and desktop bridge together:
- guard status display
- guard event log
- auto-interrupt the running session when a blocked app is detected
- Upgraded frontend visuals and testing guidance:
- quick-fill register/login actions
- better hero and panel hierarchy
- clearer browser-vs-desktop separation
- Installed Electron dependencies inside the project workspace.
- Kept this install cache local to
desktop\.npm-cachethrough a one-time environment variable. - Avoided creating
.npmrcand avoided changing long-term npm configuration. - Confirmed
npm run checkpassed after install.
pip install -e .failed (TOMLDecodeError): fixed by removing BOM frompyproject.toml.- MySQL connection refused (
10061): fixed by starting MySQL service and validating port3306listening. - MySQL access denied (
1045): fixed by correcting root password and syncing.envDB credentials. - PowerShell script parameter conflict (
Hostis reserved/read-only): fixed by renaming toDbHost/DbPort/DbUser. - SQL seed import failed under Chinese path: avoided
SOURCE <path>dependency and switched to path-safe script execution. seed_demo.ps1became corrupted during edits: rewrote the script from scratch and revalidated parser syntax.- bcrypt warning/error with passlib (
password > 72 bytesbehavior mismatch): pinnedbcrypt==4.0.1for compatibility. uvicorncommand not recognized: fixed by activating conda env and usingpython -m uvicorn ....- Swagger
422confusion: clarified that422in docs is an expected schema response type, not always a runtime failure. - AI provider format mismatch (ModelScope uses Anthropic-style messages): added dual-format adapter (
openai_compatible+anthropic_compatible). - Local outbound socket restriction during validation: retried with allowed execution mode and completed live API verification.
- Frontend workspace was missing and startup steps were ambiguous: created
frontend/and added exact CMD startup commands. - A heavy Node-based scaffold would increase local setup friction early: used a zero-install static MVP first so validation can proceed immediately.
- Frontend needed a real smoke check instead of file-only delivery: served it locally and verified
index.html,app.js, andstyles.cssall returned200. - Desktop shell implementation needed to stay storage-aware: created the Electron project files and docs first, without installing
node_modulesyet. - Medium-strength site blocking needed to be reversible: restricted hosts-file edits to a managed marker section only.
- Long one-shot shell writes became unreliable for large frontend files: switched to chunked writes for large JS content.
- PowerShell regex replacement inserted literal newline tokens into desktop guard code: replaced that approach with a clean full-file rewrite.
- First Electron install attempt timed out against
registry.npmjs.org: retried with a one-time registry mirror and Electron mirror. - User did not want persistent npm cache config: used only
npm_config_cacheenvironment variable for the current install session and did not create.npmrc. - Local
npm run checkfirst failed due tool sandbox refresh, not project code: reran with allowed execution mode and confirmed the script passed.
- Backend compile checks passed for all modules.
- Auth flow passed: register -> login -> current user retrieval.
- Focus flow passed: start -> complete -> points settled.
- Redeem flow passed: create -> verify -> cancel(second order) -> ledger consistency.
- Learning flow passed:
- Simplified the focus page by removing extra small labels and hiding the timer-side session summary chips that were cluttering the layout.
- Reworked blocked website entry on the focus page into repeatable input rows so users can add multiple websites one by one.
- Added desktop-side app list IPC plumbing so the focus page can request a selectable app list from Electron instead of asking users to guess process names manually.
- Added frontend blocked-app search, refresh handling, and multi-select state management for the new focus-session setup flow.
- Fixed the Windows app-list PowerShell script so Electron can actually load selectable apps, and added an app-list load event to the focus-page guard log.
- Hid the remaining focus-page headline banner and simplified the focus blocker labels to plain "Apps" and "Websites".
- Simplified app labels by removing
.exefrom the UI and set the Windows PowerShell output encoding to UTF-8 so Chinese app names can display correctly. - Added English display-name mappings for common Chinese desktop apps and changed the app selection cards to a larger single-line layout with ellipsis for long names.
- Restored the top guide banner on the Learning page so it matches the Rankings page instead of leaving an empty strip above the focus controls.
- Simplified the Learning page guide header to one clear sentence and hid the extra subtext on that page.
- Compressed the Learning page hero into a simple guide header by hiding the image and hero status cards there, then replaced the long title with a shorter plain sentence.
- daily question returns
200 - ai-chat returns
200with configured ModelScope credentials
- Frontend delivery smoke test passed:
GET /->200GET /src/app.js->200GET /src/styles.css->200
- Desktop syntax validation passed:
node --check desktop/main.jsnode --check desktop/preload.jsnode --check desktop/guard/focusGuard.js
- Desktop Windows script parse passed:
siteBlock.ps1parsed successfully through PowerShell scriptblock validation
- Desktop dependency validation passed:
npm installcompleted successfullynpm run checkcompleted successfully
- Database: local MySQL 8, schema initialized and seeded.
- Python: conda env
study_focus_backend. - Backend API docs:
http://127.0.0.1:8000/docs. - Frontend local entry:
http://127.0.0.1:5173. - Desktop dependency paths now exist inside the workspace:
D:\daima\cursor\合作项目\desktop\node_modulesD:\daima\cursor\合作项目\desktop\.npm-cacheD:\daima\cursor\合作项目\desktop\package-lock.json
- Run the first real Electron desktop session test.
- Add merchant role-based auth for redeem verification endpoint.
- Add automated tests (pytest + frontend smoke checks).
- Add stronger desktop guard options such as foreground-window checks and optional terminate-on-violation mode.
- Migrate the frontend MVP to Vue 3 + Electron when interaction details are stable.
- Ran a live desktop guard process-watch test outside the sandbox.
- Started guard with blocked app list containing
ping.exe. - Spawned a real
pingprocess and confirmed guard emittedblocked_app_detected. - Result:
GUARD_PROCESS_WATCH=OK. - Launched the Electron app once for a smoke test and confirmed an
electronprocess started successfully. - Result:
ELECTRON_SMOKE=OK. - The smoke test process was then terminated cleanly after validation.
- Live system hosts-file write was not executed automatically in this round because it is administrator-sensitive and affects machine networking.
- Confirmed the real MySQL password exists only in
backend/.env. - Confirmed
.envis ignored by.gitignore, whilebackend/.env.examplekeeps placeholder values for safe sharing. - Confirmed this workspace is not yet initialized as a git repository.
- Strengthened
.gitignoreto exclude*.egg-info/build artifacts before GitHub upload.
- Current browser and desktop core flows are working.
- AI integration still needs another debugging pass in the user's local environment, even though earlier API validation succeeded in controlled checks.
- The codebase is being uploaded first so iteration can continue from GitHub with a cleaner collaboration flow.
- AI call path is not fully stable in the latest user-side manual test and needs follow-up debugging after repository upload.
- The desktop website blacklist path exists in code, but a full live validation with administrator permission is still pending.
- Browser AI chat should be retested after confirming the active ModelScope key and backend runtime environment.
- Website blacklist should be retested in Electron under administrator mode with sample domains such as
youtube.comandbilibili.com. - Process blacklist validation already passed and should be treated as the current confirmed medium-strength anti-distraction feature.
- Created and switched to the dedicated working branch
sprint1-qin-tianfor Sprint 1 document preparation. - Reviewed
Something_to_write/计划.mdand limited the document scope to Sprint 1 deliverables only. - Updated
12_ Project Problem Domain Activity Sheet.docxto align the group naming with the current Sprint 1 submission set. - Completed
SPRINT 1A - Retrospective Activity Sheet.docxwith Sprint 1 summary, accomplishments, and further-work notes. - Completed the relevant Sprint 1 section in
Team Leader Report Template.docxwith finished work, pending work, and current schedule status. - Added Sprint 1 meeting records to
Team Meeting Summary Template.docxand kept later unused rows untouched. - Confirmed the current open issues are still the AI call follow-up and the pending administrator-mode validation for website blacklist control.
- Re-read the backend, frontend, Electron guard, schemas, and SQL structure before making Sprint 2 changes.
- Confirmed the architecture is still a thin static frontend + FastAPI backend + Electron desktop shell, with business logic concentrated in service-layer modules.
- Identified the first Sprint 2 priority as the focus settlement loophole in
backend/app/services/focus_service.py. - Confirmed that
complete_session()had been defaultingactual_minutestoplanned_minutes, which meant a user could finish immediately and still receive full points. - Identified the second priority as redeem verification authorization in
backend/app/api/v1/redeem_orders.py, because/verifycurrently requires only a logged-in user and has no merchant-role boundary yet. - Confirmed the AI instability issue still matters, but it is lower priority than the focus reward integrity bug.
- Confirmed the desktop website blacklist path still needs clearer validation messaging and later administrator-mode live testing.
- Planned Sprint 2 execution order: fix focus reward integrity first, then tighten redeem verification boundaries, then improve AI stability and desktop site-block validation feedback.
- Updated
backend/app/services/focus_service.pyso a running session can only be completed after the planned duration has actually elapsed. - Removed the previous trust in client-provided completion minutes for reward settlement.
- The backend now rejects early completion attempts with a clear error message and keeps interruption as the intended early-exit path.
- Added
backend/tests/test_focus_service.pyto cover both failure and success paths for session completion settlement. - Verified with
python -m unittest discover -s tests -vinbackend/and confirmed both focus completion tests passed.
- Adjusted focus lifecycle semantics based on teacher feedback:
interruptnow preserves elapsed time for resume, whileabandonclears elapsed time. - Updated
backend/app/services/focus_service.py:- interrupted sessions now keep
actual_minutes, remain unsettled, and can be resumed - added
resume_session()to continue from saved elapsed time - abandoned sessions now reset
actual_minutesto0 - blocked creating a new session when an unfinished interrupted session already exists
- interrupted sessions now keep
- Added
POST /api/v1/focus-sessions/{id}/resumeinbackend/app/api/v1/focus_sessions.py. - Updated the frontend focus panel so interrupted sessions can be resumed from the dashboard without losing saved progress.
- Updated the desktop guard interruption flow so a guard-triggered interrupt now pauses the session instead of clearing its saved elapsed time.
- Expanded
backend/tests/test_focus_service.pyto cover interrupt, resume, abandon, and the interrupted-session start guard. - Verified with:
python -m unittest discover -s tests -vpython -m compileall app testsnode --check frontend/src/app.js
- Tightened the redeem verification path so
/api/v1/redeem-orders/verifyis no longer available to any logged-in user without extra merchant proof. - Added
REDEEM_VERIFY_TOKENto backend configuration and.env.example. - Updated
backend/app/services/redeem_service.pyto require:- a configured merchant verify token
- a valid
X-Merchant-Tokenrequest header verifier_idmatching the current logged-in username
- Updated
backend/app/api/v1/redeem_orders.pyto return clearer HTTP statuses for verify failures:403for permission problems503when merchant verification is not configured400for business-state errors such as expired or already-verified orders
- Updated the frontend verify form to collect the merchant token and send it via
X-Merchant-Token. - Bound the frontend verifier ID to the current logged-in username so the UI no longer encourages verifier spoofing.
- Added
backend/tests/test_redeem_service.pyto cover token configuration, invalid token rejection, verifier mismatch rejection, and successful verification.
- Improved
desktop/scripts/windows/siteBlock.ps1so it now checks for administrator permission before editing the Windows hosts file. - Switched hosts-file writing to an explicit UTF-8 without BOM write path and wrapped it in clearer error handling.
- Updated
desktop/guard/focusGuard.jsso site-block failures are classified more clearly, especially the administrator-required case. - Added
siteBlockReasonto guard status and surfaced a clearerpermission_requiredstate for renderer messaging. - Updated the frontend desktop-guard status note so Electron now tells the user directly when site blocking needs administrator launch, instead of only showing a vague failure.
- Updated the blocked-app guard copy to match the new pause/resume semantics introduced earlier in Sprint 2.
- AI stability hardening work was intentionally deferred in this round after the user chose to postpone AI changes and explore cloud deployment options for a distilled model later.
- Verified with
python -m unittest discover -s tests -v. - Verified with
python -m compileall app tests. - Verified frontend syntax with
node --check frontend/src/app.js. - Verified desktop guard syntax with
node --check desktop/guard/focusGuard.js. - Verified PowerShell parsing with
[scriptblock]::Create((Get-Content 'desktop/scripts/windows/siteBlock.ps1' -Raw)).
- Added a new
feedback_messagetable indb/schema.sqland created the matching backend model, schema, service, and API route files. - Added authenticated feedback APIs so logged-in users can submit improvement suggestions with
POST /api/v1/feedbackand review their recent submissions withGET /api/v1/feedback/my. - The feedback payload now stores category, title, content, optional contact email, and timestamps, which makes the suggestion box a real data collection path instead of a frontend-only mock.
- Updated the frontend dashboard with a dedicated feedback panel so users can leave improvement ideas directly inside the product and immediately see their recent messages.
- Wired feedback loading into the normal dashboard refresh flow so new submissions appear after save without manual page reload.
- Added
backend/tests/test_feedback_service.pyto cover trim behavior, post-trim validation, and newest-first ordering.
- Re-verified with
python -m unittest discover -s tests -vafter the feedback module landed. - Re-verified with
python -m compileall app tests. - Re-verified frontend syntax with
node --check frontend/src/app.js.
- Added
db/add_feedback_message.sqlso an already-initialized local MySQL database can enable the feedback module without a full schema reset.
- Decided to keep the current AI path on the user's existing free API for Sprint 2 instead of switching to a self-hosted distilled model.
- The main reason is delivery risk control: the current
backend/app/services/ai_service.pyadapter already supports provider switching, while self-hosting would add new deployment and runtime variables late in the sprint. - This keeps the AI feature aligned with the present backend design and leaves self-hosted distilled-model deployment as a later optimization path rather than a Sprint 2 dependency.
- If the local MySQL database was initialized before the feedback module was added, run
db/add_feedback_message.sqlonce before testing the new feedback feature. - Start the backend with the configured AI API environment variables and verify
http://127.0.0.1:8000/docsloads successfully. - Start the static frontend on port
5173and confirm login, dashboard refresh, and authenticated API calls work normally. - Optional but recommended: start Electron and confirm desktop guard status appears in the dashboard.
- Focus flow manual check:
- start a session
- interrupt it and confirm saved minutes remain
- resume it and confirm the timer continues
- abandon it and confirm the session is dropped without retained progress
- Redeem flow manual check:
- create a redeem order
- verify it with the configured merchant token
- confirm invalid or missing token requests are rejected
- Feedback flow manual check:
- submit one message in the new feedback panel
- refresh the dashboard
- confirm the message appears in the recent feedback list
- AI flow manual check:
- send one simple study question through the dashboard
- confirm the reply returns through the configured free API
- if the provider limit is hit, record the error message and treat it as a quota issue rather than a backend routing failure
- Website blacklist manual check remains pending under administrator-launched Electron and should be tested separately with sample domains such as
youtube.comandbilibili.com.
- Replaced the previous
urllib-based AI HTTP transport inbackend/app/services/ai_service.pywith an explicit UTF-8 JSON request flow. - The goal of this change is to avoid the previous request-path encoding failure observed when sending Chinese questions such as
你是谁. - Added
backend/tests/test_ai_service.pyto verify that Chinese prompt content is emitted as UTF-8 in the outbound provider request body.
- Updated
backend/app/services/focus_service.pyso interrupted sessions now resume from the exact saved elapsed duration instead of only the floored whole-minute value. - Updated
frontend/src/app.jsso the paused-session countdown is rendered from the exact saved elapsed time, which means an interrupt at24:15remaining will now resume from24:15rather than jumping back to25:00. - Added a backend test for sub-minute pause/resume continuity in
backend/tests/test_focus_service.py.
- Re-verified with
python -m unittest discover -s tests -vafter the AI transport and exact-resume fixes. - Re-verified with
python -m compileall app tests. - Re-verified frontend syntax with
node --check frontend/src/app.js.
- Added
backend/scripts/smoke_ai_chat.pyfor direct login-plus-AI endpoint testing. - Added
backend/scripts/smoke_focus_resume.pyfor direct interrupt/resume remaining-time testing.
- Expanded the leaderboard backend to support college, school, and cross-school scopes with optional school and college selection.
- Enriched leaderboard rows with school and college names so the UI can show full campus labels during demos.
- Simplified the redeem panel to focus on coupon-code generation and generated-code display instead of making verification the main workflow.
- Updated demo dictionary seed data to use full campus names such as
Hubei UniversityandWuhan University of Science and Technology. - Added
db/add_demo_leaderboard_dicts.sqlfor incremental demo dictionary updates on existing databases. - Added
db/add_demo_leaderboard_samples.sqlso existing databases can seed one Hubei University college sample and one Wuhan University of Science and Technology sample for leaderboard demos.
- Removed the remaining dashboard-side redeem verification and cancel actions so the user flow now focuses on generating and copying coupon codes only.
- Cleaned the leaderboard context strings and campus labels so demo separators render as normal
/text instead of encoding-garbled characters. - Kept the backend redeem verify endpoint available for future merchant flows, but it is no longer part of the main Sprint 2 demo path.
- Refreshed the leaderboard presentation in
frontend/src/app.jsandfrontend/src/styles.cssso ranking entries now render as showcase cards instead of plain rows. - Highlighted the top three positions with distinct visual treatment and added clearer score, campus, and focus-stat chips for demo readability.
- Kept the college, school, and all-schools filter structure unchanged while improving the visual hierarchy for presentation use.
- Adjusted the desktop-guard violation flow so blocked-app detection now abandons the active session instead of creating a resumable interrupt.
- This means guard-triggered violations now clear saved progress and award zero points, while manual interrupt still remains resumable.
- Updated the desktop guard event wording to match the new no-reward abandonment behavior for demos and teacher review.
- Extended the Electron guard so website monitoring now also inspects visible browser window titles for blocked domain keywords such as
bilibiliandyoutube. - Added desktop popup alerts for blocked app and blocked site violations so the user gets an immediate warning window when focus rules are broken.
- Updated the renderer guard flow so both blocked apps and blocked sites now end the session with abandon-style clearing and zero reward.
- Adjusted the Electron focus-window policy so the app no longer pins itself above every other window during testing.
- FULL_LOCK still uses full-screen presentation, but users can now Alt+Tab away to deliberately open blocked apps or blocked websites for validation.
- This keeps the demo visually strong while making manual guard testing practical.
- Added dual monitoring behavior:
- website mode now checks whether the user leaves the Guide Page after consent
- desktop mode still uses Electron for stronger app/site monitoring after consent
- Added a 15-second grace window before website-mode leave-page violations are settled.
- Added delete support to the local plan notebook so tasks can now be removed as well as checked off.
- Simplified the visible daily-question UI on the Learning page by removing extra top badges, refresh action, inline answer-result text, and hint copy.
- Shortened the feedback headline to
Collect improvement notes.for a cleaner demo surface. - Hardened AI response parsing so OpenAI-compatible providers that return non-
choicespayload shapes can still produce an answer instead of failing immediately. - Updated frontend versioned asset references again to force browsers onto the latest static bundle.
- Website mode is intentionally honest about its limits: it detects leaving the study page, not exact external websites.
- Desktop mode is still the only path that can inspect blocked apps and browser-window titles locally.
- AI should now be retested against the user's active provider credentials after restarting the backend process.
- Added a stronger browser-mode violation notice flow so leaving the Guide Page now persists a pending warning and shows a blocking alert when the user returns.
- Kept the website-mode grace window at 15 seconds, but made the abandon result much more explicit than a background toast.
- Removed the
NONEoption from the Guide Page lock-mode selector so the public demo no longer suggests an unguarded mode.
- Removed the visible
Lock Modeselector from the Guide Page form and now submitAPP_BLOCKas the default mode behind the scenes so the UI stays simpler for the web demo. - Removed visible
Lock ...badges from the running-session and session-history summaries so the public focus flow no longer exposes extra mode jargon. - Reworked website-mode away tracking to persist the leave timestamp and trigger reason, then settle the violation when the user returns to the Guide Page instead of relying on background-tab timers.
- Bumped the frontend asset version to
sprint4r15so the updated Guide Page / Learning rename and website-mode popup behavior can break through cached static files.
- Renamed the main focus surface from
Guide PagetoLearningand renamed the former daily-question route toBreak Spaceso the navigation no longer shows two competing learning labels. - Added
pagehidetracking plus a post-refresh return check so same-tab jumps to external sites like bilibili can still be settled when the user comes back to the Learning page. - Changed browser-mode violation notices so they only render on the Learning page itself instead of popping on unrelated routes such as Feedback or Rankings.
- Expanded the OpenAI-compatible backend adapter so it now parses more payload shapes, including legacy
choices[].text, nested response wrappers, and provider error payloads. - Added a backend fallback from
chat/completionstoresponseswhen the primary endpoint returns an empty-but-successful body, which should reduce theNo choices in OpenAI responsefailures seen in the web demo. - Added a lightweight frontend retry for AI chat so one transient 5xx or empty-response style failure does not immediately surface as a red error bubble to the user.
- Bumped the frontend asset version to
sprint4r16so the AI retry behavior can break through cached static files.
- Removed the visible
Complete Sessionbutton from the Learning page because it was just a manual settlement control that added clutter to the demo. - Added automatic session completion when the countdown reaches zero, so points are still awarded without requiring an extra click.
- Bumped the frontend asset version to
sprint4r17so the button removal and auto-complete behavior can break through cached static files.
- Expanded
db/add_demo_leaderboard_samples.sqlso demo data now covers richer rankings plus at least one row in each major business table: users, focus sessions, point ledger, daily question attempts, redeem orders, and feedback messages. - Added extra demo accounts across both schools and colleges so the day leaderboard looks fuller and no longer appears nearly empty during teacher demos.
- Updated
seed_demo.ps1to load the daily-question migration and the richer showcase seed set by default, so a fresh deployment can reach the same visible state as local testing with one command. - Updated
seed_leaderboard_demo.ps1andDEPLOYMENT.mdso existing environments can refresh only the showcase dataset without re-running the full schema bootstrap.
- Added a second popup after monitoring consent so each login session can choose
New UserorExperienced User. New Usernow shows a simple three-step guide card at the top of the Focus, Rankings, Break Space, Rewards, and Feedback pages.Experienced Userkeeps only the normal page header and hides the extra guide cards, which matches the lighter teacher-demo flow.- Bumped the frontend asset version to
sprint4r23so the new guide-mode popup and page-guide layout can break through cached static files.
- Changed the local desktop/static frontend default API target to
http://175.24.206.75/api/v1so the current demo build points to the deployed server without manual input. - Added migration logic that replaces older cached
127.0.0.1:8000API values with the new server default when the app is opened fromfile://or another local page. - Bumped the frontend asset version to
sprint4r24so the updated API-base fallback can break through cached static files.