fix: persist launch_at_login's honest result, not the request - #4507
Conversation
…4498) The /settings handler wrote the requested launch_at_login value first and only attached set_launch_at_login's result to the response -- which nothing reads. Off macOS (and in a macOS checkout) registration always returns {"enabled": false}, so the toggle rendered on, persisted, and survived restarts while no login item existed. Now the platform action runs first and the persisted value is coerced to what actually happened. Co-authored-by: MervinPraison <MervinPraison@users.noreply.github.com>
|
@coderabbitai review |
|
/review |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
Greptile SummaryThe PR persists the effective launch-at-login result and reconciles the settings UI with server responses.
Confidence Score: 3/5The PR is not yet safe to merge because stale settings responses can override newer user choices and a failed settings write can still leave login registration inconsistent with durable state. Settings requests are neither serialized nor checked for stale responses, while the login-item side effect still occurs before a fallible persistence operation without rollback. Files Needing Attention: src/praisonai-desktop/ui/index.html and src/praisonai-desktop/engine/server.py
|
| Filename | Overview |
|---|---|
| src/praisonai-desktop/engine/server.py | Persists the platform-reported login-item state, but the previously reported registration-before-persistence divergence remains outstanding. |
| src/praisonai-desktop/ui/index.html | Reconciles optimistic settings with server responses, but unsequenced responses can restore an older value after rapid repeated changes. |
| src/praisonai-desktop/engine/test_portability.py | Adds focused coverage for persisting successful and declined launch-at-login outcomes. |
Sequence Diagram
sequenceDiagram
participant U as User
participant UI as Settings UI
participant S as Desktop engine
participant OS as Login-item service
participant D as Settings file
U->>UI: Change launch_at_login
UI->>S: POST /settings
S->>OS: set_launch_at_login(requested)
OS-->>S: Effective enabled state
S->>D: Persist effective state
S-->>UI: Saved settings and platform result
UI->>UI: Reconcile and rerender
Reviews (2): Last reviewed commit: "fix: reconcile launch_at_login toggle fr..." | Re-trigger Greptile
| result = set_launch_at_login(bool(patch["launch_at_login"])) | ||
| patch = {**patch, "launch_at_login": bool(result.get("enabled"))} | ||
| saved = dict(save_settings(patch)) |
There was a problem hiding this comment.
Registration can outlive persistence
If login-item registration succeeds and save_settings then raises, the new ordering leaves the login item registered without updating durable settings, causing the application to launch at login after restart while the saved option remains off or stale.
Knowledge Base Used: Persistence, security, and configuration
|
@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Review changes in this PR. Python SDK: praisonaiagents, praisonai. TypeScript SDK: src/praisonai-ts/. Do NOT modify src/praisonai-rust. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding. Phase 1: Review per AGENTS.md
Phase 2: FIX Valid Issues Phase 3: Final Verdict |
|
Claude finished @MervinPraison's task —— View job Final Architecture Review — PR #4507
AssessmentThe core fix in Reviewer feedbackGreptile P1 #1 — "Effective state stays stale" → VALID, FIXED.
Greptile P1 #2 — "Registration can outlive persistence" → acknowledged, NOT fixed (low value / high risk). Verification
Files modified by me
Skipped
Verdict: ✅ ApproveThe server persists the honest result and the UI now reflects it in-session with a clear explanation. Backward-compatible, no hot-path impact, no core-SDK surface change. |
The settings client optimistically set launch_at_login=true and ignored the POST response, so when the OS declined to register a login item the toggle stayed on for the session even though the server persisted false. saveCfg now reads the response and reconciles any keys the server wrote back, and the launch_at_login handler surfaces the explanation. Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
| // any key it wrote back so the current session never shows a value that was | ||
| // never saved -- e.g. "Open at login" the OS refused to register. | ||
| if(saved && typeof saved==='object'){ | ||
| for(const k of Object.keys(patch)) if(k in saved){ CFG[k]=saved[k]; cfg[k]=saved[k]; } |
There was a problem hiding this comment.
|
Merge gate scan — eligible for assessment. Claude merge gate will assess and may auto-merge if |
|
Merged by Claude PR merge gate ( |
Fixes #4498
Problem
The desktop
/settingshandler wrote the requestedlaunch_at_loginvalue first, then only attached
set_launch_at_login(...)'s result to theresponse as
launch_at_login_result— which nothing reads. On Windows/Linux,and on macOS running from a checkout,
set_launch_at_loginalways returns{"enabled": false, "message": "Only available in the installed app."}. Sothe toggle rendered on, persisted, and survived restarts while no login item
was ever registered.
Fix (
engine/server.py)Run the platform action first, coerce the persisted
launch_at_logintowhat actually happened (
result["enabled"]), then save. The honest result isstill surfaced as
launch_at_login_resultso the UI can show the explanationwhen
enabledcame back false.Test (
engine/test_portability.py)New
LaunchAtLoginclass drives the real/settingsPOST handler withset_launch_at_loginstubbed to the non-bundle result and asserts thepersisted settings read back
falseand the response carries theexplanation. Verified this fails on the old code (persisted
true) and passeswith the fix. Full suite: 49 tests pass.
Generated with Claude Code