Skip to content

fix: surface living ui persistence failures - #378

Merged
CraftOS-dev merged 2 commits into
CraftOS-dev:devfrom
BharadwajKanneveti:fix/living-ui-save-projects
Jul 13, 2026
Merged

fix: surface living ui persistence failures#378
CraftOS-dev merged 2 commits into
CraftOS-dev:devfrom
BharadwajKanneveti:fix/living-ui-save-projects

Conversation

@BharadwajKanneveti

Copy link
Copy Markdown
Contributor

What

  • Updated _save_projects() to re-raise persistence errors instead of silently swallowing them.
  • Added caller-level handling for project save failures based on the execution context.
  • Added warning handling for running projects when state persistence fails, while allowing the active process to continue.

Why

_save_projects() previously caught all write failures internally and only logged them. This caused project state changes to be silently lost when persistence failed due to issues like permission errors or disk failures.

As a result, projects could disappear after restart, auto-launch state could be lost, and task links could become unavailable.

This change ensures persistence failures are visible and handled appropriately instead of being silently ignored.

Closes #214

Signed-off-by: Bharadwaj <bharadwajkanneveti@gmail.com>
@BharadwajKanneveti

Copy link
Copy Markdown
Contributor Author

Hi @AlanAAG I have raised the PR please check and let me know if you find any issue

@AlanAAG

AlanAAG commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Hi @AlanAAG I have raised the PR please check and let me know if you find any issue

Hey @BharadwajKanneveti Thank you for the contribution will review promptly! Will let you know over here.

@AlanAAG AlanAAG left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BharadwajKanneveti hey some comments after review

Correct core fix — _save_projects() re-raises, all 17 real callsites are wrapped and correctly triaged into the 3 buckets, _load_projects() correctly untouched. ruff clean.

1. Two callsites outside this file aren't wrapped

app/ui_layer/settings/profile_bundle.py:939 (_register_living_ui_via_manager) and :974 (_wipe_living_ui_state) call _save_projects() unwrapped. Caught by an outer except Exception in import_profile() so nothing crashes, but a Living UI save failure now reports the entire profile-bundle import as "Import failed", even if skills/MCP/personality already applied successfully. Fix: wrap both in try/except, log-and-continue bucket.

2. The warning key never reaches a user — this is the one that matters

Traced every caller of launch_and_verify() / _launch_servers_only() and confirmed by test:

  • launch_project() (browser adapter's entry point) collapses the result to a bare bool.
  • living_ui_actions.py::living_ui_notify_ready() and app/living_ui/actions.py::restart_living_ui() both rebuild their own success dict without checking result.get("warning").

Result: the warning: state_not_persisted key computed in the 3 critical paths is dead code — no user, toast, or agent message will ever see it. Right now this fix makes failures visible in server logs only; it doesn't yet deliver the user-visible warning the issue requires ("the user must know the state won't survive a restart"). Fix: have the 3 callers of launch_and_verify()/_launch_servers_only() check for and relay warning up through to their response.

@zfoong

zfoong commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

@BharadwajKanneveti @AlanAAG The warning does not have to surface to the user, toast, or agent message for now. We are revamping the LivingUI system, so as long as the warning is surface to service log, then it should be fine.

@BharadwajKanneveti

Copy link
Copy Markdown
Contributor Author

Thanks for the clarification!

@AlanAAG @zfoong
Just to confirm before I update the PR: based on your comment, should I only implement the profile_bundle.py changes and leave the warning propagation (launch_project(), living_ui_notify_ready(), and restart_living_ui()) unchanged, since logging the warning is sufficient for now?

@zfoong

zfoong commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the clarification!

@AlanAAG @zfoong Just to confirm before I update the PR: based on your comment, should I only implement the profile_bundle.py changes and leave the warning propagation (launch_project(), living_ui_notify_ready(), and restart_living_ui()) unchanged, since logging the warning is sufficient for now?

Yes I think we can go with that for now. Thanks! Another PR is also making big changes to Living UI, so let's leave it as it is.

Signed-off-by: Bharadwaj <bharadwajkanneveti@gmail.com>
@BharadwajKanneveti

BharadwajKanneveti commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Hi @zfoong @AlanAAG I have made the changes please check and let me know if you find any issue.

@CraftOS-dev
CraftOS-dev merged commit 3bfb5a9 into CraftOS-dev:dev Jul 13, 2026
ahmad-ajmal added a commit that referenced this pull request Aug 7, 2026
## Sync V1.4.1 → dev

Brings dev up to date with the V1.4.1 line (55 commits). The headline
changes:

### Living UI platform
- **Trigger plane (app → agent communication)**: Living UIs declare
  triggers in `triggers.json`; fires land in an in-app `agent_requests`
  queue, pass capability/consent/era gates at the host, and the agent
  claims, acts, and posts the result back to the app and chat. Includes
  gate enforcement (derived `capabilities.triggers`, no self-answering
  hooks), kit helpers (`fireAgentTrigger`/`useAgentRequest`), and
  `lui trigger`/`lui requests` CLI commands.
- **Rename `living-ui-v2` → `living-ui`**: directory, runner module/class,
  log tags, CI workflow, and all prose — the manifest's
  `livingUIVersion: 2` protocol field is unchanged.
- Verifier hardening: turn budgets, early-end guard, evidence rules
  (incl. `callLLM` for AI features), `browser_drag`, spec supersession
  (`~~strikethrough~~` in `## Changes`), throttled-LLM classification.

### Run stop (#410)
Cancellation now genuinely reaches in-flight actions and settlement waits
for them — no more output landing after "Run stopped." (compat `wait_for`
shim, executor thread wait, action-manager re-raise; 5 regression tests).

### UI
Dashboard revamp (grid layout, widget sizing, token-usage fixes), mobile
chat fixes, tooltips.
**Note:** run `npm install` in `app/ui_layer/browser/frontend` after
pulling — the dashboard adds `react-grid-layout`.

### Conflict resolution
The only conflicted file was `app/living_ui/manager.py`: dev's PR #378
(guard `_save_projects()` call sites) was written against the old
two-process Living UI architecture that V1.4.1 has since replaced.
Resolution: V1.4.1's architecture wins wholesale, with PR #378's intent
ported onto it — persist failures in the watchdog paths now log instead of
breaking restart/escalation. The launch-path guards weren't ported because
the new action layer already surfaces persist failures as honest action
errors. Dropped `project.backend_process` (attribute no longer exists).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants