fix(web/ctx): widen Sync All status coverage to error/aborted (#799)#801
Merged
fix(web/ctx): widen Sync All status coverage to error/aborted (#799)#801
Conversation
PR #798 (#774) added a Sync All branch for `needs_confirmation` only. The route's per-result status is one of `ok` / `skipped` / `error` / `needs_confirmation` / `aborted`, so the same "resp.ok hides per-result failure" class still bit users when a generator returned `error` (canonical or target file is malformed JSON) or `aborted` (mtime conflict during merge): the unconditional `sync_success` toast lied about a merge that never landed. Widen the handler to a severity ladder: `error` (error toast, route's `reason` carried through `toast.sync_failed`) > `aborted` (warning, `settings.ctx.mtime_conflict`) > `needs_confirmation` (info partial + Open Settings action, unchanged from #774) > all-`ok`/`skipped` (`sync_success`). Both new branches reuse i18n keys already used by the per-target Sync flow, so no new translations are needed. Symmetric pin per `feedback_pin_invert_symmetric_assertion`: `test_issue_799_sync_all_status_coverage` asserts both `firstWithStatus('error')` and `firstWithStatus('aborted')` literals plus `t('toast.sync_failed'` / `t('settings.ctx.mtime_conflict')`, and inverts on `showToast(t('settings.ctx.sync_success'))` so a regression that collapses the ladder back to a single branch fails. Co-Authored-By: Claude <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
okSettings status, notjust
needs_confirmation(fix(web/ctx): Sync All silently skips Settings host-write target on default allow_host_writes=False #774 left two siblings on the table).error→ error toast carrying the route'sreasonvia
toast.sync_failed;aborted→ warning toast viasettings.ctx.mtime_conflict. Both reuse i18n keys already used bythe per-target Sync flow — zero new translations.
error>aborted>needs_confirmation>all-
ok/skipped.Why
Closes #799.
generate_all_settings(
packages/memtomem/src/memtomem/context/settings.py:261) returns oneof five per-result statuses:
ok/skipped/error/needs_confirmation/aborted. PR #798 (#774) only added a branchfor
needs_confirmation, so the underlying "resp.ok hides per-resultfailure" pathology still applied to
errorandaborted:error— canonical or target file is malformed JSON. Route returns{"results": [{"name": "claude_settings", "status": "error", "reason": "/path/to/file is not valid JSON. Fix the file manually..."}]}. Pre-fix(web/ctx): Sync All toastssync_successfor non-okSettings statuses (error,aborted) #799 JS toastedsync_successregardless.aborted— concurrent-write mtime conflict. Route returns{"results": [{"status": "aborted", ...}]}. Same lie.The dedicated per-target Sync flow at
web/static/context-gateway.js:653, 946-955already surfaces theseas
mtime_conflict(warning) /request_failed(error). This PRbrings Sync All in line with the same shape.
Concrete edits
web/static/context-gateway.js.some()check with afirstWithStatus(s)helper + severity ladder (error→aborted→needs_confirmation→ success). Comment block updated to enumerate all five statuses + map to toast classes.web/static/index.htmlcontext-gateway.js?v=14→?v=15(cache-bust perfeedback_static_asset_cache_bust).tests/test_i18n.pytest_issue_799_sync_all_status_coverage— symmetric pin with positive markers (firstWithStatus('error'),firstWithStatus('aborted'),t('toast.sync_failed',t('settings.ctx.mtime_conflict')) + inverted marker (showToast(t('settings.ctx.sync_success'))survives the new ladder's else branch).CHANGELOG.md[Unreleased] → ### Fixedentry.Total diff: 4 files, +92 / −15.
Pin shape
test_issue_799_sync_all_status_coverageasserts:firstWithStatus('error')literal exists — pre-PR shape only had'needs_confirmation', so the assertion fails on the old code.firstWithStatus('aborted')literal exists — same.t('toast.sync_failed'exists in the file — already there in thecatchblock, so the assertion holds; the newerrorbranchshares the same key, so a regression that drops the new branch
leaves
toast.sync_failedreachable only on transport-layerfailure (no positive marker remains for the per-result
errorcase — which is exactly what
firstWithStatus('error')catches).t('settings.ctx.mtime_conflict')exists — pre-PR the onlyreference was the per-target Sync handler, so this assertion
formerly held; with the new branch it has a second reference
and the assertion still holds. The
firstWithStatus('aborted')marker provides the strict positive pin for the new site.
showToast(t('settings.ctx.sync_success'))must remain in the file. A regression that collapses the new
severity ladder into a single error toast (e.g. removes the else
branch) drops this literal and fails the assertion.
Test plan
uv run pytest -m "not ollama" packages/memtomem/tests/test_i18n.py packages/memtomem/tests/test_context_settings.py— 57/57 green(incl. the new
test_issue_799_sync_all_status_coverage).uv run ruff check packages/memtomem/src && uv run ruff format --check packages/memtomem/src— clean. Tests file ruff-formattedin the same commit.
canonical
.memtomem/settings.jsonis malformed JSON (routereturns
status="error"); confirm an error-level toast surfacesthe reason instead of
sync_success.Out of scope
Sync Nowhost-write confirmationflow (
settings-hooks-watchdog.js) — Option 2 from fix(web/ctx): Sync All silently skips Settings host-write target on default allow_host_writes=False #774, larger UXcut.
except claude_settings — ..."). The current ladder uses generic
reasons; a future cut can name the generator if multi-generator
settings sync becomes more common.
Refs: #774 (parent), PR #798 (
needs_confirmationbranch), #761 /#771 (gate-flip that exposed the silent-skip class).
🤖 Generated with Claude Code