Problem
mm web Context Gateway "Sync All" inspects the Settings sync response body
for status === 'needs_confirmation' (#774, PR #798) but treats every other
non-ok per-result status as full success. The route at
/api/context/settings/sync (generate_all_settings,
packages/memtomem/src/memtomem/context/settings.py:261) can return five
status values per generator:
| status |
meaning |
ok |
merged + written |
skipped |
runtime not installed / no canonical source (benign) |
error |
canonical or target file is malformed JSON |
needs_confirmation |
host-write target without allow_host_writes=true |
aborted |
mtime conflict during merge (concurrent write race) |
After PR #798 the JS at web/static/context-gateway.js:248-265 only
branches on needs_confirmation. So:
error → still toasts settings.ctx.sync_success even though the merge
failed because of malformed JSON.
aborted → still toasts sync_success even though the merge was
rolled back due to a concurrent writer.
skipped → benign; success toast is fine.
This is the same class of bug as #774 (resp.ok hides per-result failure)
just with different status values.
Repro
- Make
~/.claude/settings.json malformed (e.g. trailing comma).
mm web → Sync All.
/api/context/settings/sync returns 200 with
{"results": [{"name": "claude_settings", "status": "error", ...}]}.
- UI toasts "Sync complete" — lie.
Proposed shape
Widen the predicate in the Sync All handler to surface a structured
toast for any result.status not in {"ok", "skipped"}:
i18n keys can mirror the existing per-status messages used elsewhere
(settings.ctx.mtime_conflict, generic toast.sync_failed). The
dedicated Settings panel's Sync Now button (settings-hooks-watchdog.js:150)
has the same gap and may be in scope or a separate cut.
Test shape
Extend tests/test_i18n.py::test_issue_774_sync_all_inspects_settings_body
(or add a sibling test) to symmetric-pin all four non-ok branches:
positive marker for each handled status + inverted assertion that the
unconditional sync_success path is gone for those statuses.
Refs
Out of scope
The Settings panel's Sync Now (settings-hooks-watchdog.js:150)
host-write confirmation flow itself (Option 2 from #774). That's a
larger UX change tracked separately.
Problem
mm webContext Gateway "Sync All" inspects the Settings sync response bodyfor
status === 'needs_confirmation'(#774, PR #798) but treats every othernon-
okper-result status as full success. The route at/api/context/settings/sync(generate_all_settings,packages/memtomem/src/memtomem/context/settings.py:261) can return fivestatus values per generator:
okskippederrorneeds_confirmationallow_host_writes=trueabortedAfter PR #798 the JS at
web/static/context-gateway.js:248-265onlybranches on
needs_confirmation. So:error→ still toastssettings.ctx.sync_successeven though the mergefailed because of malformed JSON.
aborted→ still toastssync_successeven though the merge wasrolled back due to a concurrent writer.
skipped→ benign; success toast is fine.This is the same class of bug as #774 (
resp.okhides per-result failure)just with different status values.
Repro
~/.claude/settings.jsonmalformed (e.g. trailing comma).mm web→ Sync All./api/context/settings/syncreturns 200 with{"results": [{"name": "claude_settings", "status": "error", ...}]}.Proposed shape
Widen the predicate in the Sync All handler to surface a structured
toast for any
result.status not in {"ok", "skipped"}:needs_confirmation→ existing partial-success toast +Open Settingsaction (already shipped via fix(web/ctx): Sync All silently skips Settings host-write target on default allow_host_writes=False #774 / PR fix(web/ctx): surface Settings needs_confirmation in Sync All toast (#774) #798).
error→ error-level toast naming the malformed file fromreason,no
sync_success.aborted→ warning-level toast with retry hint (matches theper-target Sync flow at
context-gateway.js:946-955).ok(or all-ok+skipped) → existingsync_successtoast.i18n keys can mirror the existing per-status messages used elsewhere
(
settings.ctx.mtime_conflict, generictoast.sync_failed). Thededicated Settings panel's
Sync Nowbutton (settings-hooks-watchdog.js:150)has the same gap and may be in scope or a separate cut.
Test shape
Extend
tests/test_i18n.py::test_issue_774_sync_all_inspects_settings_body(or add a sibling test) to symmetric-pin all four non-
okbranches:positive marker for each handled status + inverted assertion that the
unconditional
sync_successpath is gone for those statuses.Refs
needs_confirmationbranch (this issue's parent).feedback_pin_invert_symmetric_assertion.mdfor test pattern.Out of scope
The Settings panel's
Sync Now(settings-hooks-watchdog.js:150)host-write confirmation flow itself (Option 2 from #774). That's a
larger UX change tracked separately.